feat: do not close addons when any Window is still open

This commit is contained in:
goat 2021-09-01 19:50:23 +02:00
parent 647d095fcc
commit 412a335b93
No known key found for this signature in database
GPG key ID: F18F057873895461
6 changed files with 68 additions and 28 deletions

View file

@ -216,7 +216,7 @@ namespace Dalamud
clientState.Enable(); clientState.Enable();
Log.Information("[T2] CS ENABLE!"); Log.Information("[T2] CS ENABLE!");
Service<DalamudSystemMenu>.Set().Enable(); Service<DalamudAtkTweaks>.Set().Enable();
this.IsReady = true; this.IsReady = true;
} }
@ -339,7 +339,7 @@ namespace Dalamud
Service<WinSockHandlers>.GetNullable()?.Dispose(); Service<WinSockHandlers>.GetNullable()?.Dispose();
Service<DataManager>.GetNullable()?.Dispose(); Service<DataManager>.GetNullable()?.Dispose();
Service<AntiDebug>.GetNullable()?.Dispose(); Service<AntiDebug>.GetNullable()?.Dispose();
Service<DalamudSystemMenu>.GetNullable()?.Dispose(); Service<DalamudAtkTweaks>.GetNullable()?.Dispose();
Service<HookManager>.GetNullable()?.Dispose(); Service<HookManager>.GetNullable()?.Dispose();
Service<SigScanner>.GetNullable()?.Dispose(); Service<SigScanner>.GetNullable()?.Dispose();

View file

@ -7,6 +7,7 @@ using Dalamud.Configuration.Internal;
using Dalamud.Hooking; using Dalamud.Hooking;
using Dalamud.Interface.Internal; using Dalamud.Interface.Internal;
using FFXIVClientStructs.FFXIV.Component.GUI; using FFXIVClientStructs.FFXIV.Component.GUI;
using Serilog;
using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.ValueType; using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.ValueType;
@ -15,7 +16,7 @@ namespace Dalamud.Game.Internal
/// <summary> /// <summary>
/// This class implements in-game Dalamud options in the in-game System menu. /// This class implements in-game Dalamud options in the in-game System menu.
/// </summary> /// </summary>
internal sealed unsafe partial class DalamudSystemMenu internal sealed unsafe partial class DalamudAtkTweaks
{ {
private readonly AtkValueChangeType atkValueChangeType; private readonly AtkValueChangeType atkValueChangeType;
private readonly AtkValueSetString atkValueSetString; private readonly AtkValueSetString atkValueSetString;
@ -24,10 +25,12 @@ namespace Dalamud.Game.Internal
// TODO: Make this into events in Framework.Gui // TODO: Make this into events in Framework.Gui
private readonly Hook<UiModuleRequestMainCommand> hookUiModuleRequestMainCommand; private readonly Hook<UiModuleRequestMainCommand> hookUiModuleRequestMainCommand;
private readonly Hook<AtkUnitBaseReceiveGlobalEvent> hookAtkUnitBaseReceiveGlobalEvent;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="DalamudSystemMenu"/> class. /// Initializes a new instance of the <see cref="DalamudAtkTweaks"/> class.
/// </summary> /// </summary>
public DalamudSystemMenu() public DalamudAtkTweaks()
{ {
var sigScanner = Service<SigScanner>.Get(); var sigScanner = Service<SigScanner>.Get();
@ -43,6 +46,11 @@ namespace Dalamud.Game.Internal
var uiModuleRequestMainCommandAddress = sigScanner.ScanText("40 53 56 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 48 8B 01 8B DA 48 8B F1 FF 90 ?? ?? ?? ??"); var uiModuleRequestMainCommandAddress = sigScanner.ScanText("40 53 56 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 48 8B 01 8B DA 48 8B F1 FF 90 ?? ?? ?? ??");
this.hookUiModuleRequestMainCommand = new Hook<UiModuleRequestMainCommand>(uiModuleRequestMainCommandAddress, this.UiModuleRequestMainCommandDetour); this.hookUiModuleRequestMainCommand = new Hook<UiModuleRequestMainCommand>(uiModuleRequestMainCommandAddress, this.UiModuleRequestMainCommandDetour);
var atkUnitBaseReceiveGlobalEventAddress =
sigScanner.ScanText("48 89 5C 24 ?? 48 89 7C 24 ?? 55 41 56 41 57 48 8B EC 48 83 EC 50 44 0F B7 F2 ");
this.hookAtkUnitBaseReceiveGlobalEvent =
new Hook<AtkUnitBaseReceiveGlobalEvent>(atkUnitBaseReceiveGlobalEventAddress, this.AtkUnitBaseReceiveGlobalEventDetour);
} }
private delegate void AgentHudOpenSystemMenuPrototype(void* thisPtr, AtkValue* atkValueArgs, uint menuSize); private delegate void AgentHudOpenSystemMenuPrototype(void* thisPtr, AtkValue* atkValueArgs, uint menuSize);
@ -53,13 +61,28 @@ namespace Dalamud.Game.Internal
private delegate void UiModuleRequestMainCommand(void* thisPtr, int commandId); private delegate void UiModuleRequestMainCommand(void* thisPtr, int commandId);
private delegate IntPtr AtkUnitBaseReceiveGlobalEvent(AtkUnitBase* thisPtr, ushort cmd, uint a3, IntPtr a4, uint* a5);
/// <summary> /// <summary>
/// Enables the <see cref="DalamudSystemMenu"/>. /// Enables the <see cref="DalamudAtkTweaks"/>.
/// </summary> /// </summary>
public void Enable() public void Enable()
{ {
this.hookAgentHudOpenSystemMenu.Enable(); this.hookAgentHudOpenSystemMenu.Enable();
this.hookUiModuleRequestMainCommand.Enable(); this.hookUiModuleRequestMainCommand.Enable();
this.hookAtkUnitBaseReceiveGlobalEvent.Enable();
}
private IntPtr AtkUnitBaseReceiveGlobalEventDetour(AtkUnitBase* thisPtr, ushort cmd, uint a3, IntPtr a4, uint* a5)
{
Log.Information($"cmd:{cmd} a3:{a3} a4:{a4:x} a5:{*a5}");
var di = Service<DalamudInterface>.Get();
// "Close Addon"
if (cmd == 12 && di.WindowSystem.HasAnyFocus)
return IntPtr.Zero;
return this.hookAtkUnitBaseReceiveGlobalEvent.Original(thisPtr, cmd, a3, a4, a5);
} }
private void AgentHudOpenSystemMenuDetour(void* thisPtr, AtkValue* atkValueArgs, uint menuSize) private void AgentHudOpenSystemMenuDetour(void* thisPtr, AtkValue* atkValueArgs, uint menuSize)
@ -157,14 +180,14 @@ namespace Dalamud.Game.Internal
/// <summary> /// <summary>
/// Implements IDisposable. /// Implements IDisposable.
/// </summary> /// </summary>
internal sealed partial class DalamudSystemMenu : IDisposable internal sealed partial class DalamudAtkTweaks : IDisposable
{ {
private bool disposed = false; private bool disposed = false;
/// <summary> /// <summary>
/// Finalizes an instance of the <see cref="DalamudSystemMenu"/> class. /// Finalizes an instance of the <see cref="DalamudAtkTweaks"/> class.
/// </summary> /// </summary>
~DalamudSystemMenu() => this.Dispose(false); ~DalamudAtkTweaks() => this.Dispose(false);
/// <summary> /// <summary>
/// Dispose of managed and unmanaged resources. /// Dispose of managed and unmanaged resources.
@ -187,6 +210,7 @@ namespace Dalamud.Game.Internal
{ {
this.hookAgentHudOpenSystemMenu.Dispose(); this.hookAgentHudOpenSystemMenu.Dispose();
this.hookUiModuleRequestMainCommand.Dispose(); this.hookUiModuleRequestMainCommand.Dispose();
this.hookAtkUnitBaseReceiveGlobalEvent.Dispose();
} }
this.disposed = true; this.disposed = true;

View file

@ -28,8 +28,6 @@ namespace Dalamud.Interface.Internal
{ {
private static readonly ModuleLog Log = new("DUI"); private static readonly ModuleLog Log = new("DUI");
private readonly WindowSystem windowSystem;
private readonly ChangelogWindow changelogWindow; private readonly ChangelogWindow changelogWindow;
private readonly ColorDemoWindow colorDemoWindow; private readonly ColorDemoWindow colorDemoWindow;
private readonly ComponentDemoWindow componentDemoWindow; private readonly ComponentDemoWindow componentDemoWindow;
@ -61,7 +59,7 @@ namespace Dalamud.Interface.Internal
{ {
var configuration = Service<DalamudConfiguration>.Get(); var configuration = Service<DalamudConfiguration>.Get();
this.windowSystem = new WindowSystem("DalamudCore"); this.WindowSystem = new WindowSystem("DalamudCore");
this.changelogWindow = new ChangelogWindow() { IsOpen = false }; this.changelogWindow = new ChangelogWindow() { IsOpen = false };
this.colorDemoWindow = new ColorDemoWindow() { IsOpen = false }; this.colorDemoWindow = new ColorDemoWindow() { IsOpen = false };
@ -77,19 +75,19 @@ namespace Dalamud.Interface.Internal
this.settingsWindow = new SettingsWindow() { IsOpen = false }; this.settingsWindow = new SettingsWindow() { IsOpen = false };
this.selfTestWindow = new SelfTestWindow() { IsOpen = false }; this.selfTestWindow = new SelfTestWindow() { IsOpen = false };
this.windowSystem.AddWindow(this.changelogWindow); this.WindowSystem.AddWindow(this.changelogWindow);
this.windowSystem.AddWindow(this.colorDemoWindow); this.WindowSystem.AddWindow(this.colorDemoWindow);
this.windowSystem.AddWindow(this.componentDemoWindow); this.WindowSystem.AddWindow(this.componentDemoWindow);
this.windowSystem.AddWindow(this.creditsWindow); this.WindowSystem.AddWindow(this.creditsWindow);
this.windowSystem.AddWindow(this.dataWindow); this.WindowSystem.AddWindow(this.dataWindow);
this.windowSystem.AddWindow(this.gamepadModeNotifierWindow); this.WindowSystem.AddWindow(this.gamepadModeNotifierWindow);
this.windowSystem.AddWindow(this.imeWindow); this.WindowSystem.AddWindow(this.imeWindow);
this.windowSystem.AddWindow(this.consoleWindow); this.WindowSystem.AddWindow(this.consoleWindow);
this.windowSystem.AddWindow(this.pluginStatWindow); this.WindowSystem.AddWindow(this.pluginStatWindow);
this.windowSystem.AddWindow(this.pluginWindow); this.WindowSystem.AddWindow(this.pluginWindow);
this.windowSystem.AddWindow(this.scratchpadWindow); this.WindowSystem.AddWindow(this.scratchpadWindow);
this.windowSystem.AddWindow(this.settingsWindow); this.WindowSystem.AddWindow(this.settingsWindow);
this.windowSystem.AddWindow(this.selfTestWindow); this.WindowSystem.AddWindow(this.selfTestWindow);
ImGuiManagedAsserts.EnableAsserts = true; ImGuiManagedAsserts.EnableAsserts = true;
@ -98,6 +96,11 @@ namespace Dalamud.Interface.Internal
Log.Information("Windows added"); Log.Information("Windows added");
} }
/// <summary>
/// Gets the <see cref="WindowSystem"/> controlling all Dalamud-internal windows.
/// </summary>
public WindowSystem WindowSystem { get; init; }
/// <summary> /// <summary>
/// Gets or sets a value indicating whether the /xldev menu is open. /// Gets or sets a value indicating whether the /xldev menu is open.
/// </summary> /// </summary>
@ -117,7 +120,7 @@ namespace Dalamud.Interface.Internal
{ {
Service<InterfaceManager>.Get().Draw -= this.OnDraw; Service<InterfaceManager>.Get().Draw -= this.OnDraw;
this.windowSystem.RemoveAllWindows(); this.WindowSystem.RemoveAllWindows();
this.creditsWindow.Dispose(); this.creditsWindow.Dispose();
this.consoleWindow.Dispose(); this.consoleWindow.Dispose();
@ -309,7 +312,7 @@ namespace Dalamud.Interface.Internal
if (Service<GameGui>.Get().GameUiHidden) if (Service<GameGui>.Get().GameUiHidden)
return; return;
this.windowSystem.Draw(); this.WindowSystem.Draw();
if (this.isImGuiDrawDemoWindow) if (this.isImGuiDrawDemoWindow)
ImGui.ShowDemoWindow(); ImGui.ShowDemoWindow();

View file

@ -57,6 +57,8 @@ namespace Dalamud.Interface.Internal.Windows
this.Size = new Vector2(500, 400); this.Size = new Vector2(500, 400);
this.SizeCondition = ImGuiCond.FirstUseEver; this.SizeCondition = ImGuiCond.FirstUseEver;
this.RespectCloseHotkey = false;
} }
private List<LogEntry> LogEntries => this.isFiltered ? this.filteredLogText : this.logText; private List<LogEntry> LogEntries => this.isFiltered ? this.filteredLogText : this.logText;

View file

@ -49,7 +49,7 @@ namespace Dalamud.Interface.Windowing
public bool IsFocused { get; private set; } public bool IsFocused { get; private set; }
/// <summary> /// <summary>
/// Allow this window to be closed with a hotkey, like Escape, and keep game addons open in turn if it is closed. /// Gets or sets a value indicating whether this window is to be closed with a hotkey, like Escape, and keep game addons open in turn if it is closed.
/// </summary> /// </summary>
public bool RespectCloseHotkey { get; set; } = true; public bool RespectCloseHotkey { get; set; } = true;
@ -112,6 +112,9 @@ namespace Dalamud.Interface.Windowing
set set
{ {
this.internalIsOpen = value; this.internalIsOpen = value;
if (value == false)
this.IsFocused = false;
} }
} }

View file

@ -22,6 +22,12 @@ namespace Dalamud.Interface.Windowing
this.Namespace = imNamespace; this.Namespace = imNamespace;
} }
/// <summary>
/// Gets a value indicating whether any window in this <see cref="WindowSystem"/> has focus and is
/// not marked to be excluded from consideration.
/// </summary>
public bool HasAnyFocus { get; private set; }
/// <summary> /// <summary>
/// Gets or sets the name/ID-space of this <see cref="WindowSystem"/>. /// Gets or sets the name/ID-space of this <see cref="WindowSystem"/>.
/// </summary> /// </summary>
@ -75,6 +81,8 @@ namespace Dalamud.Interface.Windowing
window.DrawInternal(); window.DrawInternal();
} }
this.HasAnyFocus = this.windows.Any(x => x.IsFocused && x.RespectCloseHotkey);
if (hasNamespace) if (hasNamespace)
ImGui.PopID(); ImGui.PopID();
} }