From c950b15a22d074a49e013fef94561b61509fa672 Mon Sep 17 00:00:00 2001 From: ItsBexy <103910869+ItsBexy@users.noreply.github.com> Date: Sun, 24 Nov 2024 13:37:39 -0700 Subject: [PATCH] Minor interface adjustments (#2121) - Further ImRaii safety in UiDebug2 - Set some mistakenly internal methods in ImGuiComponents to public - Added SpanFullWidth flag to trees in Util.ShowStruct --- .../Components/ImGuiComponents.IconButton.cs | 2 +- .../ImGuiComponents.IconButtonSelect.cs | 4 +- .../UiDebug2/Browsing/AddonTree.AtkValues.cs | 10 +- .../Internal/UiDebug2/Browsing/Events.cs | 6 +- .../UiDebug2/Browsing/NodeTree.Editor.cs | 3 +- .../UiDebug2/Browsing/NodeTree.Image.cs | 5 +- .../Browsing/NodeTree.NineGrid.Offsets.cs | 69 ---- .../UiDebug2/Browsing/NodeTree.NineGrid.cs | 60 ++++ .../UiDebug2/Browsing/NodeTree.Res.cs | 8 +- .../UiDebug2/Browsing/NodeTree.Text.cs | 2 +- .../UiDebug2/Browsing/TimelineTree.cs | 11 +- .../Internal/UiDebug2/ElementSelector.cs | 10 +- .../Internal/UiDebug2/Popout.Addon.cs | 3 +- .../Internal/UiDebug2/Popout.Node.cs | 3 +- .../Internal/UiDebug2/UiDebug2.Sidebar.cs | 16 +- .../Interface/Internal/UiDebug2/UiDebug2.cs | 4 +- .../Internal/UiDebug2/Utility/Gui.cs | 12 +- Dalamud/Utility/Util.cs | 318 +++++++++--------- 18 files changed, 282 insertions(+), 264 deletions(-) delete mode 100644 Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.NineGrid.Offsets.cs diff --git a/Dalamud/Interface/Components/ImGuiComponents.IconButton.cs b/Dalamud/Interface/Components/ImGuiComponents.IconButton.cs index 5e64fe463..d2b1b4a36 100644 --- a/Dalamud/Interface/Components/ImGuiComponents.IconButton.cs +++ b/Dalamud/Interface/Components/ImGuiComponents.IconButton.cs @@ -270,7 +270,7 @@ public static partial class ImGuiComponents /// Icon to use. /// Text to use. /// Width. - internal static float GetIconButtonWithTextWidth(FontAwesomeIcon icon, string text) + public static float GetIconButtonWithTextWidth(FontAwesomeIcon icon, string text) { using (ImRaii.PushFont(UiBuilder.IconFont)) { diff --git a/Dalamud/Interface/Components/ImGuiComponents.IconButtonSelect.cs b/Dalamud/Interface/Components/ImGuiComponents.IconButtonSelect.cs index 3f9c469bb..ad83c7201 100644 --- a/Dalamud/Interface/Components/ImGuiComponents.IconButtonSelect.cs +++ b/Dalamud/Interface/Components/ImGuiComponents.IconButtonSelect.cs @@ -24,7 +24,7 @@ public static partial class ImGuiComponents /// The color of the actively-selected button. /// The color of the buttons when hovered. /// True if any button is clicked. - internal static bool IconButtonSelect(string label, ref T val, IEnumerable optionIcons, IEnumerable optionValues, uint columns = 0, Vector2? buttonSize = null, Vector4? defaultColor = null, Vector4? activeColor = null, Vector4? hoveredColor = null) + public static bool IconButtonSelect(string label, ref T val, IEnumerable optionIcons, IEnumerable optionValues, uint columns = 0, Vector2? buttonSize = null, Vector4? defaultColor = null, Vector4? activeColor = null, Vector4? hoveredColor = null) { var options = optionIcons.Zip(optionValues, static (icon, value) => new KeyValuePair(icon, value)); return IconButtonSelect(label, ref val, options, columns, buttonSize, defaultColor, activeColor, hoveredColor); @@ -43,7 +43,7 @@ public static partial class ImGuiComponents /// The color of the actively-selected button. /// The color of the buttons when hovered. /// True if any button is clicked. - internal static unsafe bool IconButtonSelect(string label, ref T val, IEnumerable> options, uint columns = 0, Vector2? buttonSize = null, Vector4? defaultColor = null, Vector4? activeColor = null, Vector4? hoveredColor = null) + public static unsafe bool IconButtonSelect(string label, ref T val, IEnumerable> options, uint columns = 0, Vector2? buttonSize = null, Vector4? defaultColor = null, Vector4? activeColor = null, Vector4? hoveredColor = null) { defaultColor ??= *ImGui.GetStyleColorVec4(ImGuiCol.Button); activeColor ??= *ImGui.GetStyleColorVec4(ImGuiCol.ButtonActive); diff --git a/Dalamud/Interface/Internal/UiDebug2/Browsing/AddonTree.AtkValues.cs b/Dalamud/Interface/Internal/UiDebug2/Browsing/AddonTree.AtkValues.cs index 4b7a531c0..c3930821b 100644 --- a/Dalamud/Interface/Internal/UiDebug2/Browsing/AddonTree.AtkValues.cs +++ b/Dalamud/Interface/Internal/UiDebug2/Browsing/AddonTree.AtkValues.cs @@ -11,6 +11,7 @@ using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.ValueType; namespace Dalamud.Interface.Internal.UiDebug2.Browsing; +/// public unsafe partial class AddonTree { /// @@ -23,12 +24,11 @@ public unsafe partial class AddonTree if (addon->AtkValuesCount > 0 && atkValue != null) { using var tree = ImRaii.TreeNode($"Atk Values [{addon->AtkValuesCount}]###atkValues_{addon->NameString}"); - if (tree) + if (tree.Success) { - using (ImRaii.Table( - "atkUnitBase_atkValueTable", - 3, - ImGuiTableFlags.Borders | ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg)) + using var tbl = ImRaii.Table("atkUnitBase_atkValueTable", 3, ImGuiTableFlags.Borders | ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg); + + if (tbl.Success) { ImGui.TableSetupColumn("Index"); ImGui.TableSetupColumn("Type"); diff --git a/Dalamud/Interface/Internal/UiDebug2/Browsing/Events.cs b/Dalamud/Interface/Internal/UiDebug2/Browsing/Events.cs index 45a2d90eb..c98cc933f 100644 --- a/Dalamud/Interface/Internal/UiDebug2/Browsing/Events.cs +++ b/Dalamud/Interface/Internal/UiDebug2/Browsing/Events.cs @@ -30,9 +30,11 @@ public static class Events using var tree = ImRaii.TreeNode($"Events##{(nint)node:X}eventTree"); - if (tree) + if (tree.Success) { - using (ImRaii.Table($"##{(nint)node:X}eventTable", 7, Resizable | SizingFixedFit | Borders | RowBg)) + using var tbl = ImRaii.Table($"##{(nint)node:X}eventTable", 7, Resizable | SizingFixedFit | Borders | RowBg); + + if (tbl.Success) { ImGui.TableSetupColumn("#", WidthFixed); ImGui.TableSetupColumn("Type", WidthFixed); diff --git a/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.Editor.cs b/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.Editor.cs index 6b6522bb4..1f5abd0bf 100644 --- a/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.Editor.cs +++ b/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.Editor.cs @@ -27,7 +27,8 @@ internal unsafe partial class ResNodeTree /// private protected void DrawNodeEditorTable() { - using (ImRaii.Table($"###Editor{(nint)this.Node}", 2, SizingStretchProp | NoHostExtendX)) + using var tbl = ImRaii.Table($"###Editor{(nint)this.Node}", 2, SizingStretchProp | NoHostExtendX); + if (tbl.Success) { this.DrawEditorRows(); } diff --git a/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.Image.cs b/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.Image.cs index 4929fa1d9..8d93b3e76 100644 --- a/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.Image.cs +++ b/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.Image.cs @@ -65,7 +65,7 @@ internal unsafe partial class ImageNodeTree : ResNodeTree using var tree = ImRaii.TreeNode($"Texture##texture{(nint)this.TexData.Texture->D3D11ShaderResourceView:X}", SpanFullWidth); - if (tree) + if (tree.Success) { PrintFieldValuePairs( ("Texture Type", $"{this.TexData.TexType}"), @@ -189,7 +189,8 @@ internal unsafe partial class ImageNodeTree : ResNodeTree private void PrintPartsTable() { - using (ImRaii.Table($"partsTable##{(nint)this.TexData.Texture->D3D11ShaderResourceView:X}", 3, Borders | RowBg | Reorderable)) + using var tbl = ImRaii.Table($"partsTable##{(nint)this.TexData.Texture->D3D11ShaderResourceView:X}", 3, Borders | RowBg | Reorderable); + if (tbl.Success) { ImGui.TableSetupColumn("Part ID", WidthFixed); ImGui.TableSetupColumn("Part Texture", WidthFixed); diff --git a/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.NineGrid.Offsets.cs b/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.NineGrid.Offsets.cs deleted file mode 100644 index 237303155..000000000 --- a/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.NineGrid.Offsets.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System.Numerics; - -using FFXIVClientStructs.FFXIV.Component.GUI; - -using static Dalamud.Interface.Internal.UiDebug2.Utility.Gui; - -namespace Dalamud.Interface.Internal.UiDebug2.Browsing; - -/// -internal unsafe partial class NineGridNodeTree -{ - /// - /// A struct representing the four offsets of an . - /// - internal struct NineGridOffsets - { - /// Top offset. - internal int Top; - - /// Left offset. - internal int Left; - - /// Right offset. - internal int Right; - - /// Bottom offset. - internal int Bottom; - - /// - /// Initializes a new instance of the struct. - /// - /// The top offset. - /// The right offset. - /// The bottom offset. - /// The left offset. - internal NineGridOffsets(int top, int right, int bottom, int left) - { - this.Top = top; - this.Right = right; - this.Left = left; - this.Bottom = bottom; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The node using these offsets. - internal NineGridOffsets(AtkNineGridNode* ngNode) - : this(ngNode->TopOffset, ngNode->RightOffset, ngNode->BottomOffset, ngNode->LeftOffset) - { - } - - private NineGridOffsets(Vector4 v) - : this((int)v.X, (int)v.Y, (int)v.Z, (int)v.W) - { - } - - public static implicit operator NineGridOffsets(Vector4 v) => new(v); - - public static implicit operator Vector4(NineGridOffsets v) => new(v.Top, v.Right, v.Bottom, v.Left); - - public static NineGridOffsets operator *(float n, NineGridOffsets a) => n * (Vector4)a; - - public static NineGridOffsets operator *(NineGridOffsets a, float n) => n * a; - - /// Prints the offsets in ImGui. - internal readonly void Print() => PrintFieldValuePairs(("Top", $"{this.Top}"), ("Bottom", $"{this.Bottom}"), ("Left", $"{this.Left}"), ("Right", $"{this.Right}")); - } -} diff --git a/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.NineGrid.cs b/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.NineGrid.cs index 8f4e8c196..48825becb 100644 --- a/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.NineGrid.cs +++ b/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.NineGrid.cs @@ -1,3 +1,5 @@ +using Dalamud.Interface.Internal.UiDebug2.Utility; + using FFXIVClientStructs.FFXIV.Component.GUI; using ImGuiNET; @@ -85,4 +87,62 @@ internal unsafe partial class NineGridNodeTree : ImageNodeTree this.DrawTextureAndParts(); } + + /// + /// A struct representing the four offsets of an . + /// + internal struct NineGridOffsets + { + /// Top offset. + internal int Top; + + /// Left offset. + internal int Left; + + /// Right offset. + internal int Right; + + /// Bottom offset. + internal int Bottom; + + /// + /// Initializes a new instance of the struct. + /// + /// The top offset. + /// The right offset. + /// The bottom offset. + /// The left offset. + internal NineGridOffsets(int top, int right, int bottom, int left) + { + this.Top = top; + this.Right = right; + this.Left = left; + this.Bottom = bottom; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The node using these offsets. + internal NineGridOffsets(AtkNineGridNode* ngNode) + : this(ngNode->TopOffset, ngNode->RightOffset, ngNode->BottomOffset, ngNode->LeftOffset) + { + } + + private NineGridOffsets(Vector4 v) + : this((int)v.X, (int)v.Y, (int)v.Z, (int)v.W) + { + } + + public static implicit operator NineGridOffsets(Vector4 v) => new(v); + + public static implicit operator Vector4(NineGridOffsets v) => new(v.Top, v.Right, v.Bottom, v.Left); + + public static NineGridOffsets operator *(float n, NineGridOffsets a) => n * (Vector4)a; + + public static NineGridOffsets operator *(NineGridOffsets a, float n) => n * a; + + /// Prints the offsets in ImGui. + internal readonly void Print() => Gui.PrintFieldValuePairs(("Top", $"{this.Top}"), ("Bottom", $"{this.Bottom}"), ("Left", $"{this.Left}"), ("Right", $"{this.Right}")); + } } diff --git a/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.Res.cs b/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.Res.cs index 2edf4e570..6c12d3b4c 100644 --- a/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.Res.cs +++ b/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.Res.cs @@ -128,11 +128,11 @@ internal unsafe partial class ResNodeTree : IDisposable return; } - using var c = ImRaii.PushColor(Text, color); + using var col = ImRaii.PushColor(Text, color); using var tree = ImRaii.TreeNode($"{label}##{(nint)nodeList:X}", SpanFullWidth); - c.Pop(); + col.Pop(); - if (tree) + if (tree.Success) { var lineStart = ImGui.GetCursorScreenPos() + new Vector2(-10, 2); @@ -319,7 +319,7 @@ internal unsafe partial class ResNodeTree : IDisposable col.Pop(); - if (tree) + if (tree.Success) { var lineStart = ImGui.GetCursorScreenPos() + new Vector2(-10, 2); try diff --git a/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.Text.cs b/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.Text.cs index d9b4e7986..7c924f503 100644 --- a/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.Text.cs +++ b/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.Text.cs @@ -85,7 +85,7 @@ internal unsafe partial class TextNodeTree : ResNodeTree { using var tree = ImRaii.TreeNode($"Text Payloads##{(nint)this.Node:X}"); - if (tree) + if (tree.Success) { var utf8String = this.NodeText; var seStringBytes = new byte[utf8String.BufUsed]; diff --git a/Dalamud/Interface/Internal/UiDebug2/Browsing/TimelineTree.cs b/Dalamud/Interface/Internal/UiDebug2/Browsing/TimelineTree.cs index 8e21f4030..57e5eff99 100644 --- a/Dalamud/Interface/Internal/UiDebug2/Browsing/TimelineTree.cs +++ b/Dalamud/Interface/Internal/UiDebug2/Browsing/TimelineTree.cs @@ -58,7 +58,7 @@ public readonly unsafe partial struct TimelineTree { using var tree = ImRaii.TreeNode($"Timeline##{(nint)this.node:X}timeline", SpanFullWidth); - if (tree) + if (tree.Success) { PrintFieldValuePair("Timeline", $"{(nint)this.NodeTimeline:X}"); @@ -312,7 +312,7 @@ public readonly unsafe partial struct TimelineTree { using var tree = ImRaii.TreeNode($"[#{a}] [Frames {animation.StartFrameIdx}-{animation.EndFrameIdx}] {(isActive ? " (Active)" : string.Empty)}###{(nint)this.node}animTree{a}"); - if (tree) + if (tree.Success) { PrintFieldValuePair("Animation", $"{address:X}"); @@ -320,10 +320,9 @@ public readonly unsafe partial struct TimelineTree if (columns.Count > 0) { - using (ImRaii.Table( - $"##{(nint)this.node}animTable{a}", - columns.Count, - Borders | SizingFixedFit | RowBg | NoHostExtendX)) + using var tbl = ImRaii.Table($"##{(nint)this.node}animTable{a}", columns.Count, Borders | SizingFixedFit | RowBg | NoHostExtendX); + + if (tbl.Success) { foreach (var c in columns) { diff --git a/Dalamud/Interface/Internal/UiDebug2/ElementSelector.cs b/Dalamud/Interface/Internal/UiDebug2/ElementSelector.cs index 6693c3fb0..65537e210 100644 --- a/Dalamud/Interface/Internal/UiDebug2/ElementSelector.cs +++ b/Dalamud/Interface/Internal/UiDebug2/ElementSelector.cs @@ -79,7 +79,9 @@ internal unsafe class ElementSelector : IDisposable /// internal void DrawInterface() { - using (ImRaii.Child("###sidebar_elementSelector", new(250, -1), true)) + using var ch = ImRaii.Child("###sidebar_elementSelector", new(250, -1), true); + + if (ch.Success) { using (ImRaii.PushFont(IconFont)) { @@ -153,9 +155,11 @@ internal unsafe class ElementSelector : IDisposable using (ImRaii.PushColor(WindowBg, new Vector4(0.5f))) { - using (ImRaii.Child("noClick", new(800, 2000), false, NoInputs | NoBackground | NoScrollWithMouse)) + using var ch = ImRaii.Child("noClick", new(800, 2000), false, NoInputs | NoBackground | NoScrollWithMouse); + if (ch.Success) { - using (ImRaii.Group()) + using var gr = ImRaii.Group(); + if (gr.Success) { Gui.PrintFieldValuePair("Mouse Position", $"{mousePos.X}, {mousePos.Y}"); ImGui.Spacing(); diff --git a/Dalamud/Interface/Internal/UiDebug2/Popout.Addon.cs b/Dalamud/Interface/Internal/UiDebug2/Popout.Addon.cs index 91dfc8067..76112945e 100644 --- a/Dalamud/Interface/Internal/UiDebug2/Popout.Addon.cs +++ b/Dalamud/Interface/Internal/UiDebug2/Popout.Addon.cs @@ -39,7 +39,8 @@ internal class AddonPopoutWindow : Window, IDisposable /// public override void Draw() { - using (ImRaii.Child($"{this.WindowName}child", new(-1, -1), true)) + using var ch = ImRaii.Child($"{this.WindowName}child", new(-1, -1), true); + if (ch.Success) { this.addonTree.Draw(); } diff --git a/Dalamud/Interface/Internal/UiDebug2/Popout.Node.cs b/Dalamud/Interface/Internal/UiDebug2/Popout.Node.cs index c07806823..fe8bc87ea 100644 --- a/Dalamud/Interface/Internal/UiDebug2/Popout.Node.cs +++ b/Dalamud/Interface/Internal/UiDebug2/Popout.Node.cs @@ -50,7 +50,8 @@ internal unsafe class NodePopoutWindow : Window, IDisposable { if (this.Node != null && this.AddonTree.ContainsNode(this.Node)) { - using (ImRaii.Child($"{(nint)this.Node:X}popoutChild", new(-1, -1), true)) + using var ch = ImRaii.Child($"{(nint)this.Node:X}popoutChild", new(-1, -1), true); + if (ch.Success) { ResNodeTree.GetOrCreate(this.Node, this.AddonTree).Print(null, this.firstDraw); this.firstDraw = false; diff --git a/Dalamud/Interface/Internal/UiDebug2/UiDebug2.Sidebar.cs b/Dalamud/Interface/Internal/UiDebug2/UiDebug2.Sidebar.cs index 4253f13bc..50967453d 100644 --- a/Dalamud/Interface/Internal/UiDebug2/UiDebug2.Sidebar.cs +++ b/Dalamud/Interface/Internal/UiDebug2/UiDebug2.Sidebar.cs @@ -53,7 +53,8 @@ internal unsafe partial class UiDebug2 private void DrawSidebar() { - using (ImRaii.Group()) + using var gr = ImRaii.Group(); + if (gr.Success) { this.DrawNameSearch(); this.DrawAddonSelectionList(); @@ -63,7 +64,9 @@ internal unsafe partial class UiDebug2 private void DrawNameSearch() { - using (ImRaii.Child("###sidebar_nameSearch", new(250, 40), true)) + using var ch = ImRaii.Child("###sidebar_nameSearch", new(250, 40), true); + + if (ch.Success) { var atkUnitBaseSearch = this.addonNameSearch; @@ -90,7 +93,8 @@ internal unsafe partial class UiDebug2 private void DrawAddonSelectionList() { - using (ImRaii.Child("###sideBar_addonList", new(250, -44), true, ImGuiWindowFlags.AlwaysVerticalScrollbar)) + using var ch = ImRaii.Child("###sideBar_addonList", new(250, -44), true, ImGuiWindowFlags.AlwaysVerticalScrollbar); + if (ch.Success) { var unitListBaseAddr = GetUnitListBaseAddr(); @@ -146,11 +150,11 @@ internal unsafe partial class UiDebug2 var countStr = $"{(usingFilter ? $"{matchCount}/" : string.Empty)}{totalCount}"; - using var col1 = ImRaii.PushColor(ImGuiCol.Text, anyVisible ? new Vector4(1) : new Vector4(0.6f, 0.6f, 0.6f, 1)); + using var col = ImRaii.PushColor(ImGuiCol.Text, anyVisible ? new Vector4(1) : new Vector4(0.6f, 0.6f, 0.6f, 1)); using var tree = ImRaii.TreeNode($"{unit.Name} [{countStr}]###unitListTree{unit.Index}"); - col1.Pop(); + col.Pop(); - if (tree) + if (tree.Success) { foreach (var option in options) { diff --git a/Dalamud/Interface/Internal/UiDebug2/UiDebug2.cs b/Dalamud/Interface/Internal/UiDebug2/UiDebug2.cs index 17c64ddca..74727f2a5 100644 --- a/Dalamud/Interface/Internal/UiDebug2/UiDebug2.cs +++ b/Dalamud/Interface/Internal/UiDebug2/UiDebug2.cs @@ -83,7 +83,9 @@ internal partial class UiDebug2 : IDisposable { ImGui.SameLine(); - using (ImRaii.Child("###uiDebugMainPanel", new(-1, -1), true, HorizontalScrollbar)) + using var ch = ImRaii.Child("###uiDebugMainPanel", new(-1, -1), true, HorizontalScrollbar); + + if (ch.Success) { if (this.elementSelector.Active) { diff --git a/Dalamud/Interface/Internal/UiDebug2/Utility/Gui.cs b/Dalamud/Interface/Internal/UiDebug2/Utility/Gui.cs index cc73b79c6..cc4f1b698 100644 --- a/Dalamud/Interface/Internal/UiDebug2/Utility/Gui.cs +++ b/Dalamud/Interface/Internal/UiDebug2/Utility/Gui.cs @@ -68,10 +68,10 @@ internal static class Gui /// Colors the text itself either white or black, depending on the luminosity of the background color. internal static void PrintColor(Vector4 color, string fmt) { - using (new ImRaii.Color().Push(Text, Luminosity(color) < 0.5f ? new Vector4(1) : new(0, 0, 0, 1)) - .Push(Button, color) - .Push(ButtonActive, color) - .Push(ButtonHovered, color)) + using (ImRaii.PushColor(Text, Luminosity(color) < 0.5f ? new Vector4(1) : new(0, 0, 0, 1)) + .Push(Button, color) + .Push(ButtonActive, color) + .Push(ButtonHovered, color)) { ImGui.SmallButton(fmt); } @@ -105,7 +105,9 @@ internal static class Gui var index = (int)Math.Floor(prog * tooltips.Length); - using (ImRaii.Tooltip()) + using var tt = ImRaii.Tooltip(); + + if (tt.Success) { ImGui.TextUnformatted(tooltips[index]); } diff --git a/Dalamud/Utility/Util.cs b/Dalamud/Utility/Util.cs index 805532025..c707081f4 100644 --- a/Dalamud/Utility/Util.cs +++ b/Dalamud/Utility/Util.cs @@ -28,6 +28,8 @@ using Windows.Win32.Storage.FileSystem; using Windows.Win32.System.Memory; using Windows.Win32.System.Ole; +using Dalamud.Interface.Utility.Raii; + using static TerraFX.Interop.Windows.Windows; using Win32_PInvoke = Windows.Win32.PInvoke; @@ -1028,74 +1030,71 @@ public static class Util dm.Invoke(null, new[] { obj, path, addr }); } +#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type + private static unsafe void ShowSpanPrivate(ulong addr, IList path, int offset, bool isTop, in Span spanobj) { -#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type if (isTop) { fixed (void* p = spanobj) { - if (!ImGui.TreeNode( - $"Span<{typeof(T).Name}> of length {spanobj.Length:n0} (0x{spanobj.Length:X})" + - $"##print-obj-{addr:X}-{string.Join("-", path)}-head")) + using var tree = ImRaii.TreeNode($"Span<{typeof(T).Name}> of length {spanobj.Length:n0} (0x{spanobj.Length:X})" + $"##print-obj-{addr:X}-{string.Join("-", path)}-head", ImGuiTreeNodeFlags.SpanFullWidth); + if (tree.Success) { - return; + ShowSpanEntryPrivate(addr, path, offset, spanobj); } } } - - try + else { - const int batchSize = 20; - if (spanobj.Length > batchSize) - { - var skip = batchSize; - while ((spanobj.Length + skip - 1) / skip > batchSize) - skip *= batchSize; - for (var i = 0; i < spanobj.Length; i += skip) - { - var next = Math.Min(i + skip, spanobj.Length); - path.Add($"{offset + i:X}_{skip}"); - if (ImGui.TreeNode( - $"{offset + i:n0} ~ {offset + next - 1:n0} (0x{offset + i:X} ~ 0x{offset + next - 1:X})" + - $"##print-obj-{addr:X}-{string.Join("-", path)}")) - { - try - { - ShowSpanPrivate(addr, path, offset + i, false, spanobj[i..next]); - } - finally - { - ImGui.TreePop(); - } - } - - path.RemoveAt(path.Count - 1); - } - } - else - { - fixed (T* p = spanobj) - { - var pointerType = typeof(T*); - for (var i = 0; i < spanobj.Length; i++) - { - ImGui.TextUnformatted($"[{offset + i:n0} (0x{offset + i:X})] "); - ImGui.SameLine(); - path.Add($"{offset + i}"); - ShowValue(addr, path, pointerType, Pointer.Box(p + i, pointerType), true); - } - } - } + ShowSpanEntryPrivate(addr, path, offset, spanobj); } - finally - { - if (isTop) - ImGui.TreePop(); - } -#pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type } + private static unsafe void ShowSpanEntryPrivate(ulong addr, IList path, int offset, Span spanobj) { + const int batchSize = 20; + if (spanobj.Length > batchSize) + { + var skip = batchSize; + while ((spanobj.Length + skip - 1) / skip > batchSize) + { + skip *= batchSize; + } + + for (var i = 0; i < spanobj.Length; i += skip) + { + var next = Math.Min(i + skip, spanobj.Length); + path.Add($"{offset + i:X}_{skip}"); + + using (var tree = ImRaii.TreeNode($"{offset + i:n0} ~ {offset + next - 1:n0} (0x{offset + i:X} ~ 0x{offset + next - 1:X})" + $"##print-obj-{addr:X}-{string.Join("-", path)}", ImGuiTreeNodeFlags.SpanFullWidth)) + { + if (tree.Success) + { + ShowSpanEntryPrivate(addr, path, offset + i, spanobj[i..next]); + } + } + + path.RemoveAt(path.Count - 1); + } + } + else + { + fixed (T* p = spanobj) + { + var pointerType = typeof(T*); + for (var i = 0; i < spanobj.Length; i++) + { + ImGui.TextUnformatted($"[{offset + i:n0} (0x{offset + i:X})] "); + ImGui.SameLine(); + path.Add($"{offset + i}"); + ShowValue(addr, path, pointerType, Pointer.Box(p + i, pointerType), true); + } + } + } + } + +#pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type + private static unsafe void ShowValue(ulong addr, IList path, Type type, object value, bool hideAddress) { if (type.IsPointer) @@ -1111,9 +1110,10 @@ public static class Util if (moduleStartAddr > 0 && unboxedAddr >= moduleStartAddr && unboxedAddr <= moduleEndAddr) { ImGui.SameLine(); - ImGui.PushStyleColor(ImGuiCol.Text, 0xffcbc0ff); - ImGuiHelpers.ClickToCopyText($"ffxiv_dx11.exe+{unboxedAddr - moduleStartAddr:X}"); - ImGui.PopStyleColor(); + using (ImRaii.PushColor(ImGuiCol.Text, 0xffcbc0ff)) + { + ImGuiHelpers.ClickToCopyText($"ffxiv_dx11.exe+{unboxedAddr - moduleStartAddr:X}"); + } } ImGui.SameLine(); @@ -1165,125 +1165,135 @@ public static class Util /// Do not print addresses. Use when displaying a copied value. private static void ShowStructInternal(object obj, ulong addr, bool autoExpand = false, IEnumerable? path = null, bool hideAddress = false) { - ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(3, 2)); - path ??= new List(); - var pathList = path is List ? (List)path : path.ToList(); - - if (moduleEndAddr == 0 && moduleStartAddr == 0) + using (ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, new Vector2(3, 2))) { - try + path ??= new List(); + var pathList = path as List ?? path.ToList(); + + if (moduleEndAddr == 0 && moduleStartAddr == 0) { - var processModule = Process.GetCurrentProcess().MainModule; - if (processModule != null) + try { - moduleStartAddr = (ulong)processModule.BaseAddress.ToInt64(); - moduleEndAddr = moduleStartAddr + (ulong)processModule.ModuleMemorySize; + var processModule = Process.GetCurrentProcess().MainModule; + if (processModule != null) + { + moduleStartAddr = (ulong)processModule.BaseAddress.ToInt64(); + moduleEndAddr = moduleStartAddr + (ulong)processModule.ModuleMemorySize; + } + else + { + moduleEndAddr = 1; + } } - else + catch { moduleEndAddr = 1; } } - catch + + if (autoExpand) { - moduleEndAddr = 1; + ImGui.SetNextItemOpen(true, ImGuiCond.Appearing); } - } - ImGui.PushStyleColor(ImGuiCol.Text, 0xFF00FFFF); - if (autoExpand) - { - ImGui.SetNextItemOpen(true, ImGuiCond.Appearing); - } + using var col = ImRaii.PushColor(ImGuiCol.Text, 0xFF00FFFF); + using var tree = ImRaii.TreeNode($"{obj}##print-obj-{addr:X}-{string.Join("-", pathList)}", ImGuiTreeNodeFlags.SpanFullWidth); + col.Pop(); - if (ImGui.TreeNode($"{obj}##print-obj-{addr:X}-{string.Join("-", pathList)}")) - { - ImGui.PopStyleColor(); - foreach (var f in obj.GetType() - .GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.Instance)) + if (tree.Success) { - var fixedBuffer = (FixedBufferAttribute)f.GetCustomAttribute(typeof(FixedBufferAttribute)); - var offset = (FieldOffsetAttribute)f.GetCustomAttribute(typeof(FieldOffsetAttribute)); + ImGui.PopStyleColor(); + foreach (var f in obj.GetType() + .GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.Instance)) + { + var fixedBuffer = (FixedBufferAttribute)f.GetCustomAttribute(typeof(FixedBufferAttribute)); + var offset = (FieldOffsetAttribute)f.GetCustomAttribute(typeof(FieldOffsetAttribute)); - 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 - { - if (offset != null) + if (fixedBuffer != null) { - ImGui.TextDisabled($"[0x{offset.Value:X}]"); + ImGui.Text("fixed"); ImGui.SameLine(); + ImGui.TextColored(new Vector4(0.2f, 0.9f, 0.9f, 1), $"{fixedBuffer.ElementType.Name}[0x{fixedBuffer.Length:X}]"); } - 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(); - - pathList.Add(f.Name); - try - { - if (f.FieldType.IsGenericType && (f.FieldType.IsByRef || f.FieldType.IsByRefLike)) - ImGui.Text("Cannot preview ref typed fields."); // object never contains ref struct - else if (f.FieldType == typeof(bool) && offset != null) - ShowValue(addr, pathList, f.FieldType, Marshal.ReadByte((nint)addr + offset.Value) > 0, hideAddress); else - ShowValue(addr, pathList, f.FieldType, f.GetValue(obj), hideAddress); + { + if (offset != null) + { + ImGui.TextDisabled($"[0x{offset.Value:X}]"); + ImGui.SameLine(); + } + 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(); + + pathList.Add(f.Name); + try + { + if (f.FieldType.IsGenericType && (f.FieldType.IsByRef || f.FieldType.IsByRefLike)) + { + ImGui.Text("Cannot preview ref typed fields."); // object never contains ref struct + } + else if (f.FieldType == typeof(bool) && offset != null) + { + ShowValue(addr, pathList, f.FieldType, Marshal.ReadByte((nint)addr + offset.Value) > 0, hideAddress); + } + else + { + ShowValue(addr, pathList, f.FieldType, f.GetValue(obj), hideAddress); + } + } + catch (Exception ex) + { + using (ImRaii.PushColor(ImGuiCol.Text, new Vector4(1f, 0.4f, 0.4f, 1f))) + { + ImGui.TextUnformatted($"Error: {ex.GetType().Name}: {ex.Message}"); + } + } + finally + { + pathList.RemoveAt(pathList.Count - 1); + } } - catch (Exception ex) + + foreach (var p in obj.GetType().GetProperties().Where(static p => p.GetGetMethod()?.GetParameters().Length == 0)) { - ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(1f, 0.4f, 0.4f, 1f)); - ImGui.TextUnformatted($"Error: {ex.GetType().Name}: {ex.Message}"); - ImGui.PopStyleColor(); - } - finally - { - pathList.RemoveAt(pathList.Count - 1); + 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(); + + pathList.Add(p.Name); + try + { + if (p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == GenericSpanType) + { + ShowSpanProperty(addr, pathList, p, obj); + } + else if (p.PropertyType.IsGenericType && (p.PropertyType.IsByRef || p.PropertyType.IsByRefLike)) + { + ImGui.Text("Cannot preview ref typed properties."); + } + else + { + ShowValue(addr, pathList, p.PropertyType, p.GetValue(obj), hideAddress); + } + } + catch (Exception ex) + { + using (ImRaii.PushColor(ImGuiCol.Text, new Vector4(1f, 0.4f, 0.4f, 1f))) + { + ImGui.TextUnformatted($"Error: {ex.GetType().Name}: {ex.Message}"); + } + } + finally + { + pathList.RemoveAt(pathList.Count - 1); + } } } - - foreach (var p in obj.GetType().GetProperties().Where(p => p.GetGetMethod()?.GetParameters().Length == 0)) - { - 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(); - - pathList.Add(p.Name); - try - { - if (p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == GenericSpanType) - ShowSpanProperty(addr, pathList, p, obj); - else if (p.PropertyType.IsGenericType && (p.PropertyType.IsByRef || p.PropertyType.IsByRefLike)) - ImGui.Text("Cannot preview ref typed properties."); - else - ShowValue(addr, pathList, p.PropertyType, p.GetValue(obj), hideAddress); - } - catch (Exception ex) - { - ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(1f, 0.4f, 0.4f, 1f)); - ImGui.TextUnformatted($"Error: {ex.GetType().Name}: {ex.Message}"); - ImGui.PopStyleColor(); - } - finally - { - pathList.RemoveAt(pathList.Count - 1); - } - } - - ImGui.TreePop(); } - else - { - ImGui.PopStyleColor(); - } - - ImGui.PopStyleVar(); } }