From 74e39c437d2a9b0c99c870b62e3039f0fa903140 Mon Sep 17 00:00:00 2001 From: Clansty Date: Fri, 27 Sep 2024 21:50:27 +0800 Subject: [PATCH] [+] Window Magic! --- AquaMai/AquaMai.csproj | 1 + AquaMai/AquaMai.toml | 6 +++ AquaMai/AquaMai.zh.toml | 6 +++ AquaMai/Config.cs | 3 ++ AquaMai/Main.cs | 2 +- AquaMai/Utils/WindowState.cs | 82 ++++++++++++++++++++++++++++++++++++ 6 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 AquaMai/Utils/WindowState.cs diff --git a/AquaMai/AquaMai.csproj b/AquaMai/AquaMai.csproj index 9b5f785e..2e833770 100644 --- a/AquaMai/AquaMai.csproj +++ b/AquaMai/AquaMai.csproj @@ -314,6 +314,7 @@ + diff --git a/AquaMai/AquaMai.toml b/AquaMai/AquaMai.toml index fa18eac3..fa4c3bee 100644 --- a/AquaMai/AquaMai.toml +++ b/AquaMai/AquaMai.toml @@ -72,6 +72,12 @@ JudgeAdjustA=0.0 JudgeAdjustB=0.0 # Touch screen delay, unit is milliseconds, one second = 1000 milliseconds. Must be an integer TouchDelay=0 +# Window the game +Windowed=false +# Width and height for windowed mode, rendering resolution for fullscreen mode +# If set to 0, windowed mode will remember the user-set size, fullscreen mode will use the current display resolution +Width=0 +Height=0 # =================================== # Save some potentially unnecessary time diff --git a/AquaMai/AquaMai.zh.toml b/AquaMai/AquaMai.zh.toml index 512023c1..d5049b7e 100644 --- a/AquaMai/AquaMai.zh.toml +++ b/AquaMai/AquaMai.zh.toml @@ -88,6 +88,12 @@ JudgeAdjustA=0.0 JudgeAdjustB=0.0 # 触摸屏延迟,单位为毫秒,一秒 = 1000 毫秒。必须是整数 TouchDelay=0 +# 窗口化游戏 +Windowed=false +# 宽度和高度窗口化时为游戏窗口大小,全屏时为渲染分辨率 +# 如果设为 0,窗口化将记住用户设定的大小,全屏时将使用当前显示器分辨率 +Width=0 +Height=0 # =================================== # 节省一些不知道有用没用的时间 diff --git a/AquaMai/Config.cs b/AquaMai/Config.cs index 5a59fa4c..746d7bc8 100644 --- a/AquaMai/Config.cs +++ b/AquaMai/Config.cs @@ -57,6 +57,9 @@ namespace AquaMai public float JudgeAdjustA { get; set; } public float JudgeAdjustB { get; set; } public int TouchDelay { get; set; } + public bool Windowed { get; set; } + public int Width { get; set; } + public int Height { get; set; } } public class TimeSavingConfig diff --git a/AquaMai/Main.cs b/AquaMai/Main.cs index 4a132b4b..bd1c5d05 100644 --- a/AquaMai/Main.cs +++ b/AquaMai/Main.cs @@ -73,7 +73,6 @@ namespace AquaMai { Patch(directiveType); } - else MelonLogger.Error($"Type not found for {categoryProp.Name}.{settingProp.Name}"); } } } @@ -119,6 +118,7 @@ namespace AquaMai // Fixes that does not have side effects // These don't need to be configurable + WindowState.Execute(); // Helpers Patch(typeof(MessageHelper)); Patch(typeof(MusicDirHelper)); diff --git a/AquaMai/Utils/WindowState.cs b/AquaMai/Utils/WindowState.cs new file mode 100644 index 00000000..f6b91028 --- /dev/null +++ b/AquaMai/Utils/WindowState.cs @@ -0,0 +1,82 @@ +using System; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using UnityEngine; + +namespace AquaMai.Utils; + +public class WindowState +{ + private const int GWL_STYLE = -16; + private const int WS_WHATEVER = 0x14CF0000; + + private static IntPtr hwnd = IntPtr.Zero; + + public static void Execute() + { + if (AquaMai.AppConfig.Utils.Windowed) + { + var alreadyWindowed = Screen.fullScreenMode == FullScreenMode.Windowed; + if (AquaMai.AppConfig.Utils.Width == 0 || AquaMai.AppConfig.Utils.Height == 0) + { + Screen.fullScreenMode = FullScreenMode.Windowed; + } + else + { + alreadyWindowed = false; + Screen.SetResolution(AquaMai.AppConfig.Utils.Width, AquaMai.AppConfig.Utils.Height, FullScreenMode.Windowed); + } + + hwnd = GetWindowHandle(); + if(alreadyWindowed) + { + SetResizeable(); + } + else + { + Task.Run(async () => + { + await Task.Delay(3000); + // Screen.SetResolution has delay + SetResizeable(); + }); + } + } + else + { + var width = AquaMai.AppConfig.Utils.Width == 0 ? Display.main.systemWidth : AquaMai.AppConfig.Utils.Width; + var height = AquaMai.AppConfig.Utils.Height == 0 ? Display.main.systemHeight : AquaMai.AppConfig.Utils.Height; + Screen.SetResolution(width, height, FullScreenMode.FullScreenWindow); + } + } + + public static void SetResizeable() + { + if (hwnd == IntPtr.Zero) return; + SetWindowLongPtr(hwnd, GWL_STYLE, WS_WHATEVER); + } + + private delegate bool EnumThreadDelegate(IntPtr hwnd, IntPtr lParam); + + [DllImport("user32.dll")] + static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam); + + [DllImport("Kernel32.dll")] + static extern int GetCurrentThreadId(); + + static IntPtr GetWindowHandle() + { + IntPtr returnHwnd = IntPtr.Zero; + var threadId = GetCurrentThreadId(); + EnumThreadWindows(threadId, + (hWnd, lParam) => + { + if (returnHwnd == IntPtr.Zero) returnHwnd = hWnd; + return true; + }, IntPtr.Zero); + return returnHwnd; + } + + [DllImport("user32.dll")] + static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, int dwNewLong); +}