using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace ScaleUI;
public static class ConfigManager
{
private const float SENTINEL_NO_OVERRIDE = -1f;
private static ConfigFile cfg;
private static ConfigEntry<float> everything;
private static readonly Dictionary<UIType, ConfigEntry<float>> overrides = new Dictionary<UIType, ConfigEntry<float>>();
public static void Init(ConfigFile configFile)
{
cfg = configFile;
everything = cfg.Bind<float>("ScaleUI", "EverythingScale", 1f, "Global UI scale multiplier (0.2 - 3.0) applied to every UI that has no custom override.");
UIType[] allScalableTypes = UIManager.AllScalableTypes;
foreach (UIType uIType in allScalableTypes)
{
overrides[uIType] = cfg.Bind<float>("ScaleUI", string.Concat(uIType, "Scale"), -1f, string.Concat("Custom scale for ", uIType, ". -1 means 'use EverythingScale'."));
}
}
public static float GetEverything()
{
return everything.Value;
}
public static void SetEverything(float value)
{
everything.Value = value;
cfg.Save();
}
public static float? GetOverride(UIType type)
{
if (!overrides.ContainsKey(type))
{
return null;
}
float value = overrides[type].Value;
if (value < 0f)
{
return null;
}
return value;
}
public static void SetOverride(UIType type, float value)
{
if (overrides.ContainsKey(type))
{
overrides[type].Value = value;
cfg.Save();
}
}
public static void ClearOverride(UIType type)
{
if (overrides.ContainsKey(type))
{
overrides[type].Value = -1f;
cfg.Save();
}
}
}
public static class GUIManager
{
private static ScrollSettings typeRow;
private static SliderSetting scaleRow;
private static Button resetButton;
private static UIType selectedType = UIType.Everything;
private static bool suppressSliderCallback;
private static readonly string[] typeNames = BuildTypeNames();
private static string[] BuildTypeNames()
{
UIType[] array = (UIType[])Enum.GetValues(typeof(UIType));
string[] array2 = new string[array.Length];
for (int i = 0; i < array.Length; i++)
{
array2[i] = UIManager.DisplayName(array[i]);
}
return array2;
}
public static void Inject(Settings settings)
{
try
{
if ((Object)(object)settings.music == (Object)null)
{
throw new Exception("Settings.music is missing");
}
Transform parent = ((Component)settings.music).transform.parent;
if ((Object)(object)parent.Find("ScaleUI_ScaleRow") != (Object)null)
{
RefreshRows();
return;
}
BuildRows(settings, parent);
RefreshRows();
Plugin.Log.LogInfo((object)"ScaleUI: rows added to this Settings screen.");
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("ScaleUI: could not add Scale UI to this Settings screen (" + ex.Message + "). The mod will stay inactive for this screen."));
}
}
private static void BuildRows(Settings settings, Transform container)
{
//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_0174: Unknown result type (might be due to invalid IL or missing references)
//IL_0151: Unknown result type (might be due to invalid IL or missing references)
//IL_015b: Expected O, but got Unknown
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_0254: Unknown result type (might be due to invalid IL or missing references)
//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
//IL_02d4: Expected O, but got Unknown
if ((Object)(object)settings.volume == (Object)null)
{
throw new Exception("Settings.volume is missing");
}
if ((Object)(object)settings.shadowQuality == (Object)null)
{
throw new Exception("Settings.shadowQuality is missing");
}
if ((Object)(object)settings.backBtn == (Object)null)
{
throw new Exception("Settings.backBtn is missing");
}
if ((Object)(object)settings.fov == (Object)null)
{
throw new Exception("Settings.fov is missing");
}
LayoutGroup component = ((Component)container).GetComponent<LayoutGroup>();
RectTransform component2 = ((Component)settings.music).GetComponent<RectTransform>();
RectTransform component3 = ((Component)settings.volume).GetComponent<RectTransform>();
Vector2 step = ((!((Object)(object)component == (Object)null) || !((Object)(object)component2 != (Object)null) || !((Object)(object)component3 != (Object)null)) ? Vector2.zero : (component2.anchoredPosition - component3.anchoredPosition));
GameObject val = Object.Instantiate<GameObject>(((Component)settings.shadowQuality).gameObject);
val.transform.SetParent(container, false);
((Object)val).name = "ScaleUI_TypeRow";
typeRow = val.GetComponent<ScrollSettings>();
typeRow.SetSettings(typeNames, (int)selectedType);
KillPersistentListeners((UnityEventBase)(object)((Setting)typeRow).onClick);
((UnityEventBase)((Setting)typeRow).onClick).RemoveAllListeners();
((UnityEvent)((Setting)typeRow).onClick).AddListener(new UnityAction(OnTypeChanged));
SetRowLabel(val, "UI Type");
PlaceRow(val, component2, step, 1, component);
GameObject val2 = Object.Instantiate<GameObject>(((Component)settings.fov).gameObject);
val2.transform.SetParent(container, false);
((Object)val2).name = "ScaleUI_ScaleRow";
scaleRow = val2.GetComponent<SliderSetting>();
scaleRow.slider.minValue = 20f;
scaleRow.slider.maxValue = 300f;
scaleRow.slider.wholeNumbers = true;
KillPersistentListeners((UnityEventBase)(object)scaleRow.slider.onValueChanged);
((UnityEventBase)scaleRow.slider.onValueChanged).RemoveAllListeners();
((UnityEvent<float>)(object)scaleRow.slider.onValueChanged).AddListener((UnityAction<float>)OnSliderChanged);
SetRowLabel(val2, "UI Scale");
PlaceRow(val2, component2, step, 2, component);
GameObject val3 = Object.Instantiate<GameObject>(((Component)settings.backBtn).gameObject);
val3.transform.SetParent(container, false);
((Object)val3).name = "ScaleUI_ResetRow";
resetButton = val3.GetComponent<Button>();
KillPersistentListeners((UnityEventBase)(object)resetButton.onClick);
((UnityEventBase)resetButton.onClick).RemoveAllListeners();
((UnityEvent)resetButton.onClick).AddListener(new UnityAction(OnResetClicked));
SetRowLabel(val3, "Reset UI Scale");
PlaceRow(val3, component2, step, 3, component);
if ((Object)(object)component != (Object)null)
{
RectTransform component4 = ((Component)container).GetComponent<RectTransform>();
if ((Object)(object)component4 != (Object)null)
{
LayoutRebuilder.ForceRebuildLayoutImmediate(component4);
}
}
FixTextFit(val);
FixTextFit(val2);
FixTextFit(val3);
}
private static void PlaceRow(GameObject row, RectTransform lastRealRow, Vector2 step, int indexAfterLast, LayoutGroup layoutGroup)
{
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
row.transform.SetAsLastSibling();
if (!((Object)(object)layoutGroup != (Object)null))
{
RectTransform component = row.GetComponent<RectTransform>();
if (!((Object)(object)component == (Object)null) && !((Object)(object)lastRealRow == (Object)null))
{
component.anchoredPosition = lastRealRow.anchoredPosition + step * (float)indexAfterLast;
}
}
}
private static void KillPersistentListeners(UnityEventBase evt)
{
int persistentEventCount = evt.GetPersistentEventCount();
for (int i = 0; i < persistentEventCount; i++)
{
evt.SetPersistentListenerState(i, (UnityEventCallState)0);
}
}
private static void SetRowLabel(GameObject clone, string label)
{
TextMeshProUGUI[] componentsInChildren = clone.GetComponentsInChildren<TextMeshProUGUI>(true);
TextMeshProUGUI[] array = componentsInChildren;
foreach (TextMeshProUGUI val in array)
{
((TMP_Text)val).text = label;
}
}
private static void FixTextFit(GameObject clone)
{
TextMeshProUGUI[] componentsInChildren = clone.GetComponentsInChildren<TextMeshProUGUI>(true);
TextMeshProUGUI[] array = componentsInChildren;
foreach (TextMeshProUGUI val in array)
{
float fontSizeMax = ((!(((TMP_Text)val).fontSize > 0f)) ? 24f : ((TMP_Text)val).fontSize);
((TMP_Text)val).enableWordWrapping = false;
((TMP_Text)val).enableAutoSizing = true;
((TMP_Text)val).fontSizeMin = 8f;
((TMP_Text)val).fontSizeMax = fontSizeMax;
}
}
private static void OnTypeChanged()
{
selectedType = (UIType)((Setting)typeRow).currentSetting;
RefreshRows();
}
private static void OnSliderChanged(float value)
{
if (!suppressSliderCallback)
{
ScaleManager.SetOverride(selectedType, value / 100f);
ScaleManager.ApplyAll();
RefreshRows();
}
}
private static void OnResetClicked()
{
ScaleManager.ResetToDefault(selectedType);
ScaleManager.ApplyAll();
RefreshRows();
}
private static void RefreshRows()
{
if (!((Object)(object)scaleRow == (Object)null))
{
float num = ScaleManager.GetEffective(selectedType) * 100f;
suppressSliderCallback = true;
scaleRow.slider.value = num;
suppressSliderCallback = false;
if ((Object)(object)scaleRow.value != (Object)null)
{
string text = ((!ScaleManager.IsCustom(selectedType)) ? " (Default)" : " (Custom)");
((TMP_Text)scaleRow.value).text = Mathf.RoundToInt(num) + "%" + text;
}
}
}
}
[HarmonyPatch(typeof(Settings), "Start")]
public static class Settings_Start_Patch
{
[HarmonyPostfix]
public static void Postfix(Settings __instance)
{
GUIManager.Inject(__instance);
}
}
[BepInPlugin("mnfksa.scaleui", "Scale UI", "3.6.0")]
public class Plugin : BaseUnityPlugin
{
public static Plugin Instance;
public static ManualLogSource Log;
private const float APPLY_INTERVAL = 0.25f;
private float applyTimer;
private void Awake()
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Expected O, but got Unknown
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
ConfigManager.Init(((BaseUnityPlugin)this).Config);
ScaleManager.Init();
Harmony val = new Harmony("mnfksa.scaleui");
val.PatchAll();
Log.LogInfo((object)"ScaleUI loaded. Open Settings in-game to find the new 'Scale UI' tab.");
}
private void Update()
{
applyTimer += Time.unscaledDeltaTime;
if (applyTimer >= 0.25f)
{
applyTimer = 0f;
ScaleManager.ApplyAll();
}
}
}
public static class ScaleManager
{
public const float MIN_SCALE = 0.2f;
public const float MAX_SCALE = 3f;
public const float DEFAULT_SCALE = 1f;
public static void Init()
{
}
public static float Clamp(float value)
{
if (value < 0.2f)
{
return 0.2f;
}
if (value > 3f)
{
return 3f;
}
return value;
}
public static float GetEverything()
{
return ConfigManager.GetEverything();
}
public static void SetEverything(float value)
{
ConfigManager.SetEverything(Clamp(value));
}
public static float GetEffective(UIType type)
{
if (type == UIType.Everything)
{
return GetEverything();
}
float? num = ConfigManager.GetOverride(type);
return (!num.HasValue) ? GetEverything() : num.Value;
}
public static bool IsCustom(UIType type)
{
if (type == UIType.Everything)
{
return !Mathf.Approximately(GetEverything(), 1f);
}
return ConfigManager.GetOverride(type).HasValue;
}
public static void SetOverride(UIType type, float value)
{
if (type == UIType.Everything)
{
SetEverything(value);
}
else
{
ConfigManager.SetOverride(type, Clamp(value));
}
}
public static void ResetToDefault(UIType type)
{
if (type == UIType.Everything)
{
SetEverything(1f);
}
else
{
ConfigManager.ClearOverride(type);
}
}
public static void ApplyAll()
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: 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)
UIType[] allScalableTypes = UIManager.AllScalableTypes;
foreach (UIType type in allScalableTypes)
{
float effective = GetEffective(type);
Vector3 val = Vector3.one * effective;
foreach (Transform root in UIManager.GetRoots(type))
{
if (!((Object)(object)root == (Object)null) && root.localScale != val)
{
root.localScale = val;
}
}
}
}
}
public enum UIType
{
Everything,
Inventory,
Chest,
Crafting,
Furnace,
Cauldron,
Trader,
Map,
Hud
}
public static class UIManager
{
public static readonly UIType[] AllScalableTypes = new UIType[8]
{
UIType.Inventory,
UIType.Chest,
UIType.Crafting,
UIType.Furnace,
UIType.Cauldron,
UIType.Trader,
UIType.Map,
UIType.Hud
};
private static float lastScanTime = -999f;
private static ChestUI cachedChest;
private static CraftingUI cachedCrafting;
private static StatusUI cachedHud;
private const float RESCAN_INTERVAL = 1f;
public static string DisplayName(UIType type)
{
return type switch
{
UIType.Everything => "Everything",
UIType.Hud => "HUD",
_ => type.ToString(),
};
}
private static void RescanIfNeeded()
{
if (Time.unscaledTime - lastScanTime < 1f)
{
return;
}
lastScanTime = Time.unscaledTime;
if ((Object)(object)cachedChest == (Object)null)
{
ChestUI[] array = Resources.FindObjectsOfTypeAll<ChestUI>();
if (array.Length > 0)
{
cachedChest = array[0];
}
}
if ((Object)(object)cachedCrafting == (Object)null)
{
CraftingUI[] array2 = Resources.FindObjectsOfTypeAll<CraftingUI>();
if (array2.Length > 0)
{
cachedCrafting = array2[0];
}
}
if ((Object)(object)cachedHud == (Object)null)
{
StatusUI[] array3 = Resources.FindObjectsOfTypeAll<StatusUI>();
if (array3.Length > 0)
{
cachedHud = array3[0];
}
}
}
public static Transform GetRoot(UIType type)
{
List<Transform> roots = GetRoots(type);
return (roots.Count <= 0) ? null : roots[0];
}
public static List<Transform> GetRoots(UIType type)
{
List<Transform> list = new List<Transform>();
try
{
switch (type)
{
case UIType.Inventory:
if ((Object)(object)InventoryUI.Instance != (Object)null)
{
list.Add(((Component)InventoryUI.Instance).transform);
}
break;
case UIType.Trader:
if ((Object)(object)TraderUI.Instance != (Object)null)
{
list.Add(((Component)TraderUI.Instance).transform);
}
break;
case UIType.Furnace:
if ((Object)(object)FurnaceUI.Instance != (Object)null)
{
list.Add(((Component)FurnaceUI.Instance).transform);
}
break;
case UIType.Cauldron:
if ((Object)(object)CauldronUI.Instance != (Object)null)
{
list.Add(((Component)CauldronUI.Instance).transform);
}
break;
case UIType.Map:
if ((Object)(object)Map.Instance != (Object)null)
{
list.Add(((Component)Map.Instance).transform);
}
break;
case UIType.Chest:
RescanIfNeeded();
if ((Object)(object)cachedChest != (Object)null)
{
list.Add(((Component)cachedChest).transform);
}
break;
case UIType.Crafting:
RescanIfNeeded();
if ((Object)(object)cachedCrafting != (Object)null)
{
list.Add(((Component)cachedCrafting).transform);
}
break;
case UIType.Hud:
RescanIfNeeded();
if ((Object)(object)cachedHud != (Object)null)
{
list.Add(((Component)cachedHud).transform);
}
break;
}
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)string.Concat("ScaleUI: failed to resolve root(s) for ", type, ": ", ex.Message));
}
return list;
}
private static void AddIfSeparate(List<Transform> list, Transform alreadyCovered, Transform candidate)
{
if (!((Object)(object)candidate == (Object)null) && (!((Object)(object)alreadyCovered != (Object)null) || (!((Object)(object)candidate == (Object)(object)alreadyCovered) && !candidate.IsChildOf(alreadyCovered))))
{
list.Add(candidate);
}
}
public static int CountAffected(UIType type)
{
if (type == UIType.Everything)
{
int num = 0;
UIType[] allScalableTypes = AllScalableTypes;
foreach (UIType type2 in allScalableTypes)
{
if ((Object)(object)GetRoot(type2) != (Object)null)
{
num++;
}
}
return num;
}
return ((Object)(object)GetRoot(type) != (Object)null) ? 1 : 0;
}
}