From 19f77d2e6e600f91e2d752a8c0988148a7691b51 Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 29 Mar 2021 12:33:26 -0400 Subject: [PATCH 1/5] Viewport support within Dalamud --- Dalamud/Dalamud.csproj | 5 ++- Dalamud/Game/Internal/Gui/GameGui.cs | 23 +++++++++++-- Dalamud/Interface/DalamudDataWindow.cs | 45 +++++++++++++++++--------- Dalamud/Interface/InterfaceManager.cs | 10 ++++-- 4 files changed, 62 insertions(+), 21 deletions(-) diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index 55e97b46f..562b2b6db 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -10,7 +10,7 @@ false true - Portable + full $(SolutionDir)\bin\Dalamud.xml @@ -30,6 +30,9 @@ false + + DEBUG;TRACE + diff --git a/Dalamud/Game/Internal/Gui/GameGui.cs b/Dalamud/Game/Internal/Gui/GameGui.cs index b15effe7d..06b0b1677 100644 --- a/Dalamud/Game/Internal/Gui/GameGui.cs +++ b/Dalamud/Game/Internal/Gui/GameGui.cs @@ -2,6 +2,7 @@ using System; using System.Runtime.InteropServices; using Dalamud.Game.Chat.SeStringHandling.Payloads; using Dalamud.Hooking; +using ImGuiNET; using Serilog; using SharpDX; @@ -287,6 +288,8 @@ namespace Dalamud.Game.Internal.Gui { // Read current ViewProjectionMatrix plus game window size var viewProjectionMatrix = new Matrix(); float width, height; + var windowPos = ImGui.GetMainViewport().Pos; + unsafe { var rawMatrix = (float*) (matrixSingleton + 0x1b4).ToPointer(); @@ -301,10 +304,12 @@ namespace Dalamud.Game.Internal.Gui { screenPos = new Vector2(pCoords.X / pCoords.Z, pCoords.Y / pCoords.Z); - screenPos.X = 0.5f * width * (screenPos.X + 1f); - screenPos.Y = 0.5f * height * (1f - screenPos.Y); + screenPos.X = 0.5f * width * (screenPos.X + 1f) + windowPos.X; + screenPos.Y = 0.5f * height * (1f - screenPos.Y) + windowPos.Y; - return pCoords.Z > 0; + return pCoords.Z > 0 && + screenPos.X > windowPos.X && screenPos.X < windowPos.X + width && + screenPos.Y > windowPos.Y && screenPos.Y < windowPos.Y + height; } /// @@ -316,6 +321,18 @@ namespace Dalamud.Game.Internal.Gui { /// True if successful. On false, worldPos's contents are undefined public bool ScreenToWorld(Vector2 screenPos, out Vector3 worldPos, float rayDistance = 100000.0f) { + // The game is only visible in the main viewport, so if the cursor is outside + // of the game window, do not bother calculating anything + var windowPos = ImGui.GetMainViewport().Pos; + var windowSize = ImGui.GetMainViewport().Size; + + if (screenPos.X < windowPos.X || screenPos.X > windowPos.X + windowSize.X || + screenPos.Y < windowPos.Y || screenPos.Y > windowPos.Y + windowSize.Y) + { + worldPos = new Vector3(); + return false; + } + // Get base object with matrices var matrixSingleton = this.getMatrixSingleton(); diff --git a/Dalamud/Interface/DalamudDataWindow.cs b/Dalamud/Interface/DalamudDataWindow.cs index 3899697bc..3f3727744 100644 --- a/Dalamud/Interface/DalamudDataWindow.cs +++ b/Dalamud/Interface/DalamudDataWindow.cs @@ -157,29 +157,44 @@ namespace Dalamud.Interface PrintActor(actor, i.ToString()); - if (this.drawActors && - this.dalamud.Framework.Gui.WorldToScreen(actor.Position, out var screenCoords) - ) { - ImGui.PushID("ActorWindow" + i); - ImGui.SetNextWindowPos(new Vector2(screenCoords.X, screenCoords.Y)); + if (this.drawActors && this.dalamud.Framework.Gui.WorldToScreen(actor.Position, out var screenCoords)) { + + // So, while WorldToScreen will return false if the point is off of game client screen, to + // to avoid performance issues, we have to manually determine if creating a window would + // produce a new viewport, and skip rendering it if so + var actorText = $"{actor.Address.ToInt64():X}:{actor.ActorId:X}[{i}] - {actor.ObjectKind} - {actor.Name}"; + + var screenPos = ImGui.GetMainViewport().Pos; + var screenSize = ImGui.GetMainViewport().Size; + + var windowSize = ImGui.CalcTextSize(actorText); + + // Add some extra safety padding + windowSize.X += ImGui.GetStyle().WindowPadding.X + 10; + windowSize.Y += ImGui.GetStyle().WindowPadding.Y + 10; + + if (screenCoords.X + windowSize.X > screenPos.X + screenSize.X || + screenCoords.Y + windowSize.Y > screenPos.Y + screenSize.Y) + continue; if (actor.YalmDistanceX > this.maxActorDrawDistance) continue; - ImGui.SetNextWindowBgAlpha( - Math.Max(1f - (actor.YalmDistanceX / this.maxActorDrawDistance), 0.2f)); - if (ImGui.Begin("Actor" + i, + ImGui.SetNextWindowPos(new Vector2(screenCoords.X, screenCoords.Y)); + + ImGui.SetNextWindowBgAlpha(Math.Max(1f - (actor.YalmDistanceX / this.maxActorDrawDistance), 0.2f)); + if (ImGui.Begin($"Actor{i}##ActorWindow{i}", ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.AlwaysAutoResize | - ImGuiWindowFlags.NoSavedSettings | ImGuiWindowFlags.NoMove | + ImGuiWindowFlags.NoSavedSettings | + ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoMouseInputs | - ImGuiWindowFlags.NoFocusOnAppearing | ImGuiWindowFlags.NoNav)) { - ImGui.Text( - $"{actor.Address.ToInt64():X}:{actor.ActorId:X}[{i}] - {actor.ObjectKind} - {actor.Name}"); - ImGui.End(); + ImGuiWindowFlags.NoDocking | + ImGuiWindowFlags.NoFocusOnAppearing | + ImGuiWindowFlags.NoNav)) { + ImGui.Text(actorText); } - - ImGui.PopID(); + ImGui.End(); } } } diff --git a/Dalamud/Interface/InterfaceManager.cs b/Dalamud/Interface/InterfaceManager.cs index c195e5a36..45f11c2a9 100644 --- a/Dalamud/Interface/InterfaceManager.cs +++ b/Dalamud/Interface/InterfaceManager.cs @@ -165,7 +165,7 @@ namespace Dalamud.Interface // So... not great, but much better than constantly crashing on unload this.Disable(); System.Threading.Thread.Sleep(500); - + this.scene?.Dispose(); this.presentHook.Dispose(); this.resizeBuffersHook.Dispose(); @@ -228,6 +228,7 @@ namespace Dalamud.Interface private IntPtr PresentDetour(IntPtr swapChain, uint syncInterval, uint presentFlags) { if (this.scene == null) { + this.scene = new RawDX11Scene(swapChain); this.scene.ImGuiIniPath = Path.Combine(Path.GetDirectoryName(this.dalamud.StartInfo.ConfigurationPath), "dalamudUI.ini"); @@ -353,7 +354,12 @@ namespace Dalamud.Interface private IntPtr ResizeBuffersDetour(IntPtr swapChain, uint bufferCount, uint width, uint height, uint newFormat, uint swapChainFlags) { - Log.Verbose($"Calling resizebuffers {bufferCount} {width} {height} {newFormat} {swapChainFlags}"); + Log.Verbose($"Calling resizebuffers swap@{swapChain.ToInt64():X}{bufferCount} {width} {height} {newFormat} {swapChainFlags}"); + + // We have to ensure we're working with the main swapchain, + // as viewports might be resizing as well + if (swapChain != this.scene.SwapChain.NativePointer) + return resizeBuffersHook.Original(swapChain, bufferCount, width, height, newFormat, swapChainFlags); this.scene?.OnPreResize(); From d0dae36294b8ea1e5fa3fb4054d75bb6e573dd1e Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 29 Mar 2021 14:42:49 -0400 Subject: [PATCH 2/5] Update resizebuffers signature --- Dalamud/Game/Internal/DXGI/SwapChainSigResolver.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Game/Internal/DXGI/SwapChainSigResolver.cs b/Dalamud/Game/Internal/DXGI/SwapChainSigResolver.cs index 623e97e8a..4b0b1f8e8 100644 --- a/Dalamud/Game/Internal/DXGI/SwapChainSigResolver.cs +++ b/Dalamud/Game/Internal/DXGI/SwapChainSigResolver.cs @@ -24,7 +24,7 @@ namespace Dalamud.Game.Internal.DXGI // This(code after the function head - offset of it) was picked to avoid running into issues with other hooks being installed into this function. Present = scanner.ScanModule("41 8B F0 8B FA 89 54 24 ?? 48 8B D9 48 89 4D ?? C6 44 24 ?? 00") - 0x37; - ResizeBuffers = scanner.ScanModule("45 8B CC 45 8B C5 33 D2 48 8B CF E8 ?? ?? ?? ?? 44 8B C0 48 8D 55 ?? 48 8D 4D ?? E8 ?? ?? ?? ?? 38 9F E8 02 00 00") - 0xA9; + ResizeBuffers = scanner.ScanModule("48 8B C4 55 41 54 41 55 41 56 41 57 48 8D 68 B1 48 81 EC ?? ?? ?? ?? 48 C7 45 ?? ?? ?? ?? ?? 48 89 58 10 48 89 70 18 48 89 78 20 45 8B F9 45 8B E0 44 8B EA 48 8B F9 8B 45 7F 89 44 24 30 8B 75 77 89 74 24 28 44 89 4C 24"); } } } From 4618bb2fde528773bb4aeedb997928e9642b7815 Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 29 Mar 2021 20:00:56 -0400 Subject: [PATCH 3/5] Move debug menu opener into the main viewport --- Dalamud/Interface/DalamudInterface.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dalamud/Interface/DalamudInterface.cs b/Dalamud/Interface/DalamudInterface.cs index 3a3b02afc..d272930a9 100644 --- a/Dalamud/Interface/DalamudInterface.cs +++ b/Dalamud/Interface/DalamudInterface.cs @@ -76,7 +76,8 @@ namespace Dalamud.Interface ImGui.PushStyleColor(ImGuiCol.BorderShadow, new Vector4(0, 0, 0, 1)); ImGui.PushStyleColor(ImGuiCol.WindowBg, new Vector4(0, 0, 0, 1)); - ImGui.SetNextWindowPos(new Vector2(0, 0), ImGuiCond.Always); + var mainViewportPos = ImGui.GetMainViewport().Pos; + ImGui.SetNextWindowPos(new Vector2(mainViewportPos.X, mainViewportPos.Y), ImGuiCond.Always); ImGui.SetNextWindowBgAlpha(1); if (ImGui.Begin("DevMenu Opener", ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoBackground | ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoSavedSettings)) From 95d4bcab06da291834c4402baca43a8cb9bf2aef Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 29 Mar 2021 20:20:31 -0400 Subject: [PATCH 4/5] update submodule --- lib/ImGuiScene | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ImGuiScene b/lib/ImGuiScene index a1b3dc2c5..80601fe0e 160000 --- a/lib/ImGuiScene +++ b/lib/ImGuiScene @@ -1 +1 @@ -Subproject commit a1b3dc2c5645001ebf93c3cb3294f02defc319b6 +Subproject commit 80601fe0e78c916da71cc02c2de939fbc7ce9dc9 From 949007b3850baa2e01df5b373a098d37834b0597 Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 29 Mar 2021 20:31:51 -0400 Subject: [PATCH 5/5] update submodule again --- lib/ImGuiScene | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ImGuiScene b/lib/ImGuiScene index 80601fe0e..b3c22cae5 160000 --- a/lib/ImGuiScene +++ b/lib/ImGuiScene @@ -1 +1 @@ -Subproject commit 80601fe0e78c916da71cc02c2de939fbc7ce9dc9 +Subproject commit b3c22cae545f293e06d03037e30c83d5b9a77dd2