From aa3c02f9b5a07dc4660aa449444ce414b7fd27b8 Mon Sep 17 00:00:00 2001 From: SadPencil Date: Sat, 28 Sep 2024 19:56:29 +0800 Subject: [PATCH 1/9] Add integer scaling feature Upgrade XNAUI to 2.3.22 --- ClientCore/ClientConfiguration.cs | 16 +- ClientCore/Settings/UserINISettings.cs | 6 +- DTAConfig/OptionPanels/DisplayOptionsPanel.cs | 4 +- DTAConfig/ScreenResolution.cs | 28 +++- DXMainClient/DXGUI/GameClass.cs | 153 +++++++++++++----- Directory.Packages.props | 2 +- 6 files changed, 161 insertions(+), 48 deletions(-) diff --git a/ClientCore/ClientConfiguration.cs b/ClientCore/ClientConfiguration.cs index d80fb6a05..1bbc27258 100644 --- a/ClientCore/ClientConfiguration.cs +++ b/ClientCore/ClientConfiguration.cs @@ -16,6 +16,7 @@ public class ClientConfiguration private const string SETTINGS = "Settings"; private const string LINKS = "Links"; private const string TRANSLATIONS = "Translations"; + private const string USER_DEFAULTS = "UserDefaults"; private const string CLIENT_SETTINGS = "DTACnCNetClient.ini"; private const string GAME_OPTIONS = "GameOptions.ini"; @@ -193,7 +194,8 @@ public void RefreshSettings() public int MaximumRenderHeight => clientDefinitionsIni.GetIntValue(SETTINGS, "MaximumRenderHeight", 800); - public string[] RecommendedResolutions => clientDefinitionsIni.GetStringValue(SETTINGS, "RecommendedResolutions", "1280x720,2560x1440,3840x2160").Split(','); + public string[] RecommendedResolutions => clientDefinitionsIni.GetStringValue(SETTINGS, "RecommendedResolutions", + $"{MinimumRenderWidth}x{MinimumRenderHeight},{MaximumRenderWidth}x{MaximumRenderHeight}").Split(','); public string WindowTitle => clientDefinitionsIni.GetStringValue(SETTINGS, "WindowTitle", string.Empty) .L10N("INI:ClientDefinitions:WindowTitle"); @@ -405,6 +407,16 @@ public IEnumerable SupplementalMapFileExtensions #endregion + #region User default settings + + public bool UserDefault_BorderlessWindowedClient => clientDefinitionsIni.GetBooleanValue(USER_DEFAULTS, "BorderlessWindowedClient", true); + + public bool UserDefault_IntegerScaledClient => clientDefinitionsIni.GetBooleanValue(USER_DEFAULTS, "IntegerScaledClient", false); + + public bool UserDefault_WriteInstallationPathToRegistry => clientDefinitionsIni.GetBooleanValue(USER_DEFAULTS, "WriteInstallationPathToRegistry", true); + + #endregion + public List GetIRCServers() { List servers = []; @@ -419,7 +431,7 @@ public List GetIRCServers() } public bool DiscordIntegrationGloballyDisabled => string.IsNullOrWhiteSpace(DiscordAppId) || DisableDiscordIntegration; - + public OSVersion GetOperatingSystemVersion() { #if NETFRAMEWORK diff --git a/ClientCore/Settings/UserINISettings.cs b/ClientCore/Settings/UserINISettings.cs index 671c823fe..9a0829d6f 100644 --- a/ClientCore/Settings/UserINISettings.cs +++ b/ClientCore/Settings/UserINISettings.cs @@ -63,7 +63,8 @@ protected UserINISettings(IniFile iniFile) Renderer = new StringSetting(iniFile, COMPATIBILITY, "Renderer", string.Empty); WindowedMode = new BoolSetting(iniFile, VIDEO, WINDOWED_MODE_KEY, false); BorderlessWindowedMode = new BoolSetting(iniFile, VIDEO, "NoWindowFrame", false); - BorderlessWindowedClient = new BoolSetting(iniFile, VIDEO, "BorderlessWindowedClient", true); + BorderlessWindowedClient = new BoolSetting(iniFile, VIDEO, "BorderlessWindowedClient", ClientConfiguration.Instance.UserDefault_BorderlessWindowedClient); + IntegerScaledClient = new BoolSetting(iniFile, VIDEO, "IntegerScaledClient", ClientConfiguration.Instance.UserDefault_IntegerScaledClient); ClientFPS = new IntSetting(iniFile, VIDEO, "ClientFPS", 60); DisplayToggleableExtraTextures = new BoolSetting(iniFile, VIDEO, "DisplayToggleableExtraTextures", true); @@ -86,7 +87,7 @@ protected UserINISettings(IniFile iniFile) ChatColor = new IntSetting(iniFile, MULTIPLAYER, "ChatColor", -1); LANChatColor = new IntSetting(iniFile, MULTIPLAYER, "LANChatColor", -1); PingUnofficialCnCNetTunnels = new BoolSetting(iniFile, MULTIPLAYER, "PingCustomTunnels", true); - WritePathToRegistry = new BoolSetting(iniFile, OPTIONS, "WriteInstallationPathToRegistry", true); + WritePathToRegistry = new BoolSetting(iniFile, OPTIONS, "WriteInstallationPathToRegistry", ClientConfiguration.Instance.UserDefault_WriteInstallationPathToRegistry); PlaySoundOnGameHosted = new BoolSetting(iniFile, MULTIPLAYER, "PlaySoundOnGameHosted", true); SkipConnectDialog = new BoolSetting(iniFile, MULTIPLAYER, "SkipConnectDialog", false); PersistentMode = new BoolSetting(iniFile, MULTIPLAYER, "PersistentMode", false); @@ -151,6 +152,7 @@ protected UserINISettings(IniFile iniFile) public IntSetting ClientResolutionX { get; set; } public IntSetting ClientResolutionY { get; set; } public BoolSetting BorderlessWindowedClient { get; private set; } + public BoolSetting IntegerScaledClient { get; private set; } public IntSetting ClientFPS { get; private set; } public BoolSetting DisplayToggleableExtraTextures { get; private set; } diff --git a/DTAConfig/OptionPanels/DisplayOptionsPanel.cs b/DTAConfig/OptionPanels/DisplayOptionsPanel.cs index 252da14d2..d2adf72bb 100644 --- a/DTAConfig/OptionPanels/DisplayOptionsPanel.cs +++ b/DTAConfig/OptionPanels/DisplayOptionsPanel.cs @@ -86,7 +86,7 @@ public override void Initialize() var maximumIngameResolution = new ScreenResolution(ClientConfiguration.Instance.MaximumIngameWidth, ClientConfiguration.Instance.MaximumIngameHeight); #if XNA - if (!ScreenResolution.HiDefLimitResolution.Fit(maximumIngameResolution)) + if (!ScreenResolution.HiDefLimitResolution.Fits(maximumIngameResolution)) maximumIngameResolution = ScreenResolution.HiDefLimitResolution; #endif @@ -769,6 +769,8 @@ public override bool Save() clientRes.Height != IniSettings.ClientResolutionY.Value) restartRequired = true; + // TODO: since DTAConfig must not rely on DXMainClient, we can't notify the client to dynamically change the resolution or togging borderless windowed mode. Thus, we need to restart the client as a workaround. + (IniSettings.ClientResolutionX.Value, IniSettings.ClientResolutionY.Value) = clientRes; if (IniSettings.BorderlessWindowedClient.Value != chkBorderlessClient.Checked) diff --git a/DTAConfig/ScreenResolution.cs b/DTAConfig/ScreenResolution.cs index 97c01c559..1b13ef38c 100644 --- a/DTAConfig/ScreenResolution.cs +++ b/DTAConfig/ScreenResolution.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; +using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace DTAConfig @@ -28,6 +29,12 @@ public ScreenResolution(int width, int height) Height = height; } + public ScreenResolution(Rectangle rectangle) + { + Width = rectangle.Width; + Height = rectangle.Height; + } + public ScreenResolution(string resolution) { List resolutionList = resolution.Trim().Split('x').Take(2).Select(int.Parse).ToList(); @@ -51,12 +58,16 @@ public void Deconstruct(out int width, out int height) public static implicit operator (int Width, int Height)(ScreenResolution resolution) => new(resolution.Width, resolution.Height); - public bool Fit(ScreenResolution child) => this.Width >= child.Width && this.Height >= child.Height; + public bool Fits(ScreenResolution child) => this.Width >= child.Width && this.Height >= child.Height; public int CompareTo(ScreenResolution other) => (this.Width, this.Height).CompareTo(other); // Accessing GraphicsAdapter.DefaultAdapter requiring DXMainClient.GameClass has been constructed. Lazy loading prevents possible null reference issues for now. private static ScreenResolution _desktopResolution = null; + + /// + /// The resolution of primary monitor. + /// public static ScreenResolution DesktopResolution => _desktopResolution ??= new(GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width, GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height); @@ -64,12 +75,16 @@ public void Deconstruct(out int width, out int height) public static ScreenResolution HiDefLimitResolution { get; } = "3840x3840"; private static ScreenResolution _safeMaximumResolution = null; + + /// + /// The resolution of primary monitor, or the maximum resolution supported by the graphic profile, whichever is smaller. + /// public static ScreenResolution SafeMaximumResolution { get { #if XNA - return _safeMaximumResolution ??= HiDefLimitResolution.Fit(DesktopResolution) ? DesktopResolution : HiDefLimitResolution; + return _safeMaximumResolution ??= HiDefLimitResolution.Fits(DesktopResolution) ? DesktopResolution : HiDefLimitResolution; #else return _safeMaximumResolution ??= DesktopResolution; #endif @@ -77,6 +92,10 @@ public static ScreenResolution SafeMaximumResolution } private static ScreenResolution _safeFullScreenResolution = null; + + /// + /// The maximum resolution supported by the graphic profile, or the largest full screen resolution supported by the primary monitor, whichever is smaller. + /// public static ScreenResolution SafeFullScreenResolution => _safeFullScreenResolution ??= GetFullScreenResolutions(minWidth: 800, minHeight: 600).Max(); public static SortedSet GetFullScreenResolutions(int minWidth, int minHeight) => @@ -123,7 +142,7 @@ public SortedSet GetIntegerScaledResolutions(ScreenResolution { ScreenResolution scaledResolution = (this.Width * i, this.Height * i); - if (maxResolution.Fit(scaledResolution)) + if (maxResolution.Fits(scaledResolution)) resolutions.Add(scaledResolution); else break; @@ -149,6 +168,9 @@ public static SortedSet GetWindowedResolutions(IEnumerable + //{ + // ScreenResolution currentWindowSize = new(wm.Game.Window.ClientBounds); + + // if (currentWindowSize != lastWindowSizeCaptured) + // { + // Logger.Log($"Window size changed from {lastWindowSizeCaptured} to {currentWindowSize}."); + // lastWindowSizeCaptured = currentWindowSize; + // SetGraphicsMode(wm, currentWindowSize.Width, currentWindowSize.Height, centerOnScreen: false); + // } + //}; + } #endif wm.Cursor.Textures = new Texture2D[] @@ -311,14 +338,34 @@ private void InitializeUISettings() /// TODO move to some helper class? /// /// The window manager - public static void SetGraphicsMode(WindowManager wm) + /// Whether to center the client window on the screen + public static void SetGraphicsMode(WindowManager wm, bool centerOnScreen = true) { - var clientConfiguration = ClientConfiguration.Instance; - int windowWidth = UserINISettings.Instance.ClientResolutionX; int windowHeight = UserINISettings.Instance.ClientResolutionY; + SetGraphicsMode(wm, windowWidth, windowHeight, centerOnScreen); + } + + /// + /// The viewport width + /// The viewport height + public static void SetGraphicsMode(WindowManager wm, int windowWidth, int windowHeight, bool centerOnScreen = true) + { bool borderlessWindowedClient = UserINISettings.Instance.BorderlessWindowedClient; + bool integerScale = UserINISettings.Instance.IntegerScaledClient; + + SetGraphicsMode(wm, windowWidth, windowHeight, borderlessWindowedClient, integerScale, centerOnScreen); + } + + /// + /// Whether to use borderless windowed mode + /// Whether to use integer scaling + public static void SetGraphicsMode(WindowManager wm, int windowWidth, int windowHeight, bool borderlessWindowedClient, bool integerScale, bool centerOnScreen = true) + { + var clientConfiguration = ClientConfiguration.Instance; + + wm.IntegerScalingOnly = integerScale; (int desktopWidth, int desktopHeight) = ScreenResolution.SafeMaximumResolution; @@ -338,53 +385,78 @@ public static void SetGraphicsMode(WindowManager wm) int renderResolutionX = 0; int renderResolutionY = 0; - int initialXRes = Math.Max(windowWidth, clientConfiguration.MinimumRenderWidth); - initialXRes = Math.Min(initialXRes, clientConfiguration.MaximumRenderWidth); - - int initialYRes = Math.Max(windowHeight, clientConfiguration.MinimumRenderHeight); - initialYRes = Math.Min(initialYRes, clientConfiguration.MaximumRenderHeight); + if (!integerScale || windowWidth < clientConfiguration.MinimumRenderWidth || windowHeight < clientConfiguration.MinimumRenderHeight) + { + int initialXRes = Math.Max(windowWidth, clientConfiguration.MinimumRenderWidth); + initialXRes = Math.Min(initialXRes, clientConfiguration.MaximumRenderWidth); - double xRatio = (windowWidth) / (double)initialXRes; - double yRatio = (windowHeight) / (double)initialYRes; + int initialYRes = Math.Max(windowHeight, clientConfiguration.MinimumRenderHeight); + initialYRes = Math.Min(initialYRes, clientConfiguration.MaximumRenderHeight); - double ratio = xRatio > yRatio ? yRatio : xRatio; + double xRatio = (windowWidth) / (double)initialXRes; + double yRatio = (windowHeight) / (double)initialYRes; - if ((windowWidth == 1366 || windowWidth == 1360) && windowHeight == 768) - { - renderResolutionX = windowWidth; - renderResolutionY = windowHeight; - } + double ratio = xRatio > yRatio ? yRatio : xRatio; - if (ratio > 1.0) - { - // Check whether we could sharp-scale our client window - for (int i = 2; i <= ScreenResolution.MAX_INT_SCALE; i++) + if (720 <= clientConfiguration.MaximumRenderHeight && clientConfiguration.MaximumRenderHeight < 768) { - int sharpScaleRenderResX = windowWidth / i; - int sharpScaleRenderResY = windowHeight / i; + // Most client interface has been designed for 1280x720 or 1280x800. + // 1280x720 upscaled to 1366x768 doesn't look great, so we allow players with 1366x768 to use their native resolution with small black bars on the sides + // This behavior is enforced even if IntegerScaledClient is turned off. + if ((windowWidth == 1366 || windowWidth == 1360) && windowHeight == 768) + { + renderResolutionX = windowWidth; + renderResolutionY = windowHeight; + } + } - if (sharpScaleRenderResX >= clientConfiguration.MinimumRenderWidth && - sharpScaleRenderResX <= clientConfiguration.MaximumRenderWidth && - sharpScaleRenderResY >= clientConfiguration.MinimumRenderHeight && - sharpScaleRenderResY <= clientConfiguration.MaximumRenderHeight) + if (ratio > 1.0) + { + // Check whether we could sharp-scale our client window + for (int i = 2; i <= ScreenResolution.MAX_INT_SCALE; i++) { - renderResolutionX = sharpScaleRenderResX; - renderResolutionY = sharpScaleRenderResY; - break; + int sharpScaleRenderResX = windowWidth / i; + int sharpScaleRenderResY = windowHeight / i; + + if (sharpScaleRenderResX >= clientConfiguration.MinimumRenderWidth && + sharpScaleRenderResX <= clientConfiguration.MaximumRenderWidth && + sharpScaleRenderResY >= clientConfiguration.MinimumRenderHeight && + sharpScaleRenderResY <= clientConfiguration.MaximumRenderHeight) + { + renderResolutionX = sharpScaleRenderResX; + renderResolutionY = sharpScaleRenderResY; + break; + } } } - } - if (renderResolutionX == 0 || renderResolutionY == 0) - { - renderResolutionX = initialXRes; - renderResolutionY = initialYRes; + if (renderResolutionX == 0 || renderResolutionY == 0) + { + renderResolutionX = initialXRes; + renderResolutionY = initialYRes; - if (ratio == xRatio) - renderResolutionY = (int)(windowHeight / ratio); + if (ratio == xRatio) + renderResolutionY = (int)(windowHeight / ratio); + } + } + else + { + // Compute integer scale ratio using minimum render resolution + // Note: this means we prefer larger scale ratio than render resolution. + // This policy works best when maximum and minimum render resolution are close. + int xScale = windowWidth / clientConfiguration.MinimumRenderWidth; + int yScale = windowHeight / clientConfiguration.MinimumRenderHeight; + int scale = Math.Min(xScale, yScale); + + // Compute render resolution + renderResolutionX = Math.Min(clientConfiguration.MaximumRenderWidth, + clientConfiguration.MinimumRenderWidth + (windowWidth - clientConfiguration.MinimumRenderWidth * scale) / scale); + renderResolutionY = Math.Min(clientConfiguration.MaximumRenderHeight, + clientConfiguration.MinimumRenderHeight + (windowHeight - clientConfiguration.MinimumRenderHeight * scale) / scale); } wm.SetBorderlessMode(borderlessWindowedClient); + #if !XNA if (borderlessWindowedClient) @@ -404,7 +476,10 @@ public static void SetGraphicsMode(WindowManager wm) } #endif - wm.CenterOnScreen(); + if (centerOnScreen) + wm.CenterOnScreen(); + + Logger.Log("Setting render resolution to " + renderResolutionX + "x" + renderResolutionY + ". Integer scaling: " + integerScale); wm.SetRenderResolution(renderResolutionX, renderResolutionY); } } diff --git a/Directory.Packages.props b/Directory.Packages.props index 182e8f440..522e63ded 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,7 +1,7 @@ true - 2.3.20 + 2.3.22 8.0.0 From 15b53321b22366154dacb895d3086ed1e906103c Mon Sep 17 00:00:00 2001 From: SadPencil Date: Mon, 4 Nov 2024 11:07:37 +0800 Subject: [PATCH 2/9] Enable resizable window only if integer scaling is on --- DXMainClient/DXGUI/GameClass.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DXMainClient/DXGUI/GameClass.cs b/DXMainClient/DXGUI/GameClass.cs index 05a039c42..e59e8e03d 100644 --- a/DXMainClient/DXGUI/GameClass.cs +++ b/DXMainClient/DXGUI/GameClass.cs @@ -158,8 +158,8 @@ protected override void Initialize() wm.SetIcon(SafePath.CombineFilePath(ProgramConstants.GetBaseResourcePath(), "clienticon.ico")); wm.SetControlBox(true); - // Enable resizable window for non-borderless windowed client - if (!UserINISettings.Instance.BorderlessWindowedClient) + // Enable resizable window for non-borderless windowed client, if integer scaling is enabled + if (!UserINISettings.Instance.BorderlessWindowedClient && UserINISettings.Instance.IntegerScaledClient) { wm.SetFormBorderStyle(FormBorderStyle.Sizable); wm.SetMaximizeBox(true); From b7392d88dbce1d1fbdacfdbb860022daf8486b8c Mon Sep 17 00:00:00 2001 From: SadPencil Date: Mon, 4 Nov 2024 11:13:45 +0800 Subject: [PATCH 3/9] Add special scaling rules for FHD cases --- DXMainClient/DXGUI/GameClass.cs | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/DXMainClient/DXGUI/GameClass.cs b/DXMainClient/DXGUI/GameClass.cs index e59e8e03d..c8078ac7b 100644 --- a/DXMainClient/DXGUI/GameClass.cs +++ b/DXMainClient/DXGUI/GameClass.cs @@ -365,8 +365,6 @@ public static void SetGraphicsMode(WindowManager wm, int windowWidth, int window { var clientConfiguration = ClientConfiguration.Instance; - wm.IntegerScalingOnly = integerScale; - (int desktopWidth, int desktopHeight) = ScreenResolution.SafeMaximumResolution; if (desktopWidth >= windowWidth && desktopHeight >= windowHeight) @@ -398,16 +396,32 @@ public static void SetGraphicsMode(WindowManager wm, int windowWidth, int window double ratio = xRatio > yRatio ? yRatio : xRatio; - if (720 <= clientConfiguration.MaximumRenderHeight && clientConfiguration.MaximumRenderHeight < 768) + // Special rule for 1360x768 and 1366x768 + if ((windowWidth == 1366 || windowWidth == 1360) && windowHeight == 768) { // Most client interface has been designed for 1280x720 or 1280x800. // 1280x720 upscaled to 1366x768 doesn't look great, so we allow players with 1366x768 to use their native resolution with small black bars on the sides // This behavior is enforced even if IntegerScaledClient is turned off. - if ((windowWidth == 1366 || windowWidth == 1360) && windowHeight == 768) - { - renderResolutionX = windowWidth; - renderResolutionY = windowHeight; - } + renderResolutionX = windowWidth; + renderResolutionY = windowHeight; + } + + // Special rule: if 1280x720 is a valid render resolution, we allow 1.5x scaling for 1920x1080. + if (windowWidth == 1920 && windowHeight == 1080 + && 1280 >= clientConfiguration.MinimumRenderWidth && 1280 <= clientConfiguration.MaximumRenderWidth + && 720 >= clientConfiguration.MinimumRenderHeight && 720 <= clientConfiguration.MaximumRenderHeight) + { + renderResolutionX = 1280; + renderResolutionY = 720; + } + + // Special rule: if 1280x800 is a valid render resolution, we allow 1.5x scaling for 1920x1200. + if (windowWidth == 1920 && windowHeight == 1200 + && 1280 >= clientConfiguration.MinimumRenderWidth && 1280 <= clientConfiguration.MaximumRenderWidth + && 800 >= clientConfiguration.MinimumRenderHeight && 800 <= clientConfiguration.MaximumRenderHeight) + { + renderResolutionX = 1280; + renderResolutionY = 800; } if (ratio > 1.0) @@ -480,6 +494,7 @@ public static void SetGraphicsMode(WindowManager wm, int windowWidth, int window wm.CenterOnScreen(); Logger.Log("Setting render resolution to " + renderResolutionX + "x" + renderResolutionY + ". Integer scaling: " + integerScale); + wm.IntegerScalingOnly = integerScale; wm.SetRenderResolution(renderResolutionX, renderResolutionY); } } From b45e23ba1273c7f1bfe2fbba423ed4dee3d24b28 Mon Sep 17 00:00:00 2001 From: SadPencil Date: Mon, 4 Nov 2024 11:17:32 +0800 Subject: [PATCH 4/9] Revise a comment line --- DXMainClient/DXGUI/GameClass.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DXMainClient/DXGUI/GameClass.cs b/DXMainClient/DXGUI/GameClass.cs index c8078ac7b..52578d0e2 100644 --- a/DXMainClient/DXGUI/GameClass.cs +++ b/DXMainClient/DXGUI/GameClass.cs @@ -424,9 +424,9 @@ public static void SetGraphicsMode(WindowManager wm, int windowWidth, int window renderResolutionY = 800; } + // Check whether we could integer-scale our client window if (ratio > 1.0) { - // Check whether we could sharp-scale our client window for (int i = 2; i <= ScreenResolution.MAX_INT_SCALE; i++) { int sharpScaleRenderResX = windowWidth / i; From 815ce24efed759cbb65cd18d331f48885ed6776c Mon Sep 17 00:00:00 2001 From: SadPencil Date: Mon, 4 Nov 2024 11:28:12 +0800 Subject: [PATCH 5/9] Add a comment line --- DXMainClient/DXGUI/GameClass.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/DXMainClient/DXGUI/GameClass.cs b/DXMainClient/DXGUI/GameClass.cs index 52578d0e2..fcff5dd14 100644 --- a/DXMainClient/DXGUI/GameClass.cs +++ b/DXMainClient/DXGUI/GameClass.cs @@ -444,6 +444,7 @@ public static void SetGraphicsMode(WindowManager wm, int windowWidth, int window } } + // No special rules are triggered. Just zoom the client to the window size with minimal black bars. if (renderResolutionX == 0 || renderResolutionY == 0) { renderResolutionX = initialXRes; From 6cbcd61485e8025a50410d5e12eecb0a24732c8f Mon Sep 17 00:00:00 2001 From: SadPencil Date: Wed, 27 Nov 2024 22:54:51 +0800 Subject: [PATCH 6/9] Reduce DPI awareness claim for GL builds --- DXMainClient/DXMainClient.csproj | 6 +- DXMainClient/Program.cs | 4 + ...app.manifest => app.PerMonitorV2.manifest} | 2 +- DXMainClient/app.SystemAware.manifest | 75 +++++++++++++++++++ 4 files changed, 84 insertions(+), 3 deletions(-) rename DXMainClient/{app.manifest => app.PerMonitorV2.manifest} (100%) create mode 100644 DXMainClient/app.SystemAware.manifest diff --git a/DXMainClient/DXMainClient.csproj b/DXMainClient/DXMainClient.csproj index 3f00a7172..a66474c76 100644 --- a/DXMainClient/DXMainClient.csproj +++ b/DXMainClient/DXMainClient.csproj @@ -9,11 +9,13 @@ CnCNet Main Client Library DTAClient clienticon.ico - PerMonitorV2 + SystemAware + PerMonitorV2 clientdx clientogl clientxna - app.manifest + app.SystemAware.manifest + app.PerMonitorV2.manifest true diff --git a/DXMainClient/Program.cs b/DXMainClient/Program.cs index 2b2ccd668..2e9a5505f 100644 --- a/DXMainClient/Program.cs +++ b/DXMainClient/Program.cs @@ -70,7 +70,11 @@ static void InitializeApplicationConfiguration() #else #if NETCOREAPP3_0_OR_GREATER +#if GL + System.Windows.Forms.Application.SetHighDpiMode(System.Windows.Forms.HighDpiMode.SystemAware); +#else System.Windows.Forms.Application.SetHighDpiMode(System.Windows.Forms.HighDpiMode.PerMonitorV2); +#endif #endif System.Windows.Forms.Application.EnableVisualStyles(); diff --git a/DXMainClient/app.manifest b/DXMainClient/app.PerMonitorV2.manifest similarity index 100% rename from DXMainClient/app.manifest rename to DXMainClient/app.PerMonitorV2.manifest index b6bf8dcfb..150ac1989 100644 --- a/DXMainClient/app.manifest +++ b/DXMainClient/app.PerMonitorV2.manifest @@ -54,6 +54,7 @@ true/PM PerMonitorV2, PerMonitor + @@ -73,4 +74,3 @@ - diff --git a/DXMainClient/app.SystemAware.manifest b/DXMainClient/app.SystemAware.manifest new file mode 100644 index 000000000..227756f65 --- /dev/null +++ b/DXMainClient/app.SystemAware.manifest @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + + + + + + From c9da6e8f305b12ab330bf051284a094da3f9cd61 Mon Sep 17 00:00:00 2001 From: MahBoiDeveloper Date: Sun, 1 Dec 2024 01:24:55 +0300 Subject: [PATCH 7/9] Add checkbox to enable/disable integer scaling --- DTAConfig/OptionPanels/DisplayOptionsPanel.cs | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/DTAConfig/OptionPanels/DisplayOptionsPanel.cs b/DTAConfig/OptionPanels/DisplayOptionsPanel.cs index d2adf72bb..38a3ea201 100644 --- a/DTAConfig/OptionPanels/DisplayOptionsPanel.cs +++ b/DTAConfig/OptionPanels/DisplayOptionsPanel.cs @@ -42,6 +42,7 @@ public DisplayOptionsPanel(WindowManager windowManager, UserINISettings iniSetti private XNAClientCheckBox chkBackBufferInVRAM; private XNAClientPreferredItemDropDown ddClientResolution; private XNAClientCheckBox chkBorderlessClient; + private XNAClientCheckBox chkIntegerScaledClient; private XNAClientDropDown ddClientTheme; private XNAClientDropDown ddTranslation; @@ -224,18 +225,27 @@ .. scaledRecommendedResolutions chkBorderlessClient.CheckedChanged += ChkBorderlessMenu_CheckedChanged; chkBorderlessClient.Checked = true; + chkIntegerScaledClient = new XNAClientCheckBox(WindowManager); + chkIntegerScaledClient.Name = nameof(chkIntegerScaledClient); + chkIntegerScaledClient.ClientRectangle = new Rectangle( + lblClientResolution.X, + lblRenderer.Y, 0, 0); + chkIntegerScaledClient.Text = "Integer Scaled Client".L10N("Client:DTAConfig:IntegerScaledClient"); + chkIntegerScaledClient.CheckedChanged += ChkIntegerScaling_CheckedChanged; + chkIntegerScaledClient.Checked = IniSettings.IntegerScaledClient.Value; + var lblClientTheme = new XNALabel(WindowManager); lblClientTheme.Name = "lblClientTheme"; lblClientTheme.ClientRectangle = new Rectangle( lblClientResolution.X, - lblRenderer.Y, 0, 0); + chkWindowedMode.Y, 0, 0); lblClientTheme.Text = "Client Theme:".L10N("Client:DTAConfig:ClientTheme"); ddClientTheme = new XNAClientDropDown(WindowManager); ddClientTheme.Name = "ddClientTheme"; ddClientTheme.ClientRectangle = new Rectangle( ddClientResolution.X, - ddRenderer.Y, + chkWindowedMode.Y, ddClientResolution.Width, ddRenderer.Height); @@ -326,6 +336,7 @@ .. scaledRecommendedResolutions AddChild(chkBorderlessWindowedMode); AddChild(chkBackBufferInVRAM); AddChild(chkBorderlessClient); + AddChild(chkIntegerScaledClient); AddChild(lblClientTheme); AddChild(ddClientTheme); AddChild(lblTranslation); @@ -584,6 +595,16 @@ private void ChkBorderlessMenu_CheckedChanged(object sender, EventArgs e) } } + private void ChkIntegerScaling_CheckedChanged(object sender, EventArgs e) + { + if (chkIntegerScaledClient.Checked) + { + } + else + { + } + } + private void ChkWindowedMode_CheckedChanged(object sender, EventArgs e) { if (chkWindowedMode.Checked) @@ -778,6 +799,11 @@ public override bool Save() IniSettings.BorderlessWindowedClient.Value = chkBorderlessClient.Checked; + if (IniSettings.IntegerScaledClient.Value != chkIntegerScaledClient.Checked) + restartRequired = true; + + IniSettings.IntegerScaledClient.Value = chkIntegerScaledClient.Checked; + restartRequired = restartRequired || IniSettings.ClientTheme != (string)ddClientTheme.SelectedItem.Tag; IniSettings.ClientTheme.Value = (string)ddClientTheme.SelectedItem.Tag; From 6b5bfd8c7f1944e98394a599830f1399de824292 Mon Sep 17 00:00:00 2001 From: MahBoiDeveloper Date: Sun, 1 Dec 2024 02:47:15 +0300 Subject: [PATCH 8/9] Remove unused code --- DTAConfig/OptionPanels/DisplayOptionsPanel.cs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/DTAConfig/OptionPanels/DisplayOptionsPanel.cs b/DTAConfig/OptionPanels/DisplayOptionsPanel.cs index 38a3ea201..cd5d5c428 100644 --- a/DTAConfig/OptionPanels/DisplayOptionsPanel.cs +++ b/DTAConfig/OptionPanels/DisplayOptionsPanel.cs @@ -231,7 +231,6 @@ .. scaledRecommendedResolutions lblClientResolution.X, lblRenderer.Y, 0, 0); chkIntegerScaledClient.Text = "Integer Scaled Client".L10N("Client:DTAConfig:IntegerScaledClient"); - chkIntegerScaledClient.CheckedChanged += ChkIntegerScaling_CheckedChanged; chkIntegerScaledClient.Checked = IniSettings.IntegerScaledClient.Value; var lblClientTheme = new XNALabel(WindowManager); @@ -595,16 +594,6 @@ private void ChkBorderlessMenu_CheckedChanged(object sender, EventArgs e) } } - private void ChkIntegerScaling_CheckedChanged(object sender, EventArgs e) - { - if (chkIntegerScaledClient.Checked) - { - } - else - { - } - } - private void ChkWindowedMode_CheckedChanged(object sender, EventArgs e) { if (chkWindowedMode.Checked) From 4cbc708cd40b12bb83068a41b2d315d18d487dd0 Mon Sep 17 00:00:00 2001 From: Kerbiter Date: Sun, 1 Dec 2024 18:02:39 +0200 Subject: [PATCH 9/9] Add tooltip for the integer scaling checkbox --- DTAConfig/OptionPanels/DisplayOptionsPanel.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/DTAConfig/OptionPanels/DisplayOptionsPanel.cs b/DTAConfig/OptionPanels/DisplayOptionsPanel.cs index cd5d5c428..d6347e5a9 100644 --- a/DTAConfig/OptionPanels/DisplayOptionsPanel.cs +++ b/DTAConfig/OptionPanels/DisplayOptionsPanel.cs @@ -232,6 +232,16 @@ .. scaledRecommendedResolutions lblRenderer.Y, 0, 0); chkIntegerScaledClient.Text = "Integer Scaled Client".L10N("Client:DTAConfig:IntegerScaledClient"); chkIntegerScaledClient.Checked = IniSettings.IntegerScaledClient.Value; + chkIntegerScaledClient.ToolTipText = + """ + Enable integer scaling for the client. This will cause the client to use + the closest fitting resolution that is required to maintain sharp graphics, + at the expense of black borders that may appear at some resolutions. + + Additionally, enabling this option will also allow the client window + to be resized (does not affect the selected client resolution). + """ + .L10N("Client:DTAConfig:IntegerScaledClientToolTip"); var lblClientTheme = new XNALabel(WindowManager); lblClientTheme.Name = "lblClientTheme";