From 65d0acaf64a584bd85427bd8440845cdc9f3d7d7 Mon Sep 17 00:00:00 2001 From: goat <16760685+goaaats@users.noreply.github.com> Date: Tue, 7 Dec 2021 21:54:05 +0100 Subject: [PATCH] feat: move UIDebug PrintOutObject into Util, add ImGuiHelpers.ClickToCopyText --- Dalamud/Interface/ImGuiHelpers.cs | 18 +++ Dalamud/Interface/Internal/UiDebug.cs | 179 ++++---------------------- Dalamud/Utility/Util.cs | 128 ++++++++++++++++++ 3 files changed, 169 insertions(+), 156 deletions(-) diff --git a/Dalamud/Interface/ImGuiHelpers.cs b/Dalamud/Interface/ImGuiHelpers.cs index f138cdf40..395d3340b 100644 --- a/Dalamud/Interface/ImGuiHelpers.cs +++ b/Dalamud/Interface/ImGuiHelpers.cs @@ -119,5 +119,23 @@ namespace Dalamud.Interface { GlobalScale = ImGui.GetIO().FontGlobalScale; } + + /// + /// Print out text that can be copied when clicked. + /// + /// The text to show. + /// The text to copy when clicked. + public static void ClickToCopyText(string text, string? textCopy = null) + { + textCopy ??= text; + ImGui.Text($"{text}"); + if (ImGui.IsItemHovered()) + { + ImGui.SetMouseCursor(ImGuiMouseCursor.Hand); + if (textCopy != text) ImGui.SetTooltip(textCopy); + } + + if (ImGui.IsItemClicked()) ImGui.SetClipboardText($"{textCopy}"); + } } } diff --git a/Dalamud/Interface/Internal/UiDebug.cs b/Dalamud/Interface/Internal/UiDebug.cs index e64ec6bc2..0a5c27004 100644 --- a/Dalamud/Interface/Internal/UiDebug.cs +++ b/Dalamud/Interface/Internal/UiDebug.cs @@ -8,6 +8,7 @@ using System.Runtime.InteropServices; using Dalamud.Game; using Dalamud.Game.Gui; +using Dalamud.Utility; using FFXIVClientStructs.FFXIV.Component.GUI; using ImGuiNET; @@ -49,8 +50,6 @@ namespace Dalamud.Interface.Internal private bool doingSearch; private string searchInput = string.Empty; private AtkUnitBase* selectedUnitBase = null; - private ulong beginModule; - private ulong endModule; /// /// Initializes a new instance of the class. @@ -88,19 +87,6 @@ namespace Dalamud.Interface.Internal ImGui.PopStyleVar(); } - private static void ClickToCopyText(string text, string textCopy = null) - { - textCopy ??= text; - ImGui.Text($"{text}"); - if (ImGui.IsItemHovered()) - { - ImGui.SetMouseCursor(ImGuiMouseCursor.Hand); - if (textCopy != text) ImGui.SetTooltip(textCopy); - } - - if (ImGui.IsItemClicked()) ImGui.SetClipboardText($"{textCopy}"); - } - private void DrawUnitBase(AtkUnitBase* atkUnitBase) { var isVisible = (atkUnitBase->Flags & 0x20) == 0x20; @@ -120,8 +106,8 @@ namespace Dalamud.Interface.Internal } ImGui.Separator(); - ClickToCopyText($"Address: {(ulong)atkUnitBase:X}", $"{(ulong)atkUnitBase:X}"); - ClickToCopyText($"Agent: {(ulong)agent:X}", $"{(ulong)agent:X}"); + ImGuiHelpers.ClickToCopyText($"Address: {(ulong)atkUnitBase:X}", $"{(ulong)atkUnitBase:X}"); + ImGuiHelpers.ClickToCopyText($"Agent: {(ulong)agent:X}", $"{(ulong)agent:X}"); ImGui.Separator(); ImGui.Text($"Position: [ {atkUnitBase->X} , {atkUnitBase->Y} ]"); @@ -132,7 +118,7 @@ namespace Dalamud.Interface.Internal object addonObj = *atkUnitBase; - this.PrintOutObject(addonObj, (ulong)atkUnitBase, new List()); + Util.PrintOutObject(addonObj, (ulong)atkUnitBase, new List()); ImGui.Dummy(new Vector2(25 * ImGui.GetIO().FontGlobalScale)); ImGui.Separator(); @@ -205,16 +191,16 @@ namespace Dalamud.Interface.Internal ImGui.Text("Node: "); ImGui.SameLine(); - ClickToCopyText($"{(ulong)node:X}"); + ImGuiHelpers.ClickToCopyText($"{(ulong)node:X}"); ImGui.SameLine(); switch (node->Type) { - case NodeType.Text: this.PrintOutObject(*(AtkTextNode*)node, (ulong)node, new List()); break; - case NodeType.Image: this.PrintOutObject(*(AtkImageNode*)node, (ulong)node, new List()); break; - case NodeType.Collision: this.PrintOutObject(*(AtkCollisionNode*)node, (ulong)node, new List()); break; - case NodeType.NineGrid: this.PrintOutObject(*(AtkNineGridNode*)node, (ulong)node, new List()); break; - case NodeType.Counter: this.PrintOutObject(*(AtkCounterNode*)node, (ulong)node, new List()); break; - default: this.PrintOutObject(*node, (ulong)node, new List()); break; + case NodeType.Text: Util.PrintOutObject(*(AtkTextNode*)node, (ulong)node); break; + case NodeType.Image: Util.PrintOutObject(*(AtkImageNode*)node, (ulong)node); break; + case NodeType.Collision: Util.PrintOutObject(*(AtkCollisionNode*)node, (ulong)node); break; + case NodeType.NineGrid: Util.PrintOutObject(*(AtkNineGridNode*)node, (ulong)node); break; + case NodeType.Counter: Util.PrintOutObject(*(AtkCounterNode*)node, (ulong)node); break; + default: Util.PrintOutObject(*node, (ulong)node, new List()); break; } this.PrintResNode(node); @@ -341,25 +327,25 @@ namespace Dalamud.Interface.Internal ImGui.Text("Node: "); ImGui.SameLine(); - ClickToCopyText($"{(ulong)node:X}"); + ImGuiHelpers.ClickToCopyText($"{(ulong)node:X}"); ImGui.SameLine(); - this.PrintOutObject(*compNode, (ulong)compNode, new List()); + Util.PrintOutObject(*compNode, (ulong)compNode); ImGui.Text("Component: "); ImGui.SameLine(); - ClickToCopyText($"{(ulong)compNode->Component:X}"); + ImGuiHelpers.ClickToCopyText($"{(ulong)compNode->Component:X}"); ImGui.SameLine(); switch (objectInfo->ComponentType) { - case ComponentType.Button: this.PrintOutObject(*(AtkComponentButton*)compNode->Component, (ulong)compNode->Component, new List()); break; - case ComponentType.Slider: this.PrintOutObject(*(AtkComponentSlider*)compNode->Component, (ulong)compNode->Component, new List()); break; - case ComponentType.Window: this.PrintOutObject(*(AtkComponentWindow*)compNode->Component, (ulong)compNode->Component, new List()); break; - case ComponentType.CheckBox: this.PrintOutObject(*(AtkComponentCheckBox*)compNode->Component, (ulong)compNode->Component, new List()); break; - case ComponentType.GaugeBar: this.PrintOutObject(*(AtkComponentGaugeBar*)compNode->Component, (ulong)compNode->Component, new List()); break; - case ComponentType.RadioButton: this.PrintOutObject(*(AtkComponentRadioButton*)compNode->Component, (ulong)compNode->Component, new List()); break; - case ComponentType.TextInput: this.PrintOutObject(*(AtkComponentTextInput*)compNode->Component, (ulong)compNode->Component, new List()); break; - case ComponentType.Icon: this.PrintOutObject(*(AtkComponentIcon*)compNode->Component, (ulong)compNode->Component, new List()); break; - default: this.PrintOutObject(*compNode->Component, (ulong)compNode->Component, new List()); break; + case ComponentType.Button: Util.PrintOutObject(*(AtkComponentButton*)compNode->Component, (ulong)compNode->Component); break; + case ComponentType.Slider: Util.PrintOutObject(*(AtkComponentSlider*)compNode->Component, (ulong)compNode->Component); break; + case ComponentType.Window: Util.PrintOutObject(*(AtkComponentWindow*)compNode->Component, (ulong)compNode->Component); break; + case ComponentType.CheckBox: Util.PrintOutObject(*(AtkComponentCheckBox*)compNode->Component, (ulong)compNode->Component); break; + case ComponentType.GaugeBar: Util.PrintOutObject(*(AtkComponentGaugeBar*)compNode->Component, (ulong)compNode->Component); break; + case ComponentType.RadioButton: Util.PrintOutObject(*(AtkComponentRadioButton*)compNode->Component, (ulong)compNode->Component); break; + case ComponentType.TextInput: Util.PrintOutObject(*(AtkComponentTextInput*)compNode->Component, (ulong)compNode->Component); break; + case ComponentType.Icon: Util.PrintOutObject(*(AtkComponentIcon*)compNode->Component, (ulong)compNode->Component); break; + default: Util.PrintOutObject(*compNode->Component, (ulong)compNode->Component); break; } this.PrintResNode(node); @@ -609,124 +595,5 @@ namespace Dalamud.Interface.Internal ImGui.GetForegroundDrawList(ImGuiHelpers.MainViewport).AddRect(position, position + size, nodeVisible ? 0xFF00FF00 : 0xFF0000FF); } - - private void PrintOutValue(ulong addr, IEnumerable path, Type type, object value) - { - if (type.IsPointer) - { - var val = (Pointer)value; - var unboxed = Pointer.Unbox(val); - if (unboxed != null) - { - var unboxedAddr = (ulong)unboxed; - ClickToCopyText($"{(ulong)unboxed:X}"); - if (this.beginModule > 0 && unboxedAddr >= this.beginModule && unboxedAddr <= this.endModule) - { - ImGui.SameLine(); - ImGui.PushStyleColor(ImGuiCol.Text, 0xffcbc0ff); - ClickToCopyText($"ffxiv_dx11.exe+{unboxedAddr - this.beginModule:X}"); - ImGui.PopStyleColor(); - } - - try - { - var eType = type.GetElementType(); - var ptrObj = Marshal.PtrToStructure(new IntPtr(unboxed), eType); - ImGui.SameLine(); - this.PrintOutObject(ptrObj, (ulong)unboxed, new List(path)); - } - catch - { - // Ignored - } - } - else - { - ImGui.Text("null"); - } - } - else - { - if (!type.IsPrimitive) - { - this.PrintOutObject(value, addr, new List(path)); - } - else - { - ImGui.Text($"{value}"); - } - } - } - - private void PrintOutObject(object obj, ulong addr, List path, bool autoExpand = false) - { - if (this.endModule == 0 && this.beginModule == 0) - { - try - { - var processModule = Process.GetCurrentProcess().MainModule; - if (processModule != null) - { - this.beginModule = (ulong)processModule.BaseAddress.ToInt64(); - this.endModule = this.beginModule + (ulong)processModule.ModuleMemorySize; - } - else - { - this.endModule = 1; - } - } - catch - { - this.endModule = 1; - } - } - - ImGui.PushStyleColor(ImGuiCol.Text, 0xFF00FFFF); - if (autoExpand) - { - ImGui.SetNextItemOpen(true, ImGuiCond.Appearing); - } - - if (ImGui.TreeNode($"{obj}##print-obj-{addr:X}-{string.Join("-", path)}")) - { - ImGui.PopStyleColor(); - foreach (var f in obj.GetType().GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.Instance)) - { - var fixedBuffer = (FixedBufferAttribute)f.GetCustomAttribute(typeof(FixedBufferAttribute)); - if (fixedBuffer != null) - { - ImGui.Text($"fixed"); - ImGui.SameLine(); - ImGui.TextColored(new Vector4(0.2f, 0.9f, 0.9f, 1), $"{fixedBuffer.ElementType.Name}[0x{fixedBuffer.Length:X}]"); - } - else - { - ImGui.TextColored(new Vector4(0.2f, 0.9f, 0.9f, 1), $"{f.FieldType.Name}"); - } - - ImGui.SameLine(); - ImGui.TextColored(new Vector4(0.2f, 0.9f, 0.4f, 1), $"{f.Name}: "); - ImGui.SameLine(); - - this.PrintOutValue(addr, new List(path) { f.Name }, f.FieldType, f.GetValue(obj)); - } - - foreach (var p in obj.GetType().GetProperties()) - { - ImGui.TextColored(new Vector4(0.2f, 0.9f, 0.9f, 1), $"{p.PropertyType.Name}"); - ImGui.SameLine(); - ImGui.TextColored(new Vector4(0.2f, 0.6f, 0.4f, 1), $"{p.Name}: "); - ImGui.SameLine(); - - this.PrintOutValue(addr, new List(path) { p.Name }, p.PropertyType, p.GetValue(obj)); - } - - ImGui.TreePop(); - } - else - { - ImGui.PopStyleColor(); - } - } } } diff --git a/Dalamud/Utility/Util.cs b/Dalamud/Utility/Util.cs index f69a75f60..fcb6d3c1d 100644 --- a/Dalamud/Utility/Util.cs +++ b/Dalamud/Utility/Util.cs @@ -1,10 +1,14 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; using System.Net.Http; +using System.Numerics; using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Text; using Dalamud.Configuration.Internal; @@ -156,6 +160,130 @@ namespace Dalamud.Utility return sb.ToString().TrimEnd(Environment.NewLine.ToCharArray()); } + private static ulong moduleStartAddr; + private static ulong moduleEndAddr; + + private static unsafe void PrintOutValue(ulong addr, IEnumerable path, Type type, object value) + { + if (type.IsPointer) + { + var val = (Pointer)value; + var unboxed = Pointer.Unbox(val); + if (unboxed != null) + { + var unboxedAddr = (ulong)unboxed; + ImGuiHelpers.ClickToCopyText($"{(ulong)unboxed:X}"); + if (moduleStartAddr > 0 && unboxedAddr >= moduleStartAddr && unboxedAddr <= moduleEndAddr) + { + ImGui.SameLine(); + ImGui.PushStyleColor(ImGuiCol.Text, 0xffcbc0ff); + ImGuiHelpers.ClickToCopyText($"ffxiv_dx11.exe+{unboxedAddr - moduleStartAddr:X}"); + ImGui.PopStyleColor(); + } + + try + { + var eType = type.GetElementType(); + var ptrObj = Marshal.PtrToStructure(new IntPtr(unboxed), eType); + ImGui.SameLine(); + PrintOutObject(ptrObj, (ulong)unboxed, new List(path)); + } + catch + { + // Ignored + } + } + else + { + ImGui.Text("null"); + } + } + else + { + if (!type.IsPrimitive) + { + PrintOutObject(value, addr, new List(path)); + } + else + { + ImGui.Text($"{value}"); + } + } + } + + public static void PrintOutObject(object obj, ulong addr, IEnumerable? path = null, bool autoExpand = false) + { + path ??= new List(); + + if (moduleEndAddr == 0 && moduleStartAddr == 0) + { + try + { + var processModule = Process.GetCurrentProcess().MainModule; + if (processModule != null) + { + moduleStartAddr = (ulong)processModule.BaseAddress.ToInt64(); + moduleEndAddr = moduleStartAddr + (ulong)processModule.ModuleMemorySize; + } + else + { + moduleEndAddr = 1; + } + } + catch + { + moduleEndAddr = 1; + } + } + + ImGui.PushStyleColor(ImGuiCol.Text, 0xFF00FFFF); + if (autoExpand) + { + ImGui.SetNextItemOpen(true, ImGuiCond.Appearing); + } + + if (ImGui.TreeNode($"{obj}##print-obj-{addr:X}-{string.Join("-", path)}")) + { + ImGui.PopStyleColor(); + foreach (var f in obj.GetType().GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.Instance)) + { + var fixedBuffer = (FixedBufferAttribute)f.GetCustomAttribute(typeof(FixedBufferAttribute)); + if (fixedBuffer != null) + { + ImGui.Text($"fixed"); + ImGui.SameLine(); + ImGui.TextColored(new Vector4(0.2f, 0.9f, 0.9f, 1), $"{fixedBuffer.ElementType.Name}[0x{fixedBuffer.Length:X}]"); + } + else + { + ImGui.TextColored(new Vector4(0.2f, 0.9f, 0.9f, 1), $"{f.FieldType.Name}"); + } + + ImGui.SameLine(); + ImGui.TextColored(new Vector4(0.2f, 0.9f, 0.4f, 1), $"{f.Name}: "); + ImGui.SameLine(); + + PrintOutValue(addr, new List(path) { f.Name }, f.FieldType, f.GetValue(obj)); + } + + foreach (var p in obj.GetType().GetProperties()) + { + ImGui.TextColored(new Vector4(0.2f, 0.9f, 0.9f, 1), $"{p.PropertyType.Name}"); + ImGui.SameLine(); + ImGui.TextColored(new Vector4(0.2f, 0.6f, 0.4f, 1), $"{p.Name}: "); + ImGui.SameLine(); + + PrintOutValue(addr, new List(path) { p.Name }, p.PropertyType, p.GetValue(obj)); + } + + ImGui.TreePop(); + } + else + { + ImGui.PopStyleColor(); + } + } + /// /// Show all properties and fields of the provided object via ImGui. ///