Decompiled source of UIFramework v0.9.0

Mods/UIFramework.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.IO;
using Il2CppTMPro;
using MelonLoader;
using MelonLoader.Logging;
using MelonLoader.Preferences;
using Tomlet;
using Tomlet.Models;
using UIFramework;
using UIFramework.Adapters;
using UIFramework.Models;
using UIFramework.UiExtensions;
using UnityEngine;
using UnityEngine.CrashReportHandler;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(Core), "UIFramework", "0.9.0", "Reverb && Spice", null)]
[assembly: MelonGame("Buckethead Entertainment", "RUMBLE")]
[assembly: MelonColor(255, 255, 255, 255)]
[assembly: MelonAuthorColor(255, 255, 255, 255)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("UIFramework")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+6407ea36d6df5576b13914293560e44d62d6a084")]
[assembly: AssemblyProduct("UIFramework")]
[assembly: AssemblyTitle("UIFramework")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace UIFramework
{
	public class UIFModel
	{
		[Obsolete("This class is just a shim for backwards compatibility and should not be used directly. Use the new models instead in UIFramework.Models")]
		public interface IModelable : UIFramework.Models.IModelable
		{
		}

		[Obsolete]
		public abstract class SelectableModelBase : UIFramework.Models.SelectableModelBase
		{
			[Obsolete("This class is just a shim for backwards compatibility and should not be used directly. Use the new models instead in UIFramework.Models")]
			public void AddSubmodel(params IModelable[] submodel)
			{
				base.AddSubmodel(submodel);
			}
		}

		[Obsolete("This class is just a shim for backwards compatibility and should not be used directly. Use the new models instead in UIFramework.Models")]
		public abstract class ModelModItem : ModModelBase
		{
		}

		public class ModelMod : MelonModel
		{
			public ModelMod(MelonBase instance, List<MelonPreferences_Category> categories)
				: base(instance, categories)
			{
			}

			public ModelMod(MelonBase instance)
				: base(instance)
			{
			}
		}

		[Obsolete("This class is just a shim for backwards compatibility and should not be used directly. Use the new models instead in UIFramework.Models")]
		public abstract class ModelCategoryItem : CategoryModelBase
		{
			[Obsolete("This class is just a shim for backwards compatibility and should not be used directly. Use the new models instead in UIFramework.Models")]
			protected ModelCategoryItem(ModelModItem parentMod)
				: base(parentMod)
			{
			}
		}

		[Obsolete("This class is just a shim for backwards compatibility and should not be used directly. Use the new models instead in UIFramework.Models")]
		public class ModelMelonCategory : MelonCategoryModel
		{
			[Obsolete("This class is just a shim for backwards compatibility and should not be used directly. Use the new models instead in UIFramework.Models")]
			public ModelMelonCategory(MelonPreferences_Category cat, ModelModItem parentMod)
				: base(cat, parentMod)
			{
			}
		}

		[Obsolete("This class is just a shim for backwards compatibility and should not be used directly. Use the new models instead in UIFramework.Models")]
		public class EmptyCategory : UIFramework.Models.EmptyCategory
		{
			[Obsolete("This class is just a shim for backwards compatibility and should not be used directly. Use the new models instead in UIFramework.Models")]
			public EmptyCategory(string identifier, ModelModItem parentMod = null)
				: base(identifier, parentMod)
			{
			}
		}

		[Obsolete("This class is just a shim for backwards compatibility and should not be used directly. Use the new models instead in UIFramework.Models")]
		public abstract class ModelEntryItem : EntryModelBase
		{
			[Obsolete("This class is just a shim for backwards compatibility and should not be used directly. Use the new models instead in UIFramework.Models")]
			protected ModelEntryItem(ModelCategoryItem parentCategory)
				: base(parentCategory)
			{
			}
		}

		[Obsolete("This class is just a shim for backwards compatibility and should not be used directly. Use the new models instead in UIFramework.Models")]
		public class ButtonEntry : UIFramework.Models.ButtonEntry
		{
			[Obsolete("This class is just a shim for backwards compatibility and should not be used directly. Use the new models instead in UIFramework.Models")]
			public ButtonEntry(Action<ButtonModelAdapter> onClick, string name, string description = "", string displayName = "", ModelCategoryItem parentCategory = null)
				: base(onClick, name, description, displayName, parentCategory)
			{
			}
		}
	}
	public static class BuildInfo
	{
		public const string Name = "UIFramework";

		public const string Author = "Reverb && Spice";

		public const string Version = "0.9.0";
	}
	public class Core : MelonMod
	{
		[CompilerGenerated]
		private sealed class <FindModUI>d__26 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public Core <>4__this;

			private GameObject <uiObject>5__1;

			private GameObject <modUiWindow>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <FindModUI>d__26(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<uiObject>5__1 = null;
				<modUiWindow>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<uiObject>5__1 = GameObject.Find("Game Instance/UI");
					<modUiWindow>5__2 = ((Component)<uiObject>5__1.transform.Find("Mod_Setting_UI")).gameObject;
					<>4__this.ModUIWindow = <modUiWindow>5__2;
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <InputToggled>d__12 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public bool matchModUI;

			public Core <>4__this;

			private bool <uifPrevState>5__1;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <InputToggled>d__12(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0079: Unknown result type (might be due to invalid IL or missing references)
				//IL_0083: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					Prefabs.UIFGameObjects.SetActive(true);
					if (<>4__this.CurrentScene == "loader")
					{
						Debug.Warning("UIFramework does not work in the loader. Please finish calibrating.");
						return false;
					}
					if ((<>4__this.ModUIWindow != null) & matchModUI)
					{
						<>2__current = (object)new WaitForSeconds(0.04f);
						<>1__state = 1;
						return true;
					}
					UI.MainWindow.SetActive(!UI.MainWindow.activeSelf);
					break;
				case 1:
					<>1__state = -1;
					<uifPrevState>5__1 = UI.MainWindow.activeSelf;
					if (<>4__this.ModUIWindow.activeSelf == <>4__this.lastModUIState)
					{
						UI.MainWindow.SetActive(!<uifPrevState>5__1);
					}
					else
					{
						UI.MainWindow.SetActive(<>4__this.ModUIWindow.activeSelf);
					}
					<>4__this.lastModUIState = <>4__this.ModUIWindow.activeSelf;
					break;
				}
				UI.MainWindow.GetComponent<WindowCoordinator>().DragHandle.ClampToBounds();
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <SyncModUIState>d__13 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public Core <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <SyncModUIState>d__13(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
				{
					<>1__state = -1;
					Core core = <>4__this;
					GameObject modUIWindow = <>4__this.ModUIWindow;
					core.lastModUIState = modUIWindow != null && modUIWindow.activeSelf;
					return false;
				}
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		internal static Core Instance;

		internal string CurrentScene = "";

		internal bool isFirstLoad = true;

		internal GameObject ModUIWindow;

		internal bool lastModUIState = false;

		internal Stopwatch displayTime = new Stopwatch();

		private static InputActionMap map = new InputActionMap("Tha Map");

		private static InputAction rightGrip = InputActionSetupExtensions.AddAction(map, "Right Trigger", (InputActionType)0, (string)null, (string)null, (string)null, (string)null, (string)null);

		private static InputAction rightPrimary = InputActionSetupExtensions.AddAction(map, "Right Primary", (InputActionType)0, (string)null, (string)null, (string)null, (string)null, (string)null);

		private static InputAction leftGrip = InputActionSetupExtensions.AddAction(map, "Left Trigger", (InputActionType)0, (string)null, (string)null, (string)null, (string)null, (string)null);

		private static InputAction leftPrimary = InputActionSetupExtensions.AddAction(map, "Left Primary", (InputActionType)0, (string)null, (string)null, (string)null, (string)null, (string)null);

		private bool VRButtonsPressed = false;

		internal int inactiveTimeLimit
		{
			get
			{
				MelonPreferences_Entry<int> inactivityTimeout = Preferences.InactivityTimeout;
				return (inactivityTimeout != null) ? (inactivityTimeout.Value * 1000) : 30000;
			}
		}

		public override void OnInitializeMelon()
		{
			InputActionSetupExtensions.AddBinding(rightGrip, "<XRController>{RightHand}/Trigger", (string)null, (string)null, (string)null);
			InputActionSetupExtensions.AddBinding(rightPrimary, "<XRController>{RightHand}/primaryButton", (string)null, (string)null, (string)null);
			InputActionSetupExtensions.AddBinding(leftGrip, "<XRController>{LeftHand}/Trigger", (string)null, (string)null, (string)null);
			InputActionSetupExtensions.AddBinding(leftPrimary, "<XRController>{LeftHand}/primaryButton", (string)null, (string)null, (string)null);
			map.Enable();
			Instance = this;
			((MelonEventBase<LemonAction<string>>)(object)MelonPreferences.OnPreferencesSaved).Subscribe((LemonAction<string>)MelPrefsSaved, 0, false);
			((MelonBase)this).LoggerInstance.Msg("Initialized.");
		}

		public override void OnLateInitializeMelon()
		{
			CrashReportHandler.enableCaptureExceptions = false;
		}

		public override void OnUpdate()
		{
			UiToggleInputCheck();
			if (!isFirstLoad)
			{
				AutoHideCheck();
			}
		}

		private void UiToggleInputCheck()
		{
			bool keyDown = Input.GetKeyDown((KeyCode)290);
			bool flag = keyDown;
			if (flag)
			{
				ToggleOptions value = Preferences.ToggleSettings.Value;
				bool flag2 = ((value == ToggleOptions.Keyboard || value == ToggleOptions.KeyAndVR) ? true : false);
				flag = flag2;
			}
			if (flag)
			{
				MelonCoroutines.Start(InputToggled(matchModUI: false));
			}
			else
			{
				bool flag3 = VRActivationAction();
				bool flag4 = flag3;
				if (flag4)
				{
					ToggleOptions value = Preferences.ToggleSettings.Value;
					bool flag2 = (uint)(value - 1) <= 1u;
					flag4 = flag2;
				}
				if (flag4)
				{
					MelonCoroutines.Start(InputToggled(matchModUI: true));
				}
			}
			if (Input.GetKeyDown((KeyCode)291))
			{
				MelonCoroutines.Start(SyncModUIState());
			}
		}

		[IteratorStateMachine(typeof(<InputToggled>d__12))]
		private IEnumerator InputToggled(bool matchModUI)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <InputToggled>d__12(0)
			{
				<>4__this = this,
				matchModUI = matchModUI
			};
		}

		[IteratorStateMachine(typeof(<SyncModUIState>d__13))]
		private IEnumerator SyncModUIState()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <SyncModUIState>d__13(0)
			{
				<>4__this = this
			};
		}

		private bool VRActivationAction()
		{
			if (isFirstLoad)
			{
				return false;
			}
			if (!Preferences.VrInputToggle.Value)
			{
				return false;
			}
			float num = 0.9f;
			float num2 = 0.1f;
			float num3 = rightGrip.ReadValue<float>();
			float num4 = rightPrimary.ReadValue<float>();
			float num5 = leftGrip.ReadValue<float>();
			float num6 = rightPrimary.ReadValue<float>();
			if (num3 >= num && num4 >= num && num5 >= num && num6 >= num && !VRButtonsPressed)
			{
				VRButtonsPressed = true;
				return true;
			}
			if (num3 <= num2 && num4 <= num2 && num5 <= num2 && num6 <= num2 && VRButtonsPressed)
			{
				VRButtonsPressed = false;
			}
			return false;
		}

		private void AutoHideCheck()
		{
			if (UI.MainWindow.activeSelf)
			{
				MelonPreferences_Entry<bool> autoHideOnInactivity = Preferences.AutoHideOnInactivity;
				if (autoHideOnInactivity != null && autoHideOnInactivity.Value)
				{
					if (UserInteracted())
					{
						if (displayTime.IsRunning)
						{
							displayTime.Reset();
						}
					}
					else if (!displayTime.IsRunning)
					{
						displayTime.Start();
					}
					if (displayTime.ElapsedMilliseconds < inactiveTimeLimit)
					{
						return;
					}
					UI.MainWindow.SetActive(false);
					if (Preferences.HijackModUI.Value)
					{
						GameObject modUIWindow = ModUIWindow;
						if (modUIWindow != null)
						{
							modUIWindow.SetActive(false);
						}
					}
					return;
				}
			}
			if (displayTime.IsRunning)
			{
				displayTime.Reset();
			}
		}

		private bool UserInteracted()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (Mouse.current != null)
			{
				Vector2 val = ((InputControl<Vector2>)(object)((Pointer)Mouse.current).delta).ReadValue();
				if (((Vector2)(ref val)).sqrMagnitude > 0f)
				{
					return true;
				}
			}
			if (Keyboard.current != null && ((ButtonControl)Keyboard.current.anyKey).wasPressedThisFrame)
			{
				return true;
			}
			return false;
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			Debug.Log($"Current buildIndex = {buildIndex} was loaded. sceneName = {sceneName}");
			CurrentScene = sceneName.ToNormal();
			if (CurrentScene == "loader")
			{
			}
			if (CurrentScene == "gym" && isFirstLoad)
			{
				FirstGymLoad();
			}
			if (isFirstLoad)
			{
				return;
			}
			if (UI.MainWindow.activeSelf)
			{
				UI.MainWindow.SetActive(!Preferences.AutoHideOnSceneLoad.Value);
				if (Preferences.HijackModUI.Value)
				{
					GameObject modUIWindow = ModUIWindow;
					if (modUIWindow != null && modUIWindow.activeSelf)
					{
						GameObject modUIWindow2 = ModUIWindow;
						if (modUIWindow2 != null)
						{
							modUIWindow2.SetActive(!Preferences.AutoHideOnSceneLoad.Value);
						}
					}
				}
			}
			Preferences.DemoString.Value = CurrentScene;
		}

		internal void FirstGymLoad()
		{
			BuildUI();
			MelonCoroutines.Start(FindModUI());
			isFirstLoad = false;
		}

		internal void BuildUI()
		{
			Preferences.InitializePrefs();
			UIFModel.ModelMod modelMod = UI.Register((MelonMod)(object)this, Preferences.CatUIFramework, Preferences.Demo, Preferences.Experimental, Preferences.TestBooleans, Preferences.TestEmptyDisplayName);
			MelonCategoryModel melonCategoryModel = (MelonCategoryModel)modelMod.GetSubmodel(Preferences.TestBooleans.Identifier);
			ButtonEntry buttonEntry = new ButtonEntry(CustomClick, "CustomButton", "just a test", "Custom Button");
			melonCategoryModel.AddSubmodel(buttonEntry);
			Prefabs.LoadAssetBundle();
			UI.InitializeUIObjects();
			UI.MainWindow.SetActive(false);
			UI.BuildUI();
		}

		[IteratorStateMachine(typeof(<FindModUI>d__26))]
		public IEnumerator FindModUI()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <FindModUI>d__26(0)
			{
				<>4__this = this
			};
		}

		public void MelPrefsSaved(string s)
		{
		}

		public void CustomClick(ButtonModelAdapter button)
		{
			Debug.Log("Clicked: " + button.DisplayName + " ", debugOnly: false);
		}

		private void SinglesaveClick()
		{
			Debug.Log("Clicked Single Save Button");
		}
	}
	[AttributeUsage(AttributeTargets.Assembly)]
	public class UIInfoAttribute : Attribute
	{
		public string DisplayName { get; }

		public UIInfoAttribute(string displayName)
		{
			DisplayName = displayName;
		}
	}
	internal static class Debug
	{
		private static string lastDiffLogMessage = string.Empty;

		public static bool debugMode => Preferences.EnableDebugMode?.Value ?? true;

		internal static void DiffLog(string message, bool debugOnly = true, int logLevel = 0)
		{
			if (message != lastDiffLogMessage)
			{
				lastDiffLogMessage = message;
				Log("DIFFLOG: " + message, debugOnly, logLevel);
			}
		}

		internal static void Log(string message, bool debugOnly = true, int logLevel = 0)
		{
			if (!(!debugMode && debugOnly))
			{
				switch (logLevel)
				{
				case 1:
					Melon<Core>.Logger.Warning(message);
					break;
				case 2:
					Melon<Core>.Logger.Error(message);
					break;
				default:
					Melon<Core>.Logger.Msg(message);
					break;
				}
			}
		}

		internal static void Deb(string message)
		{
			Log(message);
		}

		internal static void Msg(string message)
		{
			Log(message, debugOnly: false);
		}

		internal static void Warning(string message)
		{
			Log(message, debugOnly: false, 1);
		}

		internal static void Error(string message)
		{
			Log(message, debugOnly: false, 2);
		}
	}
	public static class UI
	{
		internal static RootModel ModelInstance = new RootModel();

		internal static GameObject MainWindow;

		internal static WindowCoordinator WindowInstance;

		public static bool IsVisible => MainWindow.activeSelf;

		[Obsolete(".Register() will be a different function in the future to support plugins.\n When that happens, no code changes are needed but you will need to rebuild your project so the compiler can find the correct method\nTo future-proof your mod, Explicitly cast your mod instance to MelonBase when registering")]
		public static UIFModel.ModelMod Register(MelonMod modInstance, params MelonPreferences_Category[] categories)
		{
			return Register((MelonBase)(object)modInstance, categories);
		}

		public static UIFModel.ModelMod Register(MelonBase modInstance, params MelonPreferences_Category[] categories)
		{
			UIFModel.ModelMod modelMod = new UIFModel.ModelMod(modInstance, categories.ToList());
			ModelInstance.AddSubmodel(modelMod);
			return modelMod;
		}

		[Obsolete(".Register() will be a different function in the future to support plugins.\n When that happens, no code changes are needed but you will need to rebuild your project so the compiler can find the correct method\nTo future-proof your mod, Explicitly cast your mod instance to MelonBase when registering")]
		public static UIFModel.ModelMod Register(MelonMod modInstance)
		{
			return Register(modInstance);
		}

		public static UIFModel.ModelMod Register(MelonBase modInstance)
		{
			UIFModel.ModelMod modelMod = new UIFModel.ModelMod(modInstance);
			ModelInstance.AddSubmodel(modelMod);
			return modelMod;
		}

		public static MelonModel RegisterMelon(MelonBase melonInstance, params MelonPreferences_Category[] categories)
		{
			MelonModel melonModel = new MelonModel(melonInstance, categories.ToList());
			ModelInstance.AddSubmodel(melonModel);
			return melonModel;
		}

		internal static void InitializeUIObjects()
		{
			MainWindow = Object.Instantiate<GameObject>(Prefabs.MainWindowSource, Prefabs.Canvas.transform);
			((Object)MainWindow).name = "MainWindow";
			MainWindow.SetActive(true);
			WindowInstance = MainWindow.GetComponent<WindowCoordinator>();
		}

		public static void CreateButtonEntry(MelonPreferences_Category category, string buttonText, string displayName, string description, Action handler)
		{
			ButtonAsEntry buttonAsEntry = new ButtonAsEntry
			{
				Handler = handler,
				ButtonText = buttonText,
				DisplayName = displayName,
				Description = description
			};
			category.CreateEntry<ButtonAsEntry>("PlaceHolder" + buttonText + displayName + description, buttonAsEntry, displayName, description, false, true, (ValueValidator)(object)buttonAsEntry);
		}

		internal static void BuildUI()
		{
			WindowInstance.SetModel(ModelInstance);
		}

		internal static void RequestRefresh(ModModelBase modModel)
		{
			Debug.Log("RefreshRequested in Framework.cs RequestRefresh(ModModelBase modModel)", debugOnly: true, 1);
			WindowInstance.RequestRefresh(modModel);
		}

		public static void RequestRefresh(MelonBase melonInstance)
		{
			Debug.Log("Refresh requested in Framework.cs RequestRefresh(MelonBase melonInstance)", debugOnly: true, 1);
			ModModelBase modModel = ModelInstance.GetModModel(melonInstance.Info.Name);
			WindowInstance.RequestRefresh(modModel);
		}

		public static GameObject GetPrefab(InputType input)
		{
			GameObject val = (GameObject)(input switch
			{
				InputType.TextField => Object.Instantiate<GameObject>(Prefabs.TextPrefab), 
				InputType.Toggle => Object.Instantiate<GameObject>(Prefabs.BoolPrefab), 
				InputType.NumericInt => Object.Instantiate<GameObject>(Prefabs.IntPrefab), 
				InputType.NumericFloat => Object.Instantiate<GameObject>(Prefabs.FloatPrefab), 
				InputType.Button => Object.Instantiate<GameObject>(Prefabs.ButtonPrefab), 
				InputType.Dropdown => Object.Instantiate<GameObject>(Prefabs.DropDownPrefab), 
				InputType.Slider => Object.Instantiate<GameObject>(Prefabs.SliderPrefab), 
				_ => Object.Instantiate<GameObject>(Prefabs.TextPrefab), 
			});
			val.transform.SetParent(Prefabs.TempStorage.transform);
			return val;
		}
	}
	public enum InputType
	{
		[Display(Name = "Default", Description = "Defaults to basic string input")]
		Default,
		[Display(Name = "Text Field", Description = "Basic text field input")]
		TextField,
		[Display(Name = "Toggle", Description = "A simple on/off toggle")]
		Toggle,
		[Display(Name = "Int input", Description = "An Input for inputing Numeric Integers")]
		NumericInt,
		[Display(Name = "Float input", Description = "An Input for inputing Floating Point Numbers")]
		NumericFloat,
		[Display(Name = "Button", Description = "A simple button that can be clicked to trigger an action")]
		Button,
		[Display(Name = "Dropdown", Description = "A dropdown menu for selecting from multiple options")]
		Dropdown,
		[Display(Name = "Slider", Description = "A slider for selecting a value within a range")]
		Slider
	}
	public class UIProperties
	{
		public bool IsEnabled { get; set; }

		public bool IsHidden { get; set; }

		public bool IsReadOnly { get; set; }

		public bool IsPasswordField { get; set; }

		public bool IsRightToLeft { get; set; }

		public Color DisplayNameColor { get; set; }

		public Color DescriptionColor { get; set; }

		public Color EntryBaseColor { get; set; }

		public Color EntryDataSectionColor { get; set; }

		public int DisplayNameFontSize { get; set; }

		public int DescriptionFontSize { get; set; }
	}
	internal static class Prefabs
	{
		internal static GameObject UIFGameObjects = new GameObject("UI");

		internal static GameObject AssetBundleLoaded;

		internal static GameObject TempStorage = new GameObject("TempStorage");

		internal static GameObject HiddenStorage = new GameObject("HiddenStorage");

		internal static GameObject Canvas;

		public static GameObject MainWindowSource;

		public static GameObject MainWindowDragHandle;

		internal static GameObject ModDisplayList;

		internal static GameObject CatDisplayList;

		internal static GameObject PrefDisplayList;

		internal static GameObject ModTab;

		internal static GameObject CatTab;

		internal static GameObject TextPrefab;

		internal static GameObject BoolPrefab;

		internal static GameObject IntPrefab;

		internal static GameObject FloatPrefab;

		internal static GameObject DropDownPrefab;

		internal static GameObject SliderPrefab;

		internal static GameObject ButtonPrefab;

		internal static Button MainActionButton;

		internal static Button DiscardButton;

		internal static Button MinimizeButton;

		internal static void LoadAssetBundle()
		{
			Debug.Log("LoadingUIFramework AssetBundle");
			Object.DontDestroyOnLoad((Object)(object)UIFGameObjects);
			TempStorage.transform.SetParent(UIFGameObjects.transform, false);
			TempStorage.SetActive(false);
			HiddenStorage.transform.SetParent(UIFGameObjects.transform, false);
			HiddenStorage.SetActive(false);
			AssetBundleLoaded = Object.Instantiate<GameObject>(Prefabs.LoadAssetFromStream<GameObject>((MelonMod)(object)Core.Instance, "UIFramework.Assets.uiframework", "UIframework"), UIFGameObjects.transform);
			((Object)AssetBundleLoaded).name = "UIFrameworkAssets";
			Transform? obj = ((IEnumerable<Transform>)((Component)AssetBundleLoaded.transform).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "UICanvas"));
			Canvas = ((obj != null) ? ((Component)obj).gameObject : null);
			Transform? obj2 = ((IEnumerable<Transform>)((Component)AssetBundleLoaded.transform).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "Root"));
			MainWindowSource = ((obj2 != null) ? ((Component)obj2).gameObject : null);
			Transform? obj3 = ((IEnumerable<Transform>)((Component)AssetBundleLoaded.transform).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "DragHandle"));
			MainWindowDragHandle = ((obj3 != null) ? ((Component)obj3).gameObject : null);
			Transform? obj4 = ((IEnumerable<Transform>)((Component)AssetBundleLoaded.transform).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "ModRegCont"));
			ModDisplayList = ((obj4 != null) ? ((Component)obj4).gameObject : null);
			Transform? obj5 = ((IEnumerable<Transform>)((Component)AssetBundleLoaded.transform).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "CatRegCont"));
			CatDisplayList = ((obj5 != null) ? ((Component)obj5).gameObject : null);
			Transform? obj6 = ((IEnumerable<Transform>)((Component)AssetBundleLoaded.transform).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "PrefRegCont"));
			PrefDisplayList = ((obj6 != null) ? ((Component)obj6).gameObject : null);
			Transform? obj7 = ((IEnumerable<Transform>)((Component)AssetBundleLoaded.transform).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "ModEntry"));
			ModTab = ((obj7 != null) ? ((Component)obj7).gameObject : null);
			Transform? obj8 = ((IEnumerable<Transform>)((Component)AssetBundleLoaded.transform).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "CategoryTab"));
			CatTab = ((obj8 != null) ? ((Component)obj8).gameObject : null);
			Transform? obj9 = ((IEnumerable<Transform>)((Component)AssetBundleLoaded.transform).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "PrefEntryText"));
			TextPrefab = ((obj9 != null) ? ((Component)obj9).gameObject : null);
			Transform? obj10 = ((IEnumerable<Transform>)((Component)AssetBundleLoaded.transform).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "PrefEntryBool"));
			BoolPrefab = ((obj10 != null) ? ((Component)obj10).gameObject : null);
			Transform? obj11 = ((IEnumerable<Transform>)((Component)AssetBundleLoaded.transform).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "PrefEntryInt"));
			IntPrefab = ((obj11 != null) ? ((Component)obj11).gameObject : null);
			Transform? obj12 = ((IEnumerable<Transform>)((Component)AssetBundleLoaded.transform).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "PrefEntryFloat"));
			FloatPrefab = ((obj12 != null) ? ((Component)obj12).gameObject : null);
			Transform? obj13 = ((IEnumerable<Transform>)((Component)AssetBundleLoaded.transform).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "PrefEntryDropdown"));
			DropDownPrefab = ((obj13 != null) ? ((Component)obj13).gameObject : null);
			Transform? obj14 = ((IEnumerable<Transform>)((Component)AssetBundleLoaded.transform).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "PrefEntrySlider"));
			SliderPrefab = ((obj14 != null) ? ((Component)obj14).gameObject : null);
			Transform? obj15 = ((IEnumerable<Transform>)((Component)AssetBundleLoaded.transform).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "PrefEntryButton"));
			ButtonPrefab = ((obj15 != null) ? ((Component)obj15).gameObject : null);
			Transform? obj16 = ((IEnumerable<Transform>)((Component)AssetBundleLoaded.transform).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "SaveActionButton"));
			MainActionButton = ((obj16 != null) ? ((Component)obj16).gameObject.GetComponent<Button>() : null);
			Transform? obj17 = ((IEnumerable<Transform>)((Component)AssetBundleLoaded.transform).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "Minimize"));
			MinimizeButton = ((obj17 != null) ? ((Component)obj17).gameObject.GetComponent<Button>() : null);
			Transform? obj18 = ((IEnumerable<Transform>)((Component)AssetBundleLoaded.transform).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "DiscardActionButton"));
			DiscardButton = ((obj18 != null) ? ((Component)obj18).gameObject.GetComponent<Button>() : null);
			((Component)DiscardButton).gameObject.SetActive(false);
			Canvas.transform.SetParent(UIFGameObjects.transform, false);
			MainWindowSource.transform.SetParent(HiddenStorage.transform, false);
			ModTab.transform.SetParent(HiddenStorage.transform, false);
			CatTab.transform.SetParent(HiddenStorage.transform, false);
			TextPrefab.transform.SetParent(HiddenStorage.transform, false);
			BoolPrefab.transform.SetParent(HiddenStorage.transform, false);
			IntPrefab.transform.SetParent(HiddenStorage.transform, false);
			FloatPrefab.transform.SetParent(HiddenStorage.transform, false);
			DropDownPrefab.transform.SetParent(HiddenStorage.transform, false);
			SliderPrefab.transform.SetParent(HiddenStorage.transform, false);
			ButtonPrefab.transform.SetParent(HiddenStorage.transform, false);
			MainWindowSource.AddComponent<WindowCoordinator>();
			TextPrefab.AddComponent<TextEntryAdapter>();
			BoolPrefab.AddComponent<BoolToggleAdapter>();
			IntPrefab.AddComponent<TextEntryAdapter>();
			FloatPrefab.AddComponent<TextEntryAdapter>();
			SliderPrefab.AddComponent<NumSliderAdapter>();
			ModTab.AddComponent<ModButtonView>();
			CatTab.AddComponent<CategoryTabView>();
			ModDisplayList.AddComponent<ModListAdapter>();
			CatDisplayList.AddComponent<CategoryListAdapter>();
			PrefDisplayList.AddComponent<PrefListAdapter>();
			DragHandle dragHandle = MainWindowDragHandle.AddComponent<DragHandle>();
			EventTrigger val = MainWindowDragHandle.AddComponent<EventTrigger>();
			MainWindowSource.SetActive(false);
		}

		internal static T LoadAssetFromStream<T>(MelonMod instance, string path, string assetName) where T : Object
		{
			using Stream stream = ((MelonBase)instance).MelonAssembly.Assembly.GetManifestResourceStream(path);
			Stream val = ConvertToIl2CppStream(stream);
			AssetBundle val2 = AssetBundle.LoadFromStream(val);
			val.Close();
			T result = val2.LoadAsset<T>(assetName);
			val2.Unload(false);
			return result;
		}

		internal static Stream ConvertToIl2CppStream(Stream stream)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			MemoryStream val = new MemoryStream();
			byte[] array = new byte[4096];
			Il2CppStructArray<byte> val2 = new Il2CppStructArray<byte>(array);
			int num;
			while ((num = stream.Read(array, 0, array.Length)) > 0)
			{
				val2 = Il2CppStructArray<byte>.op_Implicit(array);
				((Stream)val).Write(val2, 0, num);
			}
			((Stream)val).Flush();
			return (Stream)(object)val;
		}
	}
	[RegisterTypeInIl2Cpp]
	public class DragHandle : MonoBehaviour
	{
		public RectTransform targetPanel;

		public RectTransform FindRootWindow()
		{
			RectTransform result = null;
			Transform parent = ((Component)this).gameObject.transform.parent;
			while ((Object)(object)parent != (Object)null)
			{
				if (((Object)parent).name.Contains("MainWindow"))
				{
					return ((Component)parent).GetComponent<RectTransform>();
				}
				parent = parent.parent;
			}
			return result;
		}

		public void OnDrag(BaseEventData data)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			PointerEventData val = ((Il2CppObjectBase)data).TryCast<PointerEventData>();
			if (val != null && !((Object)(object)targetPanel == (Object)null))
			{
				Canvas componentInParent = ((Component)targetPanel).GetComponentInParent<Canvas>();
				float num = (((Object)(object)componentInParent != (Object)null) ? componentInParent.scaleFactor : 1f);
				RectTransform obj = targetPanel;
				obj.anchoredPosition += val.delta / num;
				ClampToBounds();
				Preferences.UiPosition.Value = targetPanel.anchoredPosition;
			}
		}

		public void ClampToBounds()
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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_00de: 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)
			if (!((Object)(object)targetPanel == (Object)null))
			{
				Canvas componentInParent = ((Component)targetPanel).GetComponentInParent<Canvas>();
				float num = (((Object)(object)componentInParent != (Object)null) ? componentInParent.scaleFactor : 1f);
				Rect pixelRect = componentInParent.pixelRect;
				Vector2 val = new Vector2(((Rect)(ref pixelRect)).width, ((Rect)(ref pixelRect)).height) / num;
				Rect rect = targetPanel.rect;
				Vector2 size = ((Rect)(ref rect)).size;
				float num2 = 0f - (size.x - 50f);
				float num3 = val.x - 30f;
				float num4 = 0f - (val.y - 30f);
				float num5 = 0f;
				targetPanel.anchoredPosition = new Vector2(Mathf.Clamp(targetPanel.anchoredPosition.x, num2, num3), Mathf.Clamp(targetPanel.anchoredPosition.y, num4, num5));
				Preferences.UiPosition.Value = targetPanel.anchoredPosition;
			}
		}

		private void Start()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			targetPanel = FindRootWindow();
			EventTrigger val = ((Component)this).GetComponent<EventTrigger>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)this).gameObject.AddComponent<EventTrigger>();
			}
			val.triggers.Clear();
			Entry val2 = new Entry();
			val2.eventID = (EventTriggerType)5;
			((UnityEvent<BaseEventData>)(object)val2.callback).AddListener(UnityAction<BaseEventData>.op_Implicit((Action<BaseEventData>)OnDrag));
			val.triggers.Add(val2);
			targetPanel.anchoredPosition = Preferences.UiPosition.Value;
			ClampToBounds();
		}
	}
	internal static class Helpers
	{
		public static string ToNormal(this string text)
		{
			return text.ToLower().Trim().Replace(" ", "");
		}
	}
	internal static class Preferences
	{
		[CompilerGenerated]
		private sealed class <DemoCount>d__45 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <DemoCount>d__45(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					if (DemoCounting.EditedValue)
					{
						MelonPreferences_Entry<int> demoInt = DemoInt;
						int value = demoInt.Value;
						demoInt.Value = value + 1;
					}
					break;
				}
				<>2__current = (object)new WaitForSeconds(1.5f);
				<>1__state = 1;
				return true;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private const string CONFIG_FILE = "config.cfg";

		private const string USER_DATA = "UserData/UIFramework/";

		internal static MelonPreferences_Category CatUIFramework;

		internal static MelonPreferences_Entry<bool> EnableDebugMode;

		internal static MelonPreferences_Entry<bool> AutoHideOnSceneLoad;

		internal static MelonPreferences_Entry<bool> AutoHideOnInactivity;

		internal static MelonPreferences_Entry<bool> VrInputToggle;

		internal static MelonPreferences_Entry<bool> HijackModUI;

		internal static MelonPreferences_Entry<ToggleOptions> ToggleSettings;

		internal static MelonPreferences_Entry<int> InactivityTimeout;

		internal static MelonPreferences_Entry<Vector2> UiPosition;

		internal static MelonPreferences_Category Experimental;

		internal static MelonPreferences_Entry<Color> ExperimentalColor;

		internal static MelonPreferences_Entry<float> ExperimentalSlider;

		internal static MelonPreferences_Entry<int> ExperimentalIntSlider;

		internal static MelonPreferences_Entry<bool> TestBool;

		internal static MelonPreferences_Entry<string> TestString;

		internal static MelonPreferences_Entry<int> TestInt;

		internal static MelonPreferences_Entry<float> TestFloat;

		internal static MelonPreferences_Entry<double> TestDouble;

		internal static MelonPreferences_Entry<InputType> TestEnum;

		internal static MelonPreferences_Entry<List<int>> TestList;

		internal static MelonPreferences_Entry<List<string>> TestListString;

		internal static MelonPreferences_Entry<NonZeroBased> NonZeroEnum;

		internal static MelonPreferences_Entry<NonContiguous> NonContiguousEnum;

		internal static MelonPreferences_Category Demo;

		internal static MelonPreferences_Entry<int> DropdownTest;

		internal static MelonPreferences_Entry<int> DropdownSelection;

		internal static MelonPreferences_Entry<bool> ShowReactivity;

		internal static MelonPreferences_Entry<bool> DemoCounting;

		internal static MelonPreferences_Entry<bool> InhibitRefreshForCount;

		internal static MelonPreferences_Entry<int> DemoInt;

		internal static MelonPreferences_Entry<string> DemoString;

		internal static DefaultRefreshInhibitor InhibitRefresh = new DefaultRefreshInhibitor
		{
			InhibitRefreshOnValueChange = true
		};

		internal static MelonPreferences_Category TestEmptyDisplayName;

		internal static MelonPreferences_Entry<string> TestEmptyDisplayPref;

		internal static MelonPreferences_Category TestBooleans;

		internal static List<MelonPreferences_Entry<bool>> TestBoolList = new List<MelonPreferences_Entry<bool>>();

		private static List<DropdownItem> demoItems = new List<DropdownItem>
		{
			new DropdownItem("zero", 0),
			new DropdownItem("one", 1)
		};

		public static DynamicDropdownDescriptor demoDropdownDescriptor = new DynamicDropdownDescriptor();

		internal static void InitializePrefs()
		{
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			if (!Directory.Exists("UserData/UIFramework/"))
			{
				Directory.CreateDirectory("UserData/UIFramework/");
			}
			CatUIFramework = MelonPreferences.CreateCategory("UI", "UI Settings");
			CatUIFramework.SetFilePath(Path.Combine("UserData/UIFramework/", "config.cfg"));
			AutoHideOnSceneLoad = CatUIFramework.CreateEntry<bool>("AutoHideOnSceneLoad", true, "Auto Hide On Scene Load", "Hides the UI Automatically in between scenes.", false, false, (ValueValidator)null, (string)null);
			AutoHideOnInactivity = CatUIFramework.CreateEntry<bool>("AutohideOnInactivity", true, "Auto Hide on Inactivity", "Hide the UI if mouse and keyboard are inactive", false, false, (ValueValidator)null, (string)null);
			InactivityTimeout = CatUIFramework.CreateEntry<int>("InactivityTimeout", 30, "Inactivity Time Out (Seconds)", "Number of seconds of inactivity for UI to hide automatically", false, false, (ValueValidator)null, (string)null);
			VrInputToggle = CatUIFramework.CreateEntry<bool>("VrInputToggle", false, "Toggle with VR buttons", "Toggle UI window by pressing both trigger and primary (A/X) on both hands", true, false, (ValueValidator)null, (string)null);
			ToggleSettings = CatUIFramework.CreateEntry<ToggleOptions>("ToggleSettings", ToggleOptions.Keyboard, "Toggle Options", "Select the input method for toggling the UI.\nKeyboard: F9 \nVR: Press both trigger and primary (A/X) buttons on both hands\n<sup>*If you have ModUI, VR Input matches ModUI. UI Framework will be visible when ModUI is visible\n</sup>", false, false, (ValueValidator)null, (string)null);
			HijackModUI = CatUIFramework.CreateEntry<bool>("HijackModUI", false, "Force Hide ModButtonView UI", "If enabled, UI Framework will find the ModUI object and hide it whenever UI Framework is also hidden.\n<size=75%>*Might cause unintended effects. Next ModUI toggle will need to be done twice</size>", false, false, (ValueValidator)null, (string)null);
			EnableDebugMode = CatUIFramework.CreateEntry<bool>("EnableDebugMode", false, "Enable Debug Logs", "Enables or disables debug logs for UIFramework.", false, false, (ValueValidator)(object)new UserEditNotifier
			{
				OnUserEdit = UpdateCategoryVis
			});
			UiPosition = CatUIFramework.CreateEntry<Vector2>("UiPosition", new Vector2(970f, -128f), "UI Position", "The position of the UI on the screen represented", true, true, (ValueValidator)null, (string)null);
			Experimental = MelonPreferences.CreateCategory("UIFrameworkExperimental", "Experimental Settings", true, true);
			Experimental.SetFilePath(Path.Combine("UserData/UIFramework/", "config.cfg"));
			ExperimentalColor = Experimental.CreateEntry<Color>("ColorTest", new Color(50f, 238f, 165f, 255f), "Test color", "ColorTest", false, false, (ValueValidator)null, (string)null);
			UI.CreateButtonEntry(Experimental, "Test Buttton", "", "This is a test button entry that should not be treated as an actual preference and should not be saved to the config file.", TestButtonAsEntry);
			ExperimentalSlider = Experimental.CreateEntry<float>("SliderTest", 0.5f, "Test Slider", "This is a test slider with a range from 0 to 1", false, false, (ValueValidator)(object)new SliderDescriptor
			{
				Min = 0f,
				Max = 1f,
				DecimalPlaces = 3
			});
			ExperimentalIntSlider = Experimental.CreateEntry<int>("IntSliderTest", 50, "Test Int Slider", "This is a test int slider with a range from 0 to 100", false, false, (ValueValidator)(object)new SliderDescriptor
			{
				Min = 0f,
				Max = 100f
			});
			TestBool = Experimental.CreateEntry<bool>("TestBool", false, "Test Bool", "This is a test bool.", false, false, (ValueValidator)null, (string)null);
			TestString = Experimental.CreateEntry<string>("TestString", "Hello, World!", "Test String", "This is a test string.", false, false, (ValueValidator)null, (string)null);
			TestInt = Experimental.CreateEntry<int>("TestInt", 42, "Test Int", "This is a test int.", false, false, (ValueValidator)null, (string)null);
			TestFloat = Experimental.CreateEntry<float>("TestFloat", 3.14f, "Test Float", "This is a test float.", false, false, (ValueValidator)null, (string)null);
			TestDouble = Experimental.CreateEntry<double>("TestDouble", 3.14159, "Test Double", "This is a test double.", false, false, (ValueValidator)null, (string)null);
			TestEnum = Experimental.CreateEntry<InputType>("TestEnum", InputType.TextField, "Test Enum", "This is a test enum.", false, false, (ValueValidator)null, (string)null);
			NonZeroEnum = Experimental.CreateEntry<NonZeroBased>("Non-Zero", NonZeroBased.a, "Non-zero-based enum test", "This tests enums that don't start from zero", false, false, (ValueValidator)null, (string)null);
			NonContiguousEnum = Experimental.CreateEntry<NonContiguous>("Non-Cont", NonContiguous.z, "Non-Contiguous enum test", "This tests enums that have gaps in between the explicitlyi named values", false, false, (ValueValidator)null, (string)null);
			TestList = Experimental.CreateEntry<List<int>>("TestList", new List<int> { 1, 2, 3 }, "Test List", "This is a test list of integers.", true, false, (ValueValidator)null, (string)null);
			TestListString = Experimental.CreateEntry<List<string>>("TestStringList", new List<string> { "hello", "world", "hi" }, "this is a test list of strings", (string)null, false, false, (ValueValidator)null, (string)null);
			TestEmptyDisplayName = MelonPreferences.CreateCategory("EmptyDisplayName", "Empty Display Name Test", true, true);
			TestEmptyDisplayName.SetFilePath(Path.Combine("UserData/UIFramework/", "config.cfg"));
			TestEmptyDisplayPref = TestEmptyDisplayName.CreateEntry<string>("NoDisplayName", "Hello, World!", (string)null, "This is a test string.", false, false, (ValueValidator)null, (string)null);
			CatUIFramework.SaveToFile(true);
			Experimental.SaveToFile(true);
			TestBooleans = MelonPreferences.CreateCategory("TestBooleans", "Test Booleans", true, true);
			TestBooleans.SetFilePath(Path.Combine("UserData/UIFramework/", "config.cfg"));
			for (int i = 0; i < 10; i++)
			{
				TestBoolList.Add(TestBooleans.CreateEntry<bool>("TestBool" + i, false, "Test Bool " + i, (string)null, false, false, (ValueValidator)null, (string)null));
			}
			Demo = MelonPreferences.CreateCategory("UIF_Demo", "Demos");
			Demo.SetFilePath(Path.Combine("UserData/UIFramework/", "config.cfg"));
			UI.CreateButtonEntry(Demo, "Add Entry", "Dropdown Test", "this should add another entry to the dropdown demo", AddDropdownDemo);
			DropdownTest = Demo.CreateEntry<int>("DropdownDemo", -1, "Dropdown Demo", "Dynamic dropdown test. Add items by clicking the button", false, false, (ValueValidator)(object)demoDropdownDescriptor.WithDropdownItemList(demoItems));
			DropdownSelection = Demo.CreateEntry<int>("SelectedDropdownItem", DropdownTest.Value, "Selected Item", "The item selected in the dropdown demo", false, false, (ValueValidator)null, (string)null);
			ShowReactivity = Demo.CreateEntry<bool>("Entry_Reactivity", false, "Show hidden Entry", "This is a demo preference to hide the reactivity demo button in the demo category.", false, false, (ValueValidator)(object)new UserEditNotifier
			{
				OnUserEdit = HideReaction
			});
			DemoCounting = Demo.CreateEntry<bool>("EnableCount", false, "Enable counting demo", "This is a demo for how the UI can update by a change of values in the background", false, false, (ValueValidator)(object)new UserEditNotifier
			{
				OnUserEdit = delegate(object newVal)
				{
					DemoCounting.EditedValue = (bool)newVal;
					UI.RequestRefresh((MelonBase)(object)Core.Instance);
				}
			});
			InhibitRefreshForCount = Demo.CreateEntry<bool>("InhibitDemoCount", true, "Inhibit Count Refresh", "Inhibit refreshing the UI when the demo int counts up", false, false, (ValueValidator)(object)new UserEditNotifier
			{
				OnUserEdit = UpdateInhibitDemo
			});
			DemoInt = Demo.CreateEntry<int>("DemoInt", 0, "Demo Int", "This is a demo int Preference", false, false, (ValueValidator)(object)InhibitRefresh);
			DemoString = Demo.CreateEntry<string>("DemoString", "Hello, World!", "Demo String", "This is a demo string preference. This should show the name of the current scene", true, false, (ValueValidator)null, (string)null);
			DemoInt.Value = 0;
			((MelonPreferences_Entry)DemoString).IsHidden = !ShowReactivity.Value;
			UpdateCategoryVis(EnableDebugMode.Value);
			InhibitRefreshForCount.Value = true;
			DemoCounting.Value = false;
			MelonCoroutines.Start(DemoCount());
			((MelonEventBase<LemonAction<int, int>>)(object)DropdownTest.OnEntryValueChanged).Subscribe((LemonAction<int, int>)ItemSelectionChanged, 0, false);
		}

		internal static void AddDropdownDemo()
		{
			int count = demoDropdownDescriptor.GetDropdownItems().Count;
			string text = new string('+', count);
			demoDropdownDescriptor.AddDropdownItem(new DropdownItem(" - " + text, count));
		}

		internal static void ItemSelectionChanged(int old, int neew)
		{
			Debug.Log($"Selected Item: {neew}");
			DropdownSelection.Value = neew;
		}

		internal static void TestButtonAsEntry()
		{
			Debug.Log("This is a test for submitting a button as a preference entry. \nThis should not be treated as an actual preference and should not be saved to the config file.");
		}

		internal static void HideReaction(object newValue)
		{
			Debug.Log($"HideReact: {newValue}");
			((MelonPreferences_Entry)DemoInt).IsHidden = !(bool)newValue;
			ShowReactivity.Value = (bool)newValue;
		}

		[IteratorStateMachine(typeof(<DemoCount>d__45))]
		internal static IEnumerator DemoCount()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DemoCount>d__45(0);
		}

		internal static void UpdateInhibitDemo(object newValue)
		{
			InhibitRefresh.InhibitRefreshOnValueChange = (bool)newValue;
		}

		internal static void UpdateCategoryVis(object newValue)
		{
			Debug.Log($"UpdateCategoryVis newValue = {newValue}");
			Debug.Log($"UpdateCategoryVis Demo.IsHidden = {Demo.IsHidden}");
			Experimental.IsHidden = !(bool)newValue;
			TestBooleans.IsHidden = !(bool)newValue;
			TestEmptyDisplayName.IsHidden = !(bool)newValue;
		}
	}
	internal enum NonZeroBased
	{
		a = 3,
		b,
		c,
		d
	}
	internal enum NonContiguous
	{
		z = 3,
		y = 5,
		x = 10,
		w = 13
	}
	internal enum ToggleOptions
	{
		[Display(Name = "Keyboard Only")]
		Keyboard,
		[Display(Name = "VR Only")]
		VR,
		[Display(Name = "VR And Keyboard")]
		KeyAndVR
	}
	public class CustomCategoryTab
	{
		public readonly List<CustomUIEntry> Entries = new List<CustomUIEntry>();

		internal CategoryModelBase CategoryModel { get; set; }

		public string Identifier { get; internal set; }

		public string DisplayName { get; set; }

		public bool IsHidden { get; set; }

		public bool IsInlined { get; set; }

		internal CustomCategoryTab(string identifier, string display_name, bool is_hidden = false, bool is_inlined = false)
		{
			Identifier = identifier;
			DisplayName = display_name;
			IsHidden = is_hidden;
			IsInlined = is_inlined;
		}

		public CustomUIEntry CreateEntry<T>(string identifier, T default_value, string display_name, bool is_hidden)
		{
			return CreateEntry(identifier, default_value, display_name, null, is_hidden);
		}

		public CustomUIEntry<T> CreateEntry<T>(string identifier, T default_value, string display_name = null, string description = null, bool is_hidden = false, ValueValidator validator = null)
		{
			if (string.IsNullOrEmpty(identifier))
			{
				throw new Exception("identifier is null or empty when calling CreateEntry");
			}
			if (display_name == null)
			{
				display_name = identifier;
			}
			CustomUIEntry<T> entry = GetEntry<T>(identifier);
			if (entry != null)
			{
				throw new Exception("Calling CreateEntry for " + display_name + " when it Already Exists");
			}
			if (validator != null && !validator.IsValid((object)default_value))
			{
				throw new ArgumentException($"Default value '{default_value}' is invalid according to the provided ValueValidator!");
			}
			entry = new CustomUIEntry<T>
			{
				Identifier = identifier,
				DisplayName = display_name,
				Description = description,
				IsHidden = is_hidden,
				Category = this,
				DefaultValue = default_value,
				Value = default_value,
				Validator = validator
			};
			Entries.Add(entry);
			return entry;
		}

		public CustomUIEntry GetEntry(string identifier)
		{
			if (string.IsNullOrEmpty(identifier))
			{
				throw new Exception("identifier cannot be null or empty when calling GetEntry");
			}
			if (Entries.Count <= 0)
			{
				return null;
			}
			return Entries.Find((CustomUIEntry x) => x.Identifier.Equals(identifier));
		}

		public CustomUIEntry<T> GetEntry<T>(string identifier)
		{
			return (CustomUIEntry<T>)GetEntry(identifier);
		}

		public bool HasEntry(string identifier)
		{
			return GetEntry(identifier) != null;
		}
	}
	public abstract class CustomUIEntry
	{
		public Action<object, object> OnEntryValueChangedUntyped;

		public string Identifier { get; internal set; }

		public string DisplayName { get; set; }

		public string Description { get; set; }

		public string Comment { get; set; }

		public bool IsHidden { get; set; }

		public bool DontSaveDefault { get; set; }

		public CustomCategoryTab Category { get; internal set; }

		public abstract object BoxedValue { get; set; }

		public abstract object BoxedEditedValue { get; set; }

		public ValueValidator Validator { get; internal set; }

		public abstract Type GetReflectedType();

		public abstract void ResetToDefault();

		public abstract string GetEditedValueAsString();

		public abstract string GetDefaultValueAsString();

		public abstract string GetValueAsString();

		public abstract TomlValue Save();

		protected void FireUntypedValueChanged(object old, object neew)
		{
			OnEntryValueChangedUntyped(old, neew);
		}
	}
	public class CustomUIEntry<T> : CustomUIEntry
	{
		private T myValue;

		public Action<T, T> OnEntryValueChanged;

		public InputType InputUIType;

		public T Value
		{
			get
			{
				return myValue;
			}
			set
			{
				if (base.Validator != null)
				{
					value = (T)base.Validator.EnsureValid((object)value);
				}
				if ((myValue != null || value != null) && (myValue == null || !myValue.Equals(value)))
				{
					T val = myValue;
					myValue = value;
					EditedValue = myValue;
					OnEntryValueChanged?.Invoke(val, value);
					FireUntypedValueChanged(val, value);
				}
			}
		}

		public T EditedValue { get; set; }

		public T DefaultValue { get; set; }

		public override object BoxedValue
		{
			get
			{
				return myValue;
			}
			set
			{
				Value = (T)value;
			}
		}

		public override object BoxedEditedValue
		{
			get
			{
				return EditedValue;
			}
			set
			{
				EditedValue = (T)value;
			}
		}

		public override void ResetToDefault()
		{
			Value = DefaultValue;
		}

		public override Type GetReflectedType()
		{
			return typeof(T);
		}

		public override string GetEditedValueAsString()
		{
			T editedValue = EditedValue;
			return (editedValue != null) ? editedValue.ToString() : null;
		}

		public override string GetDefaultValueAsString()
		{
			T defaultValue = DefaultValue;
			return (defaultValue != null) ? defaultValue.ToString() : null;
		}

		public override string GetValueAsString()
		{
			T value = Value;
			return (value != null) ? value.ToString() : null;
		}

		public override TomlValue Save()
		{
			Value = EditedValue;
			TomlValue val = TomletMain.ValueFrom<T>(Value, (TomlSerializerOptions)null);
			val.Comments.PrecedingComment = base.Description;
			val.Comments.InlineComment = base.Comment;
			if (!string.IsNullOrEmpty(val.Comments.InlineComment))
			{
				val.Comments.InlineComment.Replace('\n', ' ');
			}
			return val;
		}
	}
}
namespace UIFramework.ValidatorExtensions
{
	public class SliderDescriptor : UIFramework.UiExtensions.SliderDescriptor
	{
	}
}
namespace UIFramework.UiExtensions
{
	public class DefaultValidator : ValueValidator, IUiExtension
	{
		public override bool IsValid(object value)
		{
			return true;
		}

		public override object EnsureValid(object value)
		{
			return value;
		}
	}
	public class TextInputBehaviorDescriptor : DefaultValidator, ITextInputBehaviorDescriptor, IUiExtension
	{
		public ContentType ContentType { get; set; } = (ContentType)0;


		public int CharacterLimit { get; set; } = 0;


		public bool IsReadOnly { get; set; } = false;

	}
	public class TextInputAppearanceDescriptor : DefaultValidator, ITextInputAppearanceDescriptor, IUiExtension
	{
		public int FontSize { get; set; } = 18;


		public bool IsAutoSizing { get; set; } = false;


		public int AutoSizeMin { get; set; } = 14;


		public int AutoSizeMax { get; set; } = 30;


		public FontStyles FontStyle { get; set; } = (FontStyles)0;


		public bool IsRichText { get; set; } = true;

	}
	public class DynamicDropdownDescriptor : DefaultValidator, IDynamicDropdownDescriptor, IUiExtension
	{
		private List<DropdownItem> _dropdownItems = new List<DropdownItem>();

		public Action OnDropdownItemsUpdated { get; set; }

		public List<DropdownItem> GetDropdownItems()
		{
			return _dropdownItems;
		}

		public void SetDropdownItems(List<DropdownItem> items)
		{
			_dropdownItems = items;
			OnDropdownItemsUpdated?.Invoke();
		}

		public void AddDropdownItem(DropdownItem item)
		{
			_dropdownItems.Add(item);
			OnDropdownItemsUpdated?.Invoke();
		}

		public void RemoveDropdownItem(DropdownItem item)
		{
			_dropdownItems?.Remove(item);
			OnDropdownItemsUpdated?.Invoke();
		}

		public DynamicDropdownDescriptor WithDropdownItemList(List<DropdownItem> dropdownItemList)
		{
			_dropdownItems = dropdownItemList;
			return this;
		}

		public DynamicDropdownDescriptor(List<DropdownItem> items)
		{
			_dropdownItems = items;
		}

		public DynamicDropdownDescriptor()
		{
			_dropdownItems = new List<DropdownItem>();
		}
	}
	public class SliderDescriptor : DefaultValidator, ISliderDescriptor, IUiExtension, IUserEditedNotifier
	{
		public float Min { get; set; } = 0f;


		public float Max { get; set; } = 1f;


		public int DecimalPlaces { get; set; } = 5;


		public Action<object> OnUserEdit { get; set; }
	}
	public class NumericUpDownDescriptor : DefaultValidator, INumericUpDownDescriptor, IUiExtension
	{
		public float Increments { get; set; }
	}
	public class UserEditNotifier : DefaultValidator, IUserEditedNotifier, IUiExtension
	{
		public Action<object> OnUserEdit { get; set; }
	}
	public class DefaultRefreshInhibitor : DefaultValidator, IRefreshInhibitor, IUiExtension
	{
		public bool InhibitRefreshOnEdit { get; set; } = false;


		public bool InhibitRefreshOnValueChange { get; set; } = false;

	}
	internal class ButtonAsEntry : DefaultValidator, IButtonDescriptor, IUiExtension
	{
		public string ButtonText { get; set; } = "";


		public string DisplayName { get; set; } = "";


		public string Description { get; set; } = "";


		public Action Handler { get; set; }

		public override bool IsValid(object value)
		{
			return true;
		}

		public override object EnsureValid(object value)
		{
			return false;
		}
	}
	public interface IUiExtension
	{
	}
	public interface ITextInputBehaviorDescriptor : IUiExtension
	{
		ContentType ContentType { get; set; }

		int CharacterLimit { get; set; }

		bool IsReadOnly { get; set; }
	}
	public interface ITextInputAppearanceDescriptor : IUiExtension
	{
		int FontSize { get; set; }

		bool IsAutoSizing { get; set; }

		int AutoSizeMin { get; set; }

		int AutoSizeMax { get; set; }

		FontStyles FontStyle { get; set; }

		bool IsRichText { get; set; }
	}
	public interface IDynamicDropdownDescriptor : IUiExtension
	{
		Action OnDropdownItemsUpdated { get; set; }

		List<DropdownItem> GetDropdownItems();

		void SetDropdownItems(List<DropdownItem> items);
	}
	public class DropdownItem
	{
		public string DisplayName { get; set; }

		public object Value { get; set; }

		public DropdownItem(string displayName, object value)
		{
			DisplayName = displayName;
			Value = value;
		}

		public DropdownItem(string value)
		{
			DisplayName = value;
			Value = value;
		}
	}
	public interface INumericUpDownDescriptor : IUiExtension
	{
		float Increments { get; set; }
	}
	public interface ISliderDescriptor : IUiExtension
	{
		float Min { get; set; }

		float Max { get; set; }

		int DecimalPlaces { get; set; }
	}
	public interface IUserEditedNotifier : IUiExtension
	{
		Action<object> OnUserEdit { get; set; }
	}
	public interface IRefreshInhibitor : IUiExtension
	{
		bool InhibitRefreshOnEdit { get; set; }

		bool InhibitRefreshOnValueChange { get; set; }
	}
	public interface ICustomUIProvider : IUiExtension
	{
		GameObject WidgetPrefab { get; set; }
	}
	public interface IButtonDescriptor : IUiExtension
	{
		string ButtonText { get; set; }

		string DisplayName { get; set; }

		string Description { get; set; }

		Action Handler { get; set; }
	}
}
namespace UIFramework.Models
{
	public abstract class ModelBase : IModelable
	{
		public abstract string Identifier { get; }

		public abstract string DisplayName { get; }

		public virtual bool IsHidden { get; set; } = false;


		public abstract GameObject GetNewUIInstance();

		public virtual void SaveAction()
		{
		}

		public virtual void DiscardAction()
		{
		}
	}
	public abstract class SelectableModelBase : ModelBase, IHoldSubmodels, IModelable
	{
		public virtual List<IModelable> SubModels { get; set; } = new List<IModelable>();


		public IModelable GetSubmodel(string name)
		{
			return SubModels.FirstOrDefault((IModelable m) => m.Identifier == name);
		}

		public virtual void AddSubmodel(params IModelable[] submodel)
		{
			SubModels.AddRange(submodel);
		}

		public override void DiscardAction()
		{
		}

		public override void SaveAction()
		{
		}
	}
	public abstract class ModModelBase : SelectableModelBase
	{
		public string _displayName;

		public List<CategoryModelBase> Categories => SubModels.Cast<CategoryModelBase>().ToList();

		public abstract MelonBase Instance { get; set; }

		public override string Identifier => Instance.Info.Name;

		public override string DisplayName => _displayName;

		public virtual string Version => Instance.Info.Version;

		public event Action OnModSaved;

		public override GameObject GetNewUIInstance()
		{
			return Object.Instantiate<GameObject>(Prefabs.ModTab);
		}

		public virtual CategoryModelBase GetModelCategory(string identifier)
		{
			return (CategoryModelBase)GetSubmodel(identifier);
		}

		public virtual void AddModelCategory(params CategoryModelBase[] categoryModel)
		{
			AddSubmodel(categoryModel.Cast<IModelable>().ToArray());
		}

		public override void SaveAction()
		{
			foreach (IModelable subModel in SubModels)
			{
				try
				{
					subModel.SaveAction();
				}
				catch (Exception ex)
				{
					Debug.Log($"Error saving category {subModel.Identifier} for mod {Instance.Info.Name}: {ex.Message}", debugOnly: false, 2);
				}
			}
			this.OnModSaved?.Invoke();
		}

		public override void DiscardAction()
		{
			foreach (IModelable subModel in SubModels)
			{
				try
				{
					subModel.DiscardAction();
				}
				catch (Exception ex)
				{
					Debug.Log($"Error loading category {subModel.Identifier} for mod {Instance.Info.Name}: {ex.Message}", debugOnly: false, 2);
				}
			}
		}

		public void RequestUpdateUI()
		{
			UI.RequestRefresh(this);
		}
	}
	public abstract class CategoryModelBase : SelectableModelBase
	{
		public ModModelBase ParentMod { get; set; }

		public override bool IsHidden { get; set; }

		protected CategoryModelBase(ModModelBase parentMod)
		{
			ParentMod = parentMod;
		}

		public override GameObject GetNewUIInstance()
		{
			return Object.Instantiate<GameObject>(Prefabs.CatTab);
		}

		public virtual void AddEntry(params IEntry[] entryModel)
		{
			AddSubmodel(entryModel.Cast<IModelable>().ToArray());
		}
	}
	public abstract class EntryModelBase : ModelBase, IEntry
	{
		public CategoryModelBase ParentCategory { get; set; }

		public abstract string Description { get; }

		public override bool IsHidden { get; set; }

		public virtual Action<PrefEntryAdapter> OnUICreated { get; set; }

		public virtual EntryState SaveState { get; set; }

		public EntryModelBase(CategoryModelBase parentCategory)
		{
			ParentCategory = parentCategory;
		}

		public override void DiscardAction()
		{
		}
	}
	public abstract class DataEntryModelBase : EntryModelBase
	{
		protected GameObject _uiPrefabSource;

		public abstract object ModelBoxedValue { get; protected set; }

		public abstract IUiExtension UiExtension { get; }

		public virtual IUserEditedNotifier EditNotifier => UiExtension as IUserEditedNotifier;

		public virtual IRefreshInhibitor RefreshInhibitor => UiExtension as IRefreshInhibitor;

		protected DataEntryModelBase(CategoryModelBase parentCategory)
			: base(parentCategory)
		{
		}

		public virtual bool TryApply(object value)
		{
			bool flag = false;
			try
			{
				SetDataValue(value);
				return true;
			}
			catch (Exception ex)
			{
				Debug.Log("ModelDataEntry TryApply: " + ex.Message + "\n" + ex.StackTrace, debugOnly: false, 2);
				return false;
			}
		}

		protected virtual void OnDataValueChanged(object newValue)
		{
			IRefreshInhibitor refreshInhibitor = RefreshInhibitor;
			if (refreshInhibitor == null || !refreshInhibitor.InhibitRefreshOnValueChange)
			{
				UI.RequestRefresh(base.ParentCategory.ParentMod);
			}
			else
			{
				Debug.Log("UI Refresh inhibited when entry value changes");
			}
		}

		protected void SetDataValue(object newValue)
		{
			Debug.Log($"New Value Applied {newValue}");
			ModelBoxedValue = newValue;
			EditNotifier?.OnUserEdit?.Invoke(ModelBoxedValue);
			IRefreshInhibitor refreshInhibitor = RefreshInhibitor;
			if (refreshInhibitor == null || !refreshInhibitor.InhibitRefreshOnEdit)
			{
				base.ParentCategory.ParentMod.RequestUpdateUI();
			}
			else
			{
				Debug.Log("UI Refresh inhibited when user edits values");
			}
		}

		public override GameObject GetNewUIInstance()
		{
			if (UiExtension is ICustomUIProvider customUIProvider && customUIProvider?.WidgetPrefab != null)
			{
				return Object.Instantiate<GameObject>(customUIProvider.WidgetPrefab);
			}
			if (UiExtension is DynamicDropdownDescriptor)
			{
				GameObject prefab = UI.GetPrefab(InputType.Dropdown);
				prefab.AddComponent<DynamicDopdownAdapter>();
				return prefab;
			}
			if (UiExtension is ISliderDescriptor)
			{
				return UI.GetPrefab(InputType.Slider);
			}
			if (UiExtension is IButtonDescriptor)
			{
				GameObject prefab2 = UI.GetPrefab(InputType.Button);
				prefab2.AddComponent<ButtonEntryAdapter>();
				return prefab2;
			}
			object modelBoxedValue = ModelBoxedValue;
			object obj = modelBoxedValue;
			if (!(obj is bool))
			{
				if (!(obj is string))
				{
					if (!(obj is Enum))
					{
						if (!(obj is sbyte) && !(obj is byte) && !(obj is short) && !(obj is ushort) && !(obj is int) && !(obj is uint) && !(obj is long) && !(obj is ulong))
						{
							if (obj is float || obj is double || obj is decimal)
							{
								return UI.GetPrefab(InputType.NumericFloat);
							}
							return UI.GetPrefab(InputType.TextField);
						}
						return UI.GetPrefab(InputType.NumericInt);
					}
					GameObject prefab3 = UI.GetPrefab(InputType.Dropdown);
					prefab3.AddComponent<EnumDropdownAdapter>();
					return prefab3;
				}
				return UI.GetPrefab(InputType.TextField);
			}
			return UI.GetPrefab(InputType.Toggle);
		}
	}
	public class EmptyCategory : CategoryModelBase
	{
		private string _displayName;

		private string _identifier;

		public override string DisplayName => _displayName;

		public override string Identifier => _identifier;

		public override bool IsHidden { get; set; } = false;


		public EmptyCategory(string identifier, string displayName, ModModelBase parentMod = null)
			: base(parentMod)
		{
			_identifier = identifier;
			_displayName = displayName;
		}

		public EmptyCategory(string identifier, ModModelBase parentMod = null)
			: base(parentMod)
		{
			_identifier = identifier;
			_displayName = identifier;
		}
	}
	public class ButtonEntry : EntryModelBase
	{
		private string _name;

		private string _description;

		private string _displayName;

		public Action<ButtonModelAdapter> OnClick;

		public override string Identifier => _name;

		public override string Description => _description;

		public override string DisplayName => _displayName;

		public override bool IsHidden { get; set; }

		public object BoxedValue { get; set; }

		public override void SaveAction()
		{
		}

		public ButtonEntry(Action<ButtonModelAdapter> onClick, string name, string description = "", string displayName = "", CategoryModelBase parentCategory = null)
			: base(parentCategory)
		{
			_name = name;
			_description = description;
			_displayName = ((displayName == "") ? name : displayName);
			OnClick = (Action<ButtonModelAdapter>)Delegate.Combine(OnClick, onClick);
		}

		public override GameObject GetNewUIInstance()
		{
			GameObject val = Object.Instantiate<GameObject>(UI.GetPrefab(InputType.Button));
			ButtonModelAdapter component = val.GetComponent<ButtonModelAdapter>();
			return val;
		}
	}
	public interface IModelable
	{
		string Identifier { get; }

		string DisplayName { get; }

		bool IsHidden { get; set; }

		GameObject GetNewUIInstance();

		void SaveAction();

		void DiscardAction();
	}
	public interface IHoldSubmodels : IModelable
	{
		List<IModelable> SubModels { get; set; }

		IModelable GetSubmodel(string identifier);

		void AddSubmodel(params IModelable[] model);
	}
	public interface IEntry
	{
		string Identifier { get; }

		string Description { get; }

		string DisplayName { get; }

		Action<PrefEntryAdapter> OnUICreated { get; set; }

		void SaveAction();

		void DiscardAction();
	}
	public interface IStorable
	{
		object BoxedValue { get; set; }

		bool TryApply(object value)
		{
			bool flag = false;
			try
			{
				BoxedValue = value;
				return true;
			}
			catch (Exception ex)
			{
				Debug.Log("MelonEntryModel TryApply: " + ex.Message, debugOnly: false, 2);
				return false;
			}
		}
	}
	public class RootModel : IHoldSubmodels, IModelable
	{
		private string _name = string.Empty;

		public virtual List<IModelable> SubModels { get; set; } = new List<IModelable>();


		public string Identifier => _name;

		public string DisplayName => _name;

		public bool IsHidden { get; set; } = false;


		public void SetName(string name)
		{
			_name = name;
		}

		public void AddSubmodel(params IModelable[] mod)
		{
			SubModels.AddRange(mod);
		}

		public IModelable GetSubmodel(string name)
		{
			return SubModels.FirstOrDefault((IModelable m) => m.Identifier == name);
		}

		public ModModelBase GetModModel(string identifier)
		{
			return (ModModelBase)GetSubmodel(identifier);
		}

		public GameObject GetNewUIInstance()
		{
			return null;
		}

		public void SaveAction()
		{
		}

		public void DiscardAction()
		{
		}
	}
	public class MelonModel : ModModelBase
	{
		public override MelonBase Instance { get; set; }

		public MelonModel(MelonBase instance, List<MelonPreferences_Category> catList)
		{
			Instance = instance;
			try
			{
				Type type = ((object)instance).GetType();
				Assembly assembly = type.Assembly;
				_displayName = assembly.GetCustomAttribute<UIInfoAttribute>()?.DisplayName ?? Identifier;
			}
			catch (Exception)
			{
			}
			foreach (MelonPreferences_Category cat in catList)
			{
				SubModels.Add(new MelonCategoryModel(cat, this));
			}
		}

		public MelonModel(MelonBase instance)
		{
			Instance = instance;
		}
	}
	public class MelonCategoryModel : CategoryModelBase
	{
		public MelonPreferences_Category PrefCat;

		public override bool IsHidden
		{
			get
			{
				return PrefCat.IsHidden;
			}
			set
			{
				PrefCat.IsHidden = value;
			}
		}

		public override string Identifier => PrefCat.Identifier;

		public override string DisplayName => (PrefCat.DisplayName.Trim() == "") ? PrefCat.Identifier : PrefCat.DisplayName;

		public MelonCategoryModel(MelonPreferences_Category cat, ModModelBase parentMod)
			: base(parentMod)
		{
			PrefCat = cat;
			foreach (MelonPreferences_Entry entry in PrefCat.Entries)
			{
				SubModels.Add(new MelonEntryModel(entry, this));
			}
		}

		public override void SaveAction()
		{
			PrefCat.SaveToFile(false);
		}

		public override void DiscardAction()
		{
			PrefCat.LoadFromFile(false);
			foreach (EntryModelBase subModel in SubModels)
			{
				subModel.DiscardAction();
			}
		}
	}
	public class MelonEntryModel : DataEntryModelBase, IModelable
	{
		public MelonPreferences_Entry PrefEntry { get; set; }

		public override bool IsHidden
		{
			get
			{
				return PrefEntry.IsHidden;
			}
			set
			{
				PrefEntry.IsHidden = value;
			}
		}

		public override string Identifier => PrefEntry.Identifier;

		public override string DisplayName => PrefEntry.DisplayName;

		public override string Description => PrefEntry.Description;

		public ValueValidator MelonValidator => PrefEntry.Validator;

		public override IUiExtension UiExtension => MelonValidator as IUiExtension;

		public override object ModelBoxedValue
		{
			get
			{
				return PrefEntry.BoxedEditedValue;
			}
			protected set
			{
				PrefEntry.BoxedEditedValue = value;
			}
		}

		public virtual object SavedValue { get; set; }

		public MelonEntryModel(MelonPreferences_Entry prefEntry, CategoryModelBase parentCategory)
			: base(parentCategory)
		{
			PrefEntry = prefEntry;
			SavedValue = prefEntry.BoxedValue;
			((MelonEventBase<LemonAction<object, object>>)(object)PrefEntry.OnEntryValueChangedUntyped).Subscribe((LemonAction<object, object>)OnValueChanged, 0, false);
		}

		protected void OnValueChanged(object oldVal, object newVal)
		{
			OnDataValueChanged(newVal);
		}

		public override void SaveAction()
		{
			SavedValue = ModelBoxedValue;
		}

		public override void DiscardAction()
		{
			PrefEntry.BoxedEditedValue = PrefEntry.BoxedValue;
		}
	}
}
namespace UIFramework.Adapters
{
	[RegisterTypeInIl2Cpp]
	public abstract class PrefEntryAdapter : SubModelAdapter, IChildable
	{
		public virtual string DescriptionText
		{
			get
			{
				return ((TMP_Text)((Component)((Component)this).gameObject.transform.Find("Description")).gameObject.GetComponent<TextMeshProUGUI>()).text;
			}
			set
			{
				((TMP_Text)((Component)((Component)this).gameObject.transform.Find("Description")).gameObject.GetComponent<TextMeshProUGUI>()).text = value;
			}
		}

		public virtual string DisplayName
		{
			get
			{
				return ((TMP_Text)((Component)((Component)this).gameObject.gameObject.transform.Find("Data/Label")).gameObject.GetComponent<TextMeshProUGUI>()).text;
			}
			set
			{
				((TMP_Text)((Component)((Component)this).gameObject.gameObject.transform.Find("Data/Label")).gameObject.GetComponent<TextMeshProUGUI>()).text = value;
			}
		}

		public virtual EntryState EntryStatus { get; set; }

		public IEntry EntryModel => (IEntry)_internalModel;

		public virtual void SaveAction()
		{
		}

		public override void ModelSet()
		{
			SetData();
			DescriptionText = EntryModel.Description;
			DisplayName = EntryModel.DisplayName;
		}

		public virtual void SetData()
		{
		}

		public string ToTomlString(object input)
		{
			return TomletMain.ValueFrom<object>(input, (TomlSerializerOptions)null).SerializedValue;
		}

		public object FromTomlString(string input, Type targetType)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			string text = "temp = " + input.Trim();
			TomlParser val = new TomlParser();
			TomlDocument val2 = val.Parse(text);
			TomlValue value = ((TomlTable)val2).GetValue("temp");
			return TomletMain.To(targetType, value, (TomlSerializerOptions)null);
		}
	}
	[RegisterTypeInIl2Cpp]
	public abstract class DataEntryAdapter : PrefEntryAdapter
	{
		protected virtual DataEntryModelBase _prefModel => (DataEntryModelBase)base.EntryModel;

		public virtual bool ValidationCheck()
		{
			return true;
		}

		public virtual void EditCheck()
		{
		}

		public override void SaveAction()
		{
			ApplyValueToPref();
			base.SaveAction();
		}

		public virtual void ApplyValueToPref()
		{
		}
	}
	[RegisterTypeInIl2Cpp]
	public class TextEntryAdapter : DataEntryAdapter
	{
		public TMP_InputField textField => ((Component)((Component)this).gameObject.transform.Find("Data/TextControl")).gameObject.GetComponent<TMP_InputField>();

		public string PlaceHolderText
		{
			set
			{
				((TMP_Text)((Component)((Component)this).gameObject.transform.Find("Data/TextControl/Text Area/Placeholder")).gameObject.GetComponent<TextMeshProUGUI>()).text = value;
			}
		}

		public override void SetData()
		{
			if (_prefModel.ModelBoxedValue.GetType() == typeof(string))
			{
				textField.text = (string)_prefModel.ModelBoxedValue;
				return;
			}
			try
			{
				textField.text = ToTomlString(_prefModel.ModelBoxedValue);
			}
			catch (Exception ex)
			{
				Debug.Log(ex.Message + "\n" + ex.StackTrace);
			}
		}

		public override void ApplyValueToPref()
		{
			if (_prefModel.ModelBoxedValue.GetType() == typeof(string))
			{
				_prefModel.TryApply(textField.text);
				return;
			}
			try
			{
				if (textField.text.Trim() != "")
				{
					_prefModel.TryApply(FromTomlString(textField.text, _prefModel.ModelBoxedValue.GetType()));
				}
			}
			catch (Exception ex)
			{
				Debug.Log(ex.Message, debugOnly: false, 2);
			}
		}

		public override void EditCheck()
		{
		}

		public virtual void EditStart(string s)
		{
			textField.textComponent.fontStyle = (FontStyles)0;
		}

		public virtual void EditEnd(string s)
		{
			textField.textComponent.fontStyle = (FontStyles)2;
			ApplyValueToPref();
		}

		protected virtual void Start()
		{
			((UnityEvent<string>)(object)textField.onSelect).AddListener(UnityAction<string>.op_Implicit((Action<string>)EditStart));
			((UnityEvent<string>)(object)textField.onDeselect).AddListener(UnityAction<string>.op_Implicit((Action<string>)EditEnd));
		}
	}
	[RegisterTypeInIl2Cpp]
	public class NumSliderAdapter : TextEntryAdapter
	{
		protected Slider Slider => ((Component)((Component)this).gameObject.transform.Find("Data/SliderControl")).gameObject.GetComponent<Slider>();

		protected TMP_InputField _textField => ((Component)((Component)this).gameObject.transform.Find("Data/TextControl")).gameObject.GetComponent<TMP_InputField>();

		protected virtual ISliderDescriptor SliderSettings => _prefModel.UiExtension as ISliderDescriptor;

		public override void SetData()
		{
			((UnityEvent<string>)(object)_textField.onEndEdit).AddListener(UnityAction<string>.op_Implicit((Action<string>)EditEnd));
			((UnityEvent<string>)(object)_textField.onSelect).AddListener(UnityAction<string>.op_Implicit((Action<string>)EditStart));
			Slider.minValue = SliderSettings?.Min ?? 0f;
			Slider.maxValue = SliderSettings?.Max ?? 100f;
			Slider.value = Convert.ToSingle(_prefModel.ModelBoxedValue);
			((UnityEvent<float>)(object)Slider.onValueChanged).AddListener(UnityAction<float>.op_Implicit((Action<float>)OnValueChanged));
			AddPointerUp();
			object modelBoxedValue = _prefModel.ModelBoxedValue;
			if ((modelBoxedValue is int || modelBoxedValue is byte || modelBoxedValue is short || modelBoxedValue is long || modelBoxedValue is sbyte || modelBoxedValue is ushort || modelBoxedValue is uint || modelBoxedValue is ulong) ? true : false)
			{
				Slider.wholeNumbers = true;
				_textField.contentType = (ContentType)2;
				_textField.text = Slider.value.ToString("F0");
			}
			else
			{
				Slider.wholeNumbers = false;
				_textField.contentType = (ContentType)3;
				_textField.text = Slider.value.ToString("F" + SliderSettings?.DecimalPlaces);
			}
		}

		public void OnValueChanged(float newValue)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Invalid comparison between Unknown and I4
			_textField.text = newValue.ToString(((int)_textField.contentType == 2) ? "F0" : ("F" + SliderSettings?.DecimalPlaces));
		}

		public override void ApplyValueToPref()
		{
			_prefModel.TryApply(Convert.ChangeType(Slider.value, _prefModel.ModelBoxedValue.GetType()));
		}

		public new virtual void EditStart(string s)
		{
			_textField.textComponent.fontStyle = (FontStyles)0;
		}

		public new virtual void EditEnd(string s)
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Invalid comparison between Unknown and I4
			_textField.textComponent.fontStyle = (FontStyles)2;
			if (float.TryParse(s, out var result))
			{
				if (SliderSettings != null)
				{
					result = Mathf.Clamp(result, SliderSettings.Min, SliderSettings.Max);
				}
				Slider.value = result;
				ApplyValueToPref();
			}
			else
			{
				Debug.Log("Invalid input for slider: " + s, debugOnly: false, 2);
				_textField.text = Slider.value.ToString(((int)_textField.contentType == 2) ? "F0" : ("F" + SliderSettings?.DecimalPlaces));
			}
		}

		public void AddPointerUp()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			EventTrigger val = ((Component)Slider).gameObject.AddComponent<EventTrigger>();
			Entry val2 = new Entry();
			val2.eventID = (EventTriggerType)3;
			((UnityEvent<BaseEventData>)(object)val2.callback).AddListener(UnityAction<BaseEventData>.op_Implicit((Action<BaseEventData>)PointerUP));
			val.triggers.Add(val2);
		}

		protected void PointerUP(BaseEventData eventData)
		{
			ApplyValueToPref();
		}
	}
	[RegisterTypeInIl2Cpp]
	public class BoolToggleAdapter : DataEntryAdapter
	{
		protected Toggle toggle => ((Component)((Component)this).gameObject.transform.Find("Data/ToggleControl")).gameObject.GetComponent<Toggle>();

		public bool EnteredValue => ((Component)((Component)this).gameObject.transform.Find("Data/ToggleControl")).gameObject.GetComponent<Toggle>().isOn;

		public override void SetData()
		{
			toggle.isOn = (bool)_prefModel.ModelBoxedValue;
			((UnityEvent<bool>)(object)toggle.onValueChanged).AddListener(UnityAction<bool>.op_Implicit((Action<bool>)OnValueChanged));
		}

		public override void EditCheck()
		{
		}

		public void OnValueChanged(bool newValue)
		{
			ApplyValueToPref();
		}

		public override void ApplyValueToPref()
		{
			try
			{
				_prefModel.TryApply(EnteredValue);
			}
			catch (Exception ex)
			{
				Debug.Log(ex.Message, debugOnly: false, 2);
			}
		}
	}
	[RegisterTypeInIl2Cpp]
	public abstract class DropDownAdapterBase : DataEntryAdapter
	{
		public List<int> _indexToValueMap = new List<int>();

		public TMP_Dropdown dropdown;

		protected new DataEntryModelBase _prefModel => (DataEntryModelBase)base.EntryModel;

		public override void SetData()
		{
			dropdown = ((Component)((Component)this).gameObject.transform.Find("Data/DropdownControl")).GetComponent<TMP_Dropdown>();
			GetDropdownData();
			((UnityEvent<int>)(object)dropdown.onValueChanged).AddListener(UnityAction<int>.op_Implicit((Action<int>)OnValueChanged));
		}

		public void OnValueChanged(int index)
		{
			ApplyValueToPref();
		}

		public virtual void GetDropdownData()
		{
		}
	}
	[RegisterTypeInIl2Cpp]
	public class EnumDropdownAdapter : DropDownAdapterBase
	{
		public Type prefEnum;

		public override void GetDropdownData()
		{
			prefEnum = base._prefModel.ModelBoxedValue.GetType();
			List<string> val = new List<string>();
			foreach (object value in Enum.GetValues(prefEnum))
			{
				val.Add((prefEnum.GetField(value.ToString())?.GetCustomAttribute<DisplayAttribute>())?.GetName() ?? value.ToString());
				_indexToValueMap.Add(Convert.ToInt32(value));
			}
			dropdown.ClearOptions();
			dropdown.AddOptions(val);
			dropdown.value = _indexToValueMap.IndexOf((int)base._prefModel.ModelBoxedValue);
		}

		public override void EditCheck()
		{
		}

		public override void ApplyValueToPref()
		{
			base._prefModel.TryApply(Enum.ToObject(prefEnum, _indexToValueMap[dropdown.value]));
		}
	}
	[RegisterTypeInIl2Cpp]
	public class DynamicDopdownAdapter : DropDownAdapterBase
	{
		public IDynamicDropdownDescriptor DropdownContents => base._prefModel.UiExtension as IDynamicDropdownDescriptor;

		public override void GetDropdownData()
		{
			try
			{
				List<string> val = new List<string>();
				foreach (DropdownItem dropdownItem in DropdownContents.GetDropdownItems())
				{
					val.Add(dropdownItem.DisplayName);
				}
				dropdown.ClearOptions();
				dropdown.AddOptions(val);
				int value = DropdownContents.GetDropdownItems().FindIndex((DropdownItem x) => object.Equals(x.Value, base._prefModel.ModelBoxedValue));
				dropdown.value = value;
			}
			catch (Exception value2)
			{
				Debug.Log($"{value2}");
			}
		}

		public override void SetData()
		{
			base.SetData();
			DropdownContents.OnDropdownItemsUpdated = GetDropdownData;
		}

		public override void ApplyValueToPref()
		{
			base._prefModel.TryApply(DropdownContents.GetDropdownItems()[dropdown.value].Value);
		}

		private void OnDestroy()
		{
			IDynamicDropdownDescriptor dropdownContents = DropdownContents;
			dropdownContents.OnDropdownItemsUpdated = (Action)Delegate.Remove(dropdownContents.OnDropdownItemsUpdated, new Action(GetDropdownData));
		}
	}
	[RegisterTypeInIl2Cpp]
	public class ButtonEntryAdapter : DataEntryAdapter
	{
		private GameObject _buttonGo;

		private Button _buttonComponent;

		private IButtonDescriptor _buttonDescrictor => _prefModel?.UiExtension as IButtonDescriptor;

		public override void SetData()
		{
			_buttonGo = ((Component)((Component)this).gameObject.transform.Find("Data/ButtonControl")).gameObject;
			_buttonComponent = _buttonGo.GetComponent<Button>();
			((UnityEvent)_buttonComponent.onClick).AddListener(UnityAction.op_Implicit(_buttonDescrictor?.Handler));
			TextMeshProUGUI component = ((Component)_buttonGo.transform.GetChild(0)).GetComponent<TextMeshProUGUI>();
			((TMP_Text)component).text = _buttonDescrictor?.ButtonText ?? "Button";
		}
	}
	[RegisterTypeInIl2Cpp]
	public class ButtonModelAdapter : PrefEntryAdapter
	{
		public GameObject ButtonGo;

		private ButtonEntry ButtonModel => (ButtonEntry)base.EntryModel;

		public override void SetData()
		{
			ButtonGo = ((Component)((Component)this).gameObject.transform.Find("Data/ButtonControl")).gameObject;
			((UnityEvent)ButtonGo.GetComponent<Button>().onClick).AddListener(UnityAction.op_Implicit((Action)OnClickRelay));
			base.SetData();
		}

		public void OnClickRelay()
		{
			ButtonModel.OnClick?.Invoke(this);
		}

		private void OnDestroy()
		{
		}
	}
	public enum EntryState
	{
		Untouched,
		Edited,
		Saved,
		Errored
	}
	[RegisterTypeInIl2Cpp]
	public abstract class ListAreaAdapterBase : SubModelAdapter
	{
		protected IHoldSubmodels _model => (IHoldSubmodels)_internalModel;

		public virtual void ContainerReset()
		{
			Model = null;
		}

		public void Infanticide()
		{
			for (int num = ((Component)this).transform.childCount - 1; num >= 0; num--)
			{
				Object.Destroy((Object)(object)((Component)((Component)this).transform.GetChild(num)).gameObject);
			}
		}

		public virtual void SetModel(IHoldSubmodels model)
		{
			if (model != null)
			{
				ContainerReset();
				Model = model;
				_rootWindow = FindRootWindow();
			}
		}

		public void BuildFromModelList()
		{
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			if (Model == null)
			{
				return;
			}
			Infanticide();
			foreach (IModelable subModel in _model.SubModels)
			{
				if (subModel.IsHidden)
				{
					Debug.Log("Model " + subModel.DisplayName + " is hidden, skipping UI creation.");
					continue;
				}
				GameObject newUIInstance = subModel.GetNewUIInstance();
				newUIInstance.SetActive(true);
				newUIInstance.transform.SetParent(((Component)this).gameObject.transform, false);
				newUIInstance.transform.localScale = Vector3.one;
				newUIInstance.transform.localPosition = Vector3.zero;
				IModelable modelable = subModel;
				IModelable modelable2 = modelable;
				IChildable component;
				if (!(modelable2 is IEntry))
				{
					if (!(modelable2 is SelectableModelBase))
					{
						Debug.Warning($"No view found for model type {subModel.GetType()}");
						continue;
					}
					component = newUIInstance.GetComponent<TabButtonController>();
					try
					{
						_rootWindow.SelectInSideBar(Model as IHoldSubmodels);
					}
					catch (Exception ex)
					{
						Debug.Log(ex.Message ?? "");
					}
				}
				else
				{
					component = newUIInstance.GetComponent<PrefEntryAdapter>();
					_rootWindow.SelectInTopBar(Model as IHoldSubmodels);
				}
				if (component != null)
				{
					component.Model = subModel;
				}
			}
			LayoutRebuilder.ForceRebuildLayoutImmediate(((Component)this).GetComponent<RectTransform>());
		}

		public void SelectTab(IHoldSubmodels buttonModel)
		{
			//IL_0057: 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)
			for (int i = 0; i < ((Component)this).transform.childCount; i++)
			{
				TabButtonController component = ((Component)((Component)this).transform.GetChild(i)).GetComponent<TabButtonController>();
				if (component == null)
				{
					break;
				}
				if (component.Model == buttonModel)
				{
					((Graphic)((Component)component).GetComponent<Image>()).color = _rootWindow.openTabColor;
				}
				else
				{
					((Graphic)((Component)component).GetComponent<Image>()).color = _rootWindow.defaultTabColor;
				}
			}
		}

		public virtual void DiscardAction()
		{
		}

		public virtual void SaveAction()
		{
		}
	}
	[RegisterTypeInIl2Cpp]
	public class ModListAdapter : ListAreaAdapterBase
	{
	}
	[RegisterTypeInIl2Cpp]
	public class CategoryListAdapter : ListAreaAdapterBase
	{
	}
	[RegisterTypeInIl2Cpp]
	public class PrefListAdapter : ListAreaAdapterBase
	{
		public CategoryModelBase SelectedCategory => Model as CategoryModelBase;

		public override void SaveAction()
		{
			SelectedCategory?.SaveAction();
		}

		public override void DiscardAction()
		{
			SelectedCategory.DiscardAction();
			BuildFromModelList();
		}
	}
	[RegisterTypeInIl2Cpp]
	public abstract class TabButtonController : SubModelAdapter, IChildable
	{
		protected WindowCoordinator ParentWindow;

		protected IHoldSubmodels _model => (IHoldSubmodels)_internalModel;

		public string Label
		{
			set
			{
				((TMP_Text)((Component)((Component)this).gameObject.transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text = value;
			}
		}

		public ColorARGB TabColor { get; set; }

		public override void ModelSet()
		{
			Label = _model.DisplayName;
			ParentWindow = _rootWindow;
		}

		public virtual void OnSelect()
		{
			throw new NotImplementedException("Implement OnSelect in inheriting class");
		}

		private void Start()
		{
			((UnityEvent)((Component)this).gameObject.GetComponent<Button>().onClick).AddListener(UnityAction.op_Implicit((Action)OnSelect));
		}

		private void OnDestroy()
		{
			((UnityEventBase)((Component)this).gameObject.GetComponent<Button>().onClick).RemoveAllListeners();
		}
	}
	[RegisterTypeInIl2Cpp]
	public class ModButtonView : TabButtonController, IChildable
	{
		protected MelonModel ModModel => (MelonModel)_internalModel;

		public override void OnSelect()
		{
			ParentWindow.SetSelectedMod(ModModel);
		}
	}
	[RegisterTypeInIl2Cpp]
	public class CategoryTabView : TabButtonController, IChildable
	{
		public override void OnSelect()
		{
			ParentWindow.SetSelectedCategory((CategoryModelBase)_internalModel);
		}
	}
	public interface IChildable
	{
		IModelable Model { get; set; }
	}
	public abstract class SubModelAdapter : MonoBehaviour
	{
		protected IModelable _internalModel;

		protected WindowCoordinator _rootWindow;

		public virtual IModelable Model
		{
			get
			{
				return _internalModel;
			}
			set
			{
				_internalModel = value;
				ModelSet();
			}
		}

		protected WindowCoordinator FindRootWindow()
		{
			WindowCoordinator result = null;
			Transform parent = ((Component)this).gameObject.transform.parent;
			while ((Object)(object)parent != (Object)null)
			{
				if (((Object)parent).name.Contains("MainWindow"))
				{
					return ((Component)parent).GetComponent<WindowCoordinator>();
				}
				parent = parent.parent;
			}
			return result;
		}

		private void OnTransformParentChanged()
		{
			_rootWindow = FindRootWindow();
		}

		private void Start()
		{
			_rootWindow = FindRootWindow();
		}

		public virtual void ModelSet()
		{
		}
	}
	[RegisterTypeInIl2Cpp]
	public class WindowCoordinator : MonoBehaviour
	{
		public Color defaultTabColor = new Color(0.22f, 0.22f, 0.22f, 1f);

		public Color openTabColor = new Color(0.24f, 0.17f, 0.42f, 1f);

		protected RootModel _model;

		protected GameObject MainCanvas;

		protected ModListAdapter ModRegistryPanel;

		protected CategoryListAdapter CatRegistryPanel;

		protected PrefListAdapter PrefRegistryPanel;

		private Button MainActionButton;

		private Button DiscardActionButton;

		private Button MinimizeButton;

		private TextMeshProUGUI WindowTitle;

		protected TextMeshProUGUI TitleButtonText;

		internal DragHandle DragHandle;

		private ModModelBase _selectedMod = null;

		private CategoryModelBase _selectedCategory = null;

		public Dictionary<ModModelBase, CategoryModelBase> LastCategorySelected = new Dictionary<ModModelBase, CategoryModelBase>();

		private bool _refreshPending = false;

		public IModelable Model => _model;

		public ModModelBase SelectedMod => _selectedMod;

		public CategoryModelBase SelectedCategory => _selectedCategory;

		private void Awake()
		{
			Debug.Log("WindowCoordinator Awake", debugOnly: true, 1);
		}

		internal void SetSelectedMod(ModModelBase mod)
		{
			_selectedMod = mod;
			((TMP_Text)TitleButtonText).text = mod.DisplayName + "\n" + mod.Instance.Info.Version;
			CatRegistryPanel.SetModel(mod);
			CategoryModelBase categoryModelBase = null;
			if (LastCategorySelected.ContainsKey(mod))
			{
				categoryModelBase = LastCategorySelected[mod];
			}
			PrefRegistryPanel.SetModel(categoryModelBase ?? ((CategoryModelBase)mod.SubModels[0]));
			RequestRefresh();
		}

		public void SetSelectedCategory(CategoryModelBase cat)
		{
			_selectedCategory = cat;
			PrefRegistryPanel.SetModel(cat);
			LastCategorySelected[_selectedMod] = cat;
			RequestRefresh();
		}

		public void SelectInSideBar(IHoldSubmodels model)
		{
			ModRegistryPanel.SelectTab(model);
		}

		public void SelectInTopBar(IHoldSubmodels model)
		{
			CatRegistryPanel.SelectTab(model);
		}

		protected void RequestRefresh()
		{
			_refreshPending = true;
		}

		public virtual void RequestRefresh(ModModelBase model)
		{
			Debug.Log("Refresh Requested by " + model.DisplayName, debugOnly: true, 1);
			if (model != _selectedMod)
			{
				Debug.Log("Denied. Calling mod is not selected mod", debugOnly: true, 1);
				return;
			}
			if (model == null)
			{
				Debug.Log("Denied Refresh Request. Reason: Calling mod is null", debugOnly: true, 1);
				return;
			}
			RequestRefresh();
			Debug.Log("Refresh Request approved", debugOnly: true, 1);
		}

		public virtual void SetModel(RootModel model)
		{
			_model = model;
			MainCanvas = ((Component)this).gameObject;
			ModRegistryPanel = ((Component)MainCanvas.transform.Find("Body/ModRegistry/Viewport/ModRegCont")).gameObject.GetComponent<ModListAdapter>();
			CatRegistryPanel = ((Component)MainCanvas.transform.Find("Body/CatRegistry/Viewport/CatRegCont")).gameObject.GetComponent<CategoryListAdapter>();
			PrefRegistryPanel = ((Component)MainCanvas.transform.Find("Body/PrefRegistry/Viewport/PrefRegCont")).gameObject.GetComponent<PrefListAdapter>();
			MainActionButton = ((Component)MainCanvas.transform.Find("Body/SaveActionButton")).gameObject.GetComponent<Button>();
			Transform? obj = ((IEnumerable<Transform>)((Component)MainCanvas.transform).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "DiscardActionButton"));
			DiscardActionButton = ((obj != null) ? ((Component)obj).gameObject.GetComponent<Button>() : null);
			MinimizeButton = ((Component)MainCanvas.transform.Find("Ribbon/Minimize")).gameObject.GetComponent<Button>();
			WindowTitle = ((Component)MainCanvas.transform.Find("Ribbon/WindowTitle")).gameObject.GetComponent<TextMeshProUGUI>();
			TitleButtonText = ((Component)MainCanvas.transform.Find("Body/TitleButton/Text")).gameObject.GetComponent<TextMeshProUGUI>();
			((UnityEvent)MainActionButton.onClick).AddListener(UnityAction.op_Implicit((Action)SaveButtonClick));
			((UnityEvent)MinimizeButton.onClick).AddListener(UnityAction.op_Implicit((Action)delegate
			{
				MainCanvas.SetActive(false);
			}));
			DragHandle = ((Component)MainCanvas.transform.Find("Ribbon/DragHandle")).gameObject.GetComponent<DragHandle>();
			((UnityEvent)DiscardActionButton.onClick).AddListener(UnityAction.op_Implicit((Action)DiscardButtonClick));
			((Component)DiscardActionButton).gameObject.SetActive(true);
			((TMP_Text)WindowTitle).text = ((MelonBase)Core.Instance).Info.Name + " v" + ((MelonBase)Core.Instance).Info.Version;
			((TMP_Text)TitleButtonText).text = ((MelonBase)Core.Instance).Info.Name + "\nv" + ((MelonBase)Core.Instance).Info.Version;
			BuildModList();
		}

		protected virtual void BuildModList()
		{
			ModRegistryPanel.ContainerReset();
			((Component)CatRegistryPanel).GetComponent<CategoryListAdapter>().ContainerReset();
			((Component)PrefRegistryPanel).GetComponent<PrefListAdapter>().ContainerReset();
			ModRegistryPanel.SetModel(_model);
			RequestRefresh();
		}

		protected virtual void SaveButtonClick()
		{
			CatRegistryPanel.Model?.SaveAction();
			RequestRefresh();
		}

		protected virtual void DiscardButtonClick()
		{
			CatRegistryPanel.Model?.DiscardAction();
			PrefRegistryPanel.DiscardAction();
			RequestRefresh();
		}

		private void Update()
		{
			if (Input.GetKeyDown((KeyCode)27))
			{
				EventSystem.current.SetSelectedGameObject((Ga