From 5f9efaaea0e04aad3bba784a1f659b6553f72557 Mon Sep 17 00:00:00 2001 From: goat <16760685+goaaats@users.noreply.github.com> Date: Fri, 14 Aug 2020 02:51:55 +0200 Subject: [PATCH] feat: add automatic UI hiding to GameGui, UiBuilder --- Dalamud/Dalamud.cs | 3 ++ Dalamud/Game/Internal/Gui/GameGui.cs | 29 +++++++++++++++++++ .../Internal/Gui/GameGuiAddressResolver.cs | 6 ++-- Dalamud/Interface/UiBuilder.cs | 17 +++++++++-- Dalamud/Plugin/DalamudPluginInterface.cs | 2 +- 5 files changed, 52 insertions(+), 5 deletions(-) diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index b1fa7fc66..7513cea3a 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -378,6 +378,9 @@ namespace Dalamud { } } + if (this.Framework.Gui.GameUiHidden) + return; + if (this.isImguiDrawLogWindow) { this.isImguiDrawLogWindow = this.logWindow != null && this.logWindow.Draw(); diff --git a/Dalamud/Game/Internal/Gui/GameGui.cs b/Dalamud/Game/Internal/Gui/GameGui.cs index 81b730178..16e2ed3e3 100644 --- a/Dalamud/Game/Internal/Gui/GameGui.cs +++ b/Dalamud/Game/Internal/Gui/GameGui.cs @@ -44,6 +44,17 @@ namespace Dalamud.Game.Internal.Gui { float *camPos, float *clipPos, float rayDistance, float *worldPos, int *unknown); private readonly ScreenToWorldNativeDelegate screenToWorldNative; + [UnmanagedFunctionPointer(CallingConvention.ThisCall)] + private delegate IntPtr ToggleUiHideDelegate(IntPtr thisPtr, byte unknownByte); + private readonly Hook toggleUiHideHook; + + public bool GameUiHidden { get; private set; } + + /// + /// Event which is fired when the game UI hiding is toggled. + /// + public event EventHandler OnUiHideToggled; + /// /// The item ID that is currently hovered by the player. 0 when no item is hovered. /// If > 1.000.000, subtract 1.000.000 and treat it as HQ @@ -90,6 +101,8 @@ namespace Dalamud.Game.Internal.Gui { this.screenToWorldNative = Marshal.GetDelegateForFunctionPointer(Address.ScreenToWorld); + + this.toggleUiHideHook = new Hook(Address.ToggleUiHide, new ToggleUiHideDelegate(ToggleUiHideDetour), this); } private IntPtr HandleSetGlobalBgmDetour(UInt16 bgmKey, byte a2, UInt32 a3, UInt32 a4, UInt32 a5, byte a6) { @@ -279,6 +292,20 @@ namespace Dalamud.Game.Internal.Gui { return isSuccess; } + private IntPtr ToggleUiHideDetour(IntPtr thisPtr, byte unknownByte) { + GameUiHidden = !GameUiHidden; + + try { + OnUiHideToggled?.Invoke(this, GameUiHidden); + } catch (Exception ex) { + Log.Error(ex, "Error on OnUiHideToggled event dispatch"); + } + + Log.Debug("UiHide toggled: {0}", GameUiHidden); + + return this.toggleUiHideHook.Original(thisPtr, unknownByte); + } + public void SetBgm(ushort bgmKey) => this.setGlobalBgmHook.Original(bgmKey, 0, 0, 0, 0, 0); public void Enable() { @@ -286,6 +313,7 @@ namespace Dalamud.Game.Internal.Gui { this.setGlobalBgmHook.Enable(); this.handleItemHoverHook.Enable(); this.handleItemOutHook.Enable(); + this.toggleUiHideHook.Enable(); } public void Dispose() { @@ -293,6 +321,7 @@ namespace Dalamud.Game.Internal.Gui { this.setGlobalBgmHook.Dispose(); this.handleItemHoverHook.Dispose(); this.handleItemOutHook.Dispose(); + this.toggleUiHideHook.Dispose(); } } } diff --git a/Dalamud/Game/Internal/Gui/GameGuiAddressResolver.cs b/Dalamud/Game/Internal/Gui/GameGuiAddressResolver.cs index 0b092fdf6..3da0ecc8a 100644 --- a/Dalamud/Game/Internal/Gui/GameGuiAddressResolver.cs +++ b/Dalamud/Game/Internal/Gui/GameGuiAddressResolver.cs @@ -3,7 +3,7 @@ using System.Runtime.InteropServices; using Serilog; namespace Dalamud.Game.Internal.Gui { - public sealed class GameGuiAddressResolver : BaseAddressResolver { + internal sealed class GameGuiAddressResolver : BaseAddressResolver { public IntPtr BaseAddress { get; private set; } public IntPtr ChatManager { get; private set; } @@ -14,6 +14,7 @@ namespace Dalamud.Game.Internal.Gui { public IntPtr GetUIObject { get; private set; } public IntPtr GetMatrixSingleton { get; private set; } public IntPtr ScreenToWorld { get; private set; } + public IntPtr ToggleUiHide { get; set; } public GameGuiAddressResolver(IntPtr baseAddress) { BaseAddress = baseAddress; @@ -34,7 +35,8 @@ namespace Dalamud.Game.Internal.Gui { HandleItemOut = sig.ScanText("48 89 5C 24 ?? 57 48 83 EC 20 48 8B FA 48 8B D9 4D"); GetUIObject = sig.ScanText("E8 ?? ?? ?? ?? 48 8B C8 48 8B 10 FF 52 40 80 88 ?? ?? ?? ?? 01 E9"); GetMatrixSingleton = sig.ScanText("E8 ?? ?? ?? ?? 48 8D 4C 24 ?? 48 89 4c 24 ?? 4C 8D 4D ?? 4C 8D 44 24 ??"); - ScreenToWorld = sig.ScanText("48 83 EC 48 48 8B 05 ?? ?? ?? ?? 4D 8B D1"); + ScreenToWorld = sig.ScanText("48 83 EC 48 48 8B 05 ?? ?? ?? ?? 4D 8B D1"); + ToggleUiHide = sig.ScanText("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 0F B6 B9 ?? ?? ?? ?? B8 ?? ?? ?? ??"); } } } diff --git a/Dalamud/Interface/UiBuilder.cs b/Dalamud/Interface/UiBuilder.cs index 444eccaa1..97989a518 100644 --- a/Dalamud/Interface/UiBuilder.cs +++ b/Dalamud/Interface/UiBuilder.cs @@ -3,9 +3,11 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using Dalamud.Game.Internal.Gui; using ImGuiNET; using ImGuiScene; using Serilog; +using SharpDX.Direct3D11; namespace Dalamud.Interface { @@ -31,8 +33,14 @@ namespace Dalamud.Interface /// public event RawDX11Scene.BuildUIDelegate OnBuildUi; + /// + /// Choose if this plugin should hide its UI automatically when the whole game hides its UI. + /// + public bool DisableAutomaticUiHide { get; set; } = false; + private readonly InterfaceManager interfaceManager; - #if DEBUG + private readonly GameGui gameGui; +#if DEBUG internal static bool DoStats { get; set; } = true; #else internal static bool DoStats { get; set; } = false; @@ -47,10 +55,11 @@ namespace Dalamud.Interface /// /// The interface manager to register on. /// The plugin namespace. - internal UiBuilder(InterfaceManager interfaceManager, string namespaceName) { + internal UiBuilder(InterfaceManager interfaceManager, GameGui gameGui, string namespaceName) { this.namespaceName = namespaceName; this.interfaceManager = interfaceManager; + this.gameGui = gameGui; this.interfaceManager.OnDraw += OnDraw; this.stopwatch = new System.Diagnostics.Stopwatch(); } @@ -118,6 +127,10 @@ namespace Dalamud.Interface private bool hasErrorWindow; private void OnDraw() { + + if (this.gameGui.GameUiHidden && !DisableAutomaticUiHide) + return; + ImGui.PushID(this.namespaceName); if (DoStats) { this.stopwatch.Restart(); diff --git a/Dalamud/Plugin/DalamudPluginInterface.cs b/Dalamud/Plugin/DalamudPluginInterface.cs index fd7230c0a..940cd7497 100644 --- a/Dalamud/Plugin/DalamudPluginInterface.cs +++ b/Dalamud/Plugin/DalamudPluginInterface.cs @@ -75,7 +75,7 @@ namespace Dalamud.Plugin this.CommandManager = dalamud.CommandManager; this.Framework = dalamud.Framework; this.ClientState = dalamud.ClientState; - this.UiBuilder = new UiBuilder(dalamud.InterfaceManager, pluginName); + this.UiBuilder = new UiBuilder(dalamud.InterfaceManager, dalamud.Framework.Gui, pluginName); this.TargetModuleScanner = dalamud.SigScanner; this.Data = dalamud.Data; this.SeStringManager = dalamud.SeStringManager;