Misc UiDebug2 Fixes

- The widget will now only check the `FFXIVClientStructs` assembly for addon type information.
- Updated ImRaii usage
- Clarified suppression in `NodeTree.Text.cs`
- Restored the original Addon Inspector in the Data window, so that both versions can coexist for the time being
This commit is contained in:
ItsBexy 2024-10-17 10:52:22 -06:00
parent e19f9284e5
commit 552aafd70d
17 changed files with 379 additions and 347 deletions

View file

@ -16,8 +16,10 @@ public unsafe partial class AddonTree
{
private static readonly Dictionary<string, Type?> AddonTypeDict = [];
private static readonly Assembly? ClientStructs = AppDomain.CurrentDomain.GetAssemblies().SingleOrDefault(static a => a.GetName().Name == "FFXIVClientStructs");
/// <summary>
/// Gets or sets a collection of names corresponding to pointers documented within the addon struct.
/// Gets or sets a collection of names for field offsets that have been documented in FFXIVClientStructs.
/// </summary>
internal Dictionary<nint, List<string>> FieldNames { get; set; } = [];
@ -28,28 +30,25 @@ public unsafe partial class AddonTree
return null;
}
if (AddonTypeDict.TryAdd(this.AddonName, null))
if (AddonTypeDict.TryAdd(this.AddonName, null) && ClientStructs != null)
{
foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
try
{
try
foreach (var t in from t in ClientStructs.GetTypes()
where t.IsPublic
let xivAddonAttr = (Addon?)t.GetCustomAttribute(typeof(Addon), false)
where xivAddonAttr != null
where xivAddonAttr.AddonIdentifiers.Contains(this.AddonName)
select t)
{
foreach (var t in from t in a.GetTypes()
where t.IsPublic
let xivAddonAttr = (Addon?)t.GetCustomAttribute(typeof(Addon), false)
where xivAddonAttr != null
where xivAddonAttr.AddonIdentifiers.Contains(this.AddonName)
select t)
{
AddonTypeDict[this.AddonName] = t;
break;
}
}
catch
{
// ignored
AddonTypeDict[this.AddonName] = t;
break;
}
}
catch
{
// ignored
}
}
return AddonTypeDict.TryGetValue(this.AddonName, out var result) && result != null ? Marshal.PtrToStructure(new(addon), result) : *addon;
@ -108,7 +107,7 @@ public unsafe partial class AddonTree
{
try
{
if (this.FieldNames.TryAdd(fieldAddr, [..path!, name]) && fieldType.DeclaringType == baseType)
if (this.FieldNames.TryAdd(fieldAddr, [..path, name]) && fieldType.DeclaringType == baseType)
{
this.PopulateFieldNames(field.GetValue(obj), fieldAddr, [..path, name]);
}
@ -140,7 +139,7 @@ public unsafe partial class AddonTree
var itemAddr = fieldAddr + (size * i);
var itemName = $"{name}[{i}]";
this.FieldNames.TryAdd(itemAddr, [..path!, itemName]);
this.FieldNames.TryAdd(itemAddr, [..path, itemName]);
var item = Marshal.PtrToStructure(itemAddr, itemType);
if (itemType.DeclaringType == baseType)
@ -176,10 +175,10 @@ public unsafe partial class AddonTree
return;
}
this.FieldNames.TryAdd(fieldAddr, [..path!, name]);
this.FieldNames.TryAdd(fieldAddr, [..path, name]);
this.FieldNames.TryAdd(pointer, [..path, name]);
if (itemType?.DeclaringType != baseType || itemType!.IsPointer)
if (itemType?.DeclaringType != baseType || itemType.IsPointer)
{
return;
}

View file

@ -26,44 +26,41 @@ public static class Events
return;
}
var tree = ImRaii.TreeNode($"Events##{(nint)node:X}eventTree");
using var tree = ImRaii.TreeNode($"Events##{(nint)node:X}eventTree");
if (tree)
{
var tab = ImRaii.Table($"##{(nint)node:X}eventTable", 7, Resizable | SizingFixedFit | Borders | RowBg);
ImGui.TableSetupColumn("#", WidthFixed);
ImGui.TableSetupColumn("Type", WidthFixed);
ImGui.TableSetupColumn("Param", WidthFixed);
ImGui.TableSetupColumn("Flags", WidthFixed);
ImGui.TableSetupColumn("Unk29", WidthFixed);
ImGui.TableSetupColumn("Target", WidthFixed);
ImGui.TableSetupColumn("Listener", WidthFixed);
ImGui.TableHeadersRow();
var i = 0;
while (evt != null)
using (ImRaii.Table($"##{(nint)node:X}eventTable", 7, Resizable | SizingFixedFit | Borders | RowBg))
{
ImGui.TableNextColumn();
ImGui.Text($"{i++}");
ImGui.TableNextColumn();
ImGui.Text($"{evt->Type}");
ImGui.TableNextColumn();
ImGui.Text($"{evt->Param}");
ImGui.TableNextColumn();
ImGui.Text($"{evt->Flags}");
ImGui.TableNextColumn();
ImGui.Text($"{evt->Unk29}");
ImGui.TableNextColumn();
Gui.ClickToCopyText($"{(nint)evt->Target:X}");
ImGui.TableNextColumn();
Gui.ClickToCopyText($"{(nint)evt->Listener:X}");
evt = evt->NextEvent;
ImGui.TableSetupColumn("#", WidthFixed);
ImGui.TableSetupColumn("Type", WidthFixed);
ImGui.TableSetupColumn("Param", WidthFixed);
ImGui.TableSetupColumn("Flags", WidthFixed);
ImGui.TableSetupColumn("Unk29", WidthFixed);
ImGui.TableSetupColumn("Target", WidthFixed);
ImGui.TableSetupColumn("Listener", WidthFixed);
ImGui.TableHeadersRow();
var i = 0;
while (evt != null)
{
ImGui.TableNextColumn();
ImGui.Text($"{i++}");
ImGui.TableNextColumn();
ImGui.Text($"{evt->Type}");
ImGui.TableNextColumn();
ImGui.Text($"{evt->Param}");
ImGui.TableNextColumn();
ImGui.Text($"{evt->Flags}");
ImGui.TableNextColumn();
ImGui.Text($"{evt->Unk29}");
ImGui.TableNextColumn();
Gui.ClickToCopyText($"{(nint)evt->Target:X}");
ImGui.TableNextColumn();
Gui.ClickToCopyText($"{(nint)evt->Listener:X}");
evt = evt->NextEvent;
}
}
tab.Dispose();
}
tree.Dispose();
}
}

View file

@ -26,11 +26,10 @@ internal unsafe partial class ResNodeTree
/// </summary>
private protected void DrawNodeEditorTable()
{
var tab = ImRaii.Table($"###Editor{(nint)this.Node}", 2, SizingStretchProp | NoHostExtendX);
this.DrawEditorRows();
tab.Dispose();
using (ImRaii.Table($"###Editor{(nint)this.Node}", 2, SizingStretchProp | NoHostExtendX))
{
this.DrawEditorRows();
}
}
/// <summary>

View file

@ -51,8 +51,8 @@ internal unsafe partial class ImageNodeTree : ResNodeTree
/// <summary>
/// Draws the texture inside the window, in either of two styles.<br/><br/>
/// <term>Full Image</term>presents the texture in full as a spritesheet.<br/>
/// <term>Parts List</term>presents the individual parts as rows in a table.
/// <term>Full Image (0)</term>presents the texture in full as a spritesheet.<br/>
/// <term>Parts List (1)</term>presents the individual parts as rows in a table.
/// </summary>
private protected void DrawTextureAndParts()
{
@ -63,7 +63,7 @@ internal unsafe partial class ImageNodeTree : ResNodeTree
return;
}
var tree = ImRaii.TreeNode($"Texture##texture{(nint)this.TexData.Texture->D3D11ShaderResourceView:X}", SpanFullWidth);
using var tree = ImRaii.TreeNode($"Texture##texture{(nint)this.TexData.Texture->D3D11ShaderResourceView:X}", SpanFullWidth);
if (tree)
{
@ -99,8 +99,6 @@ internal unsafe partial class ImageNodeTree : ResNodeTree
this.DrawFullTexture();
}
}
tree.Dispose();
}
/// <summary>
@ -191,58 +189,62 @@ internal unsafe partial class ImageNodeTree : ResNodeTree
private void PrintPartsTable()
{
var tab = ImRaii.Table($"partsTable##{(nint)this.TexData.Texture->D3D11ShaderResourceView:X}", 3, Borders | RowBg | Reorderable);
ImGui.TableSetupColumn("Part ID", WidthFixed);
ImGui.TableSetupColumn("Part Texture", WidthFixed);
ImGui.TableSetupColumn("Coordinates", WidthFixed);
ImGui.TableHeadersRow();
var tWidth = this.TexData.Texture->Width;
var tHeight = this.TexData.Texture->Height;
var textureSize = new Vector2(tWidth, tHeight);
for (ushort i = 0; i < this.TexData.PartCount; i++)
using (ImRaii.Table($"partsTable##{(nint)this.TexData.Texture->D3D11ShaderResourceView:X}", 3, Borders | RowBg | Reorderable))
{
ImGui.TableNextColumn();
ImGui.TableSetupColumn("Part ID", WidthFixed);
ImGui.TableSetupColumn("Part Texture", WidthFixed);
ImGui.TableSetupColumn("Coordinates", WidthFixed);
var col = i == this.TexData.PartId ? new Vector4(0, 0.85F, 1, 1) : new(1);
ImGui.TextColored(col, $"#{i.ToString().PadLeft(this.TexData.PartCount.ToString().Length, '0')}");
ImGui.TableHeadersRow();
ImGui.TableNextColumn();
var tWidth = this.TexData.Texture->Width;
var tHeight = this.TexData.Texture->Height;
var textureSize = new Vector2(tWidth, tHeight);
var part = this.TexData.PartsList->Parts[i];
var hiRes = this.TexData.HiRes;
for (ushort i = 0; i < this.TexData.PartCount; i++)
{
ImGui.TableNextColumn();
var u = hiRes ? part.U * 2f : part.U;
var v = hiRes ? part.V * 2f : part.V;
var width = hiRes ? part.Width * 2f : part.Width;
var height = hiRes ? part.Height * 2f : part.Height;
var col = i == this.TexData.PartId ? new Vector4(0, 0.85F, 1, 1) : new(1);
ImGui.TextColored(col, $"#{i.ToString().PadLeft(this.TexData.PartCount.ToString().Length, '0')}");
ImGui.Image(new(this.TexData.Texture->D3D11ShaderResourceView), new(width, height), new Vector2(u, v) / textureSize, new Vector2(u + width, v + height) / textureSize);
ImGui.TableNextColumn();
ImGui.TableNextColumn();
var part = this.TexData.PartsList->Parts[i];
var hiRes = this.TexData.HiRes;
ImGui.TextColored(!hiRes ? new(1) : new(0.6f, 0.6f, 0.6f, 1), "Standard:\t");
ImGui.SameLine();
var cursX = ImGui.GetCursorPosX();
var u = hiRes ? part.U * 2f : part.U;
var v = hiRes ? part.V * 2f : part.V;
var width = hiRes ? part.Width * 2f : part.Width;
var height = hiRes ? part.Height * 2f : part.Height;
PrintPartCoords(u / 2f, v / 2f, width / 2f, height / 2f);
ImGui.Image(
new(this.TexData.Texture->D3D11ShaderResourceView),
new(width, height),
new Vector2(u, v) / textureSize,
new Vector2(u + width, v + height) / textureSize);
ImGui.TextColored(hiRes ? new(1) : new(0.6f, 0.6f, 0.6f, 1), "Hi-Res:\t");
ImGui.SameLine();
ImGui.SetCursorPosX(cursX);
ImGui.TableNextColumn();
PrintPartCoords(u, v, width, height);
ImGui.TextColored(!hiRes ? new(1) : new(0.6f, 0.6f, 0.6f, 1), "Standard:\t");
ImGui.SameLine();
var cursX = ImGui.GetCursorPosX();
ImGui.Text("UV:\t");
ImGui.SameLine();
ImGui.SetCursorPosX(cursX);
PrintPartCoords(u / 2f, v / 2f, width / 2f, height / 2f);
PrintPartCoords(u / tWidth, v / tWidth, (u + width) / tWidth, (v + height) / tHeight, true, true);
ImGui.TextColored(hiRes ? new(1) : new(0.6f, 0.6f, 0.6f, 1), "Hi-Res:\t");
ImGui.SameLine();
ImGui.SetCursorPosX(cursX);
PrintPartCoords(u, v, width, height);
ImGui.Text("UV:\t");
ImGui.SameLine();
ImGui.SetCursorPosX(cursX);
PrintPartCoords(u / tWidth, v / tWidth, (u + width) / tWidth, (v + height) / tHeight, true, true);
}
}
tab.Dispose();
}
/// <summary>

View file

@ -90,11 +90,11 @@ internal unsafe partial class ResNodeTree : IDisposable
NodeType.ClippingMask => new ClippingMaskNodeTree(node, addonTree),
NodeType.Counter => new CounterNodeTree(node, addonTree),
NodeType.Collision => new CollisionNodeTree(node, addonTree),
_ => new ResNodeTree(node, addonTree),
_ => new ResNodeTree(node, addonTree)
};
/// <summary>
/// Prints a list of NodeTree for a given list of nodes.
/// Prints a list of NodeTrees for a given list of nodes.
/// </summary>
/// <param name="nodeList">The address of the start of the list.</param>
/// <param name="count">The number of nodes in the list.</param>
@ -122,8 +122,8 @@ internal unsafe partial class ResNodeTree : IDisposable
return;
}
var c = ImRaii.PushColor(Text, color);
var tree = ImRaii.TreeNode($"{label}##{(nint)nodeList:X}", SpanFullWidth);
using var c = ImRaii.PushColor(Text, color);
using var tree = ImRaii.TreeNode($"{label}##{(nint)nodeList:X}", SpanFullWidth);
c.Pop();
if (tree)
@ -139,8 +139,6 @@ internal unsafe partial class ResNodeTree : IDisposable
ImGui.GetWindowDrawList().AddLine(lineStart, lineEnd, RgbaVector4ToUint(color), 1);
}
}
tree.Dispose();
}
/// <summary>
@ -275,8 +273,8 @@ internal unsafe partial class ResNodeTree : IDisposable
ImGui.SetNextItemOpen(true, ImGuiCond.Always);
}
var col = ImRaii.PushColor(Text, displayColor);
var tree = ImRaii.TreeNode(label, SpanFullWidth);
using var col = ImRaii.PushColor(Text, displayColor);
using var tree = ImRaii.TreeNode(label, SpanFullWidth);
if (ImGui.IsItemHovered())
{
@ -331,8 +329,6 @@ internal unsafe partial class ResNodeTree : IDisposable
ImGui.GetWindowDrawList().AddLine(lineStart, lineEnd, RgbaVector4ToUint(displayColor), 1);
}
}
tree.Dispose();
}
private void DrawBasicControls()

View file

@ -50,7 +50,6 @@ internal unsafe partial class TextNodeTree : ResNodeTree
ImGui.TextColored(new(1), "Text:");
ImGui.SameLine();
#pragma warning disable
try
{
var style = new SeStringDrawParams
@ -61,13 +60,14 @@ internal unsafe partial class TextNodeTree : ResNodeTree
EdgeStrength = 1f
};
#pragma warning disable SeStringRenderer
ImGuiHelpers.SeStringWrapped(this.NodeText.AsSpan(), style);
#pragma warning restore SeStringRenderer
}
catch
{
ImGui.Text(Marshal.PtrToStringAnsi(new(this.NodeText.StringPtr)) ?? "");
}
#pragma warning restore
PrintFieldValuePairs(
("Font", $"{this.TxtNode->FontType}"),
@ -83,7 +83,7 @@ internal unsafe partial class TextNodeTree : ResNodeTree
private void PrintPayloads()
{
var tree = ImRaii.TreeNode($"Text Payloads##{(nint)this.Node:X}");
using var tree = ImRaii.TreeNode($"Text Payloads##{(nint)this.Node:X}");
if (tree)
{
@ -116,7 +116,5 @@ internal unsafe partial class TextNodeTree : ResNodeTree
}
}
}
tree.Dispose();
}
}

View file

@ -56,7 +56,7 @@ public readonly unsafe partial struct TimelineTree
if (count > 0)
{
var tree = ImRaii.TreeNode($"Timeline##{(nint)this.node:X}timeline", SpanFullWidth);
using var tree = ImRaii.TreeNode($"Timeline##{(nint)this.node:X}timeline", SpanFullWidth);
if (tree)
{
@ -81,8 +81,6 @@ public readonly unsafe partial struct TimelineTree
this.PrintAnimation(animation, a, isActive, (nint)(this.NodeTimeline->Resource->Animations + (a * sizeof(AtkTimelineAnimation))));
}
}
tree.Dispose();
}
}
@ -310,45 +308,46 @@ public readonly unsafe partial struct TimelineTree
{
var columns = this.BuildColumns(animation);
var col = ImRaii.PushColor(ImGuiCol.Text, isActive ? new Vector4(1, 0.65F, 0.4F, 1) : new(1));
var tree = ImRaii.TreeNode($"[#{a}] [Frames {animation.StartFrameIdx}-{animation.EndFrameIdx}] {(isActive ? " (Active)" : string.Empty)}###{(nint)this.node}animTree{a}");
col.Dispose();
if (tree)
using (ImRaii.PushColor(ImGuiCol.Text, new Vector4(1, 0.65F, 0.4F, 1), isActive))
{
PrintFieldValuePair("Animation", $"{address:X}");
using var tree = ImRaii.TreeNode($"[#{a}] [Frames {animation.StartFrameIdx}-{animation.EndFrameIdx}] {(isActive ? " (Active)" : string.Empty)}###{(nint)this.node}animTree{a}");
ShowStruct((AtkTimelineAnimation*)address);
if (columns.Count > 0)
if (tree)
{
var table = ImRaii.Table($"##{(nint)this.node}animTable{a}", columns.Count, Borders | SizingFixedFit | RowBg | NoHostExtendX);
PrintFieldValuePair("Animation", $"{address:X}");
foreach (var c in columns)
ShowStruct((AtkTimelineAnimation*)address);
if (columns.Count > 0)
{
ImGui.TableSetupColumn(c.Name, WidthFixed, c.Width);
}
ImGui.TableHeadersRow();
var rows = columns.Select(static c => c.Count).Max();
for (var i = 0; i < rows; i++)
{
ImGui.TableNextRow();
foreach (var c in columns)
using (ImRaii.Table(
$"##{(nint)this.node}animTable{a}",
columns.Count,
Borders | SizingFixedFit | RowBg | NoHostExtendX))
{
ImGui.TableNextColumn();
c.PrintValueAt(i);
foreach (var c in columns)
{
ImGui.TableSetupColumn(c.Name, WidthFixed, c.Width);
}
ImGui.TableHeadersRow();
var rows = columns.Select(static c => c.Count).Max();
for (var i = 0; i < rows; i++)
{
ImGui.TableNextRow();
foreach (var c in columns)
{
ImGui.TableNextColumn();
c.PrintValueAt(i);
}
}
}
}
table.Dispose();
}
}
tree.Dispose();
}
private List<IKeyGroupColumn> BuildColumns(AtkTimelineAnimation animation)

View file

@ -79,43 +79,53 @@ internal unsafe class ElementSelector : IDisposable
/// </summary>
internal void DrawInterface()
{
var ch = ImRaii.Child("###sidebar_elementSelector", new(250, 0), true);
var f = ImRaii.PushFont(IconFont);
var col = ImRaii.PushColor(Text, this.Active ? new Vector4(1, 1, 0.2f, 1) : new(1));
if (ImGui.Button($"{(char)ObjectUngroup}"))
using (ImRaii.Child("###sidebar_elementSelector", new(250, 0), true))
{
this.Active = !this.Active;
}
using var f = ImRaii.PushFont(IconFont);
using var col = ImRaii.PushColor(Text, new Vector4(1, 1, 0.2f, 1), this.Active);
if (Countdown > 0)
{
Countdown -= 1;
if (Countdown < 0)
if (ImGui.Button($"{(char)ObjectUngroup}"))
{
Countdown = 0;
this.Active = !this.Active;
}
if (Countdown > 0)
{
Countdown -= 1;
if (Countdown < 0)
{
Countdown = 0;
}
}
col.Pop();
f.Pop();
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Element Selector");
}
ImGui.SameLine();
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X - 32);
ImGui.InputTextWithHint(
"###addressSearchInput",
"Address Search",
ref this.addressSearchInput,
18,
ImGuiInputTextFlags.AutoSelectAll);
ImGui.SameLine();
if (ImGuiComponents.IconButton("###elemSelectorAddrSearch", Search) && nint.TryParse(
this.addressSearchInput,
NumberStyles.HexNumber | NumberStyles.AllowHexSpecifier,
InvariantInfo,
out var address))
{
this.PerformSearch(address);
}
}
col.Pop();
f.Pop();
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Element Selector");
}
ImGui.SameLine();
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X - 32);
ImGui.InputTextWithHint("###addressSearchInput", "Address Search", ref this.addressSearchInput, 18, ImGuiInputTextFlags.AutoSelectAll);
ImGui.SameLine();
if (ImGuiComponents.IconButton("###elemSelectorAddrSearch", Search) && nint.TryParse(this.addressSearchInput, NumberStyles.HexNumber | NumberStyles.AllowHexSpecifier, InvariantInfo, out var address))
{
this.PerformSearch(address);
}
ch.Dispose();
}
/// <summary>
@ -141,72 +151,71 @@ internal unsafe class ElementSelector : IDisposable
var mousePos = ImGui.GetMousePos() - MainViewport.Pos;
var addonResults = GetAtkUnitBaseAtPosition(mousePos);
var col = ImRaii.PushColor(WindowBg, new Vector4(0.5f));
var ch = ImRaii.Child("noClick", new(800, 2000), false, NoInputs | NoBackground | NoScrollWithMouse);
var g = ImRaii.Group();
Gui.PrintFieldValuePair("Mouse Position", $"{mousePos.X}, {mousePos.Y}");
ImGui.Spacing();
ImGui.Text("RESULTS:\n");
var i = 0;
foreach (var a in addonResults)
using var col = ImRaii.PushColor(WindowBg, new Vector4(0.5f));
using (ImRaii.Child("noClick", new(800, 2000), false, NoInputs | NoBackground | NoScrollWithMouse))
{
var name = a.Addon->NameString;
ImGui.Text($"[Addon] {name}");
ImGui.Indent(15);
foreach (var n in a.Nodes)
using (ImRaii.Group())
{
var nSelected = i++ == this.index;
Gui.PrintFieldValuePair("Mouse Position", $"{mousePos.X}, {mousePos.Y}");
ImGui.Spacing();
ImGui.Text("RESULTS:\n");
PrintNodeHeaderOnly(n.Node, nSelected, a.Addon);
if (nSelected && ImGui.IsMouseClicked(ImGuiMouseButton.Left))
var i = 0;
foreach (var a in addonResults)
{
this.Active = false;
this.uiDebug2.SelectedAddonName = a.Addon->NameString;
var ptrList = new List<nint> { (nint)n.Node };
var nextNode = n.Node->ParentNode;
while (nextNode != null)
var name = a.Addon->NameString;
ImGui.Text($"[Addon] {name}");
ImGui.Indent(15);
foreach (var n in a.Nodes)
{
ptrList.Add((nint)nextNode);
nextNode = nextNode->ParentNode;
var nSelected = i++ == this.index;
PrintNodeHeaderOnly(n.Node, nSelected, a.Addon);
if (nSelected && ImGui.IsMouseClicked(ImGuiMouseButton.Left))
{
this.Active = false;
this.uiDebug2.SelectedAddonName = a.Addon->NameString;
var ptrList = new List<nint> { (nint)n.Node };
var nextNode = n.Node->ParentNode;
while (nextNode != null)
{
ptrList.Add((nint)nextNode);
nextNode = nextNode->ParentNode;
}
SearchResults = [.. ptrList];
Countdown = 100;
Scrolled = false;
}
if (nSelected)
{
n.NodeBounds.DrawFilled(new(1, 1, 0.2f, 1));
}
}
SearchResults = [.. ptrList];
Countdown = 100;
Scrolled = false;
ImGui.Indent(-15);
}
if (nSelected)
if (i != 0)
{
n.NodeBounds.DrawFilled(new(1, 1, 0.2f, 1));
this.index -= (int)ImGui.GetIO().MouseWheel;
while (this.index < 0)
{
this.index += i;
}
while (this.index >= i)
{
this.index -= i;
}
}
}
ImGui.Indent(-15);
}
if (i != 0)
{
this.index -= (int)ImGui.GetIO().MouseWheel;
while (this.index < 0)
{
this.index += i;
}
while (this.index >= i)
{
this.index -= i;
}
}
g.Dispose();
ch.Dispose();
col.Pop();
}
private static List<AddonResult> GetAtkUnitBaseAtPosition(Vector2 position)
@ -384,9 +393,8 @@ internal unsafe class ElementSelector : IDisposable
return;
}
var col = ImRaii.PushColor(Text, selected ? new Vector4(1, 1, 0.2f, 1) : new(0.6f, 0.6f, 0.6f, 1));
using var col = ImRaii.PushColor(Text, selected ? new Vector4(1, 1, 0.2f, 1) : new(0.6f, 0.6f, 0.6f, 1));
ResNodeTree.GetOrCreate(node, tree).WriteTreeHeading();
col.Pop();
}
private void PerformSearch(nint address)

View file

@ -39,9 +39,10 @@ internal class AddonPopoutWindow : Window, IDisposable
/// <inheritdoc/>
public override void Draw()
{
var ch = ImRaii.Child($"{this.WindowName}child", new(-1, -1), true);
this.addonTree.Draw();
ch.Dispose();
using (ImRaii.Child($"{this.WindowName}child", new(-1, -1), true))
{
this.addonTree.Draw();
}
}
/// <inheritdoc/>

View file

@ -50,10 +50,11 @@ internal unsafe class NodePopoutWindow : Window, IDisposable
{
if (this.Node != null && this.AddonTree.ContainsNode(this.Node))
{
var ch = ImRaii.Child($"{(nint)this.Node:X}popoutChild", new(-1, -1), true);
ResNodeTree.GetOrCreate(this.Node, this.AddonTree).Print(null, this.firstDraw);
ch.Dispose();
this.firstDraw = false;
using (ImRaii.Child($"{(nint)this.Node:X}popoutChild", new(-1, -1), true))
{
ResNodeTree.GetOrCreate(this.Node, this.AddonTree).Print(null, this.firstDraw);
this.firstDraw = false;
}
}
else
{

View file

@ -16,7 +16,7 @@ namespace Dalamud.Interface.Internal.UiDebug2;
/// <inheritdoc cref="UiDebug2"/>
internal unsafe partial class UiDebug2
{
/// <summary>
/// <summary>
/// All unit lists to check for addons.
/// </summary>
internal static readonly List<UnitListOption> UnitListOptions =
@ -38,7 +38,7 @@ internal unsafe partial class UiDebug2
new(12, "Depth Layer 13"),
new(15, "Units 16"),
new(16, "Units 17"),
new(17, "Units 18"),
new(17, "Units 18")
];
private string addonNameSearch = string.Empty;
@ -53,54 +53,54 @@ internal unsafe partial class UiDebug2
private void DrawSidebar()
{
var g = ImRaii.Group();
this.DrawNameSearch();
this.DrawAddonSelectionList();
this.elementSelector.DrawInterface();
g.Dispose();
using (ImRaii.Group())
{
this.DrawNameSearch();
this.DrawAddonSelectionList();
this.elementSelector.DrawInterface();
}
}
private void DrawNameSearch()
{
var ch = ImRaii.Child("###sidebar_nameSearch", new(250, 40), true);
var atkUnitBaseSearch = this.addonNameSearch;
Vector4? defaultColor = this.visFilter ? new(0.0f, 0.8f, 0.2f, 1f) : new Vector4(0.6f, 0.6f, 0.6f, 1);
if (ImGuiComponents.IconButton("filter", LowVision, defaultColor))
using (ImRaii.Child("###sidebar_nameSearch", new(250, 40), true))
{
this.visFilter = !this.visFilter;
var atkUnitBaseSearch = this.addonNameSearch;
Vector4? defaultColor = this.visFilter ? new(0.0f, 0.8f, 0.2f, 1f) : new Vector4(0.6f, 0.6f, 0.6f, 1);
if (ImGuiComponents.IconButton("filter", LowVision, defaultColor))
{
this.visFilter = !this.visFilter;
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Filter by visibility");
}
ImGui.SameLine();
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X);
if (ImGui.InputTextWithHint("###atkUnitBaseSearch", "Filter by name", ref atkUnitBaseSearch, 0x20))
{
this.addonNameSearch = atkUnitBaseSearch;
}
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Filter by visibility");
}
ImGui.SameLine();
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X);
if (ImGui.InputTextWithHint("###atkUnitBaseSearch", "Filter by name", ref atkUnitBaseSearch, 0x20))
{
this.addonNameSearch = atkUnitBaseSearch;
}
ch.Dispose();
}
private void DrawAddonSelectionList()
{
var ch = ImRaii.Child("###sideBar_addonList", new(250, -44), true, ImGuiWindowFlags.AlwaysVerticalScrollbar);
var unitListBaseAddr = GetUnitListBaseAddr();
foreach (var unit in UnitListOptions)
using (ImRaii.Child("###sideBar_addonList", new(250, -44), true, ImGuiWindowFlags.AlwaysVerticalScrollbar))
{
this.DrawUnitListOption(unitListBaseAddr, unit);
}
var unitListBaseAddr = GetUnitListBaseAddr();
ch.Dispose();
foreach (var unit in UnitListOptions)
{
this.DrawUnitListOption(unitListBaseAddr, unit);
}
;
}
}
private void DrawUnitListOption(AtkUnitList* unitListBaseAddr, UnitListOption unit)
@ -148,25 +148,23 @@ internal unsafe partial class UiDebug2
var countStr = $"{(usingFilter ? $"{matchCount}/" : string.Empty)}{totalCount}";
var col1 = ImRaii.PushColor(ImGuiCol.Text, anyVisible ? new Vector4(1) : new Vector4(0.6f, 0.6f, 0.6f, 1));
var tree = ImRaii.TreeNode($"{unit.Name} [{countStr}]###unitListTree{unit.Index}");
using var col1 = 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();
if (tree)
{
foreach (var option in options)
{
var col2 = ImRaii.PushColor(ImGuiCol.Text, option.Visible ? new Vector4(0.1f, 1f, 0.1f, 1f) : new Vector4(0.6f, 0.6f, 0.6f, 1));
if (ImGui.Selectable($"{option.Name}##select{option.Name}", this.SelectedAddonName == option.Name))
using (ImRaii.PushColor(ImGuiCol.Text, option.Visible ? new Vector4(0.1f, 1f, 0.1f, 1f) : new Vector4(0.6f, 0.6f, 0.6f, 1)))
{
this.SelectedAddonName = option.Name;
if (ImGui.Selectable($"{option.Name}##select{option.Name}", this.SelectedAddonName == option.Name))
{
this.SelectedAddonName = option.Name;
}
}
col2.Pop();
}
}
tree.Dispose();
}
/// <summary>

View file

@ -31,17 +31,13 @@ internal partial class UiDebug2 : IDisposable
internal UiDebug2()
{
this.elementSelector = new(this);
GameGui = Service<GameGui>.Get();
Log = new ModuleLog("UiDebug2");
}
/// <inheritdoc cref="ModuleLog"/>
internal static ModuleLog Log { get; set; } = null!;
internal static ModuleLog Log { get; set; } = new("UiDebug2");
/// <inheritdoc cref="IGameGui"/>
internal static IGameGui GameGui { get; set; } = null!;
internal static IGameGui GameGui { get; set; } = Service<GameGui>.Get();
/// <summary>
/// Gets a collection of <see cref="AddonTree"/> instances, each representing an <see cref="FFXIVClientStructs.FFXIV.Component.GUI.AtkUnitBase"/>.
@ -86,28 +82,28 @@ internal partial class UiDebug2 : IDisposable
private void DrawMainPanel()
{
ImGui.SameLine();
var ch = ImRaii.Child("###uiDebugMainPanel", new(-1, -1), true, HorizontalScrollbar);
if (this.elementSelector.Active)
using (ImRaii.Child("###uiDebugMainPanel", new(-1, -1), true, HorizontalScrollbar))
{
this.elementSelector.DrawSelectorOutput();
}
else
{
if (this.SelectedAddonName != null)
if (this.elementSelector.Active)
{
var addonTree = AddonTree.GetOrCreate(this.SelectedAddonName);
if (addonTree == null)
this.elementSelector.DrawSelectorOutput();
}
else
{
if (this.SelectedAddonName != null)
{
this.SelectedAddonName = null;
return;
}
var addonTree = AddonTree.GetOrCreate(this.SelectedAddonName);
addonTree.Draw();
if (addonTree == null)
{
this.SelectedAddonName = null;
return;
}
addonTree.Draw();
}
}
}
ch.Dispose();
}
}

View file

@ -24,8 +24,8 @@ internal static class Gui
/// <typeparam name="T">The type of value being set.</typeparam>
/// <param name="label">The label for the inputs.</param>
/// <param name="val">The value being set.</param>
/// <param name="options">A list of all options to create buttons for.</param>
/// <param name="icons">A list of the icons to use for each option.</param>
/// <param name="options">A list of all options.</param>
/// <param name="icons">A list of icons corresponding to the options.</param>
/// <returns>true if a button is clicked.</returns>
internal static unsafe bool IconSelectInput<T>(string label, ref T val, List<T> options, List<FontAwesomeIcon> icons)
{
@ -104,14 +104,11 @@ internal static class Gui
/// <remarks>Colors the text itself either white or black, depending on the luminosity of the background color.</remarks>
internal static void PrintColor(Vector4 color, string fmt)
{
var c = 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 (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))
{
ImGui.SmallButton(fmt);
}
ImGui.SmallButton(fmt);
c.Pop(4);
return;
static double Luminosity(Vector4 vector4) =>
@ -125,20 +122,21 @@ internal static class Gui
/// <inheritdoc cref="ImGuiHelpers.ClickToCopyText"/>
internal static void ClickToCopyText(string text, string? textCopy = null)
{
var c = ImRaii.PushColor(Text, new Vector4(0.6f, 0.6f, 0.6f, 1));
ImGuiHelpers.ClickToCopyText(text, textCopy);
c.Pop();
using (ImRaii.PushColor(Text, new Vector4(0.6f, 0.6f, 0.6f, 1)))
{
ImGuiHelpers.ClickToCopyText(text, textCopy);
}
if (ImGui.IsItemHovered())
{
var t = ImRaii.Tooltip();
var f = ImRaii.PushFont(UiBuilder.IconFont);
ImGui.Text(FontAwesomeIcon.Copy.ToIconString());
f.Pop();
ImGui.SameLine();
ImGui.Text($"{textCopy ?? text}");
t.Dispose();
using (ImRaii.Tooltip())
{
using var f = ImRaii.PushFont(UiBuilder.IconFont);
ImGui.Text(FontAwesomeIcon.Copy.ToIconString());
f.Pop();
ImGui.SameLine();
ImGui.Text($"{textCopy ?? text}");
}
}
}
@ -161,9 +159,10 @@ internal static class Gui
var index = (int)Math.Floor(prog * tooltips.Length);
var t = ImRaii.Tooltip();
ImGui.Text(tooltips[index]);
t.Dispose();
using (ImRaii.Tooltip())
{
ImGui.Text(tooltips[index]);
}
return true;
}

View file

@ -7,6 +7,7 @@ using FFXIVClientStructs.FFXIV.Component.GUI;
using ImGuiNET;
using static System.Math;
using static Dalamud.Interface.ColorHelpers;
namespace Dalamud.Interface.Internal.UiDebug2.Utility;
@ -61,8 +62,8 @@ public unsafe struct NodeBounds
if (this.Points.Count == 1)
{
ImGui.GetBackgroundDrawList().AddCircle(this.Points[0], 10, ColorHelpers.RgbaVector4ToUint(col with { W = col.W / 2 }), 12, thickness);
ImGui.GetBackgroundDrawList().AddCircle(this.Points[0], thickness, ColorHelpers.RgbaVector4ToUint(col), 12, thickness + 1);
ImGui.GetBackgroundDrawList().AddCircle(this.Points[0], 10, RgbaVector4ToUint(col with { W = col.W / 2 }), 12, thickness);
ImGui.GetBackgroundDrawList().AddCircle(this.Points[0], thickness, RgbaVector4ToUint(col), 12, thickness + 1);
}
else
{
@ -73,7 +74,7 @@ public unsafe struct NodeBounds
}
ImGui.GetBackgroundDrawList()
.AddPolyline(ref path[0], path.Length, ColorHelpers.RgbaVector4ToUint(col), ImDrawFlags.Closed, thickness);
.AddPolyline(ref path[0], path.Length, RgbaVector4ToUint(col), ImDrawFlags.Closed, thickness);
path.Dispose();
}
@ -94,8 +95,8 @@ public unsafe struct NodeBounds
if (this.Points.Count == 1)
{
ImGui.GetBackgroundDrawList()
.AddCircleFilled(this.Points[0], 10, ColorHelpers.RgbaVector4ToUint(col with { W = col.W / 2 }), 12);
ImGui.GetBackgroundDrawList().AddCircle(this.Points[0], 10, ColorHelpers.RgbaVector4ToUint(col), 12, thickness);
.AddCircleFilled(this.Points[0], 10, RgbaVector4ToUint(col with { W = col.W / 2 }), 12);
ImGui.GetBackgroundDrawList().AddCircle(this.Points[0], 10, RgbaVector4ToUint(col), 12, thickness);
}
else
{
@ -106,9 +107,9 @@ public unsafe struct NodeBounds
}
ImGui.GetBackgroundDrawList()
.AddConvexPolyFilled(ref path[0], path.Length, ColorHelpers.RgbaVector4ToUint(col with { W = col.W / 2 }));
.AddConvexPolyFilled(ref path[0], path.Length, RgbaVector4ToUint(col with { W = col.W / 2 }));
ImGui.GetBackgroundDrawList()
.AddPolyline(ref path[0], path.Length, ColorHelpers.RgbaVector4ToUint(col), ImDrawFlags.Closed, thickness);
.AddPolyline(ref path[0], path.Length, RgbaVector4ToUint(col), ImDrawFlags.Closed, thickness);
path.Dispose();
}
@ -147,7 +148,9 @@ public unsafe struct NodeBounds
var sinR = (float)Sin(r);
var d = (p - o) * s;
return new(o.X + (d.X * cosR) - (d.Y * sinR), o.Y + (d.X * sinR) + (d.Y * cosR));
return new(
o.X + (d.X * cosR) - (d.Y * sinR),
o.Y + (d.X * sinR) + (d.Y * cosR));
}
private void TransformPoints(AtkResNode* transformNode)

View file

@ -21,6 +21,7 @@ internal class DataWindow : Window, IDisposable
private readonly IDataWindowWidget[] modules =
{
new AddonInspectorWidget(),
new AddonInspectorWidget2(),
new AddonLifecycleWidget(),
new AddonWidget(),
new AddressesWidget(),

View file

@ -5,7 +5,7 @@ namespace Dalamud.Interface.Internal.Windows.Data.Widgets;
/// </summary>
internal class AddonInspectorWidget : IDataWindowWidget
{
private UiDebug2.UiDebug2? addonInspector;
private UiDebug? addonInspector;
/// <inheritdoc/>
public string[]? CommandShortcuts { get; init; } = { "ai", "addoninspector" };
@ -19,7 +19,7 @@ internal class AddonInspectorWidget : IDataWindowWidget
/// <inheritdoc/>
public void Load()
{
this.addonInspector = new UiDebug2.UiDebug2();
this.addonInspector = new UiDebug();
if (this.addonInspector is not null)
{

View file

@ -0,0 +1,35 @@
namespace Dalamud.Interface.Internal.Windows.Data.Widgets;
/// <summary>
/// Widget for displaying addon inspector.
/// </summary>
internal class AddonInspectorWidget2 : IDataWindowWidget
{
private UiDebug2.UiDebug2? addonInspector2;
/// <inheritdoc/>
public string[]? CommandShortcuts { get; init; } = ["ai2", "addoninspector2"];
/// <inheritdoc/>
public string DisplayName { get; init; } = "Addon Inspector v2 (Testing)";
/// <inheritdoc/>
public bool Ready { get; set; }
/// <inheritdoc/>
public void Load()
{
this.addonInspector2 = new UiDebug2.UiDebug2();
if (this.addonInspector2 is not null)
{
this.Ready = true;
}
}
/// <inheritdoc/>
public void Draw()
{
this.addonInspector2?.Draw();
}
}