using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("SuperUltrawideSupport")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Riintouge")]
[assembly: AssemblyProduct("SuperUltrawideSupport")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("8ca56582-078a-4428-b55f-0e59e84925ff")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.2.0.0")]
namespace SuperUltrawideSupport;
internal class OriginalRectTransform
{
public readonly float minX;
public readonly float minY;
public readonly float maxX;
public readonly float maxY;
public readonly WeakReference<RectTransform> original;
public OriginalRectTransform(RectTransform rectTransform)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
minX = rectTransform.anchorMin.x;
minY = rectTransform.anchorMin.y;
maxX = rectTransform.anchorMax.x;
maxY = rectTransform.anchorMax.y;
original = new WeakReference<RectTransform>(rectTransform);
}
}
internal class AspectLerper
{
private Dictionary<string, OriginalRectTransform> originals = new Dictionary<string, OriginalRectTransform>();
private int targetWidth;
private int targetHeight;
private float xBufferNormalized;
private float yBufferNormalized;
private bool enabled = true;
public AspectLerper(int currentWidth, int currentHeight, float targetAspectWidth, float targetAspectHeight)
{
Update(currentWidth, currentHeight, targetAspectWidth, targetAspectHeight);
}
public void Update(int currentWidth, int currentHeight, float targetAspectWidth, float targetAspectHeight)
{
lock (originals)
{
float num = Math.Min(currentHeight, (float)currentWidth / targetAspectWidth * targetAspectHeight);
float num2 = num / targetAspectHeight * targetAspectWidth;
targetHeight = (int)Math.Floor(num);
targetWidth = (int)Math.Floor(num2);
xBufferNormalized = (float)(currentWidth - targetWidth) / 2f / (float)currentWidth;
yBufferNormalized = (float)(currentHeight - targetHeight) / 2f / (float)currentHeight;
Update();
}
}
public void Update()
{
lock (originals)
{
HashSet<string> hashSet = new HashSet<string>();
foreach (KeyValuePair<string, OriginalRectTransform> original in originals)
{
if (!original.Value.original.TryGetTarget(out var target) || !LerpCore(target, original.Value))
{
hashSet.Add(original.Key);
}
}
foreach (string item in hashSet)
{
originals.Remove(item);
}
}
}
public void Update(bool enable)
{
lock (originals)
{
if (enabled != enable)
{
enabled = enable;
Update();
}
}
}
public void Register(RectTransform rectTransform)
{
lock (originals)
{
if (!((Object)(object)rectTransform == (Object)null))
{
string text = AbsoluteTransformPath((Transform)(object)rectTransform);
if (originals.ContainsKey(text))
{
Unregister(text);
originals.Remove(text);
}
originals.Add(text, new OriginalRectTransform(rectTransform));
}
}
}
public void RegisterLerpAndUpdate(RectTransform rectTransform)
{
lock (originals)
{
if (!((Object)(object)rectTransform == (Object)null))
{
Register(rectTransform);
Lerp(rectTransform);
Update();
}
}
}
protected void Unregister(string transformPath, RectTransform rectTransform, OriginalRectTransform original)
{
//IL_002a: 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)
lock (originals)
{
if ((Object)(object)rectTransform != (Object)null && original != null)
{
rectTransform.anchorMin = new Vector2(original.minX, original.minY);
rectTransform.anchorMax = new Vector2(original.maxX, original.maxY);
}
originals.Remove(transformPath);
}
}
public void Unregister(RectTransform rectTransform)
{
lock (originals)
{
if ((Object)(object)rectTransform != (Object)null && originals.TryGetValue(((Object)rectTransform).name, out var value))
{
Unregister(((Object)rectTransform).name, rectTransform, value);
}
}
}
public void Unregister(string transformPath)
{
lock (originals)
{
if (transformPath != null && originals.TryGetValue(transformPath, out var value) && value.original.TryGetTarget(out var target))
{
Unregister(transformPath, target, value);
}
}
}
public void Lerp(RectTransform rectTransform)
{
lock (originals)
{
if ((Object)(object)rectTransform != (Object)null && originals.TryGetValue(((Object)rectTransform).name, out var value))
{
LerpCore(rectTransform, value);
}
}
}
protected bool LerpCore(RectTransform rectTransform, OriginalRectTransform original)
{
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
lock (originals)
{
try
{
if (enabled)
{
rectTransform.anchorMin = new Vector2(Mathf.Lerp(xBufferNormalized, 1f - xBufferNormalized, original.minX), Mathf.Lerp(yBufferNormalized, 1f - yBufferNormalized, original.minY));
rectTransform.anchorMax = new Vector2(Mathf.Lerp(xBufferNormalized, 1f - xBufferNormalized, original.maxX), Mathf.Lerp(yBufferNormalized, 1f - yBufferNormalized, original.maxY));
}
else
{
rectTransform.anchorMin = new Vector2(original.minX, original.minY);
rectTransform.anchorMax = new Vector2(original.maxX, original.maxY);
}
return true;
}
catch (NullReferenceException)
{
}
return false;
}
}
public void InverseLerp(RectTransform rectTransform)
{
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
lock (originals)
{
if (enabled)
{
float num = xBufferNormalized / (1f - xBufferNormalized * 2f);
float num2 = yBufferNormalized / (1f - yBufferNormalized * 2f);
rectTransform.anchorMin = new Vector2(rectTransform.anchorMin.x - num, rectTransform.anchorMin.y - num2);
rectTransform.anchorMax = new Vector2(rectTransform.anchorMax.x + num, rectTransform.anchorMax.y + num2);
}
}
}
public static string AbsoluteTransformPath(Transform transform)
{
List<string> list = new List<string>();
while ((Object)(object)transform != (Object)null)
{
list.Add(((Object)transform).name);
Transform parent = transform.parent;
object obj;
if (parent == null)
{
obj = null;
}
else
{
GameObject gameObject = ((Component)parent).gameObject;
obj = ((gameObject != null) ? gameObject.transform : null);
}
transform = (Transform)obj;
}
string text = string.Empty;
for (int num = list.Count - 1; num >= 0; num--)
{
text = text + "/" + list[num];
}
return text;
}
}
[BepInPlugin("com.riintouge.superultrawidesupport", "Super Ultrawide Support", "1.2.0")]
[BepInProcess("valheim.exe")]
public class SuperUltrawideSupport : BaseUnityPlugin
{
[HarmonyPatch(typeof(Barber))]
private class BarberPatch
{
[HarmonyPatch("Interact")]
[HarmonyPostfix]
private static void InteractPostfix(ref Barber __instance)
{
GameObject gameObject = PlayerCustomizaton.m_barberInstance.m_rootPanel.gameObject;
if (gameObject.activeInHierarchy)
{
RectTransform val = Common.FindChildOfParent(gameObject.transform, "root", "BarberGui");
if ((Object)(object)val != (Object)null)
{
Lerper.RegisterLerpAndUpdate(val);
}
}
}
}
[HarmonyPatch(typeof(FejdStartup))]
private class FejdStartupPatch
{
private static HashSet<string> TransformPaths = new HashSet<string>();
private static void Reset()
{
foreach (string transformPath in TransformPaths)
{
Lerper.Unregister(transformPath);
}
TransformPaths.Clear();
}
[HarmonyPatch("Awake")]
[HarmonyPostfix]
private static void AwakePostfix(ref FejdStartup __instance)
{
Reset();
Transform val = Common.FindParentOrSelf((Transform)(object)__instance.m_creditsList, "StartGui");
if ((Object)(object)val != (Object)null)
{
for (int i = 0; i < val.childCount; i++)
{
Transform child = val.GetChild(i);
RectTransform val2 = (RectTransform)(object)((child is RectTransform) ? child : null);
if ((Object)(object)val2 != (Object)null && ((Object)val2).name != "BLACK" && ((Object)val2).name != "Loading" && ((Object)val2).name != "PleaseWait" && ((Object)val2).name != "Scaled 3D Viewport")
{
TransformPaths.Add(((Object)val2).name);
Lerper.Register(val2);
Lerper.Lerp(val2);
}
}
}
if (TransformPaths.Count > 0)
{
Lerper.Update();
}
}
[HarmonyPatch("OnDestroy")]
[HarmonyPrefix]
private static void OnDestroyPrefix()
{
Reset();
}
}
[HarmonyPatch(typeof(Hud))]
private class HudPatch
{
private static string TransformPath;
[HarmonyPatch("Awake")]
[HarmonyPostfix]
private static void AwakePostfix(ref Hud __instance)
{
Transform obj = ((Component)__instance).transform.Find("hudroot");
RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
if ((Object)(object)val != (Object)null)
{
TransformPath = AspectLerper.AbsoluteTransformPath((Transform)(object)val);
Lerper.RegisterLerpAndUpdate(val);
}
}
[HarmonyPatch("OnDestroy")]
[HarmonyPrefix]
private static void OnDestroyPrefix()
{
Lerper.Unregister(TransformPath);
}
}
[HarmonyPatch(typeof(InventoryGui))]
private class InventoryGuiPatch
{
private static HashSet<string> TransformPaths = new HashSet<string>();
private static void Reset()
{
foreach (string transformPath in TransformPaths)
{
Lerper.Unregister(transformPath);
}
TransformPaths.Clear();
}
[HarmonyPatch("Awake")]
[HarmonyPostfix]
private static void AwakePostfix(ref InventoryGui __instance)
{
Reset();
for (int i = 0; i < __instance.m_inventoryRoot.childCount; i++)
{
Transform child = __instance.m_inventoryRoot.GetChild(i);
RectTransform val = (RectTransform)(object)((child is RectTransform) ? child : null);
if ((Object)(object)val != (Object)null && ((Object)val).name != "dropButton")
{
TransformPaths.Add(AspectLerper.AbsoluteTransformPath((Transform)(object)val));
Lerper.Register(val);
Lerper.Lerp(val);
}
}
if (TransformPaths.Count > 0)
{
Lerper.Update();
}
}
[HarmonyPatch("OnDestroy")]
[HarmonyPrefix]
private static void OnDestroyPrefix()
{
Reset();
}
}
[HarmonyPatch(typeof(MessageHud))]
private class MessageHudPatch
{
private static HashSet<string> TransformPaths = new HashSet<string>();
private static void Reset()
{
foreach (string transformPath in TransformPaths)
{
Lerper.Unregister(transformPath);
}
TransformPaths.Clear();
}
[HarmonyPatch("Awake")]
[HarmonyPostfix]
private static void AwakePostfix(ref MessageHud __instance)
{
Transform obj = Common.FindParentOrSelf(((Component)__instance).transform, "HudMessage");
RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
if ((Object)(object)val != (Object)null)
{
TransformPaths.Add(AspectLerper.AbsoluteTransformPath((Transform)(object)val));
Lerper.RegisterLerpAndUpdate(val);
}
RectTransform val2 = Common.FindChildOfParent(((Component)__instance.m_messageText).gameObject.transform, "root", "TopLeftMessage");
if ((Object)(object)val2 != (Object)null)
{
TransformPaths.Add(AspectLerper.AbsoluteTransformPath((Transform)(object)val2));
Lerper.RegisterLerpAndUpdate(val2);
}
}
[HarmonyPatch("OnDestroy")]
[HarmonyPrefix]
private static void OnDestroyPrefix()
{
Reset();
}
}
[HarmonyPatch(typeof(Minimap))]
private class MinimapPatch
{
private static RectTransform LargeTransform;
private static float MinX;
private static float MinY;
private static float MaxX;
private static float MaxY;
private static bool AppliedInverseLerp;
public static void Update(bool userUpdate)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Invalid comparison between Unknown and I4
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)LargeTransform == (Object)null) && (int)Minimap.instance.m_mode == 2)
{
if (userUpdate)
{
Minimap.instance.SetMapMode((MapMode)1);
Minimap.instance.SetMapMode((MapMode)2);
}
LargeTransform.anchorMin = new Vector2(MinX, MinY);
LargeTransform.anchorMax = new Vector2(MaxX, MaxY);
AppliedInverseLerp = false;
if (IsEnabled.Value && FullSizeMap.Value && !AppliedInverseLerp)
{
Lerper.InverseLerp(LargeTransform);
AppliedInverseLerp = true;
}
}
}
[HarmonyPatch("Awake")]
[HarmonyPostfix]
private static void AwakePostfix(ref Minimap __instance)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: 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_0057: Unknown result type (might be due to invalid IL or missing references)
Transform transform = __instance.m_largeRoot.transform;
LargeTransform = (RectTransform)(object)((transform is RectTransform) ? transform : null);
MinX = LargeTransform.anchorMin.x;
MinY = LargeTransform.anchorMin.y;
MaxX = LargeTransform.anchorMax.x;
MaxY = LargeTransform.anchorMax.y;
AppliedInverseLerp = false;
}
[HarmonyPatch("OnDestroy")]
[HarmonyPrefix]
private static void OnDestroyPrefix()
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)LargeTransform != (Object)null)
{
LargeTransform.anchorMin = new Vector2(MinX, MinY);
LargeTransform.anchorMax = new Vector2(MaxX, MaxY);
}
LargeTransform = null;
MinX = 0f;
MinY = 0f;
MaxX = 0f;
MaxY = 0f;
AppliedInverseLerp = false;
}
[HarmonyPatch("SetMapMode")]
[HarmonyPrefix]
private static void SetMapModePrefix(ref Minimap __instance, ref MapMode mode, out MapMode __state)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Expected I4, but got Unknown
__state = (MapMode)(int)__instance.m_mode;
}
[HarmonyPatch("SetMapMode")]
[HarmonyPostfix]
private static void SetMapModePostfix(ref Minimap __instance, ref MapMode mode, ref MapMode __state)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Invalid comparison between Unknown and I4
if ((int)__instance.m_mode != (int)__state)
{
Update(userUpdate: false);
}
}
}
[HarmonyPatch(typeof(StoreGui))]
private class StoreGuiPatch
{
private static string TransformPath;
[HarmonyPatch("Awake")]
[HarmonyPostfix]
private static void AwakePostfix(ref StoreGui __instance)
{
RectTransform val = Common.FindChildOfParent(((Component)__instance).transform, "Store", "Store_Screen");
if ((Object)(object)val != (Object)null)
{
TransformPath = AspectLerper.AbsoluteTransformPath((Transform)(object)val);
Lerper.RegisterLerpAndUpdate(val);
}
}
[HarmonyPatch("OnDestroy")]
[HarmonyPrefix]
private static void OnDestroyPrefix()
{
Lerper.Unregister(TransformPath);
}
}
[HarmonyPatch(typeof(Terminal))]
private class TerminalPatch
{
[HarmonyPatch("Awake")]
[HarmonyPostfix]
private static void AwakePostfix(ref Terminal __instance)
{
RectTransform val = Common.FindChildOfParent((Transform)(object)__instance.m_chatWindow, "root", "Chat_box") ?? __instance.m_chatWindow;
if ((Object)(object)val != (Object)null)
{
Lerper.RegisterLerpAndUpdate(val);
}
}
}
public static SuperUltrawideSupport Instance = null;
public static ConfigEntry<bool> IsEnabled;
public static ConfigEntry<bool> LoadOnStart;
public static ConfigEntry<string> AspectRatio;
internal static AspectLerper Lerper = null;
private string LastAspectRatio = "16:9";
private static int LastAspectWidth = 16;
private static int LastAspectHeight = 9;
private static Coroutine ScreenSizeDetectorCoroutine = null;
private static int LastScreenWidth = -1;
private static int LastScreenHeight = -1;
public static ConfigEntry<bool> FullSizeMap;
private readonly Harmony Harmony = new Harmony("com.riintouge.superultrawidesupport");
private void Awake()
{
IsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Core", "Enable", true, "Whether this plugin has any effect when loaded.");
LoadOnStart = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Core", "LoadOnStart", true, "Whether this plugin loads on game start.");
AspectRatio = ((BaseUnityPlugin)this).Config.Bind<string>("1 - General", "AspectRatio", LastAspectRatio, "The desired aspect ratio in whole numbers, like \"" + LastAspectRatio + "\".");
FullSizeMap = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "FullSizeMap", true, "Whether the map appears at full size regardless of the specified aspect ratio.");
if (LoadOnStart.Value)
{
Instance = this;
Harmony.PatchAll();
UpdateAspectRatio(AspectRatio.Value);
((BaseUnityPlugin)this).Config.SettingChanged += Config_SettingChanged;
ScreenSizeDetectorCoroutine = ((MonoBehaviour)Instance).StartCoroutine(CoCheckForScreenResize());
}
}
private void OnDestroy()
{
if (ScreenSizeDetectorCoroutine != null)
{
((MonoBehaviour)Instance).StopCoroutine(ScreenSizeDetectorCoroutine);
}
Harmony.UnpatchSelf();
}
private IEnumerator CoCheckForScreenResize()
{
while (true)
{
yield return (object)new WaitForSecondsRealtime(3f);
if (LastScreenWidth != Screen.width || LastScreenHeight != Screen.height)
{
LastScreenWidth = Screen.width;
LastScreenHeight = Screen.height;
Lerper.Update(LastScreenWidth, LastScreenHeight, LastAspectWidth, LastAspectHeight);
MinimapPatch.Update(userUpdate: true);
}
}
}
private void Config_SettingChanged(object sender, SettingChangedEventArgs e)
{
if (e.ChangedSetting == IsEnabled)
{
Lerper.Update(IsEnabled.Value);
MinimapPatch.Update(userUpdate: true);
}
else if (e.ChangedSetting == AspectRatio)
{
UpdateAspectRatio(AspectRatio.Value);
}
else if (e.ChangedSetting == FullSizeMap)
{
MinimapPatch.Update(userUpdate: true);
}
}
private void UpdateAspectRatio(string value)
{
try
{
int num = 0;
int num2 = 0;
if (value == string.Empty)
{
num = Screen.width;
num2 = Screen.height;
}
else
{
string[] array = value.Split(new char[1] { ':' });
num = int.Parse(array[0]);
num2 = int.Parse(array[1]);
}
if (num > 0 && num2 > 0)
{
LastAspectRatio = $"{num}:{num2}";
LastAspectWidth = num;
LastAspectHeight = num2;
if (Lerper == null)
{
Lerper = new AspectLerper(Screen.width, Screen.height, LastAspectWidth, LastAspectHeight);
Lerper.Update(IsEnabled.Value);
}
else
{
Lerper.Update(Screen.width, Screen.height, LastAspectWidth, LastAspectHeight);
}
MinimapPatch.Update(userUpdate: true);
}
}
catch (Exception)
{
AspectRatio.Value = ((AspectRatio.Value != LastAspectRatio) ? LastAspectRatio : string.Empty);
}
}
}
public static class Common
{
public static RectTransform FindChildOfParent(Transform transform, string childName, string parentName)
{
Transform obj = FindParentOrSelf(transform, parentName);
Transform obj2 = ((obj != null) ? obj.Find(childName) : null);
return (RectTransform)(object)((obj2 is RectTransform) ? obj2 : null);
}
public static Transform FindParentOrSelf(Transform transform, string name)
{
while ((Object)(object)transform != (Object)null)
{
if (((Object)transform).name == name)
{
return transform;
}
Transform parent = transform.parent;
object obj;
if (parent == null)
{
obj = null;
}
else
{
GameObject gameObject = ((Component)parent).gameObject;
obj = ((gameObject != null) ? gameObject.transform : null);
}
transform = (Transform)obj;
}
Console.WriteLine("Unable to find parent or self transform \"" + name + "\"!");
return null;
}
public static void PrintRectTransform(string text, RectTransform rectTransform)
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
Console.WriteLine(text + " " + ((Object)rectTransform).name + ":");
Console.WriteLine($"\t{rectTransform.anchorMin} <-> {rectTransform.anchorMax} @ {rectTransform.anchoredPosition}");
}
public static void PrintParents(Transform transform)
{
Console.WriteLine("Parents of " + ((Object)transform).name + ":");
while ((Object)(object)transform != (Object)null)
{
Console.WriteLine($"{((Object)transform).name} is {((object)transform).GetType()}");
Transform parent = transform.parent;
object obj;
if (parent == null)
{
obj = null;
}
else
{
GameObject gameObject = ((Component)parent).gameObject;
obj = ((gameObject != null) ? gameObject.transform : null);
}
transform = (Transform)obj;
}
}
public static void PrintChildren(Transform transform)
{
Console.WriteLine("Children of " + ((Object)transform).name + ":");
for (int i = 0; i < transform.childCount; i++)
{
Transform child = transform.GetChild(i);
Console.WriteLine($"{((Object)child).name} is {((object)child).GetType()}");
}
}
public static void DumpTransformTree(Transform transform, int indent = 0)
{
if (!((Object)(object)transform == (Object)null))
{
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < indent; i++)
{
stringBuilder.Append(" ");
}
Console.WriteLine($"{stringBuilder}{((Object)transform).name}");
for (int j = 0; j < transform.childCount; j++)
{
DumpTransformTree(transform.GetChild(j), indent + 1);
}
}
}
}