Decompiled source of OpenShot v2.0.4

OpenShot.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using OpenShot.Core;
using OpenShot.Events;
using OpenShot.UI;
using OpenShot.UI.Menu;
using Shooterlatro.Core;
using Shooterlatro.Game;
using Shooterlatro.Gameplay;
using Shooterlatro.Player;
using Shooterlatro.Shop;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
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("OpenShot")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Core API for Lucky Shot modding: diegetic MODS menu, fluent ModMenu API, MainMenu cards, GameEvents, Audio/Input/Save APIs.")]
[assembly: AssemblyFileVersion("2.0.3.0")]
[assembly: AssemblyInformationalVersion("2.0.3+4135dd1490a61fe647f2a0e54287f36471f5cf7f")]
[assembly: AssemblyProduct("OpenShot")]
[assembly: AssemblyTitle("OpenShot")]
[assembly: AssemblyVersion("2.0.3.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 OpenShot
{
	[BepInPlugin("com.liamgaming.openshot", "OpenShot API", "2.0.3")]
	public class OpenShotPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.liamgaming.openshot";

		public const string PluginName = "OpenShot API";

		public const string PluginVersion = "2.0.3";

		private Harmony harmony;

		public static OpenShotPlugin Instance { get; private set; }

		public static ManualLogSource Log { get; private set; }

		public static ConfigEntry<bool> DevConsoleEnabled { get; private set; }

		public static ConfigEntry<bool> VerboseLogging { get; private set; }

		public static ConfigEntry<bool> CheckUpdates { get; private set; }

		public static ConfigEntry<float> UiScale { get; private set; }

		private void Awake()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_0057: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			//IL_007e: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"[OpenShot API] Initializing API...");
			BindAndRegisterOpenShotMenu();
			SaveAPI.Initialize();
			GameEvents.Initialize();
			LocalizationAPI.LoadLanguage("en");
			((MonoBehaviour)this).StartCoroutine(DeferredStartup());
			GameObject val = new GameObject("OpenShotAPIs");
			Object.DontDestroyOnLoad((Object)val);
			val.AddComponent<ModMenu>();
			val.AddComponent<DevConsole>();
			val.AddComponent<MainMenuBootstrap>();
			UpdateChecker checker = val.AddComponent<UpdateChecker>();
			AudioAPI.Initialize(val);
			InputAPI.Initialize(val);
			if (CheckUpdates.Value)
			{
				((MonoBehaviour)this).StartCoroutine(DeferredUpdateCheck(checker));
			}
			((MonoBehaviour)this).StartCoroutine(DeferredHarmonyPatch());
			Log.LogInfo((object)"[OpenShot API] Successfully loaded.");
		}

		private IEnumerator DeferredHarmonyPatch()
		{
			yield return null;
			harmony = new Harmony("com.liamgaming.openshot");
			harmony.PatchAll(typeof(OpenShotPlugin).Assembly);
			Log.LogInfo((object)"[OpenShot API] Harmony patches applied.");
		}

		private IEnumerator DeferredUpdateCheck(UpdateChecker checker)
		{
			for (int i = 0; i < 90; i++)
			{
				yield return null;
			}
			checker.CheckForUpdate("LiamGaming-OpenShot", "2.0.3");
		}

		private IEnumerator DeferredStartup()
		{
			for (int i = 0; i < 120; i++)
			{
				yield return null;
			}
			yield return AttributeScanner.ScanAndRegisterAsync();
		}

		private void BindAndRegisterOpenShotMenu()
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Expected O, but got Unknown
			DevConsoleEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("OpenShot", "DevConsole", true, "Allow the developer console (~ key).");
			VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("OpenShot", "VerboseLogging", false, "Extra OpenShot debug logs.");
			CheckUpdates = ((BaseUnityPlugin)this).Config.Bind<bool>("OpenShot", "CheckUpdates", true, "Check Thunderstore for OpenShot updates on startup.");
			UiScale = ((BaseUnityPlugin)this).Config.Bind<float>("OpenShot", "UiScale", 1f, new ConfigDescription("World-space scale of OpenShot settings panels (0.5 = smaller, 1.5 = larger). Applies live.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 1.5f), Array.Empty<object>()));
			ModMenu.Tab("OpenShot").Toggle(DevConsoleEnabled).Slider("SCALE", UiScale, 0.1f, "0.0")
				.Bool("LOG", VerboseLogging)
				.Bool("UPDATE", CheckUpdates);
			UiScale.SettingChanged += delegate
			{
				SettingsEvents.Raise("OpenShot", "SCALE", "Config");
			};
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}
	}
	public static class OpenShotApi
	{
		public const string Guid = "com.liamgaming.openshot";

		public const string Name = "OpenShot API";

		public const string Version = "2.0.3";

		public static bool IsLoaded => (Object)(object)OpenShotPlugin.Instance != (Object)null;

		public static event Action OnMainMenuReady;

		public static event Action<SettingsChangedContext> OnSettingsChanged
		{
			add
			{
				SettingsEvents.Changed += value;
			}
			remove
			{
				SettingsEvents.Changed -= value;
			}
		}

		public static bool Try(Action action)
		{
			if (!IsLoaded || action == null)
			{
				return false;
			}
			action();
			return true;
		}

		internal static void RaiseMainMenuReady()
		{
			OpenShotApi.OnMainMenuReady?.Invoke();
		}

		public static void NotifySettingsChanged(string modTab, string settingLabel = null, string source = "Mod")
		{
			SettingsEvents.Raise(modTab, settingLabel, source);
		}
	}
}
namespace OpenShot.UI
{
	public static class UIHelper
	{
		private static GUIStyle labelStyle;

		private static GUIStyle buttonStyle;

		private static Texture2D MakeTex(int width, int height, Color col)
		{
			//IL_000f: 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)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			Color[] array = (Color[])(object)new Color[width * height];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = col;
			}
			Texture2D val = new Texture2D(width, height);
			val.SetPixels(array);
			val.Apply();
			return val;
		}

		public static void InitializeStyles()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_0084: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: 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_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Expected O, but got Unknown
			if (labelStyle == null)
			{
				GUIStyle val = new GUIStyle(GUI.skin.label)
				{
					fontSize = 15,
					wordWrap = true
				};
				val.normal.textColor = new Color(0.9f, 0.9f, 0.9f);
				labelStyle = val;
			}
			if (buttonStyle == null)
			{
				GUIStyle val2 = new GUIStyle(GUI.skin.button)
				{
					fontSize = 15,
					fontStyle = (FontStyle)1,
					padding = new RectOffset(15, 15, 10, 10)
				};
				val2.normal.textColor = Color.white;
				val2.normal.background = MakeTex(2, 2, new Color(0.15f, 0.15f, 0.15f, 0.95f));
				val2.hover.textColor = new Color(0f, 1f, 0.8f);
				val2.hover.background = MakeTex(2, 2, new Color(0.25f, 0.25f, 0.25f, 1f));
				val2.active.textColor = Color.black;
				val2.active.background = MakeTex(2, 2, new Color(0f, 1f, 0.8f, 1f));
				buttonStyle = val2;
			}
		}

		public static void DrawLabel(string text)
		{
			InitializeStyles();
			GUILayout.Label(text, labelStyle, Array.Empty<GUILayoutOption>());
		}

		public static bool DrawButton(string text)
		{
			InitializeStyles();
			return GUILayout.Button(text, buttonStyle, Array.Empty<GUILayoutOption>());
		}

		public static void DrawHeader(string text)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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)
			//IL_0026: Expected O, but got Unknown
			GUIStyle val = new GUIStyle(GUI.skin.label)
			{
				fontSize = 18,
				fontStyle = (FontStyle)1,
				alignment = (TextAnchor)4
			};
			GUILayout.Label(text, val, Array.Empty<GUILayoutOption>());
			GUILayout.Space(10f);
		}

		public static bool DrawSettings(object settingsObj)
		{
			bool result = false;
			if (settingsObj == null)
			{
				return false;
			}
			FieldInfo[] fields = settingsObj.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public);
			foreach (FieldInfo fieldInfo in fields)
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label(fieldInfo.Name, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) });
				if (fieldInfo.FieldType == typeof(bool))
				{
					bool flag = (bool)fieldInfo.GetValue(settingsObj);
					bool flag2 = GUILayout.Toggle(flag, "", Array.Empty<GUILayoutOption>());
					if (flag2 != flag)
					{
						fieldInfo.SetValue(settingsObj, flag2);
						result = true;
					}
				}
				else if (fieldInfo.FieldType == typeof(string))
				{
					string text = ((string)fieldInfo.GetValue(settingsObj)) ?? "";
					string text2 = GUILayout.TextField(text, Array.Empty<GUILayoutOption>());
					if (text2 != text)
					{
						fieldInfo.SetValue(settingsObj, text2);
						result = true;
					}
				}
				else if (fieldInfo.FieldType == typeof(int))
				{
					int num = (int)fieldInfo.GetValue(settingsObj);
					if (int.TryParse(GUILayout.TextField(num.ToString(), Array.Empty<GUILayoutOption>()), out var result2) && result2 != num)
					{
						fieldInfo.SetValue(settingsObj, result2);
						result = true;
					}
				}
				else if (fieldInfo.FieldType == typeof(float))
				{
					float num2 = (float)fieldInfo.GetValue(settingsObj);
					if (float.TryParse(GUILayout.TextField(num2.ToString(), Array.Empty<GUILayoutOption>()), out var result3) && result3 != num2)
					{
						fieldInfo.SetValue(settingsObj, result3);
						result = true;
					}
				}
				GUILayout.EndHorizontal();
			}
			return result;
		}
	}
	public class ModMenu : MonoBehaviour
	{
		public struct ModTab
		{
			public string Name;

			public Action Draw;
		}

		public struct ModToggle
		{
			public string TabName;

			public ConfigEntry<bool> Config;
		}

		public struct ModSetting
		{
			public string TabName;

			public string Label;

			public Func<string> GetDisplay;

			public Action Cycle;

			public Action<float> SetFraction;

			public Func<float> GetFraction;
		}

		public struct ModButton
		{
			public string TabName;

			public string Label;

			public Action OnPress;
		}

		public struct ModInfo
		{
			public string TabName;

			public string Text;
		}

		public enum ModEntryKind
		{
			Info,
			Setting,
			Button
		}

		public struct ModEntry
		{
			public string TabName;

			public ModEntryKind Kind;

			public string InfoText;

			public ModSetting Setting;

			public ModButton Button;
		}

		private static readonly List<ModTab> ModDrawCallbacks = new List<ModTab>();

		private static readonly List<ModToggle> ModToggles = new List<ModToggle>();

		private static readonly List<ModSetting> ModSettings = new List<ModSetting>();

		private static readonly List<ModButton> ModButtons = new List<ModButton>();

		private static readonly List<ModInfo> ModInfos = new List<ModInfo>();

		private static readonly List<ModEntry> ModEntries = new List<ModEntry>();

		public static ModMenu Instance { get; private set; }

		public static ModMenuTabBuilder Tab(string name)
		{
			return new ModMenuTabBuilder(name);
		}

		public static bool HasTab(string name)
		{
			if (string.IsNullOrWhiteSpace(name))
			{
				return false;
			}
			foreach (ModTab modDrawCallback in ModDrawCallbacks)
			{
				if (string.Equals(modDrawCallback.Name, name, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		public static void EnsureTab(string name)
		{
			if (!string.IsNullOrWhiteSpace(name))
			{
				name = name.Trim();
				if (!HasTab(name))
				{
					ModDrawCallbacks.Add(new ModTab
					{
						Name = name,
						Draw = null
					});
				}
			}
		}

		public static void RegisterTab(string name, Action drawCallback)
		{
			if (string.IsNullOrWhiteSpace(name))
			{
				return;
			}
			name = name.Trim();
			for (int i = 0; i < ModDrawCallbacks.Count; i++)
			{
				if (string.Equals(ModDrawCallbacks[i].Name, name, StringComparison.OrdinalIgnoreCase))
				{
					ModTab value = ModDrawCallbacks[i];
					value.Draw = drawCallback;
					ModDrawCallbacks[i] = value;
					return;
				}
			}
			ModDrawCallbacks.Add(new ModTab
			{
				Name = name,
				Draw = drawCallback
			});
		}

		public static void RegisterTab(Action drawCallback)
		{
			RegisterTab(drawCallback?.Method.Name ?? "Mod", drawCallback);
		}

		public static void RegisterToggle(string tabName, ConfigEntry<bool> config)
		{
			if (string.IsNullOrWhiteSpace(tabName) || config == null)
			{
				return;
			}
			tabName = tabName.Trim();
			EnsureTab(tabName);
			for (int i = 0; i < ModToggles.Count; i++)
			{
				if (string.Equals(ModToggles[i].TabName, tabName, StringComparison.OrdinalIgnoreCase))
				{
					ModToggles[i] = new ModToggle
					{
						TabName = tabName,
						Config = config
					};
					return;
				}
			}
			ModToggles.Add(new ModToggle
			{
				TabName = tabName,
				Config = config
			});
		}

		public static void RegisterSetting(string tabName, string label, Func<string> getDisplay, Action cycle, Action<float> setFraction = null, Func<float> getFraction = null)
		{
			if (string.IsNullOrWhiteSpace(tabName))
			{
				return;
			}
			tabName = tabName.Trim();
			label = label ?? string.Empty;
			EnsureTab(tabName);
			ModSetting modSetting = new ModSetting
			{
				TabName = tabName,
				Label = label,
				GetDisplay = (getDisplay ?? ((Func<string>)(() => string.Empty))),
				Cycle = (cycle ?? ((Action)delegate
				{
				})),
				SetFraction = setFraction,
				GetFraction = getFraction
			};
			for (int num = 0; num < ModSettings.Count; num++)
			{
				if (!string.Equals(ModSettings[num].TabName, tabName, StringComparison.OrdinalIgnoreCase) || !string.Equals(ModSettings[num].Label, label, StringComparison.OrdinalIgnoreCase))
				{
					continue;
				}
				ModSettings[num] = modSetting;
				for (int num2 = 0; num2 < ModEntries.Count; num2++)
				{
					if (ModEntries[num2].Kind == ModEntryKind.Setting && string.Equals(ModEntries[num2].TabName, tabName, StringComparison.OrdinalIgnoreCase) && string.Equals(ModEntries[num2].Setting.Label, label, StringComparison.OrdinalIgnoreCase))
					{
						ModEntry value = ModEntries[num2];
						value.Setting = modSetting;
						ModEntries[num2] = value;
						break;
					}
				}
				return;
			}
			ModSettings.Add(modSetting);
			ModEntries.Add(new ModEntry
			{
				TabName = tabName,
				Kind = ModEntryKind.Setting,
				Setting = modSetting
			});
		}

		public static void RegisterFloatSetting(string tabName, string label, ConfigEntry<float> config, float step, float min, float max, string format = "F2")
		{
			if (config == null)
			{
				return;
			}
			RegisterSetting(tabName, label, () => config.Value.ToString(format), delegate
			{
				float num = config.Value + step;
				if (num > max)
				{
					num = min;
				}
				config.Value = num;
			}, delegate(float fraction)
			{
				config.Value = Mathf.Lerp(min, max, Mathf.Clamp01(fraction));
			}, () => Mathf.InverseLerp(min, max, config.Value));
		}

		public static void RegisterFloatSetting(string tabName, string label, ConfigEntry<float> config, float step = 0.1f, string format = "F2")
		{
			if (config != null)
			{
				ResolveRange(config, 0f, 1f, out var min, out var max);
				RegisterFloatSetting(tabName, label, config, step, min, max, format);
			}
		}

		public static void RegisterIntSetting(string tabName, string label, ConfigEntry<int> config, int step, int min, int max)
		{
			if (config == null)
			{
				return;
			}
			RegisterSetting(tabName, label, () => config.Value.ToString(), delegate
			{
				int num = config.Value + step;
				if (num > max)
				{
					num = min;
				}
				config.Value = num;
			}, delegate(float fraction)
			{
				config.Value = Mathf.RoundToInt(Mathf.Lerp((float)min, (float)max, Mathf.Clamp01(fraction)));
			}, () => Mathf.InverseLerp((float)min, (float)max, (float)config.Value));
		}

		public static void RegisterIntSetting(string tabName, string label, ConfigEntry<int> config, int step = 1)
		{
			if (config != null)
			{
				ResolveRange(config, 0, 10, out var min, out var max);
				RegisterIntSetting(tabName, label, config, step, min, max);
			}
		}

		public static void RegisterBoolSetting(string tabName, string label, ConfigEntry<bool> config)
		{
			if (config != null)
			{
				RegisterSetting(tabName, label, () => (!config.Value) ? "OFF" : "ON", delegate
				{
					config.Value = !config.Value;
				});
			}
		}

		public static void RegisterEnumSetting<T>(string tabName, string label, ConfigEntry<T> config) where T : struct, Enum
		{
			if (config == null)
			{
				return;
			}
			T[] values = (T[])Enum.GetValues(typeof(T));
			if (values.Length == 0)
			{
				return;
			}
			RegisterSetting(tabName, label, () => config.Value.ToString(), delegate
			{
				int num = Array.IndexOf(values, config.Value);
				if (num < 0)
				{
					num = 0;
				}
				config.Value = values[(num + 1) % values.Length];
			});
		}

		public static void RegisterInfo(string tabName, string text)
		{
			if (!string.IsNullOrWhiteSpace(tabName) && !string.IsNullOrWhiteSpace(text))
			{
				tabName = tabName.Trim();
				EnsureTab(tabName);
				ModInfo item = new ModInfo
				{
					TabName = tabName,
					Text = text.Trim()
				};
				ModInfos.Add(item);
				ModEntries.Add(new ModEntry
				{
					TabName = tabName,
					Kind = ModEntryKind.Info,
					InfoText = item.Text
				});
			}
		}

		public static void RegisterButton(string tabName, string label, Action onPress)
		{
			if (string.IsNullOrWhiteSpace(tabName) || onPress == null)
			{
				return;
			}
			tabName = tabName.Trim();
			label = label ?? "ACTION";
			EnsureTab(tabName);
			ModButton modButton = new ModButton
			{
				TabName = tabName,
				Label = label,
				OnPress = onPress
			};
			for (int i = 0; i < ModButtons.Count; i++)
			{
				if (!string.Equals(ModButtons[i].TabName, tabName, StringComparison.OrdinalIgnoreCase) || !string.Equals(ModButtons[i].Label, label, StringComparison.OrdinalIgnoreCase))
				{
					continue;
				}
				ModButtons[i] = modButton;
				for (int j = 0; j < ModEntries.Count; j++)
				{
					if (ModEntries[j].Kind == ModEntryKind.Button && string.Equals(ModEntries[j].TabName, tabName, StringComparison.OrdinalIgnoreCase) && string.Equals(ModEntries[j].Button.Label, label, StringComparison.OrdinalIgnoreCase))
					{
						ModEntry value = ModEntries[j];
						value.Button = modButton;
						ModEntries[j] = value;
						break;
					}
				}
				return;
			}
			ModButtons.Add(modButton);
			ModEntries.Add(new ModEntry
			{
				TabName = tabName,
				Kind = ModEntryKind.Button,
				Button = modButton
			});
		}

		public static IReadOnlyList<ModTab> GetTabs()
		{
			return ModDrawCallbacks;
		}

		public static IReadOnlyList<ModToggle> GetToggles()
		{
			return ModToggles;
		}

		public static IReadOnlyList<ModButton> GetButtons()
		{
			return ModButtons;
		}

		public static IReadOnlyList<ModInfo> GetInfos()
		{
			return ModInfos;
		}

		public static ConfigEntry<bool> GetToggleFor(string tabName)
		{
			foreach (ModToggle modToggle in ModToggles)
			{
				if (string.Equals(modToggle.TabName, tabName, StringComparison.OrdinalIgnoreCase))
				{
					return modToggle.Config;
				}
			}
			return null;
		}

		public static List<ModSetting> GetSettingsFor(string tabName)
		{
			List<ModSetting> list = new List<ModSetting>();
			foreach (ModSetting modSetting in ModSettings)
			{
				if (string.Equals(modSetting.TabName, tabName, StringComparison.OrdinalIgnoreCase))
				{
					list.Add(modSetting);
				}
			}
			return list;
		}

		public static List<ModButton> GetButtonsFor(string tabName)
		{
			List<ModButton> list = new List<ModButton>();
			foreach (ModButton modButton in ModButtons)
			{
				if (string.Equals(modButton.TabName, tabName, StringComparison.OrdinalIgnoreCase))
				{
					list.Add(modButton);
				}
			}
			return list;
		}

		public static List<ModInfo> GetInfosFor(string tabName)
		{
			List<ModInfo> list = new List<ModInfo>();
			foreach (ModInfo modInfo in ModInfos)
			{
				if (string.Equals(modInfo.TabName, tabName, StringComparison.OrdinalIgnoreCase))
				{
					list.Add(modInfo);
				}
			}
			return list;
		}

		public static List<ModEntry> GetEntriesFor(string tabName)
		{
			List<ModEntry> list = new List<ModEntry>();
			foreach (ModEntry modEntry in ModEntries)
			{
				if (string.Equals(modEntry.TabName, tabName, StringComparison.OrdinalIgnoreCase))
				{
					list.Add(modEntry);
				}
			}
			return list;
		}

		public static int GetContentRowCount(string tabName)
		{
			return ((GetToggleFor(tabName) != null) ? 1 : 0) + GetEntriesFor(tabName).Count;
		}

		internal static void ResolveRange<T>(ConfigEntry<T> config, T fallbackMin, T fallbackMax, out T min, out T max) where T : struct, IComparable
		{
			min = fallbackMin;
			max = fallbackMax;
			object obj;
			if (config == null)
			{
				obj = null;
			}
			else
			{
				ConfigDescription description = ((ConfigEntryBase)config).Description;
				obj = ((description != null) ? description.AcceptableValues : null);
			}
			if (obj is AcceptableValueRange<T> val)
			{
				min = val.MinValue;
				max = val.MaxValue;
			}
		}

		private void Awake()
		{
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
		}
	}
	public sealed class ModMenuTabBuilder
	{
		private readonly string _name;

		public string Name => _name;

		public ModMenuTabBuilder(string name)
		{
			_name = (string.IsNullOrWhiteSpace(name) ? "Mod" : name.Trim());
			ModMenu.EnsureTab(_name);
		}

		public ModMenuTabBuilder Toggle(ConfigEntry<bool> config)
		{
			ModMenu.RegisterToggle(_name, config);
			return this;
		}

		public ModMenuTabBuilder Bool(string label, ConfigEntry<bool> config)
		{
			ModMenu.RegisterBoolSetting(_name, label, config);
			return this;
		}

		public ModMenuTabBuilder Float(string label, ConfigEntry<float> config, float step, float min, float max, string format = "F2")
		{
			ModMenu.RegisterFloatSetting(_name, label, config, step, min, max, format);
			return this;
		}

		public ModMenuTabBuilder Float(string label, ConfigEntry<float> config, float step = 0.1f, string format = "F2")
		{
			ModMenu.RegisterFloatSetting(_name, label, config, step, format);
			return this;
		}

		public ModMenuTabBuilder Slider(string label, ConfigEntry<float> config, float step, float min, float max, string format = "F2")
		{
			return Float(label, config, step, min, max, format);
		}

		public ModMenuTabBuilder Slider(string label, ConfigEntry<float> config, float step = 0.1f, string format = "F2")
		{
			return Float(label, config, step, format);
		}

		public ModMenuTabBuilder Int(string label, ConfigEntry<int> config, int step, int min, int max)
		{
			ModMenu.RegisterIntSetting(_name, label, config, step, min, max);
			return this;
		}

		public ModMenuTabBuilder Int(string label, ConfigEntry<int> config, int step = 1)
		{
			ModMenu.RegisterIntSetting(_name, label, config, step);
			return this;
		}

		public ModMenuTabBuilder Cycle(string label, Func<string> getDisplay, Action cycle)
		{
			ModMenu.RegisterSetting(_name, label, getDisplay, cycle);
			return this;
		}

		public ModMenuTabBuilder Enum<T>(string label, ConfigEntry<T> config) where T : struct, Enum
		{
			ModMenu.RegisterEnumSetting<T>(_name, label, config);
			return this;
		}

		public ModMenuTabBuilder Setting(string label, Func<string> getDisplay, Action cycle, Action<float> setFraction = null, Func<float> getFraction = null)
		{
			ModMenu.RegisterSetting(_name, label, getDisplay, cycle, setFraction, getFraction);
			return this;
		}

		public ModMenuTabBuilder Button(string label, Action onPress)
		{
			ModMenu.RegisterButton(_name, label, onPress);
			return this;
		}

		public ModMenuTabBuilder Info(string text)
		{
			ModMenu.RegisterInfo(_name, text);
			return this;
		}
	}
	public class DevConsole : MonoBehaviour
	{
		private bool isVisible;

		private string input = "";

		private Vector2 scrollPosition;

		private Rect windowRect = new Rect(10f, 10f, 600f, 300f);

		private static List<string> logs = new List<string>();

		private static Dictionary<string, Action<string[]>> commands = new Dictionary<string, Action<string[]>>();

		public static DevConsole Instance { get; private set; }

		public static void RegisterCommand(string commandName, Action<string[]> handler)
		{
			commands[commandName.ToLower()] = handler;
		}

		public static void Log(string message)
		{
			logs.Add($"[{DateTime.Now:HH:mm:ss}] {message}");
			if (logs.Count > 100)
			{
				logs.RemoveAt(0);
			}
		}

		private void Awake()
		{
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			RegisterCommand("help", delegate
			{
				Log("Available commands:");
				foreach (string key in commands.Keys)
				{
					Log("- " + key);
				}
			});
			RegisterCommand("clear", delegate
			{
				logs.Clear();
			});
		}

		private void Update()
		{
			if (Keyboard.current != null && ((ButtonControl)Keyboard.current.backquoteKey).wasPressedThisFrame && (OpenShotPlugin.DevConsoleEnabled == null || OpenShotPlugin.DevConsoleEnabled.Value))
			{
				isVisible = !isVisible;
				if (isVisible)
				{
					Cursor.lockState = (CursorLockMode)0;
					Cursor.visible = true;
				}
			}
		}

		private void OnGUI()
		{
			//IL_0017: 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_0037: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (isVisible)
			{
				GUI.depth = -100;
				windowRect = GUILayout.Window(1002, windowRect, new WindowFunction(DrawConsole), "Developer Console", Array.Empty<GUILayoutOption>());
			}
		}

		private void DrawConsole(int windowID)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Invalid comparison between Unknown and I4
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Invalid comparison between Unknown and I4
			scrollPosition = GUILayout.BeginScrollView(scrollPosition, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(230f) });
			foreach (string log in logs)
			{
				GUILayout.Label(log, Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndScrollView();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUI.SetNextControlName("ConsoleInput");
			input = GUILayout.TextField(input, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			if ((GUILayout.Button("Submit", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }) || ((int)Event.current.type == 4 && (int)Event.current.keyCode == 13)) && !string.IsNullOrWhiteSpace(input))
			{
				Log("> " + input);
				ExecuteCommand(input);
				input = "";
			}
			GUILayout.EndHorizontal();
			GUI.DragWindow(new Rect(0f, 0f, 10000f, 20f));
		}

		private void ExecuteCommand(string inputLine)
		{
			string[] array = inputLine.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
			if (array.Length == 0)
			{
				return;
			}
			string text = array[0].ToLower();
			if (commands.ContainsKey(text))
			{
				string[] array2 = new string[array.Length - 1];
				Array.Copy(array, 1, array2, 0, array2.Length);
				try
				{
					commands[text](array2);
					return;
				}
				catch (Exception ex)
				{
					Log("Error executing command: " + ex.Message);
					return;
				}
			}
			Log("Unknown command: " + text);
		}
	}
	public class SettingsOverlay : MonoBehaviour
	{
		private bool visible;

		private string tabName = "";

		private Action onBack;

		private Texture2D panelTex;

		private Texture2D dimTex;

		private Texture2D accentTex;

		private Texture2D btnTex;

		private Texture2D btnHoverTex;

		private GUIStyle titleStyle;

		private GUIStyle labelStyle;

		private GUIStyle valueStyle;

		private GUIStyle backStyle;

		private GUIStyle toggleStyle;

		private bool stylesReady;

		private CursorLockMode prevLock;

		private bool prevCursorVisible;

		public static SettingsOverlay Instance { get; private set; }

		public bool IsVisible => visible;

		private void Awake()
		{
			Instance = this;
		}

		public void Open(string tab, Action backCallback)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			tabName = tab ?? "";
			onBack = backCallback;
			if (!visible)
			{
				prevLock = Cursor.lockState;
				prevCursorVisible = Cursor.visible;
			}
			visible = true;
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
		}

		public void Close()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			if (visible)
			{
				visible = false;
				Cursor.lockState = prevLock;
				Cursor.visible = prevCursorVisible;
			}
		}

		private void Update()
		{
			if (visible && InputAPI.WasPressedThisFrame((KeyCode)27))
			{
				GoBack();
			}
		}

		private void OnGUI()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: 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)
			if (!visible)
			{
				return;
			}
			EnsureStyles();
			GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)dimTex);
			float num = Mathf.Clamp((float)Screen.width * 0.42f, 380f, 560f);
			float num2 = Mathf.Clamp((float)Screen.height * 0.62f, 360f, 580f);
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((float)Screen.width - num) * 0.5f, ((float)Screen.height - num2) * 0.5f, num, num2);
			GUI.DrawTexture(val, (Texture)(object)panelTex);
			GUI.DrawTexture(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y + 58f, ((Rect)(ref val)).width, 3f), (Texture)(object)accentTex);
			GUILayout.BeginArea(new Rect(((Rect)(ref val)).x + 20f, ((Rect)(ref val)).y + 14f, ((Rect)(ref val)).width - 40f, ((Rect)(ref val)).height - 28f));
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("←  BACK", backStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(108f),
				GUILayout.Height(34f)
			}))
			{
				GoBack();
			}
			GUILayout.FlexibleSpace();
			GUILayout.Label((tabName ?? "").ToUpperInvariant(), titleStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(34f) });
			GUILayout.FlexibleSpace();
			GUILayout.Space(108f);
			GUILayout.EndHorizontal();
			GUILayout.Space(22f);
			ConfigEntry<bool> config = ModMenu.GetToggleFor(tabName);
			if (config != null)
			{
				DrawRow("Enabled", delegate
				{
					//IL_0000: Unknown result type (might be due to invalid IL or missing references)
					//IL_0005: Unknown result type (might be due to invalid IL or missing references)
					//IL_0038: 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)
					//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
					Color backgroundColor = GUI.backgroundColor;
					GUI.backgroundColor = (config.Value ? new Color(0.15f, 0.9f, 0.6f) : new Color(0.55f, 0.25f, 0.3f));
					if (GUILayout.Button(config.Value ? "ON" : "OFF", toggleStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
					{
						GUILayout.Width(96f),
						GUILayout.Height(30f)
					}))
					{
						config.Value = !config.Value;
					}
					GUI.backgroundColor = backgroundColor;
				});
				GUILayout.Space(10f);
			}
			List<ModMenu.ModSetting> settingsFor = ModMenu.GetSettingsFor(tabName);
			foreach (ModMenu.ModSetting item in settingsFor)
			{
				DrawSetting(item);
				GUILayout.Space(12f);
			}
			if (config == null && settingsFor.Count == 0)
			{
				GUILayout.FlexibleSpace();
				GUILayout.Label("No settings for this mod.", labelStyle, Array.Empty<GUILayoutOption>());
			}
			GUILayout.FlexibleSpace();
			GUILayout.Label("Esc / Back to return", valueStyle, Array.Empty<GUILayoutOption>());
			GUILayout.EndArea();
		}

		private void DrawRow(string label, Action right)
		{
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(label, labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) });
			GUILayout.FlexibleSpace();
			right?.Invoke();
			GUILayout.EndHorizontal();
		}

		private void DrawSetting(ModMenu.ModSetting setting)
		{
			string text = (string.IsNullOrEmpty(setting.Label) ? "Setting" : setting.Label);
			bool num = setting.SetFraction != null && setting.GetFraction != null;
			GUILayout.Label(text.ToUpperInvariant(), labelStyle, Array.Empty<GUILayoutOption>());
			if (num)
			{
				float num2 = Mathf.Clamp01(setting.GetFraction());
				GUILayout.Space(4f);
				float num3 = GUILayout.HorizontalSlider(num2, 0f, 1f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(20f) });
				if (!Mathf.Approximately(num3, num2))
				{
					setting.SetFraction(num3);
				}
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.FlexibleSpace();
				GUILayout.Label(setting.GetDisplay?.Invoke() ?? num3.ToString("0.00"), valueStyle, Array.Empty<GUILayoutOption>());
				GUILayout.EndHorizontal();
			}
			else
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.FlexibleSpace();
				if (GUILayout.Button(setting.GetDisplay?.Invoke() ?? "—", toggleStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.MinWidth(110f),
					GUILayout.Height(30f)
				}))
				{
					setting.Cycle?.Invoke();
				}
				GUILayout.EndHorizontal();
			}
		}

		private void GoBack()
		{
			Close();
			onBack?.Invoke();
		}

		private void EnsureStyles()
		{
			//IL_0025: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Expected O, but got Unknown
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: 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_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Expected O, but got Unknown
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Expected O, but got Unknown
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: 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)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: 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_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Expected O, but got Unknown
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Expected O, but got Unknown
			if (!stylesReady)
			{
				stylesReady = true;
				dimTex = MakeTex(new Color(0f, 0f, 0f, 0.6f));
				panelTex = MakeTex(new Color(0.08f, 0.07f, 0.11f, 0.96f));
				accentTex = MakeTex(new Color(1f, 0.35f, 0.55f, 1f));
				btnTex = MakeTex(new Color(0.22f, 0.16f, 0.24f, 1f));
				btnHoverTex = MakeTex(new Color(0.32f, 0.24f, 0.36f, 1f));
				GUIStyle val = new GUIStyle(GUI.skin.label)
				{
					fontSize = 22,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)4
				};
				val.normal.textColor = new Color(1f, 0.45f, 0.65f);
				titleStyle = val;
				GUIStyle val2 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 14,
					fontStyle = (FontStyle)1
				};
				val2.normal.textColor = new Color(0.88f, 0.88f, 0.92f);
				labelStyle = val2;
				GUIStyle val3 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 13,
					alignment = (TextAnchor)5
				};
				val3.normal.textColor = new Color(0f, 1f, 0.85f);
				valueStyle = val3;
				GUIStyle val4 = new GUIStyle(GUI.skin.button)
				{
					fontSize = 14,
					fontStyle = (FontStyle)1
				};
				val4.normal.textColor = Color.white;
				val4.normal.background = btnTex;
				val4.hover.textColor = new Color(0f, 1f, 0.85f);
				val4.hover.background = btnHoverTex;
				val4.active.textColor = Color.black;
				val4.active.background = MakeTex(new Color(0f, 1f, 0.85f, 1f));
				backStyle = val4;
				toggleStyle = new GUIStyle(backStyle)
				{
					fontSize = 15
				};
			}
		}

		private static Texture2D MakeTex(Color col)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			val.SetPixels((Color[])(object)new Color[4] { col, col, col, col });
			val.Apply();
			return val;
		}
	}
	public static class MainMenu
	{
		private static readonly List<Action> ReadyCallbacks = new List<Action>();

		private static bool isReady;

		public static bool IsReady => isReady;

		public static void WhenReady(Action action)
		{
			if (action != null)
			{
				if (isReady)
				{
					action();
				}
				else
				{
					ReadyCallbacks.Add(action);
				}
			}
		}

		internal static void NotifyReady()
		{
			isReady = true;
			for (int i = 0; i < ReadyCallbacks.Count; i++)
			{
				try
				{
					ReadyCallbacks[i]?.Invoke();
				}
				catch (Exception arg)
				{
					ManualLogSource log = OpenShotPlugin.Log;
					if (log != null)
					{
						log.LogError((object)$"[MainMenu.WhenReady] {arg}");
					}
				}
			}
			ReadyCallbacks.Clear();
			OpenShotApi.RaiseMainMenuReady();
		}

		internal static void NotifyMenuLost()
		{
			isReady = false;
		}

		public static void AddButton(string label, Action onShot)
		{
			if (onShot == null)
			{
				throw new ArgumentNullException("onShot");
			}
			AddButton(label, (Action<Vector3>)delegate
			{
				onShot();
			});
		}

		public static void AddButton(string label, Action<Vector3> onShot)
		{
			ButtonRegistry.AddButton(label, onShot);
		}

		public static void SetLabel(string existingLabel, string newLabel)
		{
			ButtonRegistry.SetLabel(existingLabel, newLabel);
		}

		public static void Hide(string existingLabel)
		{
			ButtonRegistry.Hide(existingLabel);
		}

		public static void OnShot(string existingLabel, Func<Vector3, bool> handler)
		{
			ButtonRegistry.OnShot(existingLabel, handler);
		}

		public static void OnShot(string existingLabel, Action onShot)
		{
			if (onShot == null)
			{
				throw new ArgumentNullException("onShot");
			}
			ButtonRegistry.OnShot(existingLabel, delegate
			{
				onShot();
				return true;
			});
		}
	}
}
namespace OpenShot.UI.Menu
{
	public static class CardFactory
	{
		private static readonly Dictionary<GameObject, Action<Vector3>> ShotRedirects = new Dictionary<GameObject, Action<Vector3>>();

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

		private static bool executePatched;

		private static bool uiHitPatched;

		private static Harmony harmony;

		public static void EnsurePatched(string componentTypeName)
		{
			TryPatchType("Shooterlatro.UI.MainMenuShootableBase");
			TryPatchType("MainMenuShootableBase");
			if (!string.IsNullOrEmpty(componentTypeName))
			{
				TryPatchType(componentTypeName);
			}
			EnsureExecutePatch();
			EnsureUiHitPatch();
		}

		private static void EnsureExecutePatch()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			if (executePatched)
			{
				return;
			}
			Type type = AccessTools.TypeByName("Shooterlatro.UI.MainMenuShootableBase") ?? AccessTools.TypeByName("MainMenuShootableBase");
			if (type == null)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.DeclaredMethod(type, "Execute", (Type[])null, (Type[])null) ?? AccessTools.Method(type, "Execute", (Type[])null, (Type[])null);
			if (!(methodInfo == null))
			{
				if (harmony == null)
				{
					harmony = new Harmony("com.liamgaming.openshot.cardfactory");
				}
				MethodInfo method = typeof(CardFactory).GetMethod("ExecutePrefix", BindingFlags.Static | BindingFlags.NonPublic);
				try
				{
					harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				catch (Exception ex)
				{
					OpenShotPlugin.Log.LogWarning((object)("[CardFactory] Execute patch skipped: " + ex.Message));
				}
				executePatched = true;
			}
		}

		private static void EnsureUiHitPatch()
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			if (uiHitPatched)
			{
				return;
			}
			Type type = AccessTools.TypeByName("Shooterlatro.Core.GameEvents");
			if (type == null)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "PublishUIShootableHit", (Type[])null, (Type[])null);
			if (!(methodInfo == null))
			{
				if (harmony == null)
				{
					harmony = new Harmony("com.liamgaming.openshot.cardfactory");
				}
				MethodInfo method = typeof(CardFactory).GetMethod("PublishUiHitPrefix", BindingFlags.Static | BindingFlags.NonPublic);
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				uiHitPatched = true;
			}
		}

		private static void TryPatchType(string componentTypeName)
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			if (string.IsNullOrEmpty(componentTypeName))
			{
				return;
			}
			Type type = AccessTools.TypeByName(componentTypeName);
			if (type == null)
			{
				return;
			}
			string text = type.FullName ?? componentTypeName;
			if (!PatchedComponentTypes.Add(text))
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.DeclaredMethod(type, "OnShotHit", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				PatchedComponentTypes.Remove(text);
				return;
			}
			string text2 = methodInfo.DeclaringType?.FullName;
			if (string.IsNullOrEmpty(text2) || !(text2 != text) || !PatchedComponentTypes.Contains(text2))
			{
				if (harmony == null)
				{
					harmony = new Harmony("com.liamgaming.openshot.cardfactory");
				}
				MethodInfo method = typeof(CardFactory).GetMethod("OnShotHitPrefix", BindingFlags.Static | BindingFlags.NonPublic);
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				OpenShotPlugin.Log.LogInfo((object)("[CardFactory] Patched " + methodInfo.DeclaringType?.FullName + ".OnShotHit."));
			}
		}

		public static void RefreshMenuColliders(GameObject root)
		{
			//IL_003f: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			BoxCollider[] componentsInChildren = root.GetComponentsInChildren<BoxCollider>(true);
			foreach (BoxCollider val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					Transform transform = ((Component)val).transform;
					RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
					if (!((Object)(object)val2 == (Object)null))
					{
						Rect rect = val2.rect;
						val.size = new Vector3(Mathf.Max(((Rect)(ref rect)).width, 12f), Mathf.Max(((Rect)(ref rect)).height, 12f), val.size.z);
						val.center = new Vector3(((Rect)(ref rect)).center.x, ((Rect)(ref rect)).center.y, val.center.z);
						((Collider)val).enabled = true;
					}
				}
			}
		}

		public static void EnsureMenuColliders(GameObject card)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_0073: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)card == (Object)null)
			{
				return;
			}
			Transform transform = card.transform;
			RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			if (!((Object)(object)val == (Object)null))
			{
				BoxCollider val2 = card.GetComponent<BoxCollider>();
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = card.AddComponent<BoxCollider>();
				}
				Rect rect = val.rect;
				val2.size = new Vector3(Mathf.Max(((Rect)(ref rect)).width, 12f), Mathf.Max(((Rect)(ref rect)).height, 12f), 40f);
				val2.center = new Vector3(((Rect)(ref rect)).center.x, ((Rect)(ref rect)).center.y, 0f);
				((Collider)val2).isTrigger = false;
				((Collider)val2).enabled = true;
			}
		}

		private static bool TryGetRedirect(MonoBehaviour behaviour, out Action<Vector3> redirect)
		{
			redirect = null;
			if ((Object)(object)behaviour == (Object)null)
			{
				return false;
			}
			Transform val = ((Component)behaviour).transform;
			while ((Object)(object)val != (Object)null)
			{
				if (ShotRedirects.TryGetValue(((Component)val).gameObject, out redirect))
				{
					return redirect != null;
				}
				val = val.parent;
			}
			return false;
		}

		private static Vector3 ReadHitPoint(MonoBehaviour behaviour, object shotHitContext)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			Vector3 result = ((Component)behaviour).transform.position;
			if (shotHitContext == null)
			{
				return result;
			}
			try
			{
				result = Traverse.Create(shotHitContext).Field("hitPoint").GetValue<Vector3>();
			}
			catch
			{
			}
			return result;
		}

		private static bool TryInvokeRedirect(MonoBehaviour behaviour, object shotHitContext)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetRedirect(behaviour, out var redirect))
			{
				return false;
			}
			redirect?.Invoke(ReadHitPoint(behaviour, shotHitContext));
			return true;
		}

		private static bool TryInvokeRedirectFromHitObject(GameObject hitObject, Vector3 hitPoint)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)hitObject == (Object)null)
			{
				return false;
			}
			Transform val = hitObject.transform;
			while ((Object)(object)val != (Object)null)
			{
				if (ShotRedirects.TryGetValue(((Component)val).gameObject, out var value))
				{
					value?.Invoke(hitPoint);
					return true;
				}
				val = val.parent;
			}
			return false;
		}

		public static void RefreshHoverTargets(GameObject root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			Type type = AccessTools.TypeByName("Shooterlatro.Core.CrosshairHoverScaleTarget") ?? AccessTools.TypeByName("CrosshairHoverScaleTarget");
			if (type == null)
			{
				return;
			}
			Component[] componentsInChildren = root.GetComponentsInChildren(type, true);
			foreach (Component val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					Traverse val2 = Traverse.Create((object)val);
					try
					{
						val2.Method("CaptureCurrentAsBaseScale", Array.Empty<object>()).GetValue();
					}
					catch
					{
					}
					try
					{
						val2.Method("ResolveReferences", Array.Empty<object>()).GetValue();
					}
					catch
					{
					}
					try
					{
						val2.Method("RefreshHoverState", Array.Empty<object>()).GetValue();
					}
					catch
					{
					}
				}
			}
		}

		public static void SetShotRedirect(GameObject card, Action<Vector3> onShot)
		{
			if (!((Object)(object)card == (Object)null))
			{
				if (onShot == null)
				{
					ShotRedirects.Remove(card);
				}
				else
				{
					ShotRedirects[card] = onShot;
				}
			}
		}

		public static void ClearShotRedirects()
		{
			ShotRedirects.Clear();
		}

		public static void RemoveDestroyedRedirects()
		{
			List<GameObject> list = new List<GameObject>();
			foreach (GameObject key in ShotRedirects.Keys)
			{
				if ((Object)(object)key == (Object)null)
				{
					list.Add(key);
				}
			}
			foreach (GameObject item in list)
			{
				ShotRedirects.Remove(item);
			}
		}

		public static void RemoveTileViewBinding(GameObject card)
		{
			if ((Object)(object)card == (Object)null)
			{
				return;
			}
			Component[] componentsInChildren = card.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && ((object)val).GetType().Name == "LocalizedTMPText")
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}

		public static void SetLabel(GameObject card, string label)
		{
			if (!((Object)(object)card == (Object)null))
			{
				RemoveTileViewBinding(card);
				TextMeshProUGUI componentInChildren = card.GetComponentInChildren<TextMeshProUGUI>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					((TMP_Text)componentInChildren).text = label ?? string.Empty;
				}
			}
		}

		public static void HideDecorativeIcons(GameObject card)
		{
			if ((Object)(object)card == (Object)null)
			{
				return;
			}
			Image[] componentsInChildren = card.GetComponentsInChildren<Image>(true);
			foreach (Image val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					string name = ((Object)((Component)val).gameObject).name;
					if (name.IndexOf("icon", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("glyph", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("symbol", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						((Behaviour)val).enabled = false;
					}
				}
			}
		}

		public static void RewireShootable(GameObject card, string componentTypeName, Action<Vector3> onShot)
		{
			EnsurePatched(componentTypeName);
			SetShotRedirect(card, onShot);
		}

		public static GameObject CreateNativeColumn(MenuDiscovery discovery, string label, Action<Vector3> onShot)
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_01a9: 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_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)discovery?.TemplateColumn == (Object)null || (Object)(object)discovery.TemplateButton == (Object)null || (Object)(object)discovery.MenuRow == (Object)null)
			{
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(discovery.TemplateColumn, discovery.MenuRow);
			((Object)val).name = (string.IsNullOrEmpty(label) ? "OpenShot_Column" : ("OpenShot_Column_" + label));
			val.SetActive(true);
			GameObject val2 = null;
			List<GameObject> list = new List<GameObject>();
			foreach (Transform item in val.transform)
			{
				Transform val3 = item;
				if (((Object)val3).name == ((Object)discovery.TemplateButton).name && (Object)(object)val2 == (Object)null)
				{
					val2 = ((Component)val3).gameObject;
				}
				else
				{
					list.Add(((Component)val3).gameObject);
				}
			}
			foreach (GameObject item2 in list)
			{
				Object.Destroy((Object)(object)item2);
			}
			if ((Object)(object)val2 == (Object)null)
			{
				{
					IEnumerator enumerator = val.transform.GetEnumerator();
					try
					{
						if (enumerator.MoveNext())
						{
							val2 = ((Component)(Transform)enumerator.Current).gameObject;
						}
					}
					finally
					{
						IDisposable disposable = enumerator as IDisposable;
						if (disposable != null)
						{
							disposable.Dispose();
						}
					}
				}
			}
			if ((Object)(object)val2 == (Object)null)
			{
				Object.Destroy((Object)(object)val);
				return null;
			}
			Transform transform = discovery.TemplateButton.transform;
			RectTransform val4 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			Transform transform2 = val2.transform;
			RectTransform val5 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null);
			if ((Object)(object)val4 != (Object)null && (Object)(object)val5 != (Object)null)
			{
				val5.anchorMin = val4.anchorMin;
				val5.anchorMax = val4.anchorMax;
				val5.pivot = val4.pivot;
				val5.sizeDelta = val4.sizeDelta;
				val5.anchoredPosition = val4.anchoredPosition;
				((Transform)val5).localScale = ((Transform)val4).localScale;
				((Transform)val5).localRotation = ((Transform)val4).localRotation;
			}
			SetLabel(val2, label);
			Action<Vector3> onShot2 = onShot ?? ((Action<Vector3>)delegate
			{
			});
			RewireShootable(val2, discovery.TemplateComponentType, onShot2);
			SetShotRedirect(val, onShot2);
			EnsureMenuColliders(val2);
			return val;
		}

		public static GameObject GetColumnCard(GameObject column)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)column == (Object)null)
			{
				return null;
			}
			IEnumerator enumerator = column.transform.GetEnumerator();
			try
			{
				if (enumerator.MoveNext())
				{
					return ((Component)(Transform)enumerator.Current).gameObject;
				}
				return column;
			}
			finally
			{
				IDisposable disposable = enumerator as IDisposable;
				if (disposable != null)
				{
					disposable.Dispose();
				}
			}
		}

		public static RectTransform EnsureColumnSliderFill(GameObject column, GameObject templateButton)
		{
			GameObject columnCard = GetColumnCard(column);
			if ((Object)(object)columnCard == (Object)null)
			{
				return null;
			}
			Transform obj = columnCard.transform.Find("Fill");
			RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			return AttachSliderFill(columnCard, templateButton);
		}

		public static GameObject CreateNativeTile(MenuDiscovery discovery, Transform parent, string label, float uniformScale, Action<Vector3> onShot, bool textOnly = false)
		{
			//IL_00a1: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: 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_0100: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)discovery?.TemplateButton == (Object)null || (Object)(object)parent == (Object)null)
			{
				return null;
			}
			Transform val = (((Object)(object)discovery.MenuRow != (Object)null) ? discovery.MenuRow : parent);
			GameObject obj = Object.Instantiate<GameObject>(discovery.TemplateButton, val);
			((Object)obj).name = (string.IsNullOrEmpty(label) ? "OpenShot_Tile" : ("OpenShot_Tile_" + label));
			obj.SetActive(true);
			RemoveTileViewBinding(obj);
			Transform transform = discovery.TemplateButton.transform;
			RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			Transform transform2 = obj.transform;
			RectTransform val3 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null);
			if ((Object)(object)val2 != (Object)null && (Object)(object)val3 != (Object)null)
			{
				val3.anchorMin = val2.anchorMin;
				val3.anchorMax = val2.anchorMax;
				val3.pivot = val2.pivot;
				val3.sizeDelta = val2.sizeDelta;
				val3.anchoredPosition = val2.anchoredPosition;
				float num = ((uniformScale > 0.01f) ? uniformScale : 1f);
				((Transform)val3).localScale = ((Transform)val2).localScale * num;
				((Transform)val3).localRotation = ((Transform)val2).localRotation;
			}
			SetLabel(obj, label);
			RewireShootable(obj, discovery.TemplateComponentType, onShot ?? ((Action<Vector3>)delegate
			{
			}));
			return obj;
		}

		public static GameObject CreateBackdropPlate(MenuDiscovery discovery, Transform parent, float scaleX, float scaleY)
		{
			//IL_0099: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = CreateNativeColumn(discovery, "", null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			((Object)val).name = "OpenShot_Backdrop";
			GameObject columnCard = GetColumnCard(val);
			TextMeshProUGUI val2 = (((Object)(object)columnCard != (Object)null) ? columnCard.GetComponentInChildren<TextMeshProUGUI>() : null);
			if ((Object)(object)val2 != (Object)null)
			{
				((Component)val2).gameObject.SetActive(false);
			}
			if ((Object)(object)columnCard != (Object)null)
			{
				Image[] componentsInChildren = columnCard.GetComponentsInChildren<Image>(true);
				if (componentsInChildren.Length != 0 && (Object)(object)componentsInChildren[0] != (Object)null)
				{
					((Graphic)componentsInChildren[0]).color = new Color(0.04f, 0.04f, 0.06f, 0.72f);
				}
			}
			((Transform)(RectTransform)val.transform).localScale = new Vector3(scaleX, scaleY, 1f);
			return val;
		}

		public static RectTransform AttachSliderFill(GameObject sliderCard, GameObject templateButton)
		{
			//IL_00b4: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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_00ee: 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_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: 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_0105: 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_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_013c: Expected O, but got Unknown
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)sliderCard == (Object)null || (Object)(object)templateButton == (Object)null)
			{
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(templateButton, sliderCard.transform);
			((Object)val).name = "Fill";
			RemoveTileViewBinding(val);
			TextMeshProUGUI componentInChildren = val.GetComponentInChildren<TextMeshProUGUI>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				((Component)componentInChildren).gameObject.SetActive(false);
			}
			Image[] componentsInChildren = val.GetComponentsInChildren<Image>(true);
			for (int i = 1; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null)
				{
					((Behaviour)componentsInChildren[i]).enabled = false;
				}
			}
			if (componentsInChildren.Length != 0 && (Object)(object)componentsInChildren[0] != (Object)null)
			{
				((Graphic)componentsInChildren[0]).color = new Color(0.15f, 1f, 0.85f, 0.8f);
			}
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchorMin = Vector2.zero;
			val2.anchorMax = new Vector2(0f, 1f);
			val2.pivot = new Vector2(0f, 0.5f);
			val2.offsetMin = Vector2.zero;
			val2.offsetMax = Vector2.zero;
			val2.anchoredPosition = Vector2.zero;
			((Transform)val2).localScale = Vector3.one;
			((Transform)val2).SetAsFirstSibling();
			TextMeshProUGUI componentInChildren2 = sliderCard.GetComponentInChildren<TextMeshProUGUI>();
			if ((Object)(object)componentInChildren2 != (Object)null)
			{
				((TMP_Text)componentInChildren2).transform.SetAsLastSibling();
			}
			return val2;
		}

		public static void SetSliderFill(RectTransform fill, float fraction)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)fill == (Object)null))
			{
				fill.anchorMax = new Vector2(Mathf.Clamp01(fraction), 1f);
			}
		}

		public static GameObject CreateCardEntry(GameObject templateButton, string templateComponentType, RectTransform parent, string label, Vector2 anchorMin, Vector2 anchorMax, Action<Vector3> onShot)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: 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)
			GameObject val = Object.Instantiate<GameObject>(templateButton, (Transform)(object)parent);
			((Object)val).name = (string.IsNullOrEmpty(label) ? "Card" : ("Card_" + label));
			RemoveTileViewBinding(val);
			TextMeshProUGUI componentInChildren = val.GetComponentInChildren<TextMeshProUGUI>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				((TMP_Text)componentInChildren).text = label ?? string.Empty;
				((TMP_Text)componentInChildren).alignment = (TextAlignmentOptions)4098;
				((TMP_Text)componentInChildren).enableAutoSizing = false;
			}
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchorMin = anchorMin;
			val2.anchorMax = anchorMax;
			val2.offsetMin = Vector2.zero;
			val2.offsetMax = Vector2.zero;
			val2.anchoredPosition = Vector2.zero;
			((Transform)val2).localScale = Vector3.one;
			if (onShot != null)
			{
				EnsurePatched(templateComponentType);
				SetShotRedirect(val, onShot);
			}
			return val;
		}

		public static bool TryComputeCurveFraction(GameObject card, Vector3 worldHitPoint, out float fraction)
		{
			//IL_00e7: 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_0114: 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_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: 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_0163: 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_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: 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_0174: 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_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			fraction = 0.5f;
			Type type = AccessTools.TypeByName("CameraSemicircleGraphicCurver");
			if (type == null)
			{
				return false;
			}
			Component componentInChildren = card.GetComponentInChildren(type, true);
			if ((Object)(object)componentInChildren == (Object)null)
			{
				return false;
			}
			Traverse val = Traverse.Create((object)componentInChildren);
			RectTransform value = val.Field("referenceRoot").GetValue<RectTransform>();
			RectTransform val2 = (RectTransform)(((Object)(object)value != (Object)null) ? ((object)value) : ((object)/*isinst with value type is only supported in some contexts*/));
			if ((Object)(object)val2 == (Object)null)
			{
				return false;
			}
			int axis = Convert.ToInt32(val.Field("widthAxis").GetValue());
			int axis2 = Convert.ToInt32(val.Field("heightAxis").GetValue());
			int axis3 = Convert.ToInt32(val.Field("depthAxis").GetValue());
			int num = Convert.ToInt32(val.Field("curvePlane").GetValue());
			bool value2 = val.Field("centerAtReferenceRect").GetValue<bool>();
			Vector3 value3 = val.Field("centerLocalOffset").GetValue<Vector3>();
			float value4 = val.Field("startAngleDeg").GetValue<float>();
			float value5 = val.Field("endAngleDeg").GetValue<float>();
			Vector3 val3 = AxisUnit(axis);
			Vector3 val4 = ((num == 1) ? AxisUnit(axis2) : AxisUnit(axis3));
			Rect rect = val2.rect;
			Vector3 val5 = (Vector3)(value2 ? new Vector3(((Rect)(ref rect)).center.x, ((Rect)(ref rect)).center.y, 0f) : Vector3.zero) + value3;
			Vector3 val6 = ((Transform)val2).InverseTransformPoint(worldHitPoint) - val5;
			float num2 = Vector3.Dot(val6, val3);
			float num3 = Vector3.Dot(val6, val4);
			if (Mathf.Approximately(num2, 0f) && Mathf.Approximately(num3, 0f))
			{
				return false;
			}
			float num4 = Mathf.Atan2(num3, num2) * 57.29578f;
			float num5 = Mathf.Min(value4, value5);
			float num6 = Mathf.Max(value4, value5);
			float num7 = num4;
			if (num7 < num5 || num7 > num6)
			{
				if (num4 + 360f >= num5 && num4 + 360f <= num6)
				{
					num7 = num4 + 360f;
				}
				else if (num4 - 360f >= num5 && num4 - 360f <= num6)
				{
					num7 = num4 - 360f;
				}
			}
			if (Mathf.Approximately(value4, value5))
			{
				return false;
			}
			fraction = Mathf.Clamp01((num7 - value4) / (value5 - value4));
			return true;
			static Vector3 AxisUnit(int num8)
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				return (Vector3)(num8 switch
				{
					2 => Vector3.forward, 
					1 => Vector3.up, 
					_ => Vector3.right, 
				});
			}
		}

		private static bool OnShotHitPrefix(object __instance, object __0)
		{
			MonoBehaviour val = (MonoBehaviour)((__instance is MonoBehaviour) ? __instance : null);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			if (ButtonRegistry.TryHandleExistingShot(((Component)val).gameObject, __0, out var suppressOriginal))
			{
				return !suppressOriginal;
			}
			if (TryInvokeRedirect(val, __0))
			{
				return false;
			}
			return true;
		}

		private static bool ExecutePrefix(object __instance)
		{
			MonoBehaviour val = (MonoBehaviour)((__instance is MonoBehaviour) ? __instance : null);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			if (TryInvokeRedirect(val, null))
			{
				return false;
			}
			return true;
		}

		private static bool PublishUiHitPrefix(object __0)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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)
			if (__0 == null)
			{
				return true;
			}
			GameObject val = null;
			Vector3 zero = Vector3.zero;
			try
			{
				Traverse obj = Traverse.Create(__0);
				val = obj.Field("hitObject").GetValue<GameObject>();
				zero = obj.Field("hitPoint").GetValue<Vector3>();
			}
			catch
			{
				return true;
			}
			if (TryInvokeRedirectFromHitObject(val, zero))
			{
				return false;
			}
			return true;
		}
	}
	public sealed class MenuDiscovery
	{
		public static readonly (string Label, string ComponentType)[] TemplateButtonCandidates = new(string, string)[3]
		{
			("COLLECTIONS", "ShootableOpenCollectionsMenu"),
			("TRIALS", "ShootableOpenTrialsMenu"),
			("STATS", "ShootableOpenStatsMenu")
		};

		public GameObject TemplateButton { get; private set; }

		public string TemplateLabel { get; private set; }

		public string TemplateComponentType { get; private set; }

		public GameObject TemplateColumn { get; private set; }

		public Transform MenuRow { get; private set; }

		public Canvas ParentCanvas { get; private set; }

		public RectTransform CanvasRect { get; private set; }

		public Dictionary<string, GameObject> CardsByLabel { get; } = new Dictionary<string, GameObject>(StringComparer.OrdinalIgnoreCase);

		public Dictionary<string, GameObject> ColumnsByLabel { get; } = new Dictionary<string, GameObject>(StringComparer.OrdinalIgnoreCase);

		public List<RectTransform> NarrowColumns { get; } = new List<RectTransform>();

		public float ColumnWidth { get; private set; }

		public float ColumnY { get; private set; }

		public float NativeSpacing { get; private set; }

		public bool TryDiscover()
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: 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_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Expected O, but got Unknown
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: 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)
			TemplateButton = FindTemplateButton(out var matchedLabel, out var matchedComponentType);
			if ((Object)(object)TemplateButton == (Object)null)
			{
				return false;
			}
			TemplateLabel = matchedLabel;
			TemplateComponentType = matchedComponentType;
			TemplateColumn = ((Component)TemplateButton.transform.parent).gameObject;
			MenuRow = TemplateColumn.transform.parent;
			ParentCanvas = TemplateButton.GetComponentInParent<Canvas>();
			CanvasRect = (((Object)(object)ParentCanvas != (Object)null) ? ((Component)ParentCanvas).GetComponent<RectTransform>() : null);
			RectTransform val = (RectTransform)TemplateColumn.transform;
			Rect rect = val.rect;
			ColumnWidth = ((Rect)(ref rect)).width;
			ColumnY = val.anchoredPosition.y;
			CardsByLabel.Clear();
			ColumnsByLabel.Clear();
			NarrowColumns.Clear();
			List<float> list = new List<float>();
			foreach (Transform item in MenuRow)
			{
				object obj = (object)item;
				RectTransform val2 = (RectTransform)((obj is RectTransform) ? obj : null);
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				rect = val2.rect;
				if (!Mathf.Approximately(((Rect)(ref rect)).width, ColumnWidth))
				{
					continue;
				}
				NarrowColumns.Add(val2);
				list.Add(val2.anchoredPosition.x);
				string text = FindPrimaryLabel(((Component)val2).gameObject);
				if (!string.IsNullOrEmpty(text))
				{
					GameObject val3 = FindCardWithLabel(((Component)val2).gameObject, text) ?? FindFirstTile(((Component)val2).gameObject);
					if (!((Object)(object)val3 == (Object)null))
					{
						string key = text.Trim().ToUpperInvariant();
						CardsByLabel[key] = val3;
						ColumnsByLabel[key] = ((Component)val2).gameObject;
					}
				}
			}
			list.Sort();
			NativeSpacing = ColumnWidth + 1f;
			if (list.Count >= 2)
			{
				NativeSpacing = list[1] - list[0];
			}
			OpenShotPlugin.Log.LogInfo((object)($"[MenuDiscovery] Found template '{TemplateLabel}', {NarrowColumns.Count} narrow columns, " + "labels=[" + string.Join(", ", CardsByLabel.Keys) + "]."));
			return true;
		}

		public static GameObject FindTemplateButton(out string matchedLabel, out string matchedComponentType)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			matchedLabel = null;
			matchedComponentType = null;
			Scene activeScene = SceneManager.GetActiveScene();
			if (!((Scene)(ref activeScene)).IsValid())
			{
				return null;
			}
			(string, string)[] templateButtonCandidates = TemplateButtonCandidates;
			for (int i = 0; i < templateButtonCandidates.Length; i++)
			{
				(string, string) tuple = templateButtonCandidates[i];
				Type type = AccessTools.TypeByName(tuple.Item2);
				if (type == null)
				{
					continue;
				}
				GameObject[] rootGameObjects = ((Scene)(ref activeScene)).GetRootGameObjects();
				for (int j = 0; j < rootGameObjects.Length; j++)
				{
					Component[] componentsInChildren = rootGameObjects[j].GetComponentsInChildren(type, true);
					foreach (Component obj in componentsInChildren)
					{
						MonoBehaviour val = (MonoBehaviour)(object)((obj is MonoBehaviour) ? obj : null);
						if (val != null)
						{
							(matchedLabel, matchedComponentType) = tuple;
							return ((Component)val).gameObject;
						}
					}
				}
			}
			return null;
		}

		private static string FindPrimaryLabel(GameObject column)
		{
			TextMeshProUGUI[] componentsInChildren = column.GetComponentsInChildren<TextMeshProUGUI>(true);
			TextMeshProUGUI[] array = componentsInChildren;
			foreach (TextMeshProUGUI val in array)
			{
				if (!((Object)(object)val == (Object)null) && !string.IsNullOrWhiteSpace(((TMP_Text)val).text))
				{
					string text = ((TMP_Text)val).text.Trim();
					if (text.Length <= 24)
					{
						return text;
					}
				}
			}
			if (componentsInChildren.Length == 0 || !((Object)(object)componentsInChildren[0] != (Object)null))
			{
				return null;
			}
			return ((TMP_Text)componentsInChildren[0]).text;
		}

		private static GameObject FindCardWithLabel(GameObject column, string label)
		{
			TextMeshProUGUI[] componentsInChildren = column.GetComponentsInChildren<TextMeshProUGUI>(true);
			foreach (TextMeshProUGUI val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && string.Equals(((TMP_Text)val).text.Trim(), label.Trim(), StringComparison.OrdinalIgnoreCase))
				{
					Transform val2 = ((TMP_Text)val).transform;
					while ((Object)(object)val2 != (Object)null && (Object)(object)val2.parent != (Object)(object)column.transform)
					{
						val2 = val2.parent;
					}
					if (!((Object)(object)val2 != (Object)null))
					{
						return ((Component)val).gameObject;
					}
					return ((Component)val2).gameObject;
				}
			}
			return null;
		}

		private static GameObject FindFirstTile(GameObject column)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			IEnumerator enumerator = column.transform.GetEnumerator();
			try
			{
				if (enumerator.MoveNext())
				{
					return ((Component)(Transform)enumerator.Current).gameObject;
				}
			}
			finally
			{
				IDisposable disposable = enumerator as IDisposable;
				if (disposable != null)
				{
					disposable.Dispose();
				}
			}
			return null;
		}
	}
	public static class MenuLayout
	{
		private const float EdgeGap = 0.35f;

		private const float OverlapSlack = 0.08f;

		public static void PlaceInjectedColumns(IReadOnlyList<RectTransform> injectedColumns, Transform menuRow, RectTransform canvasRect, float columnY, float nativeColumnWidth, float nativeSpacing)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: 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_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: 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_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			if (injectedColumns == null || injectedColumns.Count == 0 || (Object)(object)menuRow == (Object)null)
			{
				return;
			}
			RectTransform val = (RectTransform)(object)((menuRow is RectTransform) ? menuRow : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			float num = ((nativeSpacing > 0.01f) ? nativeSpacing : (nativeColumnWidth + 0.35f));
			float num2 = Mathf.Max(0.35f, num - nativeColumnWidth);
			List<RectTransform> list = CollectOriginalColumns(menuRow);
			Vector3 val2 = ResolveNativeScale(list, injectedColumns);
			float num3 = Mathf.Max(0.01f, Mathf.Abs(val2.x));
			float num4 = nativeColumnWidth * 0.5f * num3;
			float num5 = float.NegativeInfinity;
			float num6 = columnY;
			foreach (RectTransform item in list)
			{
				GetHorizontalBoundsInRowSpace(val, item, out var _, out var right, out var centerY);
				if (right > num5)
				{
					num5 = right;
					num6 = centerY;
				}
			}
			if (float.IsNegativeInfinity(num5))
			{
				num5 = 0f - num4;
			}
			float num7 = num5 + num2 + num4;
			float num8 = num6;
			for (int i = 0; i < 32; i++)
			{
				if (!OverlapsAnyOriginal(val, num7, num4, num8, list))
				{
					break;
				}
				num7 = FindRightmostOriginalEdge(val, list) + num2 + num4;
			}
			float num9 = 1f;
			if ((Object)(object)canvasRect != (Object)null)
			{
				num9 = ComputeCanvasFitScale(val, canvasRect, num7, num4, injectedColumns.Count, num, num2, val2);
			}
			for (int j = 0; j < injectedColumns.Count; j++)
			{
				RectTransform val3 = injectedColumns[j];
				if (!((Object)(object)val3 == (Object)null))
				{
					EnsureIgnoredByLayout(val3);
					float num10 = Mathf.Sign((val2.x == 0f) ? 1f : val2.x) * Mathf.Abs(val2.x) * num9;
					float num11 = val2.y * num9;
					((Transform)val3).localScale = new Vector3(num10, num11, val2.z);
					float num12 = num4 * num9;
					if (j > 0)
					{
						num7 = GetColumnRightEdge(val, injectedColumns[j - 1]) + num2 + num12;
					}
					val3.anchoredPosition = new Vector2(num7, num8);
					if (OverlapsAnyOriginal(val, num7, num12, num8, list))
					{
						num7 = FindRightmostOriginalEdge(val, list) + num2 + num12;
						val3.anchoredPosition = new Vector2(num7, num8);
					}
				}
			}
			ManualLogSource log = OpenShotPlugin.Log;
			string text = $"[MenuLayout] Placed {injectedColumns.Count} injected column(s) ";
			object arg = num5;
			RectTransform obj = injectedColumns[0];
			log.LogInfo((object)(text + $"after x={arg:F2} → firstCenter={((obj != null) ? new float?(obj.anchoredPosition.x) : ((float?)null)):F2}, " + $"y={num8:F2}, gap={num2:F2}, scale={num9:F2}."));
		}

		public static void PlaceCenteredColumns(IReadOnlyList<RectTransform> columns, RectTransform canvasRect, float columnY, float nativeColumnWidth, float nativeSpacing)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: 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_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			if (columns == null || columns.Count == 0)
			{
				return;
			}
			float num = ((nativeSpacing > 0.01f) ? nativeSpacing : (nativeColumnWidth + 0.35f));
			float num2;
			if (!((Object)(object)canvasRect != (Object)null))
			{
				num2 = 40f;
			}
			else
			{
				Rect rect = canvasRect.rect;
				num2 = ((Rect)(ref rect)).width / 2f;
			}
			float num3 = num2 * 2f - 0.7f;
			Vector3 val = (((Object)(object)columns[0] != (Object)null) ? ((Transform)columns[0]).localScale : Vector3.one);
			float num4 = Mathf.Max(0.01f, Mathf.Abs(val.x));
			float num5 = nativeColumnWidth * num4;
			float num6 = Mathf.Max(num5 * 1.05f, num * 0.92f);
			int num7 = Mathf.Max(1, Mathf.FloorToInt((num3 + 0.001f) / num));
			if ((float)num7 * num - (num - num5) > num3 + 0.01f)
			{
				num7 = Mathf.Max(1, num7 - 1);
			}
			int count = columns.Count;
			int num8 = Mathf.CeilToInt((float)count / (float)num7);
			for (int i = 0; i < count; i++)
			{
				RectTransform val2 = columns[i];
				if (!((Object)(object)val2 == (Object)null))
				{
					EnsureIgnoredByLayout(val2);
					int num9 = i / num7;
					int num10 = i % num7;
					float num11 = (0f - (float)(Math.Min(num7, count - num9 * num7) - 1) * num) * 0.5f;
					float num12 = columnY - (float)num9 * num6;
					val2.anchoredPosition = new Vector2(num11 + (float)num10 * num, num12);
					float num13 = Mathf.Sign((val.x == 0f) ? 1f : val.x);
					((Transform)val2).localScale = new Vector3(num13 * Mathf.Abs(val.x), val.y, val.z);
				}
			}
			OpenShotPlugin.Log.LogInfo((object)($"[MenuLayout] Placed {count} hub column(s) in {num8} row(s) × {num7} max, " + $"spacing={num:F2}, pitch={num6:F2}."));
		}

		private static List<RectTransform> CollectOriginalColumns(Transform menuRow)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			List<RectTransform> list = new List<RectTransform>();
			foreach (Transform item in menuRow)
			{
				Transform val = item;
				if (!((Object)(object)val == (Object)null) && !((Object)val).name.StartsWith("OpenShot_", StringComparison.Ordinal))
				{
					RectTransform val2 = (RectTransform)(object)((val is RectTransform) ? val : null);
					if (val2 != null && ((Component)val2).gameObject.activeInHierarchy)
					{
						list.Add(val2);
					}
				}
			}
			return list;
		}

		private static Vector3 ResolveNativeScale(List<RectTransform> originals, IReadOnlyList<RectTransform> injectedColumns)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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_0058: 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)
			foreach (RectTransform original in originals)
			{
				if ((Object)(object)original != (Object)null)
				{
					return ((Transform)original).localScale;
				}
			}
			if (!((Object)(object)injectedColumns[0] != (Object)null))
			{
				return Vector3.one;
			}
			return ((Transform)injectedColumns[0]).localScale;
		}

		private static void EnsureIgnoredByLayout(RectTransform col)
		{
			LayoutElement val = ((Component)col).GetComponent<LayoutElement>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)col).gameObject.AddComponent<LayoutElement>();
			}
			val.ignoreLayout = true;
		}

		private static float ComputeCanvasFitScale(RectTransform rowRt, RectTransform canvasRect, float firstCenterX, float halfWidth, int count, float spacing, float edgeGap, Vector3 nativeScale)
		{
			GetHorizontalBoundsInRowSpace(rowRt, canvasRect, out var left, out var right, out var _);
			float num = firstCenterX;
			if (count > 1)
			{
				num = firstCenterX + (float)(count - 1) * spacing;
			}
			float num2 = num + halfWidth;
			float num3 = firstCenterX - halfWidth;
			float num4 = left + 0.35f;
			float num5 = right - 0.35f;
			float num6 = 1f;
			if (num2 > num5)
			{
				float num7 = num2 - num5;
				num6 = Mathf.Clamp(1f - num7 / Mathf.Max(num2 - firstCenterX + halfWidth, 1f), 0.72f, 1f);
			}
			if (num3 < num4 && num6 >= 1f)
			{
				float num8 = num4 - num3;
				num6 = Mathf.Clamp(1f - num8 / Mathf.Max(halfWidth * 2f, 1f), 0.72f, 1f);
			}
			return num6;
		}

		private static bool OverlapsAnyOriginal(RectTransform rowRt, float centerX, float halfWidth, float centerY, List<RectTransform> originals)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			float num = centerX - halfWidth;
			float num2 = centerX + halfWidth;
			foreach (RectTransform original in originals)
			{
				GetHorizontalBoundsInRowSpace(rowRt, original, out var left, out var right, out var centerY2);
				Rect rect = original.rect;
				float num3 = ((Rect)(ref rect)).height * 0.5f * Mathf.Abs(((Transform)original).localScale.y);
				if (!(Mathf.Abs(centerY2 - centerY) > num3 + halfWidth * 0.25f) && num2 > left + 0.08f && num < right - 0.08f)
				{
					return true;
				}
			}
			return false;
		}

		private static float FindRightmostOriginalEdge(RectTransform rowRt, List<RectTransform> originals)
		{
			float num = float.NegativeInfinity;
			foreach (RectTransform original in originals)
			{
				GetHorizontalBoundsInRowSpace(rowRt, original, out var _, out var right, out var _);
				if (right > num)
				{
					num = right;
				}
			}
			if (!float.IsNegativeInfinity(num))
			{
				return num;
			}
			return 0f;
		}

		private static float GetColumnRightEdge(RectTransform rowRt, RectTransform col)
		{
			GetHorizontalBoundsInRowSpace(rowRt, col, out var _, out var right, out var _);
			return right;
		}

		private static void GetHorizontalBoundsInRowSpace(RectTransform rowRt, RectTransform col, out float left, out float right, out float centerY)
		{
			//IL_0052: 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_005c: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			left = (right = (centerY = 0f));
			if ((Object)(object)rowRt == (Object)null || (Object)(object)col == (Object)null)
			{
				return;
			}
			Vector3[] array = (Vector3[])(object)new Vector3[4];
			col.GetWorldCorners(array);
			float num = float.PositiveInfinity;
			float num2 = float.NegativeInfinity;
			float num3 = 0f;
			for (int i = 0; i < 4; i++)
			{
				Vector3 val = ((Transform)rowRt).InverseTransformPoint(array[i]);
				if (val.x < num)
				{
					num = val.x;
				}
				if (val.x > num2)
				{
					num2 = val.x;
				}
				num3 += val.y;
			}
			left = num;
			right = num2;
			centerY = num3 * 0.25f;
		}
	}
	public static class ButtonRegistry
	{
		public struct CustomButton
		{
			public string Label;

			public Action<Vector3> OnShot;
		}

		private static readonly List<CustomButton> CustomButtons = new List<CustomButton>();

		private static readonly Dictionary<string, string> LabelOverrides = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

		private static readonly HashSet<string> HiddenLabels = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, Func<Vector3, bool>> ExistingShotHandlers = new Dictionary<string, Func<Vector3, bool>>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<GameObject, Func<Vector3, bool>> ExistingShotByCard = new Dictionary<GameObject, Func<Vector3, bool>>();

		private static readonly List<GameObject> InjectedColumns = new List<GameObject>();

		private static readonly HashSet<GameObject> HiddenColumns = new HashSet<GameObject>();

		public static IReadOnlyList<CustomButton> GetCustomButtons()
		{
			return CustomButtons;
		}

		public static bool IsHiddenColumn(GameObject column)
		{
			if ((Object)(object)column != (Object)null)
			{
				return HiddenColumns.Contains(column);
			}
			return false;
		}

		public static void AddButton(string label, Action<Vector3> onShot)
		{
			if (string.IsNullOrWhiteSpace(label))
			{
				throw new ArgumentException("Label is required.", "label");
			}
			if (onShot == null)
			{
				throw new ArgumentNullException("onShot");
			}
			string text = label.Trim();
			for (int i = 0; i < CustomButtons.Count; i++)
			{
				if (string.Equals(CustomButtons[i].Label, text, StringComparison.OrdinalIgnoreCase))
				{
					CustomButtons[i] = new CustomButton
					{
						Label = text,
						OnShot = onShot
					};
					return;
				}
			}
			CustomButtons.Add(new CustomButton
			{
				Label = text,
				OnShot = onShot
			});
		}

		public static void SetLabel(string existingLabel, string newLabel)
		{
			if (!string.IsNullOrWhiteSpace(existingLabel))
			{
				LabelOverrides[existingLabel.Trim()] = newLabel ?? string.Empty;
			}
		}

		public static void Hide(string existingLabel)
		{
			if (!string.IsNullOrWhiteSpace(existingLabel))
			{
				HiddenLabels.Add(existingLabel.Trim());
			}
		}

		public static void OnShot(string existingLabel, Func<Vector3, bool> handler)
		{
			if (!string.IsNullOrWhiteSpace(existingLabel) && handler != null)
			{
				ExistingShotHandlers[existingLabel.Trim()] = handler;
			}
		}

		public static void ClearInjectedColumns()
		{
			foreach (GameObject injectedColumn in InjectedColumns)
			{
				if ((Object)(object)injectedColumn != (Object)null)
				{
					Object.Destroy((Object)(object)injectedColumn);
				}
			}
			InjectedColumns.Clear();
			ExistingShotByCard.Clear();
			HiddenColumns.Clear();
		}

		public static bool TryHandleExistingShot(GameObject card, object shotHitContext, out bool suppressOriginal)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due t