Decompiled source of REPOUW v1.0.0

REPOUW.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using REPOUW.Utils;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("REPOUW")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("REPOUW")]
[assembly: AssemblyTitle("REPOUW")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace REPOUW
{
	internal static class UWConfig
	{
		public static ConfigEntry<bool> Enabled;

		public static ConfigEntry<KeyCode> ToggleKey;

		public static ConfigEntry<float> QualityScale;

		public static void Bind(ConfigFile cfg)
		{
			Enabled = cfg.Bind<bool>("General", "Enabled", true, "Resize REPO's internal render target to match your screen aspect, giving true ultrawide / non-16:9 rendering. REPO's own HUD anchors (dollar counter, compass, level intro overlay) are NOT re-laid-out — they sit at their 16:9 positions with empty space alongside.");
			ToggleKey = cfg.Bind<KeyCode>("General", "ToggleKey", (KeyCode)283, "Key to toggle the override at runtime.");
			QualityScale = cfg.Bind<float>("General", "QualityScale", 1f, "Render resolution as a fraction of native screen. 1.0 = native, 0.75 = 75% downsample, 0.5 = half. REPO's in-game Render Size dropdown maps Small→0.5, Medium→0.75, Large→this value, so set this to your preferred max-quality scale.");
		}
	}
	[BepInPlugin("com.wearebonkers.repouw", "REPO Ultrawide", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.wearebonkers.repouw";

		public const string PluginName = "REPO Ultrawide";

		public const string PluginVersion = "1.0.0";

		private GameObject _host;

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Logger { get; private set; }

		private void Awake()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			UWConfig.Bind(((BaseUnityPlugin)this).Config);
			_host = new GameObject("REPOUW_Host");
			((Object)_host).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)_host);
			_host.AddComponent<UltrawidePatcher>();
			Logger.LogInfo((object)"REPO Ultrawide 1.0.0 loaded.");
		}
	}
	internal class UltrawidePatcher : MonoBehaviour
	{
		private struct ImageState
		{
			public RawImage img;

			public Vector2 anchorMin;

			public Vector2 anchorMax;

			public Vector2 offsetMin;

			public Vector2 offsetMax;

			public bool hadFitter;

			public bool fitterEnabled;

			public AspectRatioFitter fitter;
		}

		private bool _applied;

		private Component _rtmCached;

		private bool _haveSavedOriginals;

		private float _savedSmallW;

		private float _savedSmallH;

		private float _savedMediumW;

		private float _savedMediumH;

		private float _savedLargeW;

		private float _savedLargeH;

		private float _savedOriginalW;

		private float _savedOriginalH;

		private readonly List<ImageState> _savedImages = new List<ImageState>();

		private int _lastScreenW;

		private int _lastScreenH;

		private void Update()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown(UWConfig.ToggleKey.Value))
			{
				UWConfig.Enabled.Value = !UWConfig.Enabled.Value;
				Plugin.Logger.LogInfo((object)$"Ultrawide override: {UWConfig.Enabled.Value}");
			}
		}

		private void LateUpdate()
		{
			bool value = UWConfig.Enabled.Value;
			Component val = ResolveRtm();
			if ((Object)(object)val != (Object)(object)_rtmCached)
			{
				_rtmCached = val;
				_applied = false;
				_haveSavedOriginals = false;
				_savedImages.Clear();
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if (value != _applied)
			{
				if (value)
				{
					Apply(val);
				}
				else
				{
					Revert(val);
				}
				_applied = value;
				_lastScreenW = Screen.width;
				_lastScreenH = Screen.height;
			}
			else if (_applied && (Screen.width != _lastScreenW || Screen.height != _lastScreenH))
			{
				Apply(val);
				_lastScreenW = Screen.width;
				_lastScreenH = Screen.height;
			}
		}

		private static Component ResolveRtm()
		{
			Type type = Reflect.FindType("RenderTextureMain");
			if (type == null)
			{
				return null;
			}
			object staticMember = Reflect.GetStaticMember(type, "instance");
			return (Component)((staticMember is Component) ? staticMember : null);
		}

		private void Apply(Component rtm)
		{
			if (!_haveSavedOriginals)
			{
				SaveOriginals(rtm);
			}
			int num = Mathf.Max(1, Screen.width);
			int num2 = Mathf.Max(1, Screen.height);
			float num3 = Mathf.Clamp(UWConfig.QualityScale.Value, 0.25f, 2f);
			float num4 = (float)num * num3;
			float num5 = (float)num2 * num3;
			SetFloat(rtm, "textureWidthSmall", (float)num * 0.5f);
			SetFloat(rtm, "textureHeightSmall", (float)num2 * 0.5f);
			SetFloat(rtm, "textureWidthMedium", (float)num * 0.75f);
			SetFloat(rtm, "textureHeightMedium", (float)num2 * 0.75f);
			SetFloat(rtm, "textureWidthLarge", num4);
			SetFloat(rtm, "textureHeightLarge", num5);
			SetFloat(rtm, "textureWidthOriginal", num4);
			SetFloat(rtm, "textureHeightOriginal", num5);
			InvokeNoArgs(rtm, "ResetResolution");
			FixDisplayImages(rtm);
			Plugin.Logger.LogInfo((object)$"Applied {num4:0}×{num5:0} (scale {num3:F2}), {_savedImages.Count} display rect(s) stretched.");
		}

		private void Revert(Component rtm)
		{
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			if (!_haveSavedOriginals)
			{
				return;
			}
			SetFloat(rtm, "textureWidthSmall", _savedSmallW);
			SetFloat(rtm, "textureHeightSmall", _savedSmallH);
			SetFloat(rtm, "textureWidthMedium", _savedMediumW);
			SetFloat(rtm, "textureHeightMedium", _savedMediumH);
			SetFloat(rtm, "textureWidthLarge", _savedLargeW);
			SetFloat(rtm, "textureHeightLarge", _savedLargeH);
			SetFloat(rtm, "textureWidthOriginal", _savedOriginalW);
			SetFloat(rtm, "textureHeightOriginal", _savedOriginalH);
			InvokeNoArgs(rtm, "ResetResolution");
			for (int i = 0; i < _savedImages.Count; i++)
			{
				ImageState imageState = _savedImages[i];
				if (!((Object)(object)imageState.img == (Object)null))
				{
					RectTransform rectTransform = ((Graphic)imageState.img).rectTransform;
					rectTransform.anchorMin = imageState.anchorMin;
					rectTransform.anchorMax = imageState.anchorMax;
					rectTransform.offsetMin = imageState.offsetMin;
					rectTransform.offsetMax = imageState.offsetMax;
					if (imageState.hadFitter && (Object)(object)imageState.fitter != (Object)null)
					{
						((Behaviour)imageState.fitter).enabled = imageState.fitterEnabled;
					}
				}
			}
			_savedImages.Clear();
			Plugin.Logger.LogInfo((object)"Reverted to authored 16:9 sizes.");
		}

		private void SaveOriginals(Component rtm)
		{
			_savedSmallW = GetFloat(rtm, "textureWidthSmall");
			_savedSmallH = GetFloat(rtm, "textureHeightSmall");
			_savedMediumW = GetFloat(rtm, "textureWidthMedium");
			_savedMediumH = GetFloat(rtm, "textureHeightMedium");
			_savedLargeW = GetFloat(rtm, "textureWidthLarge");
			_savedLargeH = GetFloat(rtm, "textureHeightLarge");
			_savedOriginalW = GetFloat(rtm, "textureWidthOriginal");
			_savedOriginalH = GetFloat(rtm, "textureHeightOriginal");
			_haveSavedOriginals = true;
		}

		private void FixDisplayImages(Component rtm)
		{
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			object member = Reflect.GetMember(rtm, "renderTexture");
			RenderTexture val = (RenderTexture)((member is RenderTexture) ? member : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			RawImage[] array = Object.FindObjectsOfType<RawImage>();
			foreach (RawImage val2 in array)
			{
				if ((Object)(object)val2 == (Object)null || (Object)(object)val2.texture != (Object)(object)val)
				{
					continue;
				}
				bool flag = false;
				for (int j = 0; j < _savedImages.Count; j++)
				{
					if ((Object)(object)_savedImages[j].img == (Object)(object)val2)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					AspectRatioFitter component = ((Component)val2).GetComponent<AspectRatioFitter>();
					_savedImages.Add(new ImageState
					{
						img = val2,
						anchorMin = ((Graphic)val2).rectTransform.anchorMin,
						anchorMax = ((Graphic)val2).rectTransform.anchorMax,
						offsetMin = ((Graphic)val2).rectTransform.offsetMin,
						offsetMax = ((Graphic)val2).rectTransform.offsetMax,
						hadFitter = ((Object)(object)component != (Object)null),
						fitterEnabled = ((Object)(object)component != (Object)null && ((Behaviour)component).enabled),
						fitter = component
					});
				}
				RectTransform rectTransform = ((Graphic)val2).rectTransform;
				rectTransform.anchorMin = Vector2.zero;
				rectTransform.anchorMax = Vector2.one;
				rectTransform.offsetMin = Vector2.zero;
				rectTransform.offsetMax = Vector2.zero;
				AspectRatioFitter component2 = ((Component)val2).GetComponent<AspectRatioFitter>();
				if ((Object)(object)component2 != (Object)null)
				{
					((Behaviour)component2).enabled = false;
				}
			}
		}

		private static float GetFloat(Component c, string field)
		{
			object member = Reflect.GetMember(c, field);
			if (member is float)
			{
				return (float)member;
			}
			if (member is int num)
			{
				return num;
			}
			return 0f;
		}

		private static void SetFloat(Component c, string field, float value)
		{
			if ((Object)(object)c == (Object)null)
			{
				return;
			}
			Type type = ((object)c).GetType();
			FieldInfo field2 = type.GetField(field, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field2 != null)
			{
				field2.SetValue(c, value);
				return;
			}
			PropertyInfo property = type.GetProperty(field, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null && property.CanWrite)
			{
				property.SetValue(c, value, null);
			}
		}

		private static void InvokeNoArgs(Component c, string method)
		{
			if (!((Object)(object)c == (Object)null))
			{
				((object)c).GetType().GetMethod(method, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null)?.Invoke(c, null);
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "REPOUW";

		public const string PLUGIN_NAME = "REPOUW";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace REPOUW.Utils
{
	internal static class Reflect
	{
		private static readonly Dictionary<string, Type> _typeCache = new Dictionary<string, Type>();

		public static Type FindType(params string[] candidateNames)
		{
			foreach (string text in candidateNames)
			{
				if (_typeCache.TryGetValue(text, out var value))
				{
					if (value != null)
					{
						return value;
					}
					continue;
				}
				Type type = null;
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				for (int j = 0; j < assemblies.Length; j++)
				{
					type = assemblies[j].GetType(text, throwOnError: false);
					if (type != null)
					{
						break;
					}
				}
				_typeCache[text] = type;
				if (type != null)
				{
					return type;
				}
			}
			return null;
		}

		public static object GetMember(object instance, params string[] memberNames)
		{
			if (instance == null)
			{
				return null;
			}
			Type type = instance.GetType();
			foreach (string name in memberNames)
			{
				FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					return field.GetValue(instance);
				}
				PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && property.CanRead)
				{
					try
					{
						return property.GetValue(instance, null);
					}
					catch
					{
					}
				}
			}
			return null;
		}

		public static object GetStaticMember(Type type, params string[] memberNames)
		{
			if (type == null)
			{
				return null;
			}
			foreach (string name in memberNames)
			{
				FieldInfo field = type.GetField(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					return field.GetValue(null);
				}
				PropertyInfo property = type.GetProperty(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && property.CanRead)
				{
					try
					{
						return property.GetValue(null, null);
					}
					catch
					{
					}
				}
			}
			return null;
		}
	}
}