Decompiled source of PeglinFonts v1.0.0

PeglinFonts.dll

Decompiled 18 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using I2.Loc;
using Microsoft.CodeAnalysis;
using PeglinFonts.Core;
using PeglinUI.SettingsMenu;
using Rewired;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.TextCore;
using UnityEngine.TextCore.LowLevel;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("PeglinFonts")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+3bdecd4c84d8f20722edfac1f645b11ef0f2a823")]
[assembly: AssemblyProduct("PeglinFonts")]
[assembly: AssemblyTitle("PeglinFonts")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace PeglinFonts
{
	internal class FontDropdown : MonoBehaviour
	{
		private const string ListName = "PeglinFonts_Dropdown";

		private static int _blockUntilFrame = -1;

		private readonly List<Button> _items = new List<Button>();

		private OptionsMenu _menu;

		private Transform _row;

		private Button _rowButton;

		private RectTransform _panel;

		private float _openedAt;

		private bool _selectedFirst;

		private GameObject _highlighted;

		private static OptionsMenu _suspendedMenu;

		private static OverrideButtonMapWhenSelected _suspendedOverride;

		private static Action<OptionsMenu, bool> _setButtonsActive;

		private static bool _lookedUpSetButtonsActive;

		public static FontDropdown Current { get; private set; }

		public static bool BlocksGameMenus
		{
			get
			{
				if (!((Object)(object)Current != (Object)null))
				{
					return Time.frameCount <= _blockUntilFrame;
				}
				return true;
			}
		}

		public static void Open(OptionsMenu menu, Transform row, Button rowButton)
		{
			if ((Object)(object)menu == (Object)null || (Object)(object)row == (Object)null || (Object)(object)rowButton == (Object)null || (Object)(object)Current != (Object)null)
			{
				Plugin.Log.LogDebug((object)$"Font list not opened: menu={(Object)(object)menu != (Object)null} row={(Object)(object)row != (Object)null} button={(Object)(object)rowButton != (Object)null} alreadyOpen={(Object)(object)Current != (Object)null}");
				return;
			}
			try
			{
				Transform val = ((Component)menu).transform.Find("PeglinFonts_Dropdown");
				if ((Object)(object)val != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)((Component)val).gameObject);
				}
				FontDropdown fontDropdown = Build(menu, rowButton);
				fontDropdown._menu = menu;
				fontDropdown._row = row;
				fontDropdown._rowButton = rowButton;
				fontDropdown.Show();
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Couldn't open the font list: {arg}");
			}
		}

		private static FontDropdown Build(OptionsMenu menu, Button rowButton)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Expected O, but got Unknown
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Expected O, but got Unknown
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Expected O, but got Unknown
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Expected O, but got Unknown
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Expected O, but got Unknown
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_031d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("PeglinFonts_Dropdown", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent(((Component)menu).transform, false);
			val2.anchorMin = Vector2.zero;
			val2.anchorMax = Vector2.one;
			val2.offsetMin = new Vector2(-4000f, -4000f);
			val2.offsetMax = new Vector2(4000f, 4000f);
			((Transform)val2).SetAsLastSibling();
			((Graphic)val.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.25f);
			val.AddComponent<KeepFont>();
			FontDropdown fontDropdown = val.AddComponent<FontDropdown>();
			Button obj = val.AddComponent<Button>();
			((Selectable)obj).transition = (Transition)0;
			Navigation navigation = default(Navigation);
			((Navigation)(ref navigation)).mode = (Mode)0;
			((Selectable)obj).navigation = navigation;
			((UnityEvent)obj.onClick).AddListener(new UnityAction(fontDropdown.Close));
			RectTransform val3 = (RectTransform)((Component)rowButton).transform;
			GameObject val4 = new GameObject("List", new Type[4]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(GridLayoutGroup),
				typeof(ContentSizeFitter)
			});
			fontDropdown._panel = (RectTransform)val4.transform;
			((Transform)fontDropdown._panel).SetParent((Transform)(object)val2, false);
			fontDropdown._panel.pivot = new Vector2(1f, 1f);
			RectTransform panel = fontDropdown._panel;
			RectTransform panel2 = fontDropdown._panel;
			Vector2 val5 = default(Vector2);
			((Vector2)(ref val5))..ctor(0.5f, 0.5f);
			panel2.anchorMax = val5;
			panel.anchorMin = val5;
			((Graphic)val4.GetComponent<Image>()).color = UiCopy.Frame;
			val4.AddComponent<SwallowClicks>();
			float num = ((Transform)val3).lossyScale.x / Mathf.Max(0.0001f, ((Transform)fontDropdown._panel).lossyScale.x);
			Rect rect = val3.rect;
			float num2 = Mathf.Max(((Rect)(ref rect)).width * num, 330f);
			rect = val3.rect;
			float num3 = Mathf.Max(((Rect)(ref rect)).height * num, 34f);
			int count = FontCatalog.All.Count;
			int num4 = MenuLayout.Columns(count);
			GridLayoutGroup component = val4.GetComponent<GridLayoutGroup>();
			((LayoutGroup)component).padding = new RectOffset(6, 6, 6, 6);
			component.spacing = new Vector2(6f, 4f);
			component.cellSize = new Vector2(num2, num3);
			component.startCorner = (Corner)0;
			component.startAxis = (Axis)1;
			component.constraint = (Constraint)1;
			component.constraintCount = num4;
			ContentSizeFitter component2 = val4.GetComponent<ContentSizeFitter>();
			component2.horizontalFit = (FitMode)2;
			component2.verticalFit = (FitMode)2;
			TMP_FontAsset gameFont = FontSwapper.GameFontOf(((Component)rowButton).GetComponentInChildren<TMP_Text>(true));
			FontChoice current = Plugin.Current;
			foreach (FontChoice item2 in FontCatalog.All)
			{
				Button item = fontDropdown.MakeItem(rowButton, item2, item2 == current, gameFont, num3);
				fontDropdown._items.Add(item);
			}
			for (int i = 0; i < fontDropdown._items.Count; i++)
			{
				Button obj2 = fontDropdown._items[i];
				navigation = default(Navigation);
				((Navigation)(ref navigation)).mode = (Mode)4;
				((Navigation)(ref navigation)).selectOnUp = (Selectable)(object)fontDropdown._items[MenuLayout.Move(i, 0, -1, count, num4)];
				((Navigation)(ref navigation)).selectOnDown = (Selectable)(object)fontDropdown._items[MenuLayout.Move(i, 0, 1, count, num4)];
				((Navigation)(ref navigation)).selectOnLeft = (Selectable)(object)fontDropdown._items[MenuLayout.Move(i, -1, 0, count, num4)];
				((Navigation)(ref navigation)).selectOnRight = (Selectable)(object)fontDropdown._items[MenuLayout.Move(i, 1, 0, count, num4)];
				((Selectable)obj2).navigation = navigation;
			}
			return fontDropdown;
		}

		private Button MakeItem(Button template, FontChoice choice, bool selected, TMP_FontAsset gameFont, float height)
		{
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Expected O, but got Unknown
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Expected O, but got Unknown
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject, (Transform)(object)_panel, false);
			((Object)val).name = "Font_" + choice.Id;
			Transform val2 = val.transform.Find("PeglinFonts_Arrow");
			if ((Object)(object)val2 != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)((Component)val2).gameObject);
			}
			MonoBehaviour[] componentsInChildren = val.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val3 in componentsInChildren)
			{
				if (!(val3 is Graphic) && !(val3 is Button) && !(val3 is LayoutElement))
				{
					Object.DestroyImmediate((Object)(object)val3);
				}
			}
			LayoutElement obj = val.GetComponent<LayoutElement>() ?? val.AddComponent<LayoutElement>();
			float minHeight = (obj.preferredHeight = height);
			obj.minHeight = minHeight;
			obj.flexibleWidth = 1f;
			Image val4 = default(Image);
			if (val.TryGetComponent<Image>(ref val4))
			{
				((Graphic)val4).color = (selected ? UiCopy.Green : UiCopy.Tan);
			}
			Outline obj2 = val.AddComponent<Outline>();
			((Shadow)obj2).effectColor = UiCopy.Highlight;
			((Shadow)obj2).effectDistance = new Vector2(5f, -5f);
			((Shadow)obj2).useGraphicAlpha = false;
			((Behaviour)obj2).enabled = false;
			val.AddComponent<SelectOnHover>();
			Button component = val.GetComponent<Button>();
			((Selectable)component).transition = (Transition)0;
			component.onClick = new ButtonClickedEvent();
			((UnityEvent)component.onClick).AddListener((UnityAction)delegate
			{
				Choose(choice);
			});
			TMP_FontAsset val5 = (choice.IsDefault ? gameFont : FontLibrary.Tmp(choice));
			TMP_Text[] componentsInChildren2 = val.GetComponentsInChildren<TMP_Text>(true);
			foreach (TMP_Text val6 in componentsInChildren2)
			{
				val6.text = choice.DisplayName;
				if ((Object)(object)val5 != (Object)null)
				{
					val6.font = val5;
					val6.fontSharedMaterial = ((TMP_Asset)val5).material;
				}
			}
			return component;
		}

		private void Show()
		{
			Current = this;
			_openedAt = Time.unscaledTime;
			Suspend(_menu, _row);
			Reposition();
			EventSystem current = EventSystem.current;
			if (current != null)
			{
				current.SetSelectedGameObject((GameObject)null);
			}
		}

		private void Reposition()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_rowButton == (Object)null))
			{
				Canvas.ForceUpdateCanvases();
				LayoutRebuilder.ForceRebuildLayoutImmediate(_panel);
				Vector3[] array = (Vector3[])(object)new Vector3[4];
				((RectTransform)((Component)_rowButton).transform).GetWorldCorners(array);
				((Transform)_panel).position = array[3];
				Canvas componentInParent = ((Component)_panel).GetComponentInParent<Canvas>();
				RectTransform val = ((!((Object)(object)componentInParent != (Object)null)) ? ((RectTransform)null) : ((RectTransform)((Component)componentInParent.rootCanvas).transform));
				if (!((Object)(object)val == (Object)null))
				{
					Vector3[] array2 = (Vector3[])(object)new Vector3[4];
					Vector3[] array3 = (Vector3[])(object)new Vector3[4];
					_panel.GetWorldCorners(array2);
					val.GetWorldCorners(array3);
					float num = (array3[1].y - array3[0].y) * 0.02f;
					RectTransform panel = _panel;
					((Transform)panel).position = ((Transform)panel).position + new Vector3(MenuLayout.ShiftInto(array2[0].x, array2[2].x, array3[0].x + num, array3[2].x - num, keepEnd: false), MenuLayout.ShiftInto(array2[0].y, array2[1].y, array3[0].y + num, array3[1].y - num, keepEnd: true), 0f);
				}
			}
		}

		private void Update()
		{
			Player val = (ReInput.isReady ? ReInput.players.GetPlayer(0) : null);
			if (val != null && (val.GetButtonDown("UICancel") || val.GetButtonDown("Pause")))
			{
				Close();
				return;
			}
			EventSystem current = EventSystem.current;
			if ((Object)(object)current == (Object)null)
			{
				return;
			}
			GameObject currentSelectedGameObject = current.currentSelectedGameObject;
			bool flag = (Object)(object)currentSelectedGameObject != (Object)null && currentSelectedGameObject.transform.IsChildOf(((Component)this).transform);
			ShowHighlight(flag ? currentSelectedGameObject : null);
			if (!_selectedFirst)
			{
				if (val == null || !val.GetButton("UISubmit"))
				{
					_selectedFirst = true;
					current.SetSelectedGameObject(((Component)_items[FontCatalog.IndexOf(Plugin.Current)]).gameObject);
				}
			}
			else if (!flag && val != null && (Mathf.Abs(val.GetAxis("UIVertical")) > 0.5f || Mathf.Abs(val.GetAxis("UIHorizontal")) > 0.5f))
			{
				current.SetSelectedGameObject(((Component)_items[FontCatalog.IndexOf(Plugin.Current)]).gameObject);
			}
		}

		private void ShowHighlight(GameObject selected)
		{
			if (!((Object)(object)selected == (Object)(object)_highlighted))
			{
				SetHighlight(_highlighted, on: false);
				SetHighlight(selected, on: true);
				_highlighted = selected;
			}
		}

		private static void SetHighlight(GameObject item, bool on)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)item == (Object)null))
			{
				Outline val = default(Outline);
				if (item.TryGetComponent<Outline>(ref val))
				{
					((Behaviour)val).enabled = on;
				}
				Image val2 = default(Image);
				if (item.TryGetComponent<Image>(ref val2))
				{
					Color val3 = ((((Object)item).name == "Font_" + Plugin.Current.Id) ? UiCopy.Green : UiCopy.Tan);
					((Graphic)val2).color = (on ? Color.Lerp(val3, Color.white, 0.35f) : val3);
				}
			}
		}

		private void LateUpdate()
		{
			KeepOptionsShortcutsOff(_menu);
			if (Time.unscaledTime - _openedAt < 0.5f)
			{
				Reposition();
			}
		}

		private void Choose(FontChoice choice)
		{
			Plugin.Choose(choice);
			OptionsMenuPatch.UpdateLabel(_row);
			Close();
		}

		private void Close()
		{
			if (!((Object)(object)Current != (Object)(object)this))
			{
				Current = null;
				_blockUntilFrame = Time.frameCount + 2;
				if ((Object)(object)_row != (Object)null && (Object)(object)EventSystem.current != (Object)null)
				{
					EventSystem.current.SetSelectedGameObject(((Component)_row).gameObject);
				}
				if ((Object)(object)FontHost.Instance != (Object)null)
				{
					((MonoBehaviour)FontHost.Instance).StartCoroutine(ResumeSoon());
				}
				else
				{
					Resume();
				}
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		private void OnDisable()
		{
			if ((Object)(object)Current == (Object)(object)this)
			{
				Current = null;
				Resume();
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		private static void Suspend(OptionsMenu menu, Transform row)
		{
			_suspendedMenu = menu;
			SetOptionsButtonsActive(menu, active: false);
			_suspendedOverride = (((Object)(object)row != (Object)null) ? ((Component)row).GetComponent<OverrideButtonMapWhenSelected>() : null);
			if ((Object)(object)_suspendedOverride != (Object)null)
			{
				((Behaviour)_suspendedOverride).enabled = false;
				if ((Object)(object)_suspendedOverride.mapperToEnable != (Object)null)
				{
					((Behaviour)_suspendedOverride.mapperToEnable).enabled = false;
				}
			}
		}

		private static IEnumerator ResumeSoon()
		{
			yield return (object)new WaitForSecondsRealtime(0.1f);
			if ((Object)(object)Current == (Object)null)
			{
				Resume();
			}
		}

		internal static void Resume()
		{
			if ((Object)(object)_suspendedMenu != (Object)null)
			{
				SetOptionsButtonsActive(_suspendedMenu, active: true);
			}
			if ((Object)(object)_suspendedOverride != (Object)null)
			{
				if ((Object)(object)_suspendedOverride.mapperToEnable != (Object)null)
				{
					((Behaviour)_suspendedOverride.mapperToEnable).enabled = false;
				}
				((Behaviour)_suspendedOverride).enabled = true;
			}
			_suspendedMenu = null;
			_suspendedOverride = null;
		}

		private static void KeepOptionsShortcutsOff(OptionsMenu menu)
		{
			if ((Object)(object)menu == (Object)null)
			{
				return;
			}
			Behaviour[] array = (Behaviour[])(object)new Behaviour[4]
			{
				(Behaviour)menu.acceptButton,
				(Behaviour)menu.applyButton,
				(Behaviour)menu.cancelButton,
				(Behaviour)menu.deleteButton
			};
			foreach (Behaviour val in array)
			{
				if ((Object)(object)val != (Object)null && val.enabled)
				{
					val.enabled = false;
				}
			}
		}

		private static void SetOptionsButtonsActive(OptionsMenu menu, bool active)
		{
			if (!_lookedUpSetButtonsActive)
			{
				_lookedUpSetButtonsActive = true;
				MethodInfo methodInfo = AccessTools.Method(typeof(OptionsMenu), "SetButtonsActive", new Type[1] { typeof(bool) }, (Type[])null);
				if (methodInfo != null)
				{
					_setButtonsActive = AccessTools.MethodDelegate<Action<OptionsMenu, bool>>(methodInfo, (object)null, true);
				}
				else
				{
					Plugin.Log.LogWarning((object)"OptionsMenu.SetButtonsActive not found; the font list switches the Options shortcuts off directly.");
				}
			}
			if ((Object)(object)menu == (Object)null)
			{
				return;
			}
			if (_setButtonsActive != null)
			{
				_setButtonsActive(menu, active);
				return;
			}
			if (!active)
			{
				KeepOptionsShortcutsOff(menu);
				return;
			}
			Behaviour[] array = (Behaviour[])(object)new Behaviour[5]
			{
				(Behaviour)menu.acceptButton,
				(Behaviour)menu.applyButton,
				(Behaviour)menu.cancelButton,
				(Behaviour)menu.deleteButton,
				(Behaviour)menu.mappedButtonOverride
			};
			foreach (Behaviour val in array)
			{
				if ((Object)(object)val != (Object)null)
				{
					val.enabled = true;
				}
			}
		}
	}
	internal class SelectOnHover : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler
	{
		public void OnPointerEnter(PointerEventData eventData)
		{
			EventSystem current = EventSystem.current;
			if (current != null)
			{
				current.SetSelectedGameObject(((Component)this).gameObject);
			}
		}
	}
	internal class SwallowClicks : MonoBehaviour, IPointerClickHandler, IEventSystemHandler
	{
		public void OnPointerClick(PointerEventData eventData)
		{
		}
	}
	internal class FontHost : MonoBehaviour
	{
		private bool _capturedSkinFont;

		private Font _skinFont;

		public static FontHost Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		private void OnDestroy()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
		}

		private void Start()
		{
			FontSwapper.ApplyAll();
		}

		private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			FontSwapper.ApplyAll();
		}

		private void OnGUI()
		{
			GUISkin skin = GUI.skin;
			if (!((Object)(object)skin == (Object)null))
			{
				if (!_capturedSkinFont)
				{
					_capturedSkinFont = true;
					_skinFont = skin.font;
				}
				Font val = FontLibrary.Legacy(Plugin.Current);
				Font val2 = (((Object)(object)val != (Object)null) ? val : _skinFont);
				if ((Object)(object)skin.font != (Object)(object)val2)
				{
					skin.font = val2;
				}
			}
		}
	}
	internal static class FontLibrary
	{
		private sealed class Loaded
		{
			public TMP_FontAsset Tmp;

			public Font Legacy;
		}

		private static string[] _installed;

		private static readonly Dictionary<string, Loaded> Cache = new Dictionary<string, Loaded>();

		private static readonly HashSet<string> Failed = new HashSet<string>();

		private static readonly HashSet<TMP_FontAsset> Ours = new HashSet<TMP_FontAsset>();

		private static readonly List<TMP_FontAsset> GameFonts = new List<TMP_FontAsset>();

		private static float _referenceCapRatio = -1f;

		private static TMP_FontAsset _reference;

		private static bool _findingReference;

		public static bool IsOurs(TMP_FontAsset font)
		{
			if ((Object)(object)font != (Object)null)
			{
				return Ours.Contains(font);
			}
			return false;
		}

		public static TMP_FontAsset Tmp(FontChoice choice)
		{
			return Load(choice)?.Tmp;
		}

		public static Font Legacy(FontChoice choice)
		{
			return Load(choice)?.Legacy;
		}

		public static void AddGameFont(TMP_FontAsset font)
		{
			if ((Object)(object)font == (Object)null || IsOurs(font) || GameFonts.Contains(font))
			{
				return;
			}
			GameFonts.Add(font);
			foreach (Loaded value in Cache.Values)
			{
				AddFallback(value.Tmp, font);
			}
		}

		private static void AddFallback(TMP_FontAsset ours, TMP_FontAsset game)
		{
			if ((Object)(object)ours == (Object)null)
			{
				return;
			}
			if (ours.fallbackFontAssetTable == null)
			{
				ours.fallbackFontAssetTable = new List<TMP_FontAsset>();
			}
			if (!ours.fallbackFontAssetTable.Contains(game))
			{
				if ((Object)(object)game == (Object)(object)ReferenceGameFont())
				{
					ours.fallbackFontAssetTable.Insert(0, game);
				}
				else
				{
					ours.fallbackFontAssetTable.Add(game);
				}
			}
		}

		private static Loaded Load(FontChoice choice)
		{
			if (choice == null || choice.IsDefault || Failed.Contains(choice.Id))
			{
				return null;
			}
			if (Cache.TryGetValue(choice.Id, out var value))
			{
				return value;
			}
			try
			{
				value = Build(choice);
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Couldn't load the {choice.DisplayName} font: {arg}");
				value = null;
			}
			if (value == null)
			{
				Failed.Add(choice.Id);
				return null;
			}
			Cache[choice.Id] = value;
			return value;
		}

		private static Loaded Build(FontChoice choice)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			string text = Extract(choice.FileName);
			Font val = new Font(text)
			{
				name = "PeglinFonts " + choice.DisplayName,
				hideFlags = (HideFlags)32
			};
			TMP_FontAsset val2 = TMP_FontAsset.CreateFontAsset(val, 64, 6, (GlyphRenderMode)4165, 1024, 1024, (AtlasPopulationMode)1, true);
			if ((Object)(object)val2 == (Object)null)
			{
				Plugin.Log.LogError((object)("Couldn't read the " + choice.DisplayName + " font file (" + text + ")."));
				return null;
			}
			((Object)val2).name = ((Object)val).name;
			((Object)val2).hideFlags = (HideFlags)32;
			if ((Object)(object)((TMP_Asset)val2).material != (Object)null)
			{
				((Object)((TMP_Asset)val2).material).name = ((Object)val).name + " Material";
				((Object)((TMP_Asset)val2).material).hideFlags = (HideFlags)32;
			}
			FaceInfo faceInfo = val2.faceInfo;
			float num = ReferenceCapRatio();
			float num2 = CapRatio(faceInfo);
			((FaceInfo)(ref faceInfo)).scale = FontCatalog.MatchScale(num, num2, choice.Scale);
			val2.faceInfo = faceInfo;
			foreach (TMP_FontAsset gameFont in GameFonts)
			{
				AddFallback(val2, gameFont);
			}
			Ours.Add(val2);
			Font val3 = LegacyFont(choice);
			Plugin.Log.LogInfo((object)($"Loaded {choice.DisplayName}: cap ratio {num2:0.000} vs game {num:0.000}, scale {((FaceInfo)(ref faceInfo)).scale:0.00}; " + "UI Text/IMGUI use " + (((Object)(object)val3 != (Object)null) ? ((Object)val3).name : "their own font (no look-alike installed)") + "."));
			return new Loaded
			{
				Tmp = val2,
				Legacy = val3
			};
		}

		private static Font LegacyFont(FontChoice choice)
		{
			if (_installed == null)
			{
				_installed = Font.GetOSInstalledFontNames() ?? new string[0];
			}
			string text = FontCatalog.PickSystemFont(choice, _installed);
			if (text == null)
			{
				return null;
			}
			Font val = Font.CreateDynamicFontFromOSFont(text, 16);
			if ((Object)(object)val != (Object)null)
			{
				((Object)val).name = text;
				((Object)val).hideFlags = (HideFlags)32;
			}
			return val;
		}

		private static float CapRatio(FaceInfo face)
		{
			if (((FaceInfo)(ref face)).pointSize <= 0)
			{
				return 0f;
			}
			return ((((FaceInfo)(ref face)).capLine > 0f) ? ((FaceInfo)(ref face)).capLine : (((FaceInfo)(ref face)).ascentLine * 0.72f)) / (float)((FaceInfo)(ref face)).pointSize * ((((FaceInfo)(ref face)).scale > 0f) ? ((FaceInfo)(ref face)).scale : 1f);
		}

		private static float ReferenceCapRatio()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (_referenceCapRatio > 0f)
			{
				return _referenceCapRatio;
			}
			TMP_FontAsset val = ReferenceGameFont();
			float num = (((Object)(object)val != (Object)null) ? CapRatio(val.faceInfo) : 0f);
			if (num > 0f)
			{
				_referenceCapRatio = num;
				Plugin.Log.LogInfo((object)("Sizing fonts to match the game's " + ((Object)val).name + "."));
			}
			return num;
		}

		public static TMP_FontAsset ReferenceGameFont()
		{
			if ((Object)(object)_reference != (Object)null || _findingReference)
			{
				return _reference;
			}
			_findingReference = true;
			try
			{
				TMP_FontAsset val = (((Object)(object)TMP_Settings.instance != (Object)null) ? TMP_Settings.defaultFontAsset : null);
				_reference = (((Object)(object)val != (Object)null && !IsOurs(val)) ? val : FontSwapper.MostUsedGameFont());
				return _reference;
			}
			finally
			{
				_findingReference = false;
			}
		}

		public static TMP_FontAsset GameFontWithAtlas(Texture atlas)
		{
			if ((Object)(object)atlas == (Object)null)
			{
				return null;
			}
			foreach (TMP_FontAsset gameFont in GameFonts)
			{
				if ((Object)(object)gameFont != (Object)null && gameFont.atlasTextures != null && ((IEnumerable<Texture>)(object)gameFont.atlasTextures).Contains(atlas))
				{
					return gameFont;
				}
			}
			return null;
		}

		private static string Extract(string fileName)
		{
			string text = "PeglinFonts." + fileName;
			byte[] array;
			using (Stream stream = typeof(FontLibrary).Assembly.GetManifestResourceStream(text))
			{
				if (stream == null)
				{
					throw new FileNotFoundException("Font missing from the mod DLL", text);
				}
				array = new byte[stream.Length];
				int num;
				for (int i = 0; i < array.Length; i += num)
				{
					num = stream.Read(array, i, array.Length - i);
					if (num <= 0)
					{
						throw new EndOfStreamException(text);
					}
				}
			}
			string text2 = Path.Combine(Paths.CachePath, "PeglinFonts");
			Directory.CreateDirectory(text2);
			string text3 = Path.Combine(text2, fileName);
			if (File.Exists(text3) && File.ReadAllBytes(text3).SequenceEqual(array))
			{
				return text3;
			}
			string text4 = text3 + "." + Process.GetCurrentProcess().Id + ".tmp";
			File.WriteAllBytes(text4, array);
			try
			{
				if (File.Exists(text3))
				{
					File.Delete(text3);
				}
				File.Move(text4, text3);
			}
			catch (IOException) when (File.Exists(text3))
			{
				File.Delete(text4);
				text3 = Path.Combine(text2, Path.GetFileNameWithoutExtension(fileName) + "." + Process.GetCurrentProcess().Id + Path.GetExtension(fileName));
				File.WriteAllBytes(text3, array);
			}
			return text3;
		}
	}
	internal class KeepFont : MonoBehaviour
	{
	}
	internal static class FontSwapper
	{
		private struct Original
		{
			public TMP_FontAsset Font;

			public Material Material;
		}

		private static readonly Dictionary<TMP_Text, Original> Originals = new Dictionary<TMP_Text, Original>();

		private static readonly Dictionary<Text, Font> LegacyOriginals = new Dictionary<Text, Font>();

		private static readonly Dictionary<Material, Original> MaterialOrigins = new Dictionary<Material, Original>();

		private static readonly HashSet<Font> OurLegacyFonts = new HashSet<Font>();

		private static bool _applying;

		private static int _errorsLogged;

		public static void Apply(TMP_Text text)
		{
			if (_applying || (Object)(object)text == (Object)null || (Object)(object)((Component)text).GetComponentInParent<KeepFont>(true) != (Object)null || !TryGetOriginal(text, out var original))
			{
				return;
			}
			TMP_FontAsset val = FontLibrary.Tmp(Plugin.Current);
			_applying = true;
			try
			{
				if ((Object)(object)val == (Object)null)
				{
					if (FontLibrary.IsOurs(text.font))
					{
						text.font = original.Font;
						text.fontSharedMaterial = (((Object)(object)original.Material != (Object)null) ? original.Material : ((TMP_Asset)original.Font).material);
					}
					return;
				}
				if ((Object)(object)text.font != (Object)(object)val)
				{
					text.font = val;
				}
				Material val2 = MaterialFor(original, val);
				if ((Object)(object)val2 != (Object)null && (Object)(object)text.fontSharedMaterial != (Object)(object)val2)
				{
					text.fontSharedMaterial = val2;
				}
			}
			finally
			{
				_applying = false;
			}
		}

		public static void Apply(Text text)
		{
			if (_applying || (Object)(object)text == (Object)null || (Object)(object)((Component)text).GetComponentInParent<KeepFont>(true) != (Object)null)
			{
				return;
			}
			if (!LegacyOriginals.TryGetValue(text, out var value))
			{
				if ((Object)(object)text.font == (Object)null || OurLegacyFonts.Contains(text.font))
				{
					return;
				}
				value = text.font;
				LegacyOriginals[text] = value;
			}
			Font val = FontLibrary.Legacy(Plugin.Current);
			if ((Object)(object)val != (Object)null)
			{
				OurLegacyFonts.Add(val);
			}
			Font val2 = (((Object)(object)val != (Object)null) ? val : value);
			if (!((Object)(object)text.font != (Object)(object)val2))
			{
				return;
			}
			_applying = true;
			try
			{
				text.font = val2;
			}
			finally
			{
				_applying = false;
			}
		}

		public static void ApplyAll()
		{
			Prune();
			foreach (TMP_Text item in InScenes<TMP_Text>((IEnumerable<TMP_Text>)Resources.FindObjectsOfTypeAll<TMP_Text>()))
			{
				Apply(item);
			}
			foreach (Text item2 in InScenes<Text>((IEnumerable<Text>)Resources.FindObjectsOfTypeAll<Text>()))
			{
				Apply(item2);
			}
		}

		public static TMP_FontAsset GameFontOf(TMP_Text text)
		{
			if (!((Object)(object)text != (Object)null) || !TryGetOriginal(text, out var original))
			{
				return null;
			}
			return original.Font;
		}

		public static TMP_FontAsset MostUsedGameFont()
		{
			return (from f in InScenes<TMP_Text>((IEnumerable<TMP_Text>)Resources.FindObjectsOfTypeAll<TMP_Text>()).Select(GameFontOf)
				where (Object)(object)f != (Object)null
				group f by f into g
				orderby g.Count() descending
				select g.Key).FirstOrDefault();
		}

		public static void Prune()
		{
			foreach (TMP_Text item in Originals.Keys.Where((TMP_Text t) => (Object)(object)t == (Object)null).ToList())
			{
				Originals.Remove(item);
			}
			foreach (Text item2 in LegacyOriginals.Keys.Where((Text t) => (Object)(object)t == (Object)null).ToList())
			{
				LegacyOriginals.Remove(item2);
			}
		}

		private static IEnumerable<T> InScenes<T>(IEnumerable<T> objects) where T : Component
		{
			return objects.Where(delegate(T o)
			{
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)o != (Object)null)
				{
					Scene scene = ((Component)o).gameObject.scene;
					return ((Scene)(ref scene)).IsValid();
				}
				return false;
			});
		}

		private static bool TryGetOriginal(TMP_Text text, out Original original)
		{
			if (Originals.TryGetValue(text, out original) && (Object)(object)original.Font != (Object)null)
			{
				return true;
			}
			TMP_FontAsset font = text.font;
			if ((Object)(object)font == (Object)null)
			{
				return false;
			}
			if (FontLibrary.IsOurs(font))
			{
				original = GuessOriginal(text.fontSharedMaterial);
				if ((Object)(object)original.Font == (Object)null)
				{
					return false;
				}
			}
			else
			{
				original = new Original
				{
					Font = font,
					Material = MatchingMaterial(font, text.fontSharedMaterial)
				};
				FontLibrary.AddGameFont(font);
			}
			Originals[text] = original;
			return true;
		}

		private static Original GuessOriginal(Material material)
		{
			if ((Object)(object)material != (Object)null)
			{
				if (MaterialOrigins.TryGetValue(material, out var value))
				{
					return value;
				}
				string text = ((Object)material).name.Replace(" (Instance)", "");
				foreach (KeyValuePair<Material, Original> materialOrigin in MaterialOrigins)
				{
					if ((Object)(object)materialOrigin.Key != (Object)null && ((Object)materialOrigin.Key).name == text)
					{
						return materialOrigin.Value;
					}
				}
				TMP_FontAsset val = FontLibrary.GameFontWithAtlas(material.HasProperty(ShaderUtilities.ID_MainTex) ? material.GetTexture(ShaderUtilities.ID_MainTex) : null);
				if ((Object)(object)val != (Object)null)
				{
					return new Original
					{
						Font = val,
						Material = material
					};
				}
			}
			TMP_FontAsset val2 = FontLibrary.ReferenceGameFont();
			return new Original
			{
				Font = val2,
				Material = (((Object)(object)val2 != (Object)null) ? ((TMP_Asset)val2).material : null)
			};
		}

		private static Material MatchingMaterial(TMP_FontAsset font, Material material)
		{
			if ((Object)(object)material != (Object)null && (Object)(object)((TMP_Asset)font).material != (Object)null && material.HasProperty(ShaderUtilities.ID_MainTex) && (Object)(object)material.GetTexture(ShaderUtilities.ID_MainTex) == (Object)(object)((TMP_Asset)font).material.GetTexture(ShaderUtilities.ID_MainTex))
			{
				return material;
			}
			return ((TMP_Asset)font).material;
		}

		private static Material MaterialFor(Original original, TMP_FontAsset target)
		{
			Material val = (((Object)(object)original.Material != (Object)null) ? original.Material : ((TMP_Asset)original.Font).material);
			if ((Object)(object)((TMP_Asset)target).material == (Object)null)
			{
				return null;
			}
			Material val2 = (((Object)(object)val != (Object)null) ? TMP_MaterialManager.GetFallbackMaterial(val, ((TMP_Asset)target).material) : ((TMP_Asset)target).material);
			if ((Object)(object)val2 != (Object)null && !MaterialOrigins.ContainsKey(val2))
			{
				MaterialOrigins[val2] = original;
			}
			return val2;
		}

		internal static void FontChangedByGame(TMP_Text text)
		{
			if (_applying || (Object)(object)text == (Object)null)
			{
				return;
			}
			TMP_FontAsset font = text.font;
			if ((Object)(object)font != (Object)null && !FontLibrary.IsOurs(font))
			{
				Original value;
				bool flag = Originals.TryGetValue(text, out value) && (Object)(object)value.Font != (Object)null;
				if (!flag || (Object)(object)value.Font != (Object)(object)font)
				{
					Material material = ((flag && (Object)(object)value.Material != (Object)null) ? value.Material : text.fontSharedMaterial);
					Originals[text] = new Original
					{
						Font = font,
						Material = MatchingMaterial(font, material)
					};
				}
				FontLibrary.AddGameFont(font);
			}
			Apply(text);
		}

		internal static void FontChangedByGame(Text text)
		{
			if (!_applying && !((Object)(object)text == (Object)null))
			{
				if ((Object)(object)text.font != (Object)null && !OurLegacyFonts.Contains(text.font))
				{
					LegacyOriginals[text] = text.font;
				}
				Apply(text);
			}
		}

		internal static void MaterialChangedByGame(TMP_Text text)
		{
			if (_applying || (Object)(object)text == (Object)null)
			{
				return;
			}
			Material fontSharedMaterial = text.fontSharedMaterial;
			if ((Object)(object)fontSharedMaterial == (Object)null)
			{
				return;
			}
			if (!Originals.TryGetValue(text, out var value) || (Object)(object)value.Font == (Object)null)
			{
				Apply(text);
				return;
			}
			if (MaterialOrigins.TryGetValue(fontSharedMaterial, out var value2))
			{
				value.Material = (((Object)(object)value2.Font == (Object)(object)value.Font) ? value2.Material : MatchingMaterial(value.Font, value2.Material));
			}
			else
			{
				value.Material = MatchingMaterial(value.Font, fontSharedMaterial);
			}
			Originals[text] = value;
			Apply(text);
		}

		internal static void Guard(Action action)
		{
			try
			{
				action();
			}
			catch (Exception arg)
			{
				if (_errorsLogged++ < 5)
				{
					Plugin.Log.LogError((object)$"Font swap failed (the text keeps its current font): {arg}");
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class TmpPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(TextMeshProUGUI), "OnEnable")]
		private static void UguiEnabled(TMP_Text __instance)
		{
			FontSwapper.Guard(delegate
			{
				FontSwapper.Apply(__instance);
			});
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(TextMeshPro), "OnEnable")]
		private static void WorldEnabled(TMP_Text __instance)
		{
			FontSwapper.Guard(delegate
			{
				FontSwapper.Apply(__instance);
			});
		}

		[HarmonyPostfix]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		private static void FontSet(TMP_Text __instance)
		{
			FontSwapper.Guard(delegate
			{
				FontSwapper.FontChangedByGame(__instance);
			});
		}

		[HarmonyPostfix]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		private static void SharedMaterialSet(TMP_Text __instance)
		{
			FontSwapper.Guard(delegate
			{
				FontSwapper.MaterialChangedByGame(__instance);
			});
		}

		[HarmonyPostfix]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		private static void MaterialSet(TMP_Text __instance)
		{
			FontSwapper.Guard(delegate
			{
				FontSwapper.MaterialChangedByGame(__instance);
			});
		}
	}
	[HarmonyPatch]
	internal static class LegacyTextPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(Text), "OnEnable")]
		private static void Enabled(Text __instance)
		{
			FontSwapper.Guard(delegate
			{
				FontSwapper.Apply(__instance);
			});
		}

		[HarmonyPostfix]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		private static void FontSet(Text __instance)
		{
			FontSwapper.Guard(delegate
			{
				FontSwapper.FontChangedByGame(__instance);
			});
		}
	}
	[HarmonyPatch]
	internal static class LocalizationPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(LocalizeTarget_TextMeshPro_UGUI), "GetFinalTerms")]
		private static void Ugui(LocalizeTarget_TextMeshPro_UGUI __instance, ref string secondaryTerm)
		{
			GameFontTerm((TMP_Text)(object)((LocalizeTarget<TextMeshProUGUI>)(object)__instance).mTarget, ref secondaryTerm);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(LocalizeTarget_TextMeshPro_Label), "GetFinalTerms")]
		private static void World(LocalizeTarget_TextMeshPro_Label __instance, ref string secondaryTerm)
		{
			GameFontTerm((TMP_Text)(object)((LocalizeTarget<TextMeshPro>)(object)__instance).mTarget, ref secondaryTerm);
		}

		private static void GameFontTerm(TMP_Text target, ref string secondaryTerm)
		{
			try
			{
				if ((Object)(object)target != (Object)null && FontLibrary.IsOurs(target.font))
				{
					TMP_FontAsset val = FontSwapper.GameFontOf(target);
					secondaryTerm = (((Object)(object)val != (Object)null) ? ((Object)val).name : string.Empty);
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Couldn't give the translation system the game's font name: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(OptionsMenu), "OnEnable")]
	internal static class OptionsMenuPatch
	{
		public const string RowName = "PeglinFonts_FontRow";

		public const string ControlsRowName = "PeglinKeybinds_ControlsRow";

		[HarmonyAfter(new string[] { "PeglinKeybinds" })]
		private static void Prefix(OptionsMenu __instance)
		{
			try
			{
				if ((Object)(object)FontDropdown.Current == (Object)null)
				{
					FontDropdown.Resume();
				}
				Transform val = FindOrAddRow(__instance);
				if (!((Object)(object)val == (Object)null))
				{
					Place(val);
					UpdateLabel(val);
					if ((Object)(object)val.parent.Find("PeglinKeybinds_ControlsRow") == (Object)null)
					{
						__instance.firstSelectable = ((Component)val).gameObject;
					}
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Couldn't add the Font row to the Options menu: {arg}");
			}
		}

		public static void UpdateAllLabels()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			OptionsMenu[] array = Resources.FindObjectsOfTypeAll<OptionsMenu>();
			foreach (OptionsMenu val in array)
			{
				object obj;
				if ((Object)(object)val != (Object)null)
				{
					Scene scene = ((Component)val).gameObject.scene;
					if (((Scene)(ref scene)).IsValid() && (Object)(object)val.deleteButtonSelectable != (Object)null)
					{
						obj = ((Component)val.deleteButtonSelectable).transform.parent;
						goto IL_004e;
					}
				}
				obj = null;
				goto IL_004e;
				IL_004e:
				Transform val2 = (Transform)obj;
				Transform val3 = (((Object)(object)val2 != (Object)null) ? val2.Find("PeglinFonts_FontRow") : null);
				if ((Object)(object)val3 != (Object)null)
				{
					UpdateLabel(val3);
				}
			}
		}

		public static void UpdateLabel(Transform row)
		{
			Button val = (((Object)(object)row != (Object)null) ? ((Component)row).GetComponentInChildren<Button>(true) : null);
			TMP_Text val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponentInChildren<TMP_Text>(true) : null);
			if ((Object)(object)val2 != (Object)null)
			{
				val2.text = Plugin.Current.DisplayName;
			}
		}

		private static Transform FindOrAddRow(OptionsMenu menu)
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Expected O, but got Unknown
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Expected O, but got Unknown
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			Selectable deleteButtonSelectable = menu.deleteButtonSelectable;
			if ((Object)(object)deleteButtonSelectable == (Object)null || (Object)(object)((Component)deleteButtonSelectable).transform.parent == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Options menu layout not recognised (no Delete Save Data row); the Font row wasn't added.");
				return null;
			}
			Transform parent = ((Component)deleteButtonSelectable).transform.parent;
			Transform val = parent.Find("PeglinFonts_FontRow");
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			GameObject val2 = new GameObject("PeglinFonts_Holder");
			val2.SetActive(false);
			GameObject row = Object.Instantiate<GameObject>(((Component)deleteButtonSelectable).gameObject, val2.transform, false);
			((Object)row).name = "PeglinFonts_FontRow";
			UiCopy.RemoveScripts(row, "Localize", "EventTrigger");
			row.SetActive(true);
			Button button = row.GetComponentInChildren<Button>(true);
			if ((Object)(object)button == (Object)null)
			{
				Object.Destroy((Object)(object)val2);
				Plugin.Log.LogWarning((object)"Options menu's Delete Save Data row has no button; the Font row wasn't added.");
				return null;
			}
			button.onClick = new ButtonClickedEvent();
			((UnityEvent)button.onClick).AddListener((UnityAction)delegate
			{
				FontDropdown.Open(menu, row.transform, button);
			});
			Image val3 = default(Image);
			if (((Component)button).TryGetComponent<Image>(ref val3))
			{
				((Graphic)val3).color = UiCopy.Tan;
			}
			TMP_Text[] componentsInChildren = row.GetComponentsInChildren<TMP_Text>(true);
			foreach (TMP_Text val4 in componentsInChildren)
			{
				if (!val4.transform.IsChildOf(((Component)button).transform))
				{
					val4.text = "Font";
				}
			}
			UiCopy.AddDropdownArrow(button);
			row.transform.SetParent(parent, false);
			Object.Destroy((Object)(object)val2);
			return row.transform;
		}

		private static void Place(Transform row)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			Transform parent = row.parent;
			List<(string, bool)> list = new List<(string, bool)>();
			foreach (Transform item in parent)
			{
				Transform val = item;
				if ((Object)(object)val != (Object)(object)row)
				{
					list.Add((((Object)val).name, (Object)(object)((Component)val).GetComponent<Selectable>() != (Object)null));
				}
			}
			int num = MenuLayout.FontRowIndex(list, "PeglinKeybinds_ControlsRow");
			if (row.GetSiblingIndex() != num)
			{
				row.SetSiblingIndex(num);
			}
			LinkNavigation(((Component)row).GetComponent<Selectable>(), parent);
		}

		private static void LinkNavigation(Selectable row, Transform contents)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Invalid comparison between Unknown and I4
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Invalid comparison between Unknown and I4
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Invalid comparison between Unknown and I4
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Invalid comparison between Unknown and I4
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Invalid comparison between Unknown and I4
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Invalid comparison between Unknown and I4
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)row == (Object)null)
			{
				return;
			}
			Selectable val = Neighbour(contents, ((Component)row).transform.GetSiblingIndex(), -1);
			Selectable val2 = Neighbour(contents, ((Component)row).transform.GetSiblingIndex(), 1);
			Navigation navigation;
			if ((Object)(object)val2 != (Object)null)
			{
				navigation = val2.navigation;
				if ((int)((Navigation)(ref navigation)).mode == 4)
				{
					goto IL_0087;
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				navigation = val.navigation;
				if ((int)((Navigation)(ref navigation)).mode == 4)
				{
					goto IL_0087;
				}
			}
			navigation = default(Navigation);
			((Navigation)(ref navigation)).mode = (Mode)3;
			row.navigation = navigation;
			return;
			IL_00fe:
			object obj;
			Selectable val3 = (Selectable)obj;
			goto IL_00ff;
			IL_00ff:
			navigation = default(Navigation);
			((Navigation)(ref navigation)).mode = (Mode)4;
			((Navigation)(ref navigation)).selectOnUp = val3;
			((Navigation)(ref navigation)).selectOnDown = val2;
			row.navigation = navigation;
			Selectable val4 = Neighbour(contents, -1, 1);
			if ((Object)(object)val2 != (Object)null && (Object)(object)val4 != (Object)null && (Object)(object)val4 != (Object)(object)val2)
			{
				for (int i = ((Component)val2).transform.GetSiblingIndex() + 1; i < contents.childCount; i++)
				{
					Selectable component = ((Component)contents.GetChild(i)).GetComponent<Selectable>();
					if (!((Object)(object)component != (Object)null))
					{
						continue;
					}
					navigation = component.navigation;
					if ((int)((Navigation)(ref navigation)).mode == 4)
					{
						navigation = component.navigation;
						if ((Object)(object)((Navigation)(ref navigation)).selectOnDown == (Object)(object)val2)
						{
							Navigation navigation2 = component.navigation;
							((Navigation)(ref navigation2)).selectOnDown = val4;
							component.navigation = navigation2;
						}
					}
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				navigation = val.navigation;
				if ((int)((Navigation)(ref navigation)).mode == 4)
				{
					Navigation navigation3 = val.navigation;
					((Navigation)(ref navigation3)).selectOnDown = row;
					val.navigation = navigation3;
				}
			}
			if ((Object)(object)val2 != (Object)null)
			{
				navigation = val2.navigation;
				if ((int)((Navigation)(ref navigation)).mode == 4)
				{
					Navigation navigation4 = val2.navigation;
					((Navigation)(ref navigation4)).selectOnUp = row;
					val2.navigation = navigation4;
				}
			}
			return;
			IL_0087:
			val3 = val;
			if ((Object)(object)val3 == (Object)null)
			{
				navigation = row.navigation;
				if ((int)((Navigation)(ref navigation)).mode == 4)
				{
					navigation = row.navigation;
					if ((Object)(object)((Navigation)(ref navigation)).selectOnUp != (Object)null)
					{
						navigation = row.navigation;
						obj = ((Navigation)(ref navigation)).selectOnUp;
						goto IL_00fe;
					}
				}
				if ((Object)(object)val2 != (Object)null)
				{
					navigation = val2.navigation;
					if ((Object)(object)((Navigation)(ref navigation)).selectOnUp != (Object)(object)row)
					{
						navigation = val2.navigation;
						obj = ((Navigation)(ref navigation)).selectOnUp;
						goto IL_00fe;
					}
				}
				obj = null;
				goto IL_00fe;
			}
			goto IL_00ff;
		}

		private static Selectable Neighbour(Transform contents, int index, int direction)
		{
			for (int i = index + direction; i >= 0 && i < contents.childCount; i += direction)
			{
				Selectable component = ((Component)contents.GetChild(i)).GetComponent<Selectable>();
				if ((Object)(object)component != (Object)null && ((Component)component).gameObject.activeSelf)
				{
					return component;
				}
			}
			return null;
		}
	}
	[HarmonyPatch(typeof(OptionsMenu), "Update")]
	internal static class OptionsMenuUpdatePatch
	{
		private static bool Prefix()
		{
			return !FontDropdown.BlocksGameMenus;
		}
	}
	[HarmonyPatch(typeof(PauseMenu), "Update")]
	internal static class PauseMenuUpdatePatch
	{
		private static bool Prefix()
		{
			return !FontDropdown.BlocksGameMenus;
		}
	}
	[BepInPlugin("PeglinFonts", "PeglinFonts", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		private sealed class FontIds : AcceptableValueBase
		{
			public FontIds()
				: base(typeof(string))
			{
			}

			public override object Clamp(object value)
			{
				return FontCatalog.Find(value as string).Id;
			}

			public override bool IsValid(object value)
			{
				string id = value as string;
				if (id != null)
				{
					return FontCatalog.All.Any((FontChoice c) => c.Id == id);
				}
				return false;
			}

			public override string ToDescriptionString()
			{
				return "# Acceptable values: " + string.Join(", ", FontCatalog.All.Select((FontChoice c) => c.Id).ToArray());
			}
		}

		public const string Guid = "PeglinFonts";

		public const string Name = "PeglinFonts";

		public const string Version = "1.0.0";

		internal const string KeybindsGuid = "PeglinKeybinds";

		internal static ManualLogSource Log;

		internal static ConfigEntry<string> FontSetting;

		internal static FontChoice Current => FontCatalog.Find(FontSetting?.Value);

		private void Awake()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			FontSetting = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Font", "default", new ConfigDescription("The font used for all text in the game, including other mods' text. Easiest to change from Options > Font (edits to this file only take effect when the game is closed).", (AcceptableValueBase)(object)new FontIds(), Array.Empty<object>()));
			FontSetting.SettingChanged += delegate
			{
				FontSwapper.ApplyAll();
				OptionsMenuPatch.UpdateAllLabels();
			};
			new Harmony("PeglinFonts").PatchAll(typeof(Plugin).Assembly);
			GameObject val = new GameObject("PeglinFonts")
			{
				hideFlags = (HideFlags)61
			};
			Object.DontDestroyOnLoad((Object)val);
			val.AddComponent<FontHost>();
			Log.LogInfo((object)("PeglinFonts 1.0.0 loaded. Font: " + Current.DisplayName + ". Change it from Options > Font."));
		}

		internal static void Choose(FontChoice choice)
		{
			if (choice != null && FontSetting.Value != choice.Id)
			{
				FontSetting.Value = choice.Id;
			}
		}
	}
	internal static class UiCopy
	{
		public static readonly Color Green = new Color(0.435f, 0.612f, 0.275f, 1f);

		public static readonly Color Tan = new Color(0.72f, 0.66f, 0.55f, 1f);

		public static readonly Color Frame = new Color(0.27f, 0.18f, 0.13f, 0.97f);

		public static readonly Color Highlight = new Color(1f, 0.93f, 0.55f, 1f);

		public const string ArrowName = "PeglinFonts_Arrow";

		private static Sprite _arrow;

		public static void RemoveScripts(GameObject root, params string[] typeNames)
		{
			MonoBehaviour[] componentsInChildren = root.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && typeNames.Contains(((object)val).GetType().Name))
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
		}

		public static void AddDropdownArrow(Button button)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)((Component)button).transform.Find("PeglinFonts_Arrow") != (Object)null))
			{
				GameObject val = new GameObject("PeglinFonts_Arrow", new Type[2]
				{
					typeof(RectTransform),
					typeof(Image)
				});
				RectTransform val2 = (RectTransform)val.transform;
				((Transform)val2).SetParent(((Component)button).transform, false);
				val2.anchorMin = new Vector2(1f, 0.5f);
				val2.anchorMax = new Vector2(1f, 0.5f);
				val2.pivot = new Vector2(1f, 0.5f);
				val2.sizeDelta = new Vector2(14f, 8f);
				val2.anchoredPosition = new Vector2(-8f, 0f);
				Image component = val.GetComponent<Image>();
				component.sprite = ArrowSprite();
				((Graphic)component).color = new Color(0.2f, 0.13f, 0.1f, 1f);
				((Graphic)component).raycastTarget = false;
			}
		}

		private static Sprite ArrowSprite()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_arrow != (Object)null)
			{
				return _arrow;
			}
			Texture2D val = new Texture2D(7, 4, (TextureFormat)4, false)
			{
				filterMode = (FilterMode)0,
				wrapMode = (TextureWrapMode)1,
				hideFlags = (HideFlags)61
			};
			for (int i = 0; i < 4; i++)
			{
				for (int j = 0; j < 7; j++)
				{
					bool flag = Mathf.Abs(j - 3) <= i;
					val.SetPixel(j, i, flag ? Color.white : Color.clear);
				}
			}
			val.Apply();
			_arrow = Sprite.Create(val, new Rect(0f, 0f, 7f, 4f), new Vector2(0.5f, 0.5f), 100f);
			((Object)_arrow).hideFlags = (HideFlags)61;
			return _arrow;
		}
	}
}
namespace PeglinFonts.Core
{
	public enum FontCategory
	{
		Default,
		Accessible,
		Serious,
		Fun
	}
	public sealed class FontChoice
	{
		public string Id { get; }

		public string DisplayName { get; }

		public FontCategory Category { get; }

		public string FileName { get; }

		public float Scale { get; }

		public string[] SystemFonts { get; }

		public bool IsDefault => FileName == null;

		public FontChoice(string id, string displayName, FontCategory category, string fileName, string[] systemFonts, float scale = 1f)
		{
			SystemFonts = systemFonts ?? new string[0];
			Id = id;
			DisplayName = displayName;
			Category = category;
			FileName = fileName;
			Scale = scale;
		}
	}
	public static class FontCatalog
	{
		public const string DefaultId = "default";

		public static readonly IReadOnlyList<FontChoice> All = new FontChoice[14]
		{
			new FontChoice("default", "Peglin (default)", FontCategory.Default, null, null),
			new FontChoice("opendyslexic", "OpenDyslexic", FontCategory.Accessible, "OpenDyslexic-Regular.otf", new string[3] { "OpenDyslexic", "Comic Sans MS", "Verdana" }),
			new FontChoice("atkinson", "Atkinson Hyperlegible", FontCategory.Accessible, "AtkinsonHyperlegible-Regular.ttf", new string[3] { "Atkinson Hyperlegible", "Verdana", "Arial" }),
			new FontChoice("lato", "Lato", FontCategory.Serious, "Lato-Regular.ttf", new string[3] { "Lato", "Segoe UI", "Arial" }),
			new FontChoice("ptserif", "PT Serif", FontCategory.Serious, "PT_Serif-Web-Regular.ttf", new string[3] { "PT Serif", "Georgia", "Times New Roman" }),
			new FontChoice("comicneue", "Comic Neue", FontCategory.Fun, "ComicNeue-Regular.ttf", new string[2] { "Comic Neue", "Comic Sans MS" }),
			new FontChoice("patrickhand", "Patrick Hand", FontCategory.Fun, "PatrickHand-Regular.ttf", new string[3] { "Patrick Hand", "Segoe Print", "Comic Sans MS" }),
			new FontChoice("permanentmarker", "Permanent Marker", FontCategory.Fun, "PermanentMarker-Regular.ttf", new string[3] { "Permanent Marker", "Ink Free", "Segoe Print" }, 0.95f),
			new FontChoice("bangers", "Bangers", FontCategory.Fun, "Bangers-Regular.ttf", new string[2] { "Bangers", "Impact" }),
			new FontChoice("vt323", "VT323 Terminal", FontCategory.Fun, "VT323-Regular.ttf", new string[3] { "VT323", "Consolas", "Courier New" }),
			new FontChoice("creepster", "Creepster", FontCategory.Fun, "Creepster-Regular.ttf", new string[3] { "Creepster", "Chiller", "Impact" }),
			new FontChoice("specialelite", "Special Elite", FontCategory.Fun, "SpecialElite-Regular.ttf", new string[2] { "Special Elite", "Courier New" }),
			new FontChoice("luckiestguy", "Luckiest Guy", FontCategory.Fun, "LuckiestGuy-Regular.ttf", new string[3] { "Luckiest Guy", "Impact", "Comic Sans MS" }),
			new FontChoice("bungee", "Bungee", FontCategory.Fun, "Bungee-Regular.ttf", new string[3] { "Bungee", "Arial Black", "Impact" })
		};

		public static FontChoice Default => All[0];

		public static FontChoice Find(string id)
		{
			if (!string.IsNullOrWhiteSpace(id))
			{
				string b = id.Trim();
				foreach (FontChoice item in All)
				{
					if (string.Equals(item.Id, b, StringComparison.OrdinalIgnoreCase))
					{
						return item;
					}
				}
			}
			return Default;
		}

		public static int IndexOf(FontChoice choice)
		{
			for (int i = 0; i < All.Count; i++)
			{
				if (All[i] == choice)
				{
					return i;
				}
			}
			return 0;
		}

		public static string PickSystemFont(FontChoice choice, IEnumerable<string> installed)
		{
			HashSet<string> hashSet = new HashSet<string>(installed ?? new string[0], StringComparer.OrdinalIgnoreCase);
			string[] systemFonts = choice.SystemFonts;
			foreach (string text in systemFonts)
			{
				if (hashSet.Contains(text))
				{
					return text;
				}
			}
			return null;
		}

		public static float MatchScale(float referenceCapRatio, float fontCapRatio, float extra = 1f)
		{
			float num = 1f;
			if (referenceCapRatio > 0f && fontCapRatio > 0f && !float.IsNaN(referenceCapRatio) && !float.IsNaN(fontCapRatio))
			{
				num = referenceCapRatio / fontCapRatio;
			}
			num *= ((extra > 0f) ? extra : 1f);
			return Math.Max(0.5f, Math.Min(1.6f, num));
		}
	}
	public static class MenuLayout
	{
		public static int FontRowIndex(IReadOnlyList<(string Name, bool Selectable)> rows, string controlsRowName)
		{
			for (int i = 0; i < rows.Count; i++)
			{
				if (rows[i].Name == controlsRowName)
				{
					return i + 1;
				}
			}
			if (rows.Count <= 0 || rows[0].Selectable)
			{
				return 0;
			}
			return 1;
		}

		public static int Columns(int count)
		{
			if (count <= 10)
			{
				return 1;
			}
			return 2;
		}

		public static int Rows(int count, int columns)
		{
			if (columns > 0)
			{
				return (count + columns - 1) / columns;
			}
			return count;
		}

		public static int Move(int index, int dx, int dy, int count, int columns)
		{
			if (count <= 0)
			{
				return 0;
			}
			int num = Rows(count, columns);
			int num2 = Clamp(index / num + dx, 0, columns - 1);
			int num3 = Clamp(index % num + dy, 0, num - 1);
			return Clamp(num2 * num + num3, 0, count - 1);
		}

		public static float ShiftInto(float start, float end, float min, float max, bool keepEnd)
		{
			if (end - start > max - min)
			{
				if (!keepEnd)
				{
					return min - start;
				}
				return max - end;
			}
			if (start < min)
			{
				return min - start;
			}
			if (!(end > max))
			{
				return 0f;
			}
			return max - end;
		}

		private static int Clamp(int value, int min, int max)
		{
			if (value >= min)
			{
				if (value <= max)
				{
					return value;
				}
				return max;
			}
			return min;
		}
	}
}