From 27ec1f0e39162677cd701686f7e427cc3004623f Mon Sep 17 00:00:00 2001 From: Jade Macho Date: Wed, 15 Jan 2025 00:52:33 +0100 Subject: [PATCH] Add hotkey, fix unload race --- CustomResolution/Configuration.cs | 55 ++++++++++++++++++ CustomResolution/Plugin.cs | 71 +++++++++++++++++------- CustomResolution/PluginUI.cs | 1 + CustomResolution/Service.cs | 3 + CustomResolution/Windows/ConfigWindow.cs | 59 +++++++++++++++++++- 5 files changed, 167 insertions(+), 22 deletions(-) diff --git a/CustomResolution/Configuration.cs b/CustomResolution/Configuration.cs index de562b4..802aa6b 100644 --- a/CustomResolution/Configuration.cs +++ b/CustomResolution/Configuration.cs @@ -1,6 +1,9 @@ using Dalamud.Configuration; +using Dalamud.Game.ClientState.Keys; using Dalamud.Plugin; using System; +using System.Collections.Generic; +using System.Reflection; namespace CustomResolution; @@ -15,6 +18,9 @@ public class Configuration : IPluginConfiguration public uint Width = 1024; public uint Height = 1024; + public VirtualKey HotkeyKey = VirtualKey.NO_KEY; + public ModifierKey HotkeyModifier = ModifierKey.NONE; + public DXVKDWMHackMode DXVKDWMHackMode = DXVKDWMHackMode.Off; [NonSerialized] @@ -68,3 +74,52 @@ public static class DXVKDWMHackModeExt _ => false }; } + +public enum ModifierKey +{ + NONE = 0, + CTRL = 1, + ALT = 2, + SHIFT = 4 +} + +public static class VirtualKeyExt +{ + private static readonly Dictionary _strings = new(); + + static VirtualKeyExt() + { + foreach (var field in typeof(VirtualKey).GetFields(BindingFlags.Public | BindingFlags.Static)) + { + var key = (VirtualKey) field.GetValue(null)!; + _strings[key] = key.GetFancyName(); + } + } + + public static string ToHumanNameString(this VirtualKey mode) + { + return _strings[mode]; + } + + public static string? ToHumanInfoString(this VirtualKey mode) => mode switch + { + _ => null + }; +} + +public static class ModifierKeyExt +{ + public static string ToHumanNameString(this ModifierKey mode) => mode switch + { + ModifierKey.NONE => "None", + ModifierKey.CTRL => "Ctrl", + ModifierKey.ALT => "Alt", + ModifierKey.SHIFT => "Shift", + _ => mode.ToString(), + }; + + public static string? ToHumanInfoString(this ModifierKey mode) => mode switch + { + _ => null + }; +} diff --git a/CustomResolution/Plugin.cs b/CustomResolution/Plugin.cs index a1ae3b8..279b408 100644 --- a/CustomResolution/Plugin.cs +++ b/CustomResolution/Plugin.cs @@ -1,9 +1,12 @@ -using Dalamud.IoC; +using Dalamud.Game.ClientState.Keys; +using Dalamud.IoC; using Dalamud.Plugin; using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel; using FFXIVClientStructs.FFXIV.Client.UI; +using FFXIVClientStructs.FFXIV.Common.Lua; using FFXIVClientStructs.Interop; +using ImGuiNET; using System; using System.Collections.Generic; using System.Linq; @@ -14,6 +17,8 @@ namespace CustomResolution; public sealed unsafe class Plugin : IDalamudPlugin { + private object _disposeLock = new(); + private readonly HRGN _invisibleRgn; private readonly List _cmds; @@ -68,12 +73,16 @@ public sealed unsafe class Plugin : IDalamudPlugin public void Dispose() { - _tickCount = 0; _unloading = true; - Service.Framework.Update -= OnFrameworkUpdate; + lock (_disposeLock) + { + _tickCount = 0; - Service.Framework.RunOnFrameworkThread(Update); + Service.Framework.Update -= OnFrameworkUpdate; + + Service.Framework.RunOnFrameworkThread(Update); + } foreach (Cmd cmd in _cmds) { @@ -310,24 +319,44 @@ public sealed unsafe class Plugin : IDalamudPlugin private void OnFrameworkUpdate(IFramework framework) { - var dev = Device.Instance(); - - _currentHwnd = (HWND) (IntPtr) dev->hWnd; - - fixed (RECT* currentClientRectPtr = &_currentClientRect) - fixed (RECT* currentWindowRectPtr = &_currentWindowRect) + lock (_disposeLock) { - GetClientRect(_currentHwnd, currentClientRectPtr); - GetWindowRect(_currentHwnd, currentWindowRectPtr); + var io = ImGui.GetIO(); + + if (Service.Config.HotkeyKey != VirtualKey.NO_KEY && + (ImGuiNative.igIsKeyPressed((ImGuiKey) Service.Config.HotkeyKey, 0) != 0 || Service.KeyState.GetRawValue(Service.Config.HotkeyKey) != 0) && + (Service.Config.HotkeyModifier switch + { + ModifierKey.NONE => !io.KeyCtrl && !io.KeyAlt && !io.KeyShift, + ModifierKey.CTRL => io.KeyCtrl && !io.KeyAlt && !io.KeyShift, + ModifierKey.ALT => !io.KeyCtrl && io.KeyAlt && !io.KeyShift, + ModifierKey.SHIFT => !io.KeyCtrl && !io.KeyAlt && io.KeyShift, + _ => false, + })) + { + Service.Config.IsEnabled = !Service.Config.IsEnabled; + Service.Config.Save(); + } + + var dev = Device.Instance(); + + _currentHwnd = (HWND) (IntPtr) dev->hWnd; + + fixed (RECT* currentClientRectPtr = &_currentClientRect) + fixed (RECT* currentWindowRectPtr = &_currentWindowRect) + { + GetClientRect(_currentHwnd, currentClientRectPtr); + GetWindowRect(_currentHwnd, currentWindowRectPtr); + } + + if (_tickCount++ >= 2) + { + _tickCount = 0; + + Update(); + } + + _tickCount++; } - - if (_tickCount++ >= 10) - { - _tickCount = 0; - - Update(); - } - - _tickCount++; } } diff --git a/CustomResolution/PluginUI.cs b/CustomResolution/PluginUI.cs index 727c5fe..6437576 100644 --- a/CustomResolution/PluginUI.cs +++ b/CustomResolution/PluginUI.cs @@ -10,6 +10,7 @@ public sealed class PluginUI : IDisposable internal PluginUI() { + Service.PluginInterface.UiBuilder.DisableGposeUiHide = true; Service.PluginInterface.UiBuilder.Draw += Draw; Service.PluginInterface.UiBuilder.OpenConfigUi += ShowConfigWindow; diff --git a/CustomResolution/Service.cs b/CustomResolution/Service.cs index 3c9b16d..5ad09bd 100644 --- a/CustomResolution/Service.cs +++ b/CustomResolution/Service.cs @@ -38,6 +38,9 @@ public sealed class Service [PluginService] public static IChatGui ChatGui { get; private set; } = null!; + [PluginService] + public static IKeyState KeyState { get; private set; } = null!; + public static void PrintChat(string msg) { ChatGui.Print(new XivChatEntry diff --git a/CustomResolution/Windows/ConfigWindow.cs b/CustomResolution/Windows/ConfigWindow.cs index bedccc3..f523360 100644 --- a/CustomResolution/Windows/ConfigWindow.cs +++ b/CustomResolution/Windows/ConfigWindow.cs @@ -1,16 +1,22 @@ -using Dalamud.Interface.Windowing; +using Dalamud.Game.ClientState.Keys; +using Dalamud.Interface.Windowing; using ImGuiNET; using System; +using System.Linq; using System.Numerics; namespace CustomResolution.Windows; public class ConfigWindow : Window, IDisposable { + private VirtualKey[] _validKeys = new VirtualKey[] { VirtualKey.NO_KEY }.Union(Service.KeyState.GetValidVirtualKeys()).ToArray(); + private int[] _displayCurrentWH = new int[2]; private int[] _displayCurrentWindowWH = new int[2]; private bool _configIsEnabled; + private VirtualKey _configHotkeyKey; + private ModifierKey _configHotkeyModifier; private bool _configIsScale; private float _configScale; private int[] _configWH = new int[2]; @@ -32,6 +38,8 @@ public class ConfigWindow : Window, IDisposable var config = Service.Config; _configIsEnabled = config.IsEnabled; + _configHotkeyKey = config.HotkeyKey; + _configHotkeyModifier = config.HotkeyModifier; _configIsScale = config.IsScale; _configScale = config.Scale; _configWH[0] = (int) config.Width; @@ -44,6 +52,8 @@ public class ConfigWindow : Window, IDisposable var config = Service.Config; config.IsEnabled = _configIsEnabled; + config.HotkeyKey = _configHotkeyKey; + config.HotkeyModifier = _configHotkeyModifier; config.IsScale = _configIsScale; config.Scale = _configScale; config.Width = (uint) _configWH[0]; @@ -70,6 +80,53 @@ public class ConfigWindow : Window, IDisposable ImGui.Checkbox("Enabled", ref _configIsEnabled); + ImGui.SameLine(); + ImGui.Dummy(new Vector2(20, 0)); + + ImGui.SameLine(); + ImGui.SetNextItemWidth(80); + if (ImGui.BeginCombo("##_configHotkeyModifier", _configHotkeyModifier.ToHumanNameString())) + { + foreach (var key in Enum.GetValues()) + { + if (ImGui.Selectable(key.ToHumanNameString(), _configHotkeyModifier == key, ImGuiSelectableFlags.None)) + { + _configHotkeyModifier = key; + } + + if (ImGui.IsItemHovered() && key.ToHumanInfoString() is { } info) + { + ImGui.SetTooltip(info); + } + } + + ImGui.EndCombo(); + } + + ImGui.SameLine(); + ImGui.SetNextItemWidth(160); + if (ImGui.BeginCombo("##_configHotkeyKey", _configHotkeyKey.ToHumanNameString())) + { + foreach (var key in _validKeys) + { + if (ImGui.Selectable(key.ToHumanNameString(), _configHotkeyKey == key, ImGuiSelectableFlags.None)) + { + _configHotkeyKey = key; + } + + if (ImGui.IsItemHovered() && key.ToHumanInfoString() is { } info) + { + ImGui.SetTooltip(info); + } + } + + ImGui.EndCombo(); + } + + ImGui.SameLine(); + ImGui.Text("Hotkey"); + + if (!_configIsEnabled) { ImGui.BeginDisabled();