Decompiled source of ModSettings v0.3.1

Mods/ModSettings.dll

Decompiled 2 days ago
using System;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppScheduleOne;
using Il2CppScheduleOne.UI.MainMenu;
using Il2CppScheduleOne.UI.Settings;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppTMPro;
using MelonLoader;
using Microsoft.CodeAnalysis;
using ModSettings;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Main), "Mod Settings", "0.3.1", "holyfurries", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("ModSettings")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.3.1.0")]
[assembly: AssemblyInformationalVersion("0.3.1+02dc52177acbdd6e341c9eb2130ab5d802413151")]
[assembly: AssemblyProduct("ModSettings")]
[assembly: AssemblyTitle("ModSettings")]
[assembly: AssemblyVersion("0.3.1.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace ModSettings
{
	public sealed class Main : MelonMod
	{
		private const float save_delay_seconds = 1f;

		public override void OnInitializeMelon()
		{
			Tab.install(((MelonBase)this).HarmonyInstance);
		}

		public override void OnUpdate()
		{
			Tab.update_capture();
			float unsaved_since_seconds = Settings.unsaved_since_seconds;
			if (float.IsNaN(unsaved_since_seconds) || Time.unscaledTime - unsaved_since_seconds < 1f)
			{
				return;
			}
			try
			{
				MelonPreferences.Save();
				Settings.unsaved_since_seconds = float.NaN;
			}
			catch (Exception ex)
			{
				Settings.unsaved_since_seconds = Time.unscaledTime;
				((MelonBase)this).LoggerInstance.Warning("Mod Settings: Could not save preferences: " + ex.Message);
			}
		}

		public override void OnDeinitializeMelon()
		{
			Tab.cancel_capture();
		}
	}
	internal enum ControlKind
	{
		Toggle,
		Slider,
		Dropdown,
		Keybind,
		Button
	}
	internal sealed class Setting
	{
		public readonly string mod;

		public readonly string label;

		public readonly ControlKind kind;

		public readonly float minimum;

		public readonly float maximum;

		public readonly bool whole_numbers;

		public readonly string[] options;

		public readonly Func<float> read;

		public readonly Action<float> write;

		private readonly Action<float>?[] views = new Action<float>[2];

		private int view_index;

		public Setting(string mod, string label, ControlKind kind, float minimum, float maximum, bool whole_numbers, string[] options, Func<float> read, Action<float> write)
		{
			if (string.IsNullOrWhiteSpace(mod) || mod.Length > 32)
			{
				throw new ArgumentOutOfRangeException("mod");
			}
			if (string.IsNullOrWhiteSpace(label) || label.Length > 48)
			{
				throw new ArgumentOutOfRangeException("label");
			}
			if (!float.IsFinite(minimum) || !float.IsFinite(maximum) || maximum <= minimum)
			{
				throw new ArgumentOutOfRangeException("maximum");
			}
			if ((whole_numbers || kind != ControlKind.Slider) && (minimum != MathF.Truncate(minimum) || maximum != MathF.Truncate(maximum)))
			{
				throw new ArgumentOutOfRangeException("minimum");
			}
			if (kind == ControlKind.Dropdown && (options.Length < 2 || options.Length > 32))
			{
				throw new ArgumentOutOfRangeException("options");
			}
			if (kind == ControlKind.Button && (options.Length != 1 || string.IsNullOrWhiteSpace(options[0]) || options[0].Length > 32))
			{
				throw new ArgumentOutOfRangeException("options");
			}
			if (kind == ControlKind.Keybind)
			{
				if (options.Length < 2 || options.Length > 512)
				{
					throw new ArgumentOutOfRangeException("options");
				}
				if (minimum != 0f || maximum != (float)(options.Length - 1))
				{
					throw new ArgumentOutOfRangeException("maximum");
				}
			}
			this.mod = mod;
			this.label = label;
			this.kind = kind;
			this.minimum = minimum;
			this.maximum = maximum;
			this.whole_numbers = whole_numbers;
			this.options = options;
			this.read = read;
			this.write = write;
		}

		public void bind(Action<float> view)
		{
			if (view == null)
			{
				throw new ArgumentNullException("view");
			}
			views[view_index] = view;
			view_index = (view_index + 1) % views.Length;
		}

		public void show(float value)
		{
			float obj = clamp(value);
			for (int i = 0; i < views.Length; i++)
			{
				views[i]?.Invoke(obj);
			}
		}

		public static string spaced(string name)
		{
			if (string.IsNullOrEmpty(name) || name.Length > 48)
			{
				throw new ArgumentOutOfRangeException("name");
			}
			StringBuilder stringBuilder = new StringBuilder(name.Length + 8);
			for (int i = 0; i < name.Length; i++)
			{
				if ((i > 0 && char.IsUpper(name[i]) && (char.IsLower(name[i - 1]) || (i + 1 < name.Length && char.IsLower(name[i + 1])))) || name[i] == '_')
				{
					stringBuilder.Append(' ');
				}
				if (name[i] != '_')
				{
					stringBuilder.Append(name[i]);
				}
			}
			return stringBuilder.ToString();
		}

		public float clamp(float value)
		{
			if (!float.IsFinite(value))
			{
				return minimum;
			}
			float num = Math.Clamp(value, minimum, maximum);
			if (!whole_numbers && kind == ControlKind.Slider)
			{
				return num;
			}
			return MathF.Round(num);
		}

		public string format(float value)
		{
			if (kind == ControlKind.Button)
			{
				return options[0];
			}
			float num = clamp(value);
			if (kind == ControlKind.Keybind)
			{
				return options[(int)num];
			}
			if (whole_numbers)
			{
				return num.ToString("0", CultureInfo.InvariantCulture);
			}
			return num.ToString((maximum - minimum >= 20f) ? "0" : "0.00", CultureInfo.InvariantCulture);
		}
	}
	internal sealed class Registry
	{
		public const int setting_count_max = 128;

		private readonly Setting[] settings = new Setting[128];

		public int count { get; private set; }

		public void add(Setting setting)
		{
			if (count == 128)
			{
				throw new InvalidOperationException("Too many mod settings registered.");
			}
			for (int i = 0; i < count; i++)
			{
				if (settings[i].mod == setting.mod && settings[i].label == setting.label)
				{
					throw new InvalidOperationException(setting.mod + " already registered \"" + setting.label + "\".");
				}
			}
			int num = count;
			for (int j = 0; j < count; j++)
			{
				if (settings[j].mod == setting.mod)
				{
					num = j + 1;
				}
			}
			Array.Copy(settings, num, settings, num + 1, count - num);
			settings[num] = setting;
			count++;
		}

		public Setting at(int index)
		{
			if (index < 0 || index >= count)
			{
				throw new ArgumentOutOfRangeException("index");
			}
			return settings[index];
		}

		public bool starts_group(int index)
		{
			if (index != 0)
			{
				return at(index).mod != at(index - 1).mod;
			}
			return true;
		}
	}
	public static class Settings
	{
		private const int slider_integer_magnitude_max = 16777216;

		internal static readonly Registry registry = new Registry();

		internal static readonly KeyCode[] key_codes = Enum.GetValues<KeyCode>();

		internal static float unsaved_since_seconds = float.NaN;

		public static void button(string mod, string label, string caption, Action action)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			if (string.IsNullOrWhiteSpace(caption) || caption.Length > 32)
			{
				throw new ArgumentOutOfRangeException("caption");
			}
			registry.add(new Setting(mod, label, ControlKind.Button, 0f, 1f, whole_numbers: true, new string[1] { caption }, () => 0f, delegate
			{
				action();
			}));
		}

		public static void toggle(string mod, string label, MelonPreferences_Entry<bool> entry)
		{
			if (entry == null)
			{
				throw new ArgumentNullException("entry");
			}
			registry.add(new Setting(mod, label, ControlKind.Toggle, 0f, 1f, whole_numbers: true, Array.Empty<string>(), () => (!entry.Value) ? 0f : 1f, delegate(float value)
			{
				entry.Value = value >= 0.5f;
			}));
			((MelonEventBase<LemonAction<bool, bool>>)(object)entry.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)delegate(bool _, bool value)
			{
				registry_show(mod, label, value ? 1f : 0f);
			}, 0, false);
		}

		public static void slider(string mod, string label, MelonPreferences_Entry<float> entry, float minimum, float maximum, bool whole_numbers = false)
		{
			if (entry == null)
			{
				throw new ArgumentNullException("entry");
			}
			registry.add(new Setting(mod, label, ControlKind.Slider, minimum, maximum, whole_numbers, Array.Empty<string>(), () => entry.Value, delegate(float value)
			{
				entry.Value = value;
			}));
			((MelonEventBase<LemonAction<float, float>>)(object)entry.OnEntryValueChanged).Subscribe((LemonAction<float, float>)delegate(float _, float value)
			{
				registry_show(mod, label, value);
			}, 0, false);
		}

		public static void slider(string mod, string label, MelonPreferences_Entry<int> entry, int minimum, int maximum)
		{
			if (entry == null)
			{
				throw new ArgumentNullException("entry");
			}
			if (minimum < -16777216)
			{
				throw new ArgumentOutOfRangeException("minimum");
			}
			if (maximum > 16777216)
			{
				throw new ArgumentOutOfRangeException("maximum");
			}
			registry.add(new Setting(mod, label, ControlKind.Slider, minimum, maximum, whole_numbers: true, Array.Empty<string>(), () => entry.Value, delegate(float value)
			{
				entry.Value = checked((int)value);
			}));
			((MelonEventBase<LemonAction<int, int>>)(object)entry.OnEntryValueChanged).Subscribe((LemonAction<int, int>)delegate(int _, int value)
			{
				registry_show(mod, label, value);
			}, 0, false);
		}

		public static void dropdown<T>(string mod, string label, MelonPreferences_Entry<T> entry) where T : struct, Enum
		{
			if (entry == null)
			{
				throw new ArgumentNullException("entry");
			}
			T[] values = Enum.GetValues<T>();
			string[] options = Array.ConvertAll(Enum.GetNames<T>(), Setting.spaced);
			registry.add(new Setting(mod, label, ControlKind.Dropdown, 0f, Math.Max(1, values.Length - 1), whole_numbers: true, options, () => Array.IndexOf(values, entry.Value), delegate(float value)
			{
				entry.Value = values[(int)value];
			}));
			((MelonEventBase<LemonAction<T, T>>)(object)entry.OnEntryValueChanged).Subscribe((LemonAction<T, T>)delegate(T _, T value)
			{
				registry_show(mod, label, Array.IndexOf(values, value));
			}, 0, false);
		}

		public unsafe static void keybind(string mod, string label, MelonPreferences_Entry<KeyCode> entry)
		{
			if (entry == null)
			{
				throw new ArgumentNullException("entry");
			}
			if (key_codes.Length < 2 || key_codes.Length > 512 || key_codes[0])
			{
				throw new InvalidOperationException("Unexpected Unity key codes.");
			}
			string[] options = Array.ConvertAll(key_codes, (KeyCode key) => ((int)key != 0) ? Setting.spaced(((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString()) : "Unbound");
			registry.add(new Setting(mod, label, ControlKind.Keybind, 0f, key_codes.Length - 1, whole_numbers: true, options, () => Array.IndexOf(key_codes, entry.Value), delegate(float value)
			{
				entry.Value = key_codes[(int)value];
			}));
			((MelonEventBase<LemonAction<KeyCode, KeyCode>>)(object)entry.OnEntryValueChanged).Subscribe((LemonAction<KeyCode, KeyCode>)delegate(KeyCode _, KeyCode value)
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				registry_show(mod, label, Array.IndexOf(key_codes, value));
			}, 0, false);
		}

		internal static void change(Setting setting, float value, float now_seconds)
		{
			float num = setting.clamp(value);
			if (num != setting.read())
			{
				setting.write(num);
				if (float.IsNaN(unsaved_since_seconds))
				{
					unsaved_since_seconds = now_seconds;
				}
			}
		}

		private static void registry_show(string mod, string label, float value)
		{
			for (int i = 0; i < registry.count; i++)
			{
				Setting setting = registry.at(i);
				if (setting.mod == mod && setting.label == label)
				{
					setting.show(value);
				}
			}
		}
	}
	internal static class SettingsLayout
	{
		public const float label_left = -4f;

		private const float value_gap = 12f;

		private const float row_height = 50f;

		private const float row_gap = 10f;

		private const float control_height_max = 48f;

		public static VerticalLayoutGroup prepare_panel(GameObject panel, VerticalLayoutGroup native_layout)
		{
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			if (((Object)panel).name != "ModSettings")
			{
				throw new InvalidOperationException("Only the Mods panel can be laid out.");
			}
			VerticalLayoutGroup obj = panel.GetComponentInChildren<VerticalLayoutGroup>(true) ?? throw new InvalidOperationException("Settings panel has no row layout.");
			ScrollRect componentInChildren = panel.GetComponentInChildren<ScrollRect>(true);
			if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.content != (Object)null)
			{
				stretch_width(componentInChildren.content);
			}
			stretch_width(((Component)obj).GetComponent<RectTransform>());
			((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false;
			((HorizontalOrVerticalLayoutGroup)obj).spacing = 10f;
			RectOffset padding = ((LayoutGroup)native_layout).padding;
			((LayoutGroup)obj).padding = new RectOffset(24, 24, padding.top, padding.bottom);
			return obj;
		}

		public static void toggle(GameObject row, UIToggle option)
		{
			//IL_00e6: 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_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: 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_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			prepare_row(row);
			if ((Object)(object)option.toggleImage == (Object)null)
			{
				return;
			}
			Transform val = ((Component)option.toggleImage).transform;
			for (int i = 0; i < 16; i++)
			{
				if (!((Object)(object)val.parent != (Object)null))
				{
					break;
				}
				if (!((Object)(object)val.parent != (Object)(object)row.transform))
				{
					break;
				}
				val = val.parent;
			}
			if ((Object)(object)val.parent != (Object)(object)row.transform)
			{
				throw new InvalidOperationException("Toggle visual has no row parent within 16 levels.");
			}
			Image val2 = null;
			Transform parent = ((Component)option.toggleImage).transform.parent;
			for (int j = 0; j < 16; j++)
			{
				if (!((Object)(object)parent != (Object)null))
				{
					break;
				}
				if (!((Object)(object)parent != (Object)(object)row.transform))
				{
					break;
				}
				val2 = ((Component)parent).GetComponent<Image>();
				if ((Object)(object)val2 != (Object)null)
				{
					break;
				}
				parent = parent.parent;
			}
			if ((Object)(object)val2 == (Object)null)
			{
				throw new InvalidOperationException("Toggle indicator has no background image.");
			}
			RectTransform rectTransform = ((Graphic)val2).rectTransform;
			Rect rect = rectTransform.rect;
			Vector2 val3 = ((Rect)(ref rect)).size;
			if (val3.y > 48f)
			{
				val3 *= 48f / val3.y;
			}
			if ((Object)(object)((Component)val2).transform == (Object)(object)val)
			{
				GameObject val4 = new GameObject("ToggleControl", (Type[])(object)new Type[1] { Il2CppType.Of<RectTransform>() });
				val4.transform.SetParent(row.transform, false);
				val4.GetComponent<RectTransform>().sizeDelta = val3;
				val = val4.transform;
			}
			RectTransform component = ((Component)val).GetComponent<RectTransform>();
			((Transform)component).SetParent(row.transform, false);
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.offsetMin = Vector2.zero;
			component.offsetMax = Vector2.zero;
			((Transform)rectTransform).SetParent(val, false);
			rectTransform.anchorMin = new Vector2(0f, 0.5f);
			rectTransform.anchorMax = rectTransform.anchorMin;
			rectTransform.pivot = new Vector2(0f, 0.5f);
			rectTransform.anchoredPosition = Vector2.zero;
			rectTransform.sizeDelta = val3;
			if ((Object)(object)option.buttonText != (Object)null)
			{
				RectTransform rectTransform2 = ((TMP_Text)option.buttonText).rectTransform;
				((Transform)rectTransform2).SetParent(val, false);
				rectTransform2.anchorMin = Vector2.zero;
				rectTransform2.anchorMax = Vector2.one;
				rectTransform2.offsetMin = new Vector2(val3.x + 12f, 0f);
				rectTransform2.offsetMax = Vector2.zero;
				((TMP_Text)option.buttonText).alignment = (TextAlignmentOptions)4097;
			}
		}

		public static void slider(GameObject row, Slider control, TextMeshProUGUI? value)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_007b: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			prepare_row(row);
			RectTransform component = ((Component)control).GetComponent<RectTransform>();
			Rect rect = component.rect;
			float num = Math.Min(((Rect)(ref rect)).height, 48f);
			LayoutElement obj = ((Component)control).GetComponent<LayoutElement>() ?? ((Component)control).gameObject.AddComponent<LayoutElement>();
			rect = component.rect;
			obj.preferredWidth = ((Rect)(ref rect)).width;
			((Transform)component).SetParent(row.transform, false);
			component.anchorMin = new Vector2(0f, 0.5f);
			component.anchorMax = new Vector2(1f, 0.5f);
			component.pivot = new Vector2(0.5f, 0.5f);
			component.offsetMin = new Vector2(0f, (0f - num) / 2f);
			component.offsetMax = new Vector2(0f, num / 2f);
			if (!((Object)(object)value == (Object)null))
			{
				RectTransform rectTransform = ((TMP_Text)value).rectTransform;
				((Transform)rectTransform).SetParent(row.transform, false);
				rectTransform.anchorMin = new Vector2(1f, 0.5f);
				rectTransform.anchorMax = rectTransform.anchorMin;
				rectTransform.pivot = new Vector2(0f, 0.5f);
				rectTransform.anchoredPosition = new Vector2(12f, 0f);
				rectTransform.sizeDelta = new Vector2(96f, 50f);
				((TMP_Text)value).alignment = (TextAlignmentOptions)4097;
				((TMP_Text)value).margin = Vector4.zero;
				((TMP_Text)value).enableWordWrapping = false;
			}
		}

		public static void dropdown(GameObject row, TMP_Dropdown control)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			Rect rect = ((Component)control).GetComponent<RectTransform>().rect;
			button(row, (Selectable)(object)control, ((Rect)(ref rect)).size);
		}

		public static void button(GameObject row, Selectable control, Vector2 size)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			prepare_row(row);
			if (!float.IsFinite(((Vector2)(ref size)).sqrMagnitude) || size.x <= 0f || size.y <= 0f)
			{
				throw new ArgumentOutOfRangeException("size");
			}
			RectTransform component = ((Component)control).GetComponent<RectTransform>();
			((Transform)component).SetParent(row.transform, false);
			component.anchorMin = new Vector2(0f, 0.5f);
			component.anchorMax = component.anchorMin;
			component.pivot = new Vector2(0f, 0.5f);
			component.anchoredPosition = Vector2.zero;
			component.sizeDelta = new Vector2(size.x, Math.Min(size.y, 48f));
			(((Component)control).GetComponent<LayoutElement>() ?? ((Component)control).gameObject.AddComponent<LayoutElement>()).preferredWidth = size.x;
		}

		public static void fit_columns(Transform rows, Registry registry)
		{
			//IL_0435: Unknown result type (might be due to invalid IL or missing references)
			//IL_043f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0452: Unknown result type (might be due to invalid IL or missing references)
			//IL_045c: Unknown result type (might be due to invalid IL or missing references)
			//IL_046f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0479: Unknown result type (might be due to invalid IL or missing references)
			//IL_048f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0499: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_050c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0516: Unknown result type (might be due to invalid IL or missing references)
			//IL_0526: Unknown result type (might be due to invalid IL or missing references)
			//IL_0530: Unknown result type (might be due to invalid IL or missing references)
			//IL_0543: Unknown result type (might be due to invalid IL or missing references)
			//IL_054d: Unknown result type (might be due to invalid IL or missing references)
			//IL_057c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0586: Unknown result type (might be due to invalid IL or missing references)
			//IL_0599: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: 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_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0391: Unknown result type (might be due to invalid IL or missing references)
			//IL_0396: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI[] array = (TextMeshProUGUI[])(object)new TextMeshProUGUI[registry.count];
			RectTransform[] array2 = (RectTransform[])(object)new RectTransform[registry.count];
			TextMeshProUGUI[] array3 = (TextMeshProUGUI[])(object)new TextMeshProUGUI[registry.count];
			float[] array4 = new float[registry.count];
			float[] array5 = new float[registry.count];
			float num = 0f;
			float num2 = 0f;
			float num3 = float.PositiveInfinity;
			int num4 = 0;
			for (int i = 0; i < Math.Min(rows.childCount, 512); i++)
			{
				GameObject gameObject = ((Component)rows.GetChild(i)).gameObject;
				if (!gameObject.activeSelf || (Object)(object)gameObject.GetComponent<TextMeshProUGUI>() != (Object)null)
				{
					continue;
				}
				if (num4 >= registry.count)
				{
					throw new InvalidOperationException("Unexpected Mods row count.");
				}
				Setting setting = registry.at(num4);
				Il2CppArrayBase<TextMeshProUGUI> componentsInChildren = gameObject.GetComponentsInChildren<TextMeshProUGUI>(true);
				TextMeshProUGUI val = null;
				for (int j = 0; j < Math.Min(componentsInChildren.Length, 32); j++)
				{
					if (!((Object)(object)((TMP_Text)componentsInChildren[j]).transform.parent != (Object)(object)gameObject.transform) && (((Object)componentsInChildren[j]).name.StartsWith("Option Name", StringComparison.Ordinal) || ((Object)componentsInChildren[j]).name == "Label"))
					{
						val = componentsInChildren[j];
						break;
					}
				}
				if ((Object)(object)val == (Object)null)
				{
					throw new InvalidOperationException("Mods row has no label.");
				}
				((TMP_Text)val).ForceMeshUpdate(true, true);
				num = Math.Max(num, ((TMP_Text)val).GetPreferredValues(setting.label).x);
				RectTransform component;
				float num5;
				Rect rect;
				if (setting.kind == ControlKind.Slider)
				{
					component = ((Component)gameObject.GetComponentInChildren<Slider>(true)).GetComponent<RectTransform>();
					num5 = ((Component)component).GetComponent<LayoutElement>().preferredWidth;
					int num6 = num4;
					UISlider componentInChildren = gameObject.GetComponentInChildren<UISlider>(true);
					array3[num6] = ((componentInChildren != null) ? componentInChildren.valueText : null);
					TextMeshProUGUI val2 = array3[num4];
					if ((Object)(object)val2 != (Object)null)
					{
						((TMP_Text)val2).ForceMeshUpdate(true, true);
						float val3 = Math.Max(((TMP_Text)val2).GetPreferredValues(setting.format(setting.minimum)).x, ((TMP_Text)val2).GetPreferredValues(setting.format(setting.maximum)).x);
						array5[num4] = Math.Max(val3, ((TMP_Text)val2).GetPreferredValues(setting.format(setting.read())).x);
					}
				}
				else if (setting.kind == ControlKind.Toggle)
				{
					UIToggle componentInChildren2 = gameObject.GetComponentInChildren<UIToggle>(true);
					Transform val4 = ((Component)componentInChildren2.toggleImage).transform;
					for (int k = 0; k < 16; k++)
					{
						if (!((Object)(object)val4.parent != (Object)(object)gameObject.transform))
						{
							break;
						}
						val4 = val4.parent;
					}
					if ((Object)(object)val4.parent != (Object)(object)gameObject.transform)
					{
						throw new InvalidOperationException("Toggle control has no row parent.");
					}
					component = ((Component)val4).GetComponent<RectTransform>();
					rect = ((Component)((Component)componentInChildren2.toggleImage).transform.parent).GetComponent<RectTransform>().rect;
					num5 = ((Rect)(ref rect)).width + 12f + ((TMP_Text)componentInChildren2.buttonText).GetPreferredValues("Off").x;
				}
				else
				{
					component = ((Component)((setting.kind == ControlKind.Dropdown) ? ((object)gameObject.GetComponentInChildren<TMP_Dropdown>(true)) : ((object)gameObject.GetComponentInChildren<Button>(true)))).GetComponent<RectTransform>();
					num5 = ((Component)component).GetComponent<LayoutElement>().preferredWidth;
				}
				if (!float.IsFinite(num5) || num5 <= 0f)
				{
					throw new InvalidOperationException("Mods control width is invalid.");
				}
				array[num4] = val;
				array2[num4] = component;
				array4[num4] = num5;
				float val5 = num5 + (((Object)(object)array3[num4] != (Object)null) ? (12f + array5[num4]) : 0f);
				num2 = Math.Max(num2, val5);
				float val6 = num3;
				rect = gameObject.GetComponent<RectTransform>().rect;
				num3 = Math.Min(val6, ((Rect)(ref rect)).width);
				num4++;
			}
			if (num4 != registry.count || !float.IsFinite(num3) || num3 <= 0f)
			{
				throw new InvalidOperationException("Mods rows have no resolved width.");
			}
			float num7 = Math.Clamp(-4f + num + 16f, 0f, Math.Max(0f, num3 - num2));
			for (int l = 0; l < num4; l++)
			{
				RectTransform rectTransform = ((TMP_Text)array[l]).rectTransform;
				rectTransform.anchorMin = new Vector2(0f, rectTransform.anchorMin.y);
				rectTransform.anchorMax = new Vector2(0f, rectTransform.anchorMax.y);
				rectTransform.offsetMin = new Vector2(-4f, rectTransform.offsetMin.y);
				rectTransform.offsetMax = new Vector2(num7 - 16f, rectTransform.offsetMax.y);
				RectTransform val7 = array2[l];
				float num8 = (((Object)(object)array3[l] != (Object)null) ? (12f + array5[l]) : 0f);
				float num9 = Math.Min(array4[l], Math.Max(0f, num3 - num7 - num8));
				val7.anchorMin = new Vector2(0f, val7.anchorMin.y);
				val7.anchorMax = new Vector2(0f, val7.anchorMax.y);
				val7.offsetMin = new Vector2(num7, val7.offsetMin.y);
				val7.offsetMax = new Vector2(num7 + num9, val7.offsetMax.y);
				TextMeshProUGUI val8 = array3[l];
				if (!((Object)(object)val8 == (Object)null))
				{
					RectTransform rectTransform2 = ((TMP_Text)val8).rectTransform;
					rectTransform2.anchorMin = new Vector2(0f, rectTransform2.anchorMin.y);
					rectTransform2.anchorMax = new Vector2(0f, rectTransform2.anchorMax.y);
					rectTransform2.offsetMin = new Vector2(num7 + num9 + 12f, rectTransform2.offsetMin.y);
					rectTransform2.offsetMax = new Vector2(num7 + num9 + 12f + array5[l], rectTransform2.offsetMax.y);
				}
			}
		}

		public static void typography(GameObject row, TextMeshProUGUI template)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: 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_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			Il2CppArrayBase<TextMeshProUGUI> componentsInChildren = row.GetComponentsInChildren<TextMeshProUGUI>(true);
			for (int i = 0; i < Math.Min(componentsInChildren.Length, 32); i++)
			{
				TextMeshProUGUI val = componentsInChildren[i];
				if (!((Object)(object)((TMP_Text)val).transform.parent != (Object)(object)row.transform) && (((Object)val).name.StartsWith("Option Name", StringComparison.Ordinal) || ((Object)val).name == "Label"))
				{
					((TMP_Text)val).font = ((TMP_Text)template).font;
					((TMP_Text)val).fontSharedMaterial = ((TMP_Text)template).fontSharedMaterial;
					((TMP_Text)val).fontSize = ((TMP_Text)template).fontSize;
					((TMP_Text)val).fontWeight = ((TMP_Text)template).fontWeight;
					((TMP_Text)val).fontStyle = ((TMP_Text)template).fontStyle;
					((TMP_Text)val).characterSpacing = ((TMP_Text)template).characterSpacing;
					((TMP_Text)val).wordSpacing = ((TMP_Text)template).wordSpacing;
					((TMP_Text)val).lineSpacing = ((TMP_Text)template).lineSpacing;
					((Graphic)val).color = ((Graphic)template).color;
					((TMP_Text)val).fontSizeMin = ((TMP_Text)template).fontSizeMin;
					((TMP_Text)val).fontSizeMax = ((TMP_Text)template).fontSizeMax;
					((TMP_Text)val).enableAutoSizing = ((TMP_Text)template).enableAutoSizing;
					((TMP_Text)val).alignment = ((TMP_Text)template).alignment;
					RectTransform rectTransform = ((TMP_Text)val).rectTransform;
					RectTransform rectTransform2 = ((TMP_Text)template).rectTransform;
					rectTransform.pivot = new Vector2(rectTransform.pivot.x, rectTransform2.pivot.y);
					rectTransform.anchorMin = new Vector2(rectTransform.anchorMin.x, rectTransform2.anchorMin.y);
					rectTransform.anchorMax = new Vector2(rectTransform.anchorMax.x, rectTransform2.anchorMax.y);
					rectTransform.offsetMin = new Vector2(rectTransform.offsetMin.x, rectTransform2.offsetMin.y);
					rectTransform.offsetMax = new Vector2(rectTransform.offsetMax.x, rectTransform2.offsetMax.y);
					((TMP_Text)val).margin = new Vector4(0f, ((TMP_Text)template).margin.y, 0f, ((TMP_Text)template).margin.w);
				}
			}
		}

		public static void label(GameObject row)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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_009d: Unknown result type (might be due to invalid IL or missing references)
			Il2CppArrayBase<TextMeshProUGUI> componentsInChildren = row.GetComponentsInChildren<TextMeshProUGUI>(true);
			for (int i = 0; i < Math.Min(componentsInChildren.Length, 32); i++)
			{
				TextMeshProUGUI val = componentsInChildren[i];
				if (!((Object)(object)((TMP_Text)val).transform.parent != (Object)(object)row.transform) && (((Object)val).name.StartsWith("Option Name", StringComparison.Ordinal) || ((Object)val).name == "Label"))
				{
					((TMP_Text)val).rectTransform.offsetMin = new Vector2(-4f, ((TMP_Text)val).rectTransform.offsetMin.y);
					((TMP_Text)val).margin = new Vector4(0f, ((TMP_Text)val).margin.y, 0f, ((TMP_Text)val).margin.w);
					((TMP_Text)val).overflowMode = (TextOverflowModes)1;
					((TMP_Text)val).enableWordWrapping = false;
				}
			}
		}

		private static void prepare_row(GameObject row)
		{
			Transform val = row.transform;
			bool flag = false;
			for (int i = 0; i < 16; i++)
			{
				if (!((Object)(object)val != (Object)null))
				{
					break;
				}
				if (((Object)val).name == "ModSettings")
				{
					flag = true;
					break;
				}
				val = val.parent;
			}
			if (!flag)
			{
				throw new InvalidOperationException("Only Mods rows can be laid out.");
			}
			ContentSizeFitter component = row.GetComponent<ContentSizeFitter>();
			if ((Object)(object)component != (Object)null)
			{
				component.horizontalFit = (FitMode)0;
				component.verticalFit = (FitMode)0;
			}
			LayoutElement obj = row.GetComponent<LayoutElement>() ?? row.AddComponent<LayoutElement>();
			obj.layoutPriority = 2;
			obj.minWidth = 0f;
			obj.preferredWidth = -1f;
			obj.flexibleWidth = 1f;
			obj.minHeight = 50f;
			obj.preferredHeight = 50f;
			obj.flexibleHeight = 0f;
			label(row);
			VerticalLayoutGroup component2 = ((Component)row.transform.parent).GetComponent<VerticalLayoutGroup>();
			if (!((Object)(object)component2 == (Object)null))
			{
				((HorizontalOrVerticalLayoutGroup)component2).childControlWidth = true;
				((HorizontalOrVerticalLayoutGroup)component2).childForceExpandWidth = true;
				((HorizontalOrVerticalLayoutGroup)component2).childControlHeight = true;
				((HorizontalOrVerticalLayoutGroup)component2).childForceExpandHeight = false;
				((HorizontalOrVerticalLayoutGroup)component2).spacing = 10f;
			}
		}

		private static void stretch_width(RectTransform rect)
		{
			//IL_001e: 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_0039: 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_0054: 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_006f: 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)
			ContentSizeFitter component = ((Component)rect).GetComponent<ContentSizeFitter>();
			if ((Object)(object)component != (Object)null)
			{
				component.horizontalFit = (FitMode)0;
			}
			rect.anchorMin = new Vector2(0f, rect.anchorMin.y);
			rect.anchorMax = new Vector2(1f, rect.anchorMax.y);
			rect.offsetMin = new Vector2(0f, rect.offsetMin.y);
			rect.offsetMax = new Vector2(0f, rect.offsetMax.y);
		}
	}
	internal static class Tab
	{
		private readonly record struct Templates(GameObject panel, SettingsToggle? toggle, SettingsSlider? slider, SettingsDropdown? dropdown, Button? keybind, TextMeshProUGUI heading, TextMeshProUGUI label);

		private sealed record KeyCapture(Setting setting, SettingsScreen screen, GameObject row, Button button, TextMeshProUGUI caption, GameObject blocker, int frame, float expires_seconds);

		private const string tab_name = "ModSettingsTab";

		private const int category_count_max = 16;

		private static KeyCapture? capture;

		public static void install(Harmony harmony)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			harmony.Patch((MethodBase)AccessTools.Method(typeof(SettingsScreen), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Tab), "add_tab", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static void add_tab(SettingsScreen __instance)
		{
			try
			{
				build(__instance);
			}
			catch (Exception value)
			{
				MelonLogger.Warning($"Mod Settings: Tab unavailable, edit UserData/MelonPreferences.cfg instead: {value}");
			}
		}

		private static void build(SettingsScreen screen)
		{
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0402: Unknown result type (might be due to invalid IL or missing references)
			//IL_0407: Unknown result type (might be due to invalid IL or missing references)
			//IL_040f: Unknown result type (might be due to invalid IL or missing references)
			//IL_041c: Expected O, but got Unknown
			Registry registry = Settings.registry;
			if (registry.count == 0)
			{
				return;
			}
			Il2CppReferenceArray<SettingsCategory> categories = screen.Categories;
			if (categories == null || ((Il2CppArrayBase<SettingsCategory>)(object)categories).Length == 0 || ((Il2CppArrayBase<SettingsCategory>)(object)categories).Length >= 16)
			{
				throw new InvalidOperationException("Unexpected settings categories.");
			}
			SettingsCategory val = ((Il2CppArrayBase<SettingsCategory>)(object)categories)[((Il2CppArrayBase<SettingsCategory>)(object)categories).Length - 1];
			if ((Object)(object)val.Toggle == (Object)null || (Object)(object)val.Panel == (Object)null)
			{
				throw new InvalidOperationException("Settings category is incomplete.");
			}
			if ((Object)(object)((Component)val.Toggle).transform.parent.Find("ModSettingsTab") != (Object)null)
			{
				return;
			}
			Templates templates = find_templates(categories);
			GameObject val2 = Object.Instantiate<GameObject>(templates.panel, templates.panel.transform.parent);
			((Object)val2).name = "ModSettings";
			val2.SetActive(false);
			VerticalLayoutGroup val3 = SettingsLayout.prepare_panel(val2, ((Component)((TMP_Text)templates.heading).transform.parent).GetComponent<VerticalLayoutGroup>());
			ScrollRect val4 = val2.GetComponentInChildren<ScrollRect>(true) ?? throw new InvalidOperationException("Settings panel has no scroll view.");
			RectTransform content = val4.content ?? throw new InvalidOperationException("Settings scroll view has no content.");
			Transform rows = ((Component)val3).transform;
			for (int i = 0; i < rows.childCount; i++)
			{
				((Component)rows.GetChild(i)).gameObject.SetActive(false);
			}
			float row_width = ((rows.childCount > 0) ? ((Component)rows.GetChild(0)).GetComponent<RectTransform>().sizeDelta.x : 450f);
			TextMeshProUGUI heading = templates.heading;
			for (int j = 0; j < registry.count; j++)
			{
				Setting setting = registry.at(j);
				if (registry.starts_group(j))
				{
					add_header(rows, heading, setting.mod, row_width, j == 0);
				}
				switch (setting.kind)
				{
				case ControlKind.Toggle:
					add_toggle(rows, templates.toggle, setting);
					break;
				case ControlKind.Slider:
					add_slider(rows, templates.slider, setting);
					break;
				case ControlKind.Dropdown:
					add_dropdown(rows, templates.dropdown, setting);
					break;
				case ControlKind.Keybind:
					add_button(screen, rows, templates.dropdown, templates.keybind, setting);
					break;
				case ControlKind.Button:
					add_button(screen, rows, templates.dropdown, templates.keybind, setting);
					break;
				default:
					throw new InvalidOperationException("Unknown control kind.");
				}
			}
			for (int k = 0; k < rows.childCount; k++)
			{
				GameObject gameObject = ((Component)rows.GetChild(k)).gameObject;
				if (gameObject.activeSelf)
				{
					SettingsLayout.typography(gameObject, templates.label);
					ContentSizeFitter component = gameObject.GetComponent<ContentSizeFitter>();
					if ((Object)(object)component != (Object)null)
					{
						component.horizontalFit = (FitMode)0;
					}
					LayoutElement obj = gameObject.GetComponent<LayoutElement>() ?? gameObject.AddComponent<LayoutElement>();
					obj.minWidth = 0f;
					obj.preferredWidth = -1f;
					obj.flexibleWidth = 1f;
				}
			}
			Toggle component2 = Object.Instantiate<GameObject>(((Component)val.Toggle).gameObject, ((Component)val.Toggle).transform.parent).GetComponent<Toggle>();
			((Object)component2).name = "ModSettingsTab";
			component2.SetIsOnWithoutNotify(false);
			TextMeshProUGUI componentInChildren = ((Component)component2).GetComponentInChildren<TextMeshProUGUI>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				((TMP_Text)componentInChildren).text = "Mods";
			}
			int index = ((Il2CppArrayBase<SettingsCategory>)(object)categories).Length;
			Il2CppReferenceArray<SettingsCategory> val5 = new Il2CppReferenceArray<SettingsCategory>((long)(index + 1));
			for (int l = 0; l < index; l++)
			{
				((Il2CppArrayBase<SettingsCategory>)(object)val5)[l] = ((Il2CppArrayBase<SettingsCategory>)(object)categories)[l];
			}
			((Il2CppArrayBase<SettingsCategory>)(object)val5)[index] = new SettingsCategory
			{
				Toggle = component2,
				Panel = val2
			};
			screen.Categories = val5;
			((UnityEvent<bool>)(object)component2.onValueChanged).AddListener(UnityAction<bool>.op_Implicit((Action<bool>)delegate(bool selected)
			{
				if (selected)
				{
					screen.ShowCategory(index);
					for (int m = 0; m < registry.count; m++)
					{
						registry.at(m).show(registry.at(m).read());
					}
					Canvas.ForceUpdateCanvases();
					LayoutRebuilder.ForceRebuildLayoutImmediate(content);
					SettingsLayout.fit_columns(rows, registry);
				}
			}));
			fit_tabs(((Component)screen).GetComponent<RectTransform>(), ((Component)component2).transform.parent);
		}

		private static Templates find_templates(Il2CppReferenceArray<SettingsCategory> categories)
		{
			GameObject val = null;
			int num = -1;
			SettingsToggle val2 = null;
			SettingsSlider val3 = null;
			SettingsDropdown val4 = null;
			Button val5 = null;
			TextMeshProUGUI val6 = null;
			TextMeshProUGUI val7 = null;
			for (int i = 0; i < ((Il2CppArrayBase<SettingsCategory>)(object)categories).Length; i++)
			{
				GameObject panel = ((Il2CppArrayBase<SettingsCategory>)(object)categories)[i].Panel;
				if ((Object)(object)panel == (Object)null)
				{
					continue;
				}
				SettingsToggle componentInChildren = panel.GetComponentInChildren<SettingsToggle>(true);
				SettingsSlider componentInChildren2 = panel.GetComponentInChildren<SettingsSlider>(true);
				SettingsDropdown componentInChildren3 = panel.GetComponentInChildren<SettingsDropdown>(true);
				if (val2 == null)
				{
					val2 = componentInChildren;
				}
				if (val3 == null)
				{
					val3 = componentInChildren2;
				}
				if (val4 == null)
				{
					val4 = componentInChildren3;
				}
				Keybinder componentInChildren4 = panel.GetComponentInChildren<Keybinder>(true);
				if ((Object)(object)componentInChildren4 != (Object)null)
				{
					if (val5 == null)
					{
						val5 = ((Component)componentInChildren4).GetComponentInChildren<Button>(true);
					}
					Il2CppArrayBase<TextMeshProUGUI> componentsInChildren = panel.GetComponentsInChildren<TextMeshProUGUI>(true);
					for (int j = 0; j < Math.Min(componentsInChildren.Length, 256); j++)
					{
						if (((TMP_Text)componentsInChildren[j]).text == "Settings")
						{
							if (val6 == null)
							{
								val6 = componentsInChildren[j];
							}
							break;
						}
					}
				}
				TextMeshProUGUI componentInChildren5 = ((Component)((Il2CppArrayBase<SettingsCategory>)(object)categories)[i].Toggle).GetComponentInChildren<TextMeshProUGUI>(true);
				if ((Object)(object)componentInChildren5 != (Object)null && ((TMP_Text)componentInChildren5).text == "Gamepad")
				{
					Il2CppArrayBase<TextMeshProUGUI> componentsInChildren2 = panel.GetComponentsInChildren<TextMeshProUGUI>(true);
					for (int k = 0; k < Math.Min(componentsInChildren2.Length, 256); k++)
					{
						TextMeshProUGUI val8 = componentsInChildren2[k];
						if (((TMP_Text)val8).text == "Settings")
						{
							val6 = val8;
						}
						if ((((Object)val8).name.StartsWith("Option Name", StringComparison.Ordinal) || ((Object)val8).name == "Label") && val7 == null)
						{
							val7 = val8;
						}
					}
				}
				if (!((Object)(object)panel.GetComponentInChildren<VerticalLayoutGroup>(true) == (Object)null))
				{
					int num2 = (((Object)(object)componentInChildren != (Object)null) ? 1 : 0) + (((Object)(object)componentInChildren2 != (Object)null) ? 1 : 0) + (((Object)(object)componentInChildren3 != (Object)null) ? 1 : 0);
					if (num2 > num)
					{
						val = panel;
						num = num2;
						val2 = componentInChildren ?? val2;
						val3 = componentInChildren2 ?? val3;
						val4 = componentInChildren3 ?? val4;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				throw new InvalidOperationException("No scrolling settings panel to copy.");
			}
			if ((Object)(object)val6 == (Object)null)
			{
				throw new InvalidOperationException("No native settings heading to copy.");
			}
			if ((Object)(object)val7 == (Object)null)
			{
				throw new InvalidOperationException("No Gamepad settings label to copy.");
			}
			return new Templates(val, val2, val3, val4, val5, val6, val7);
		}

		private static void add_header(Transform rows, TextMeshProUGUI label_template, string mod, float row_width, bool first)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(((Component)label_template).gameObject, rows);
			((Object)val).name = "Header";
			TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>();
			((TMP_Text)component).enableWordWrapping = false;
			((TMP_Text)component).enableAutoSizing = false;
			Vector4 margin = ((TMP_Text)label_template).margin;
			((TMP_Text)component).margin = new Vector4(-4f, margin.y, margin.z, margin.w);
			((Graphic)component).raycastTarget = false;
			((TMP_Text)component).text = mod;
			((TMP_Text)component).ForceMeshUpdate(true, true);
			float preferredHeight = ((TMP_Text)component).preferredHeight;
			if (!float.IsFinite(preferredHeight) || preferredHeight <= 0f)
			{
				throw new InvalidOperationException("Native heading height is invalid.");
			}
			float num = (first ? 0f : 20f);
			preferredHeight += num;
			((TMP_Text)component).margin = new Vector4(-4f, margin.y + num, margin.z, margin.w);
			val.GetComponent<RectTransform>().sizeDelta = new Vector2(row_width, preferredHeight);
			LayoutElement obj = val.GetComponent<LayoutElement>() ?? val.AddComponent<LayoutElement>();
			obj.layoutPriority = 2;
			obj.minHeight = preferredHeight;
			obj.preferredHeight = preferredHeight;
			obj.flexibleHeight = 0f;
		}

		private static void add_toggle(Transform rows, SettingsToggle? template, Setting setting)
		{
			if ((Object)(object)template == (Object)null)
			{
				throw new InvalidOperationException("No switch row to copy.");
			}
			GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject, rows);
			Object.DestroyImmediate((Object)(object)val.GetComponent<SettingsToggle>());
			UIToggle toggle = val.GetComponent<UIToggle>() ?? throw new InvalidOperationException("Switch row has no UIToggle.");
			((UIOption)toggle).optionName = setting.label;
			name_row(val, setting.label);
			SettingsLayout.toggle(val, toggle);
			toggle.OnChanged.AddListener(UnityAction<bool>.op_Implicit((Action<bool>)delegate(bool value)
			{
				Settings.change(setting, value ? 1f : 0f, Time.unscaledTime);
			}));
			setting.bind(delegate(float value)
			{
				if ((Object)(object)toggle != (Object)null)
				{
					toggle.SetStateWithoutNotify(value >= 0.5f);
				}
			});
			val.SetActive(true);
		}

		private static void add_slider(Transform rows, SettingsSlider? template, Setting setting)
		{
			if ((Object)(object)template == (Object)null)
			{
				throw new InvalidOperationException("No slider row to copy.");
			}
			GameObject val = Object.Instantiate<GameObject>(((Component)(((Object)(object)((Component)((Component)template).transform.parent).GetComponent<UISlider>() != (Object)null) ? ((Component)template).transform.parent : ((Component)template).transform)).gameObject, rows);
			Object.DestroyImmediate((Object)(object)val.GetComponentInChildren<SettingsSlider>(true));
			Slider slider = val.GetComponentInChildren<Slider>(true) ?? throw new InvalidOperationException("Slider row has no Slider.");
			UISlider componentInChildren = val.GetComponentInChildren<UISlider>(true);
			TextMeshProUGUI value_text = ((componentInChildren != null) ? componentInChildren.valueText : null);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				((UIOption)componentInChildren).optionName = setting.label;
				componentInChildren.canUpdateValueText = false;
				componentInChildren.stepSize = (setting.whole_numbers ? 1f : ((setting.maximum - setting.minimum) / 20f));
			}
			name_row(val, setting.label);
			slider.minValue = setting.minimum;
			slider.maxValue = setting.maximum;
			slider.wholeNumbers = setting.whole_numbers;
			SettingsLayout.slider(val, slider, value_text);
			if ((Object)(object)value_text != (Object)null)
			{
				((Component)value_text).gameObject.SetActive(true);
				((TMP_Text)value_text).alpha = 1f;
				((TMP_Text)value_text).enableWordWrapping = false;
			}
			((UnityEvent<float>)(object)slider.onValueChanged).AddListener(UnityAction<float>.op_Implicit((Action<float>)delegate(float value)
			{
				Settings.change(setting, value, Time.unscaledTime);
				if ((Object)(object)value_text != (Object)null)
				{
					((TMP_Text)value_text).text = setting.format(value);
				}
			}));
			setting.bind(delegate(float value)
			{
				if (!((Object)(object)slider == (Object)null))
				{
					slider.SetValueWithoutNotify(value);
					if ((Object)(object)value_text != (Object)null)
					{
						((TMP_Text)value_text).text = setting.format(value);
					}
				}
			});
			val.SetActive(true);
		}

		private static void add_dropdown(Transform rows, SettingsDropdown? template, Setting setting)
		{
			if ((Object)(object)template == (Object)null)
			{
				throw new InvalidOperationException("No dropdown row to copy.");
			}
			GameObject val = Object.Instantiate<GameObject>(((Component)((Component)template).transform.parent).gameObject, rows);
			Object.DestroyImmediate((Object)(object)val.GetComponentInChildren<SettingsDropdown>(true));
			TMP_Dropdown dropdown = val.GetComponentInChildren<TMP_Dropdown>(true) ?? throw new InvalidOperationException("Dropdown row has no TMP_Dropdown.");
			name_row(val, setting.label);
			SettingsLayout.dropdown(val, dropdown);
			List<string> val2 = new List<string>();
			string[] options = setting.options;
			foreach (string text in options)
			{
				val2.Add(text);
			}
			dropdown.ClearOptions();
			dropdown.AddOptions(val2);
			((UnityEvent<int>)(object)dropdown.onValueChanged).AddListener(UnityAction<int>.op_Implicit((Action<int>)delegate(int value)
			{
				Settings.change(setting, value, Time.unscaledTime);
			}));
			setting.bind(delegate(float value)
			{
				if ((Object)(object)dropdown != (Object)null)
				{
					dropdown.SetValueWithoutNotify((int)value);
				}
			});
			val.SetActive(true);
		}

		private static void add_button(SettingsScreen screen, Transform rows, SettingsDropdown? template, Button? button_template, Setting setting)
		{
			//IL_0103: 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_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_0368: Unknown result type (might be due to invalid IL or missing references)
			//IL_036d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: 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)
			if ((Object)(object)template == (Object)null)
			{
				throw new InvalidOperationException("No keybind row to copy.");
			}
			if ((Object)(object)button_template == (Object)null)
			{
				throw new InvalidOperationException("No native keybind button to copy.");
			}
			GameObject row = Object.Instantiate<GameObject>(((Component)((Component)template).transform.parent).gameObject, rows);
			Object.DestroyImmediate((Object)(object)row.GetComponentInChildren<SettingsDropdown>(true));
			TMP_Dropdown val = row.GetComponentInChildren<TMP_Dropdown>(true) ?? throw new InvalidOperationException("Keybind row has no dropdown.");
			TextMeshProUGUI caption = ((Il2CppObjectBase)val.captionText).TryCast<TextMeshProUGUI>() ?? throw new InvalidOperationException("Keybind row has no caption.");
			GameObject gameObject = ((Component)val).gameObject;
			val.Hide();
			Object.DestroyImmediate((Object)(object)val);
			Transform val2 = gameObject.transform.Find("Arrow");
			if ((Object)(object)val2 != (Object)null)
			{
				((Component)val2).gameObject.SetActive(false);
			}
			Button button = gameObject.AddComponent<Button>();
			((Selectable)button).targetGraphic = (Graphic)(object)gameObject.GetComponent<Image>();
			((Selectable)button).transition = ((Selectable)button_template).transition;
			((Selectable)button).colors = ((Selectable)button_template).colors;
			((Selectable)button).spriteState = ((Selectable)button_template).spriteState;
			Image val3 = ((Il2CppObjectBase)((Selectable)button).targetGraphic).TryCast<Image>();
			Image val4 = ((Il2CppObjectBase)((Selectable)button_template).targetGraphic).TryCast<Image>();
			if ((Object)(object)val3 != (Object)null && (Object)(object)val4 != (Object)null)
			{
				val3.sprite = val4.sprite;
				val3.type = val4.type;
				((Graphic)val3).color = ((Graphic)val4).color;
			}
			((Component)caption).gameObject.SetActive(true);
			((Behaviour)caption).enabled = true;
			((Graphic)caption).color = Color.white;
			((TMP_Text)caption).alpha = 1f;
			((TMP_Text)caption).alignment = (TextAlignmentOptions)4098;
			((Graphic)caption).raycastTarget = false;
			((TMP_Text)caption).enableAutoSizing = true;
			((TMP_Text)caption).fontSizeMax = ((TMP_Text)caption).fontSize;
			((TMP_Text)caption).fontSizeMin = ((TMP_Text)caption).fontSizeMax * 0.75f;
			TextMeshProUGUI componentInChildren = ((Component)button_template).GetComponentInChildren<TextMeshProUGUI>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				((TMP_Text)caption).font = ((TMP_Text)componentInChildren).font;
				((TMP_Text)caption).fontSizeMax = ((TMP_Text)componentInChildren).fontSize;
				((TMP_Text)caption).fontSizeMin = ((TMP_Text)componentInChildren).fontSize * 0.75f;
				((TMP_Text)caption).fontStyle = ((TMP_Text)componentInChildren).fontStyle;
				((Graphic)caption).color = ((Graphic)componentInChildren).color;
			}
			((TMP_Text)caption).overflowMode = (TextOverflowModes)1;
			((TMP_Text)caption).margin = new Vector4(12f, 0f, 12f, 0f);
			((TMP_Text)caption).rectTransform.anchorMin = Vector2.zero;
			((TMP_Text)caption).rectTransform.anchorMax = Vector2.one;
			((TMP_Text)caption).rectTransform.offsetMin = Vector2.zero;
			((TMP_Text)caption).rectTransform.offsetMax = Vector2.zero;
			((TMP_Text)caption).text = setting.format(setting.read());
			name_row(row, setting.label);
			GameObject row2 = row;
			Button control = button;
			Rect rect = ((Component)button_template).GetComponent<RectTransform>().rect;
			SettingsLayout.button(row2, (Selectable)(object)control, ((Rect)(ref rect)).size);
			((UnityEvent)button.onClick).AddListener(UnityAction.op_Implicit((Action)delegate
			{
				//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a7: Expected O, but got Unknown
				//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
				//IL_0104: Unknown result type (might be due to invalid IL or missing references)
				//IL_010f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0119: Unknown result type (might be due to invalid IL or missing references)
				//IL_013f: Unknown result type (might be due to invalid IL or missing references)
				//IL_015e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0163: Unknown result type (might be due to invalid IL or missing references)
				//IL_016f: Expected O, but got Unknown
				if (setting.kind == ControlKind.Button)
				{
					try
					{
						setting.write(0f);
						return;
					}
					catch (Exception ex)
					{
						MelonLogger.Warning("Mod Settings: " + setting.mod + " button failed: " + ex.Message);
						return;
					}
				}
				if ((Object)(object)capture?.row == (Object)(object)row)
				{
					return;
				}
				try
				{
					cancel_capture();
					Canvas val5 = row.GetComponentInParent<Canvas>() ?? throw new InvalidOperationException("Keybind row has no canvas.");
					GameObject val6 = new GameObject("KeybindCapture", (Type[])(object)new Type[1] { Il2CppType.Of<RectTransform>() });
					capture = new KeyCapture(setting, screen, row, button, caption, val6, Time.frameCount, Time.unscaledTime + 10f);
					val6.transform.SetParent(((Component)val5).transform, false);
					RectTransform component = val6.GetComponent<RectTransform>();
					component.anchorMin = Vector2.zero;
					component.anchorMax = Vector2.one;
					component.offsetMin = Vector2.zero;
					component.offsetMax = Vector2.zero;
					Image val7 = val6.AddComponent<Image>();
					((Graphic)val7).color = new Color(0f, 0f, 0f, 0.05f);
					((Graphic)val7).raycastTarget = true;
					Button obj = val6.AddComponent<Button>();
					((Selectable)obj).targetGraphic = (Graphic)(object)val7;
					((Selectable)obj).navigation = new Navigation
					{
						mode = (Mode)0
					};
					((Selectable)obj).Select();
					name_row(row, "Esc cancels · Backspace clears");
					((TMP_Text)caption).text = "Press a key…";
				}
				catch (Exception ex2)
				{
					cancel_capture();
					MelonLogger.Warning("Mod Settings: Could not start key capture: " + ex2.Message);
				}
			}));
			setting.bind(delegate(float value)
			{
				if ((Object)(object)caption != (Object)null && (Object)(object)capture?.caption != (Object)(object)caption)
				{
					((TMP_Text)caption).text = setting.format(value);
				}
			});
			row.SetActive(true);
		}

		public static void update_capture()
		{
			KeyCapture keyCapture = capture;
			if (keyCapture == null)
			{
				return;
			}
			try
			{
				if ((Object)(object)keyCapture.screen == (Object)null || !((MenuScreen)keyCapture.screen).IsOpen || (Object)(object)keyCapture.row == (Object)null || !keyCapture.row.activeInHierarchy || !Application.isFocused || Time.unscaledTime >= keyCapture.expires_seconds)
				{
					cancel_capture();
				}
				else
				{
					if (Time.frameCount <= keyCapture.frame)
					{
						return;
					}
					if (Input.GetKeyDown((KeyCode)27))
					{
						cancel_capture();
						return;
					}
					int num = ((!Input.GetKeyDown((KeyCode)8)) ? (-1) : 0);
					if (num < 0)
					{
						for (int i = 1; i < Settings.key_codes.Length; i++)
						{
							if (Input.GetKeyDown(Settings.key_codes[i]))
							{
								num = i;
								break;
							}
						}
					}
					if (num >= 0)
					{
						cancel_capture();
						Settings.change(keyCapture.setting, num, Time.unscaledTime);
					}
				}
			}
			catch (Exception ex)
			{
				cancel_capture();
				MelonLogger.Warning("Mod Settings: Could not capture key: " + ex.Message);
			}
		}

		public static void cancel_capture()
		{
			KeyCapture keyCapture = capture;
			capture = null;
			if (keyCapture == null)
			{
				return;
			}
			if ((Object)(object)keyCapture.blocker != (Object)null)
			{
				Object.Destroy((Object)(object)keyCapture.blocker);
			}
			if ((Object)(object)keyCapture.row != (Object)null)
			{
				name_row(keyCapture.row, keyCapture.setting.label);
				if ((Object)(object)keyCapture.screen != (Object)null && ((MenuScreen)keyCapture.screen).IsOpen && keyCapture.row.activeInHierarchy && (Object)(object)keyCapture.button != (Object)null)
				{
					((Selectable)keyCapture.button).Select();
				}
			}
			keyCapture.setting.show(keyCapture.setting.read());
		}

		private static void name_row(GameObject row, string label)
		{
			((Object)row).name = label;
			foreach (TextMeshProUGUI componentsInChild in row.GetComponentsInChildren<TextMeshProUGUI>(true))
			{
				if (!((Object)(object)((TMP_Text)componentsInChild).transform.parent != (Object)(object)row.transform))
				{
					if (((Object)componentsInChild).name.StartsWith("Option Name", StringComparison.Ordinal) || ((Object)componentsInChild).name == "Label")
					{
						((TMP_Text)componentsInChild).text = label;
					}
					else if (((Object)componentsInChild).name.StartsWith("Label (", StringComparison.Ordinal))
					{
						((Component)componentsInChild).gameObject.SetActive(false);
					}
				}
			}
			SettingsLayout.label(row);
		}

		private static void fit_tabs(RectTransform screen, Transform tabs)
		{
			//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_0093: 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_00af: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			for (int i = 0; i < tabs.childCount; i++)
			{
				if (((Component)tabs.GetChild(i)).gameObject.activeSelf)
				{
					num++;
				}
			}
			if (num == 0 || num > 16)
			{
				throw new InvalidOperationException("Unexpected settings tab count.");
			}
			Rect rect = screen.rect;
			float num2 = (((Rect)(ref rect)).width - 42f - 5f * (float)(num - 1)) / (float)num;
			if (!float.IsFinite(num2) || num2 < 30f)
			{
				throw new InvalidOperationException("Settings tabs do not fit.");
			}
			for (int j = 0; j < tabs.childCount; j++)
			{
				RectTransform component = ((Component)tabs.GetChild(j)).GetComponent<RectTransform>();
				component.sizeDelta = new Vector2(Math.Min(component.sizeDelta.x, num2), component.sizeDelta.y);
				TextMeshProUGUI componentInChildren = ((Component)component).GetComponentInChildren<TextMeshProUGUI>(true);
				if (!((Object)(object)componentInChildren == (Object)null) && !((TMP_Text)componentInChildren).enableAutoSizing)
				{
					((TMP_Text)componentInChildren).fontSizeMax = ((TMP_Text)componentInChildren).fontSize;
					((TMP_Text)componentInChildren).fontSizeMin = 6f;
					((TMP_Text)componentInChildren).enableAutoSizing = true;
				}
			}
		}
	}
}