using System;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("BepInEx.GraphicsSettings")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("BepInEx.GraphicsSettings")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("9bba5dae-624e-4ff0-80a2-f14029ee34e9")]
[assembly: AssemblyFileVersion("1.3")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace GraphicsSettings;
internal sealed class ConfigurationManagerAttributes
{
public bool? ShowRangeAsPercent;
public Action<ConfigEntryBase> CustomDrawer;
public bool? Browsable;
public string Category;
public object DefaultValue;
public bool? HideDefaultButton;
public string Description;
public string DispName;
public int? Order;
public bool? ReadOnly;
public bool? IsAdvanced;
public Func<object, string> ObjToStr;
public Func<string, object> StrToObj;
}
[BepInPlugin("keelhauled.graphicssettings", "Graphics Settings", "1.3")]
public class GraphicsSettings : BaseUnityPlugin
{
public const string GUID = "keelhauled.graphicssettings";
public const string Version = "1.3";
private const string CATEGORY_GENERAL = "General";
private const string CATEGORY_RENDER = "Rendering";
private const string DESCRIPTION_RESOLUTION = "Dummy setting for the custom drawer. Resolution is saved automatically by the game after clicking apply.";
private const string DESCRIPTION_ANISOFILTER = "Improves distant textures when they are being viewer from indirect angles.";
private const string DESCRIPTION_VSYNC = "VSync synchronizes the output video of the graphics card to the refresh rate of the monitor. This prevents tearing and produces a smoother video output.\nHalf vsync synchronizes the output to half the refresh rate of your monitor.";
private const string DESCRIPTION_FRAMERATELIMIT = "Limits your framerate to whatever value is set. -1 equals unlocked framerate.\nVSync has to be disabled for this setting to take effect.";
private const string DESCRIPTION_ANTIALIASING = "Smooths out jagged edges on objects.";
private const string DESCRIPTION_RUNINBACKGROUND = "Should the game be running when it is in the background (when the window is not focused)?\n";
private const string DESCRIPTION_OPTIMIZEINBACKGROUND = "Optimize the game when it is the background and unfocused. Settings such as anti-aliasing will be turned off or reduced in this state.";
private string resolutionX = Screen.width.ToString();
private string resolutionY = Screen.height.ToString();
private bool framerateToggle;
private WinAPI.WindowStyleFlags backupStandard;
private WinAPI.WindowStyleFlags backupExtended;
private bool backupDone;
private Object configManager;
private bool configManagerSearch;
private int lastAntiAliasingValue = -1;
private ConfigEntry<string> Resolution { get; set; }
private ConfigEntry<SettingEnum.DisplayMode> DisplayMode { get; set; }
private ConfigEntry<int> SelectedMonitor { get; set; }
private ConfigEntry<SettingEnum.VSyncType> VSync { get; set; }
private ConfigEntry<int> FramerateLimit { get; set; }
private ConfigEntry<SettingEnum.AntiAliasingMode> AntiAliasing { get; set; }
private ConfigEntry<SettingEnum.AnisotropicFilteringMode> AnisotropicFiltering { get; set; }
private ConfigEntry<SettingEnum.RunInBackgroundMode> RunInBackground { get; set; }
private ConfigEntry<bool> OptimizeInBackground { get; set; }
private void Awake()
{
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Expected O, but got Unknown
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Expected O, but got Unknown
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: Expected O, but got Unknown
//IL_012f: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: Expected O, but got Unknown
//IL_0192: Unknown result type (might be due to invalid IL or missing references)
//IL_019c: Expected O, but got Unknown
//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
//IL_01c9: Expected O, but got Unknown
//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
//IL_01f6: Expected O, but got Unknown
//IL_0219: Unknown result type (might be due to invalid IL or missing references)
//IL_0223: Expected O, but got Unknown
//IL_0246: Unknown result type (might be due to invalid IL or missing references)
//IL_0250: Expected O, but got Unknown
Resolution = ((BaseUnityPlugin)this).Config.AddSetting<string>("Rendering", "Resolution", "", new ConfigDescription("Dummy setting for the custom drawer. Resolution is saved automatically by the game after clicking apply.", (AcceptableValueBase)null, new object[1]
{
new ConfigurationManagerAttributes
{
Order = 9,
HideDefaultButton = true,
CustomDrawer = ResolutionDrawer
}
}));
DisplayMode = ((BaseUnityPlugin)this).Config.AddSetting<SettingEnum.DisplayMode>("Rendering", "Display mode", SettingEnum.DisplayMode.Default, new ConfigDescription("", (AcceptableValueBase)null, new object[1]
{
new ConfigurationManagerAttributes
{
Order = 10
}
}));
SelectedMonitor = ((BaseUnityPlugin)this).Config.AddSetting<int>("Rendering", "Selected monitor", 0, new ConfigDescription("", (AcceptableValueBase)(object)new AcceptableValueList<int>(Enumerable.Range(0, Display.displays.Length).ToArray()), new object[1]
{
new ConfigurationManagerAttributes
{
Order = 8
}
}));
VSync = ((BaseUnityPlugin)this).Config.AddSetting<SettingEnum.VSyncType>("Rendering", "VSync", SettingEnum.VSyncType.Default, new ConfigDescription("VSync synchronizes the output video of the graphics card to the refresh rate of the monitor. This prevents tearing and produces a smoother video output.\nHalf vsync synchronizes the output to half the refresh rate of your monitor.", (AcceptableValueBase)null, new object[1]
{
new ConfigurationManagerAttributes
{
Order = 7
}
}));
FramerateLimit = ((BaseUnityPlugin)this).Config.AddSetting<int>("Rendering", "Framerate limit", Application.targetFrameRate, new ConfigDescription("Limits your framerate to whatever value is set. -1 equals unlocked framerate.\nVSync has to be disabled for this setting to take effect.", (AcceptableValueBase)null, new object[1]
{
new ConfigurationManagerAttributes
{
Order = 6,
HideDefaultButton = true,
CustomDrawer = FramerateLimitDrawer
}
}));
AntiAliasing = ((BaseUnityPlugin)this).Config.AddSetting<SettingEnum.AntiAliasingMode>("Rendering", "Anti-aliasing multiplier", SettingEnum.AntiAliasingMode.Default, new ConfigDescription("Smooths out jagged edges on objects.", (AcceptableValueBase)null, new object[0]));
AnisotropicFiltering = ((BaseUnityPlugin)this).Config.AddSetting<SettingEnum.AnisotropicFilteringMode>("Rendering", "Anisotropic filtering", SettingEnum.AnisotropicFilteringMode.Default, new ConfigDescription("Improves distant textures when they are being viewer from indirect angles.", (AcceptableValueBase)null, new object[0]));
RunInBackground = ((BaseUnityPlugin)this).Config.AddSetting<SettingEnum.RunInBackgroundMode>("General", "Run in background", SettingEnum.RunInBackgroundMode.Default, new ConfigDescription("Should the game be running when it is in the background (when the window is not focused)?\n", (AcceptableValueBase)null, new object[0]));
OptimizeInBackground = ((BaseUnityPlugin)this).Config.AddSetting<bool>("General", "Optimize in background", true, new ConfigDescription("Optimize the game when it is the background and unfocused. Settings such as anti-aliasing will be turned off or reduced in this state.", (AcceptableValueBase)null, new object[0]));
if (DisplayMode.Value == SettingEnum.DisplayMode.BorderlessFullscreen)
{
((MonoBehaviour)this).StartCoroutine(RemoveBorder());
}
DisplayMode.SettingChanged += delegate
{
SetDisplayMode();
};
SelectedMonitor.SettingChanged += delegate
{
((MonoBehaviour)this).StartCoroutine(SelectMonitor());
};
InitSetting<int>(FramerateLimit, SetFramerateLimit);
InitSetting<SettingEnum.VSyncType>(VSync, delegate
{
if (VSync.Value != SettingEnum.VSyncType.Default)
{
QualitySettings.vSyncCount = (int)VSync.Value;
}
});
InitSetting<SettingEnum.AntiAliasingMode>(AntiAliasing, delegate
{
if (AntiAliasing.Value != SettingEnum.AntiAliasingMode.Default)
{
QualitySettings.antiAliasing = (int)AntiAliasing.Value;
}
});
InitSetting<SettingEnum.AnisotropicFilteringMode>(AnisotropicFiltering, delegate
{
if (AnisotropicFiltering.Value != SettingEnum.AnisotropicFilteringMode.Default)
{
QualitySettings.anisotropicFiltering = (AnisotropicFiltering)AnisotropicFiltering.Value;
}
});
InitSetting<SettingEnum.RunInBackgroundMode>(RunInBackground, delegate
{
if (RunInBackground.Value != SettingEnum.RunInBackgroundMode.Default)
{
Application.runInBackground = RunInBackground.Value == SettingEnum.RunInBackgroundMode.Yes;
}
});
}
private void OnApplicationFocus(bool hasFocus)
{
if (OptimizeInBackground.Value)
{
if (lastAntiAliasingValue < 0 || !hasFocus)
{
lastAntiAliasingValue = QualitySettings.antiAliasing;
}
if (!hasFocus)
{
QualitySettings.antiAliasing = 0;
}
else if (AntiAliasing.Value != SettingEnum.AntiAliasingMode.Default)
{
QualitySettings.antiAliasing = (int)AntiAliasing.Value;
}
else
{
QualitySettings.antiAliasing = lastAntiAliasingValue;
}
}
}
private void ResolutionDrawer(ConfigEntryBase configEntry)
{
string text = GUILayout.TextField(resolutionX, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
string text2 = GUILayout.TextField(resolutionY, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
if (text != resolutionX && int.TryParse(text, out var result))
{
resolutionX = text;
}
if (text2 != resolutionY && int.TryParse(text2, out result))
{
resolutionY = text2;
}
if (GUILayout.Button("Apply", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }))
{
int num = int.Parse(resolutionX);
int num2 = int.Parse(resolutionY);
if (Screen.width != num || Screen.height != num2)
{
((MonoBehaviour)this).StartCoroutine(SetResolution(num, num2));
}
}
GUILayout.Space(5f);
if (GUILayout.Button("Reset", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }))
{
Display val = Display.displays[SelectedMonitor.Value];
if (Screen.width != val.renderingWidth || Screen.height != val.renderingHeight)
{
((MonoBehaviour)this).StartCoroutine(SetResolution(val.renderingWidth, val.renderingHeight));
}
}
IEnumerator SetResolution(int width, int height)
{
Screen.SetResolution(width, height, Screen.fullScreen);
yield return null;
UpdateConfigManagerSize();
resolutionX = Screen.width.ToString();
resolutionY = Screen.height.ToString();
if (DisplayMode.Value == SettingEnum.DisplayMode.BorderlessFullscreen)
{
((MonoBehaviour)this).StartCoroutine(RemoveBorder());
}
}
}
private void FramerateLimitDrawer(ConfigEntryBase configEntry)
{
//IL_0037: 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)
bool flag = GUILayout.Toggle(framerateToggle, "Enabled", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) });
if (flag != framerateToggle)
{
framerateToggle = flag;
if (flag)
{
Resolution currentResolution = Screen.currentResolution;
int refreshRate = ((Resolution)(ref currentResolution)).refreshRate;
FramerateLimit.Value = refreshRate;
Application.targetFrameRate = refreshRate;
}
else
{
FramerateLimit.Value = -1;
Application.targetFrameRate = -1;
}
}
int num = (int)GUILayout.HorizontalSlider((float)FramerateLimit.Value, 30f, 200f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
if (num != FramerateLimit.Value && framerateToggle)
{
FramerateLimit.Value = (Application.targetFrameRate = num);
if (!framerateToggle)
{
framerateToggle = true;
}
}
GUILayout.Space(5f);
GUILayout.TextField(FramerateLimit.Value.ToString(), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) });
}
private void SetDisplayMode()
{
switch (DisplayMode.Value)
{
case SettingEnum.DisplayMode.Windowed:
MakeWindowed();
break;
case SettingEnum.DisplayMode.Fullscreen:
MakeFullscreen();
break;
case SettingEnum.DisplayMode.BorderlessFullscreen:
((MonoBehaviour)this).StartCoroutine(RemoveBorder());
break;
case SettingEnum.DisplayMode.Default:
break;
}
}
private void SetFramerateLimit()
{
Application.targetFrameRate = FramerateLimit.Value;
framerateToggle = FramerateLimit.Value > 0;
}
private IEnumerator SelectMonitor()
{
PlayerPrefs.SetInt("UnitySelectMonitor", SelectedMonitor.Value);
Screen.SetResolution(800, 600, Screen.fullScreen);
yield return null;
Display val = Display.displays[SelectedMonitor.Value];
Screen.SetResolution(val.renderingWidth, val.renderingHeight, Screen.fullScreen);
yield return null;
UpdateConfigManagerSize();
resolutionX = Screen.width.ToString();
resolutionY = Screen.height.ToString();
if (DisplayMode.Value == SettingEnum.DisplayMode.BorderlessFullscreen)
{
((MonoBehaviour)this).StartCoroutine(RemoveBorder());
}
}
private IEnumerator RemoveBorder()
{
if (Screen.fullScreen)
{
Screen.SetResolution(Screen.width, Screen.height, false);
yield return null;
}
IntPtr activeWindow = WinAPI.GetActiveWindow();
if (!backupDone)
{
backupStandard = WinAPI.GetWindowLongPtr(activeWindow, WinAPI.WindowLongIndex.Style);
backupExtended = WinAPI.GetWindowLongPtr(activeWindow, WinAPI.WindowLongIndex.ExtendedStyle);
backupDone = true;
}
WinAPI.WindowStyleFlags dwNewLong = backupStandard & ~WinAPI.WindowStyleFlags.OverlappedWindow;
WinAPI.WindowStyleFlags dwNewLong2 = backupExtended & ~(WinAPI.WindowStyleFlags.ExtendedOverlappedWindow | WinAPI.WindowStyleFlags.ClipChildren | WinAPI.WindowStyleFlags.SystemMenu | WinAPI.WindowStyleFlags.ThickFrame | WinAPI.WindowStyleFlags.Group | WinAPI.WindowStyleFlags.ExtendedDlgModalFrame | WinAPI.WindowStyleFlags.ExtendedToolWindow);
int width = Screen.width;
int height = Screen.height;
WinAPI.SetWindowLongPtr(activeWindow, WinAPI.WindowLongIndex.Style, dwNewLong);
WinAPI.SetWindowLongPtr(activeWindow, WinAPI.WindowLongIndex.ExtendedStyle, dwNewLong2);
WinAPI.SetWindowPos(activeWindow, 0, 0, 0, width, height, WinAPI.SetWindowPosFlags.NoMove);
}
private void MakeWindowed()
{
RestoreBorder();
Screen.SetResolution(Screen.width, Screen.height, false);
}
private void MakeFullscreen()
{
RestoreBorder();
Screen.SetResolution(Screen.width, Screen.height, true);
}
private void InitSetting<T>(ConfigEntry<T> configEntry, Action setter)
{
setter();
configEntry.SettingChanged += delegate
{
setter();
};
}
private void RestoreBorder()
{
if (backupDone && DisplayMode.Value != SettingEnum.DisplayMode.BorderlessFullscreen)
{
IntPtr activeWindow = WinAPI.GetActiveWindow();
WinAPI.SetWindowLongPtr(activeWindow, WinAPI.WindowLongIndex.Style, backupStandard);
WinAPI.SetWindowLongPtr(activeWindow, WinAPI.WindowLongIndex.ExtendedStyle, backupExtended);
}
}
private void UpdateConfigManagerSize()
{
if (!configManagerSearch && !Object.op_Implicit(configManager))
{
configManagerSearch = true;
Type type = Type.GetType("ConfigurationManager.ConfigurationManager, ConfigurationManager", throwOnError: false);
if ((object)type != null)
{
configManager = Object.FindObjectOfType(type);
}
}
if (Object.op_Implicit(configManager))
{
Traverse.Create((object)configManager).Method("CalculateWindowRect", new object[0]).GetValue();
}
}
}
internal class SettingEnum
{
public enum VSyncType
{
Default = -1,
Disabled,
Enabled,
Half
}
public enum DisplayMode
{
Default,
Fullscreen,
[Description("Borderless fullscreen")]
BorderlessFullscreen,
Windowed
}
public enum AntiAliasingMode
{
Default = -1,
Disabled = 0,
[Description("2x MSAA")]
X2 = 2,
[Description("4x MSAA")]
X4 = 4,
[Description("8x MSAA")]
X8 = 8
}
public enum AnisotropicFilteringMode
{
Default = -1,
Disable,
Enable,
ForceEnable
}
public enum RunInBackgroundMode
{
Default = -1,
No,
Yes
}
}
internal static class WinAPI
{
public enum WindowLongIndex
{
Style = -16,
ExtendedStyle = -20
}
[Flags]
public enum WindowStyleFlags : uint
{
Overlapped = 0u,
Popup = 0x80000000u,
Child = 0x40000000u,
Minimize = 0x20000000u,
Visible = 0x10000000u,
Disabled = 0x8000000u,
ClipSiblings = 0x4000000u,
ClipChildren = 0x2000000u,
Maximize = 0x1000000u,
Border = 0x800000u,
DialogFrame = 0x400000u,
Vscroll = 0x200000u,
Hscroll = 0x100000u,
SystemMenu = 0x80000u,
ThickFrame = 0x40000u,
Group = 0x20000u,
Tabstop = 0x10000u,
MinimizeBox = 0x20000u,
MaximizeBox = 0x10000u,
Caption = 0xC00000u,
Tiled = 0u,
Iconic = 0x20000000u,
SizeBox = 0x40000u,
TiledWindow = 0u,
OverlappedWindow = 0xCF0000u,
ChildWindow = 0x40000000u,
ExtendedDlgModalFrame = 1u,
ExtendedNoParentNotify = 4u,
ExtendedTopmost = 8u,
ExtendedAcceptFiles = 0x10u,
ExtendedTransparent = 0x20u,
ExtendedMDIChild = 0x40u,
ExtendedToolWindow = 0x80u,
ExtendedWindowEdge = 0x100u,
ExtendedClientEdge = 0x200u,
ExtendedContextHelp = 0x400u,
ExtendedRight = 0x1000u,
ExtendedLeft = 0u,
ExtendedRTLReading = 0x2000u,
ExtendedLTRReading = 0u,
ExtendedLeftScrollbar = 0x4000u,
ExtendedRightScrollbar = 0u,
ExtendedControlParent = 0x10000u,
ExtendedStaticEdge = 0x20000u,
ExtendedAppWindow = 0x40000u,
ExtendedOverlappedWindow = 0x300u,
ExtendedPaletteWindow = 0x188u,
ExtendedLayered = 0x80000u,
ExtendedNoinheritLayout = 0x100000u,
ExtendedLayoutRTL = 0x400000u,
ExtendedComposited = 0x2000000u,
ExtendedNoActivate = 0x8000000u
}
[Flags]
public enum SetWindowPosFlags
{
AsyncWindowPos = 0x4000,
DeferBase = 0x2000,
DrawFrame = 0x20,
FrameChanged = 0x20,
HideWindow = 0x80,
NoActivate = 0x10,
NoCopyBits = 0x100,
NoMove = 2,
NoOwnerZOrder = 0x200,
NoReDraw = 8,
NoRePosition = 0x200,
NoSendChanging = 0x400,
NoSize = 1,
NoZOrder = 4,
ShowWindow = 0x40
}
[DllImport("user32.dll")]
public static extern IntPtr GetActiveWindow();
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int cx, int cy, SetWindowPosFlags wFlags);
[DllImport("user32.dll", EntryPoint = "SetWindowLong", SetLastError = true)]
public static extern WindowStyleFlags SetWindowLongPtr32(IntPtr hWnd, WindowLongIndex nIndex, WindowStyleFlags dwNewLong);
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", SetLastError = true)]
public static extern WindowStyleFlags SetWindowLongPtr64(IntPtr hWnd, WindowLongIndex nIndex, WindowStyleFlags dwNewLong);
public static WindowStyleFlags SetWindowLongPtr(IntPtr hWnd, WindowLongIndex nIndex, WindowStyleFlags dwNewLong)
{
if (IntPtr.Size != 8)
{
return SetWindowLongPtr32(hWnd, nIndex, dwNewLong);
}
return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
}
[DllImport("user32.dll", EntryPoint = "GetWindowLong")]
public static extern WindowStyleFlags GetWindowLongPtr32(IntPtr hWnd, WindowLongIndex nIndex);
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
public static extern WindowStyleFlags GetWindowLongPtr64(IntPtr hWnd, WindowLongIndex nIndex);
public static WindowStyleFlags GetWindowLongPtr(IntPtr hWnd, WindowLongIndex nIndex)
{
if (IntPtr.Size != 8)
{
return GetWindowLongPtr32(hWnd, nIndex);
}
return GetWindowLongPtr64(hWnd, nIndex);
}
}