diff --git a/UXAssist/Common/WinApi.cs b/UXAssist/Common/WinApi.cs index 2eccee5..3297a63 100644 --- a/UXAssist/Common/WinApi.cs +++ b/UXAssist/Common/WinApi.cs @@ -3,55 +3,78 @@ using System.Runtime.InteropServices; namespace UXAssist.Common; -[Flags] -public enum WindowStyles: int -{ - WS_BORDER = 0x00800000, - WS_CAPTION = 0x00C00000, - WS_CHILD = 0x40000000, - WS_CHILDWINDOW = 0x40000000, - WS_CLIPCHILDREN = 0x02000000, - WS_CLIPSIBLINGS = 0x04000000, - WS_DISABLED = 0x08000000, - WS_DLGFRAME = 0x00400000, - WS_GROUP = 0x00020000, - WS_HSCROLL = 0x00100000, - WS_ICONIC = 0x20000000, - WS_MAXIMIZE = 0x01000000, - WS_MAXIMIZEBOX = 0x00010000, - WS_MINIMIZE = 0x20000000, - WS_MINIMIZEBOX = 0x00020000, - WS_OVERLAPPED = 0x00000000, - WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, - WS_POPUP = unchecked((int)0x80000000), - WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU, - WS_SIZEBOX = 0x00040000, - WS_SYSMENU = 0x00080000, - WS_TABSTOP = 0x00010000, - WS_THICKFRAME = 0x00040000, - WS_TILED = 0x00000000, - WS_TILEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, - WS_VISIBLE = 0x10000000, - WS_VSCROLL = 0x00200000 -} - -[Flags] -public enum WindowLongFlags: int -{ - GWL_EXSTYLE = -20, - GWLP_HINSTANCE = -6, - GWLP_HWNDPARENT = -8, - GWLP_ID = -12, - GWL_STYLE = -16, - GWLP_USERDATA = -21, - GWLP_WNDPROC = -4, - DWLP_DLGPROC = 0x4, - DWLP_MSGRESULT = 0, - DWLP_USER = 0x8 -} - public static class WinApi { + #region Styles + + public const int WS_BORDER = 0x00800000; + public const int WS_CAPTION = 0x00C00000; + public const int WS_CHILD = 0x40000000; + public const int WS_CHILDWINDOW = 0x40000000; + public const int WS_CLIPCHILDREN = 0x02000000; + public const int WS_CLIPSIBLINGS = 0x04000000; + public const int WS_DISABLED = 0x08000000; + public const int WS_DLGFRAME = 0x00400000; + public const int WS_GROUP = 0x00020000; + public const int WS_HSCROLL = 0x00100000; + public const int WS_ICONIC = 0x20000000; + public const int WS_MAXIMIZE = 0x01000000; + public const int WS_MAXIMIZEBOX = 0x00010000; + public const int WS_MINIMIZE = 0x20000000; + public const int WS_MINIMIZEBOX = 0x00020000; + public const int WS_OVERLAPPED = 0x00000000; + public const int WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX; + public const int WS_POPUP = unchecked((int)0x80000000); + public const int WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU; + public const int WS_SIZEBOX = 0x00040000; + public const int WS_SYSMENU = 0x00080000; + public const int WS_TABSTOP = 0x00010000; + public const int WS_THICKFRAME = 0x00040000; + public const int WS_TILED = 0x00000000; + public const int WS_TILEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX; + public const int WS_VISIBLE = 0x10000000; + public const int WS_VSCROLL = 0x00200000; + + #endregion + + #region GetWindowLong and SetWindowLong Flags + + public const int GWL_EXSTYLE = -20; + public const int GWLP_HINSTANCE = -6; + public const int GWLP_HWNDPARENT = -8; + public const int GWLP_ID = -12; + public const int GWL_STYLE = -16; + public const int GWLP_USERDATA = -21; + public const int GWLP_WNDPROC = -4; + public const int DWLP_DLGPROC = 0x4; + public const int DWLP_MSGRESULT = 0; + public const int DWLP_USER = 0x8; + + #endregion + + #region Messages + + public const int WM_CREATE = 0x0001; + public const int WM_DESTROY = 0x0002; + public const int WM_MOVE = 0x0003; + public const int WM_SIZE = 0x0005; + public const int WM_ACTIVATE = 0x0006; + public const int WM_SETFOCUS = 0x0007; + public const int WM_KILLFOCUS = 0x0008; + public const int WM_ENABLE = 0x000A; + public const int WM_CLOSE = 0x0010; + public const int WM_QUIT = 0x0012; + public const int WM_SIZING = 0x0214; + + #endregion + + #region Errors + + private const int ERROR_INSUFFICIENT_BUFFER = 122; + + #endregion + + #region Structs [StructLayout(LayoutKind.Sequential)] public struct Rect @@ -59,6 +82,10 @@ public static class WinApi public int Left, Top, Right, Bottom; } + #endregion + + public delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); + [DllImport("user32", CharSet = CharSet.Unicode)] public static extern int GetWindowLong(IntPtr hwnd, int nIndex); @@ -79,4 +106,162 @@ public static class WinApi [DllImport("user32", ExactSpelling = true)] public static extern bool MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool bRepaint); + + [DllImport("kernel32", ExactSpelling = true, SetLastError = true)] + public static extern bool GetProcessAffinityMask(IntPtr hProcess, out IntPtr lpProcessAffinityMask, out IntPtr lpSystemAffinityMask); + + [DllImport("kernel32", ExactSpelling = true, SetLastError = true)] + public static extern IntPtr GetCurrentProcess(); + + [DllImport("kernel32", ExactSpelling = true, SetLastError = true)] + public static extern bool SetProcessAffinityMask(IntPtr hProcess, IntPtr dwProcessAffinityMask); + + // GetPriorityClass and SetPriorityClass + [DllImport("kernel32", ExactSpelling = true, SetLastError = true)] + public static extern int GetPriorityClass(IntPtr hProcess); + + [DllImport("kernel32", ExactSpelling = true, SetLastError = true)] + public static extern bool SetPriorityClass(IntPtr hProcess, int dwPriorityClass); + + [DllImport("user32", CharSet = CharSet.Unicode)] + public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong); + + [DllImport("user32", CharSet = CharSet.Unicode)] + public static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam); + + #region GetLogicalProcessorInformation + + [Flags] + public enum LOGICAL_PROCESSOR_RELATIONSHIP + { + RelationProcessorCore, + RelationNumaNode, + RelationCache, + RelationProcessorPackage, + RelationGroup, + RelationAll = 0xffff + } + + [StructLayout(LayoutKind.Sequential)] + public struct PROCESSORCORE + { + public byte Flags; + } + + [StructLayout(LayoutKind.Sequential)] + public struct NUMANODE + { + public uint NodeNumber; + } + + public enum PROCESSOR_CACHE_TYPE + { + CacheUnified, + CacheInstruction, + CacheData, + CacheTrace + } + + [StructLayout(LayoutKind.Sequential)] + public struct CACHE_DESCRIPTOR + { + public byte Level; + public byte Associativity; + public ushort LineSize; + public uint Size; + public PROCESSOR_CACHE_TYPE Type; + } + + [StructLayout(LayoutKind.Explicit)] + public struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION_UNION + { + [FieldOffset(0)] + public PROCESSORCORE ProcessorCore; + [FieldOffset(0)] + public NUMANODE NumaNode; + [FieldOffset(0)] + public CACHE_DESCRIPTOR Cache; + [FieldOffset(0)] + private UInt64 Reserved1; + [FieldOffset(8)] + private UInt64 Reserved2; + } + + public struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION + { + public UIntPtr ProcessorMask; + public LOGICAL_PROCESSOR_RELATIONSHIP Relationship; + public SYSTEM_LOGICAL_PROCESSOR_INFORMATION_UNION ProcessorInformation; + } + + [DllImport(@"kernel32", SetLastError=true)] + private static extern bool GetLogicalProcessorInformation( + IntPtr buffer, + ref uint returnLength + ); + + public struct LogicalProcessorDetails + { + public int CoreCount; + public int ThreadCount; + public int PerformanceCoreCount; + public int EfficiencyCoreCount; + public ulong PerformanceCoreMask; + public ulong EfficiencyCoreMask; + public bool HybridArchitecture => PerformanceCoreCount > 0 && EfficiencyCoreCount > 0; + } + + public static LogicalProcessorDetails GetLogicalProcessorDetails() + { + uint returnLength = 0; + GetLogicalProcessorInformation(IntPtr.Zero, ref returnLength); + var result = new LogicalProcessorDetails(); + if (Marshal.GetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER) return result; + var ptr = Marshal.AllocHGlobal((int)returnLength); + try + { + if (!GetLogicalProcessorInformation(ptr, ref returnLength)) + return result; + var size = Marshal.SizeOf(typeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)); + var len = (int)returnLength / size; + var item = ptr; + for (var i = 0; i < len; i++) + { + var buffer = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION)Marshal.PtrToStructure(item, typeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)); + item += size; + if (buffer.Relationship != LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore) continue; + result.CoreCount++; + var tcount = CountBitsSet((ulong)buffer.ProcessorMask); + result.ThreadCount += tcount; + if (tcount > 1) + { + result.PerformanceCoreCount ++; + result.PerformanceCoreMask |= (ulong)buffer.ProcessorMask; + } + else + { + result.EfficiencyCoreCount ++; + result.EfficiencyCoreMask |= (ulong)buffer.ProcessorMask; + } + } + } + finally + { + Marshal.FreeHGlobal(ptr); + } + return result; + + int CountBitsSet(ulong mask) + { + var count = 0; + while (mask != 0) + { + mask &= mask - 1; + count++; + } + return count; + } + } + + #endregion } \ No newline at end of file diff --git a/UXAssist/Functions/WindowFunctions.cs b/UXAssist/Functions/WindowFunctions.cs new file mode 100644 index 0000000..ad14b40 --- /dev/null +++ b/UXAssist/Functions/WindowFunctions.cs @@ -0,0 +1,149 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; +using UXAssist.Common; + +namespace UXAssist.Functions; + +public static class WindowFunctions +{ + public static string ProfileName { get; private set; } + + private const string GameWindowClass = "UnityWndClass"; + private static string _gameWindowTitle = "Dyson Sphere Program"; + + private static IntPtr _oldWndProc = IntPtr.Zero; + private static IntPtr _gameWindowHandle = IntPtr.Zero; + + public static void Start() + { + var wndProc = new WinApi.WndProc(GameWndProc); + var gameWnd = FindGameWindow(); + if (gameWnd != IntPtr.Zero) + { + _oldWndProc = WinApi.SetWindowLongPtr(gameWnd, WinApi.GWLP_WNDPROC, Marshal.GetFunctionPointerForDelegate(wndProc)); + } + } + + private static IntPtr GameWndProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam) + { + switch (uMsg) + { + case WinApi.WM_ACTIVATE: + UXAssist.Logger.LogDebug($"Activate: {wParam.ToInt32()}, {lParam.ToInt32()}"); + // TODO: Set Priority like: WinApi.SetPriorityClass(WinApi.GetCurrentProcess(), 0x00000080); + break; + case WinApi.WM_DESTROY: + if (_oldWndProc != IntPtr.Zero && _gameWindowHandle != IntPtr.Zero) + { + WinApi.SetWindowLongPtr(_gameWindowHandle, WinApi.GWLP_WNDPROC, _oldWndProc); + } + break; + } + + return WinApi.CallWindowProc(_oldWndProc, hWnd, uMsg, wParam, lParam); + } + public static void ShowCPUInfo() + { + var details = WinApi.GetLogicalProcessorDetails(); + var msg = $"Cores: {details.CoreCount}\nThreads: {details.ThreadCount}"; + var hybrid = details.HybridArchitecture; + if (hybrid) + { + msg += "\nP-Cores: {details.PerformanceCoreCount}\nE-Cores: {details.EfficiencyCoreCount}"; + } + + var handle = WinApi.GetCurrentProcess(); + var prio = (ProcessPriorityClass)WinApi.GetPriorityClass(handle); + msg += $"\nPriority: {prio}"; + + var aff = 0UL; + if (WinApi.GetProcessAffinityMask(handle, out var processMask, out var systemMask)) + aff = (ulong)processMask & (ulong)systemMask; + + msg += $"\nEnabled CPUs: "; + var first = true; + for (var i = 0; aff != 0UL; i++) + { + if ((aff & 1UL) != 0) + { + if (first) + first = false; + else + msg += ","; + msg += i; + if (hybrid) + { + if ((details.PerformanceCoreMask & (1UL << i)) != 0) + msg += "(P)"; + else if ((details.EfficiencyCoreMask & (1UL << i)) != 0) + msg += "(E)"; + } + } + + aff >>= 1; + } + + UIMessageBox.Show("CPU Info".Translate(), msg, "OK".Translate(), -1); + } + + public static void SetWindowTitle() + { + // Get profile name from command line arguments, and set window title accordingly + var args = Environment.GetCommandLineArgs(); + for (var i = 0; i < args.Length - 1; i++) + { + if (args[i] != "--doorstop-target") continue; + var arg = args[i + 1]; + const string doorstopPathSuffix = @"\BepInEx\core\BepInEx.Preloader.dll"; + if (!arg.EndsWith(doorstopPathSuffix, StringComparison.OrdinalIgnoreCase)) + break; + arg = arg.Substring(0, arg.Length - doorstopPathSuffix.Length); + const string profileSuffix = @"\profiles\"; + var index = arg.LastIndexOf(profileSuffix, StringComparison.OrdinalIgnoreCase); + if (index < 0) + break; + arg = arg.Substring(index + profileSuffix.Length); + var wnd = WinApi.FindWindow(GameWindowClass, _gameWindowTitle); + if (wnd == IntPtr.Zero) return; + ProfileName = arg; + _gameWindowTitle = $"Dyson Sphere Program - {arg}"; + WinApi.SetWindowText(wnd, _gameWindowTitle); + break; + } + } + + public static void RefreshSavePath() + { + if (ProfileName == null) return; + + if (UIRoot.instance.loadGameWindow.gameObject.activeSelf) + { + UIRoot.instance.loadGameWindow._Close(); + } + if (UIRoot.instance.saveGameWindow.gameObject.activeSelf) + { + UIRoot.instance.saveGameWindow._Close(); + } + + string gameSavePath; + if (Patches.GamePatch.ProfileBasedSaveFolderEnabled.Value && string.Compare(Patches.GamePatch.DefaultProfileName.Value, ProfileName, StringComparison.OrdinalIgnoreCase) != 0) + gameSavePath = $"{GameConfig.overrideDocumentFolder}{GameConfig.gameName}/Save/{ProfileName}/"; + else + gameSavePath = $"{GameConfig.overrideDocumentFolder}{GameConfig.gameName}/Save/"; + if (string.Compare(GameConfig.gameSavePath, gameSavePath, StringComparison.OrdinalIgnoreCase) == 0) return; + GameConfig.gameSavePath = gameSavePath; + if (!Directory.Exists(GameConfig.gameSavePath)) + { + Directory.CreateDirectory(GameConfig.gameSavePath); + } + } + + public static IntPtr FindGameWindow() + { + if (_gameWindowHandle == IntPtr.Zero) + _gameWindowHandle = WinApi.FindWindow(GameWindowClass, _gameWindowTitle); + return _gameWindowHandle; + } +} diff --git a/UXAssist/Patches/GamePatch.cs b/UXAssist/Patches/GamePatch.cs index d26421b..5bb8c2c 100644 --- a/UXAssist/Patches/GamePatch.cs +++ b/UXAssist/Patches/GamePatch.cs @@ -12,11 +12,6 @@ namespace UXAssist.Patches; public class GamePatch: PatchImpl { - private const string GameWindowClass = "UnityWndClass"; - private static string _gameWindowTitle = "Dyson Sphere Program"; - - public static string ProfileName { get; private set; } - public static ConfigEntry EnableWindowResizeEnabled; public static ConfigEntry LoadLastWindowRectEnabled; public static ConfigEntry MouseCursorScaleUpMultiplier; @@ -75,28 +70,7 @@ public class GamePatch: PatchImpl I18N.Add("KEYUPSSpeedUp", "Increase logical frame rate", "提升逻辑帧率"); I18N.Add("Logical frame rate: {0}x", "Logical frame rate: {0}x", "逻辑帧速率: {0}x"); - // Get profile name from command line arguments, and set window title accordingly - var args = Environment.GetCommandLineArgs(); - for (var i = 0; i < args.Length - 1; i++) - { - if (args[i] != "--doorstop-target") continue; - var arg = args[i + 1]; - const string doorstopPathSuffix = @"\BepInEx\core\BepInEx.Preloader.dll"; - if (!arg.EndsWith(doorstopPathSuffix, StringComparison.OrdinalIgnoreCase)) - break; - arg = arg.Substring(0, arg.Length - doorstopPathSuffix.Length); - const string profileSuffix = @"\profiles\"; - var index = arg.LastIndexOf(profileSuffix, StringComparison.OrdinalIgnoreCase); - if (index < 0) - break; - arg = arg.Substring(index + profileSuffix.Length); - var wnd = WinApi.FindWindow(GameWindowClass, _gameWindowTitle); - if (wnd == IntPtr.Zero) return; - ProfileName = arg; - _gameWindowTitle = $"Dyson Sphere Program - {arg}"; - WinApi.SetWindowText(wnd, _gameWindowTitle); - break; - } + Functions.WindowFunctions.SetWindowTitle(); EnableWindowResizeEnabled.SettingChanged += (_, _) => EnableWindowResize.Enable(EnableWindowResizeEnabled.Value); LoadLastWindowRectEnabled.SettingChanged += (_, _) => LoadLastWindowRect.Enable(LoadLastWindowRectEnabled.Value); @@ -107,8 +81,8 @@ public class GamePatch: PatchImpl }; // AutoSaveOptEnabled.SettingChanged += (_, _) => AutoSaveOpt.Enable(AutoSaveOptEnabled.Value); ConvertSavesFromPeaceEnabled.SettingChanged += (_, _) => ConvertSavesFromPeace.Enable(ConvertSavesFromPeaceEnabled.Value); - ProfileBasedSaveFolderEnabled.SettingChanged += (_, _) => RefreshSavePath(); - DefaultProfileName.SettingChanged += (_, _) => RefreshSavePath(); + ProfileBasedSaveFolderEnabled.SettingChanged += (_, _) => Functions.WindowFunctions.RefreshSavePath(); + DefaultProfileName.SettingChanged += (_, _) => Functions.WindowFunctions.RefreshSavePath(); GameUpsFactor.SettingChanged += (_, _) => { if (!EnableGameUpsFactor || GameUpsFactor.Value == 0.0) return; @@ -158,36 +132,10 @@ public class GamePatch: PatchImpl } } - private static void RefreshSavePath() - { - if (ProfileName == null) return; - - if (UIRoot.instance.loadGameWindow.gameObject.activeSelf) - { - UIRoot.instance.loadGameWindow._Close(); - } - if (UIRoot.instance.saveGameWindow.gameObject.activeSelf) - { - UIRoot.instance.saveGameWindow._Close(); - } - - string gameSavePath; - if (ProfileBasedSaveFolderEnabled.Value && string.Compare(DefaultProfileName.Value, ProfileName, StringComparison.OrdinalIgnoreCase) != 0) - gameSavePath = $"{GameConfig.overrideDocumentFolder}{GameConfig.gameName}/Save/{ProfileName}/"; - else - gameSavePath = $"{GameConfig.overrideDocumentFolder}{GameConfig.gameName}/Save/"; - if (string.Compare(GameConfig.gameSavePath, gameSavePath, StringComparison.OrdinalIgnoreCase) == 0) return; - GameConfig.gameSavePath = gameSavePath; - if (!Directory.Exists(GameConfig.gameSavePath)) - { - Directory.CreateDirectory(GameConfig.gameSavePath); - } - } - [HarmonyPrefix, HarmonyPatch(typeof(GameMain), nameof(GameMain.HandleApplicationQuit))] private static void GameMain_HandleApplicationQuit_Prefix() { - var wnd = WinApi.FindWindow(GameWindowClass, _gameWindowTitle); + var wnd = Functions.WindowFunctions.FindGameWindow(); if (wnd == IntPtr.Zero) return; WinApi.GetWindowRect(wnd, out var rect); LastWindowRect.Value = new Vector4(rect.Left, rect.Top, Screen.width, Screen.height); @@ -200,7 +148,7 @@ public class GamePatch: PatchImpl protected override void OnEnable() { - var wnd = WinApi.FindWindow(GameWindowClass, _gameWindowTitle); + var wnd = Functions.WindowFunctions.FindGameWindow(); if (wnd == IntPtr.Zero) { Enable(false); @@ -208,33 +156,33 @@ public class GamePatch: PatchImpl } _enabled = true; - WinApi.SetWindowLong(wnd, (int)WindowLongFlags.GWL_STYLE, - WinApi.GetWindowLong(wnd, (int)WindowLongFlags.GWL_STYLE) | (int)WindowStyles.WS_THICKFRAME | (int)WindowStyles.WS_MAXIMIZEBOX); + WinApi.SetWindowLong(wnd, WinApi.GWL_STYLE, + WinApi.GetWindowLong(wnd, WinApi.GWL_STYLE) | WinApi.WS_THICKFRAME | WinApi.WS_MAXIMIZEBOX); } protected override void OnDisable() { - var wnd = WinApi.FindWindow(GameWindowClass, _gameWindowTitle); + var wnd = Functions.WindowFunctions.FindGameWindow(); if (wnd == IntPtr.Zero) return; _enabled = false; - WinApi.SetWindowLong(wnd, (int)WindowLongFlags.GWL_STYLE, - WinApi.GetWindowLong(wnd, (int)WindowLongFlags.GWL_STYLE) & ~((int)WindowStyles.WS_THICKFRAME | (int)WindowStyles.WS_MAXIMIZEBOX)); + WinApi.SetWindowLong(wnd, WinApi.GWL_STYLE, + WinApi.GetWindowLong(wnd, WinApi.GWL_STYLE) & ~(WinApi.WS_THICKFRAME | WinApi.WS_MAXIMIZEBOX)); } [HarmonyPostfix] [HarmonyPatch(typeof(UIOptionWindow), nameof(UIOptionWindow.ApplyOptions))] private static void UIOptionWindow_ApplyOptions_Postfix() { - var wnd = WinApi.FindWindow(GameWindowClass, _gameWindowTitle); + var wnd = Functions.WindowFunctions.FindGameWindow(); if (wnd == IntPtr.Zero) return; if (_enabled) - WinApi.SetWindowLong(wnd, (int)WindowLongFlags.GWL_STYLE, - WinApi.GetWindowLong(wnd, (int)WindowLongFlags.GWL_STYLE) | (int)WindowStyles.WS_THICKFRAME | (int)WindowStyles.WS_MAXIMIZEBOX); + WinApi.SetWindowLong(wnd, WinApi.GWL_STYLE, + WinApi.GetWindowLong(wnd, WinApi.GWL_STYLE) | WinApi.WS_THICKFRAME | WinApi.WS_MAXIMIZEBOX); else - WinApi.SetWindowLong(wnd, (int)WindowLongFlags.GWL_STYLE, - WinApi.GetWindowLong(wnd, (int)WindowLongFlags.GWL_STYLE) & ~((int)WindowStyles.WS_THICKFRAME | (int)WindowStyles.WS_MAXIMIZEBOX)); + WinApi.SetWindowLong(wnd, WinApi.GWL_STYLE, + WinApi.GetWindowLong(wnd, WinApi.GWL_STYLE) & ~(WinApi.WS_THICKFRAME | WinApi.WS_MAXIMIZEBOX)); } } @@ -301,7 +249,7 @@ public class GamePatch: PatchImpl private static void MoveWindowPosition() { if (Screen.fullScreenMode is FullScreenMode.ExclusiveFullScreen or FullScreenMode.FullScreenWindow or FullScreenMode.MaximizedWindow || GameMain.isRunning) return; - var wnd = WinApi.FindWindow(GameWindowClass, _gameWindowTitle); + var wnd = Functions.WindowFunctions.FindGameWindow(); if (wnd == IntPtr.Zero) return; var rect = LastWindowRect.Value; if (rect is { z: 0f, w: 0f }) return; @@ -334,7 +282,7 @@ public class GamePatch: PatchImpl { if (_loaded || Screen.fullScreenMode is FullScreenMode.ExclusiveFullScreen or FullScreenMode.FullScreenWindow or FullScreenMode.MaximizedWindow) return; _loaded = true; - var wnd = WinApi.FindWindow(GameWindowClass, _gameWindowTitle); + var wnd = Functions.WindowFunctions.FindGameWindow(); if (wnd == IntPtr.Zero) return; var rect = LastWindowRect.Value; if (rect is { z: 0f, w: 0f }) return; @@ -345,8 +293,8 @@ public class GamePatch: PatchImpl Screen.SetResolution(w, h, false); WinApi.SetWindowPos(wnd, IntPtr.Zero, x, y, 0, 0, 0x0235); if (EnableWindowResizeEnabled.Value) - WinApi.SetWindowLong(wnd, (int)WindowLongFlags.GWL_STYLE, - WinApi.GetWindowLong(wnd, (int)WindowLongFlags.GWL_STYLE) | (int)WindowStyles.WS_THICKFRAME | (int)WindowStyles.WS_MAXIMIZEBOX); + WinApi.SetWindowLong(wnd, WinApi.GWL_STYLE, + WinApi.GetWindowLong(wnd, WinApi.GWL_STYLE) | WinApi.WS_THICKFRAME | WinApi.WS_MAXIMIZEBOX); } private static GameOption _gameOption; diff --git a/UXAssist/UIConfigWindow.cs b/UXAssist/UIConfigWindow.cs index bac42b1..16b3bc0 100644 --- a/UXAssist/UIConfigWindow.cs +++ b/UXAssist/UIConfigWindow.cs @@ -147,7 +147,7 @@ public static class UIConfigWindow */ y += 36f; wnd.AddCheckBox(x, y, tab1, GamePatch.ConvertSavesFromPeaceEnabled, "Convert old saves to Combat Mode on loading"); - if (GamePatch.ProfileName != null) + if (WindowFunctions.ProfileName != null) { y += 36f; checkBoxForMeasureTipsPos = wnd.AddCheckBox(x, y, tab1, GamePatch.ProfileBasedSaveFolderEnabled, "Profile-based save folder"); @@ -162,6 +162,10 @@ public static class UIConfigWindow y += 18f; } + x = 400f; + y = 10f; + wnd.AddButton(x, y, tab1, "Show CPU Info", 16, "button-show-cpu-info", WindowFunctions.ShowCPUInfo); + if (!ModsCompat.BulletTimeWrapper.HasBulletTime) { y += 36f; @@ -351,6 +355,7 @@ public static class UIConfigWindow cb1.gameObject.SetActive(true); return; } + var on = !ModsCompat.AuxilaryfunctionWrapper.ShowStationInfo.Value; cb0.gameObject.SetActive(on); cb1.gameObject.SetActive(on); diff --git a/UXAssist/UXAssist.cs b/UXAssist/UXAssist.cs index dcdce29..460568b 100644 --- a/UXAssist/UXAssist.cs +++ b/UXAssist/UXAssist.cs @@ -158,7 +158,8 @@ public class UXAssist : BaseUnityPlugin, IModCanSave UIConfigWindow.Init(); - _patches = Common.Util.GetTypesInNamespace(Assembly.GetExecutingAssembly(), "UXAssist.Patches"); + _patches = Common.Util.GetTypesFiltered(Assembly.GetExecutingAssembly(), + t => string.Equals(t.Namespace, "UXAssist.Patches", StringComparison.Ordinal) || string.Equals(t.Namespace, "UXAssist.Functions", StringComparison.Ordinal)); _patches?.Do(type => type.GetMethod("Init")?.Invoke(null, null)); _compats = Common.Util.GetTypesInNamespace(Assembly.GetExecutingAssembly(), "UXAssist.ModsCompat"); _compats?.Do(type => type.GetMethod("Init")?.Invoke(null, null));