Dalamud/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.NineGrid.cs
ItsBexy c950b15a22
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
2024-11-24 21:37:39 +01:00

148 lines
5.3 KiB
C#

using Dalamud.Interface.Internal.UiDebug2.Utility;
using FFXIVClientStructs.FFXIV.Component.GUI;
using ImGuiNET;
using static Dalamud.Interface.ColorHelpers;
using static Dalamud.Utility.Util;
using Vector2 = System.Numerics.Vector2;
using Vector4 = System.Numerics.Vector4;
namespace Dalamud.Interface.Internal.UiDebug2.Browsing;
/// <summary>
/// A tree for an <see cref="AtkNineGridNode"/> that can be printed and browsed via ImGui.
/// </summary>
internal unsafe partial class NineGridNodeTree : ImageNodeTree
{
/// <summary>
/// Initializes a new instance of the <see cref="NineGridNodeTree"/> class.
/// </summary>
/// <param name="node">The node to create a tree for.</param>
/// <param name="addonTree">The tree representing the containing addon.</param>
internal NineGridNodeTree(AtkResNode* node, AddonTree addonTree)
: base(node, addonTree)
{
}
/// <inheritdoc/>
private protected override uint PartId => this.NgNode->PartId;
/// <inheritdoc/>
private protected override AtkUldPartsList* PartsList => this.NgNode->PartsList;
private AtkNineGridNode* NgNode => (AtkNineGridNode*)this.Node;
private NineGridOffsets Offsets => new(this.NgNode);
/// <inheritdoc/>
private protected override void DrawPartOutline(uint partId, Vector2 cursorScreenPos, Vector2 cursorLocalPos, Vector4 col, bool reqHover = false)
{
var part = this.TexData.PartsList->Parts[partId];
var hrFactor = this.TexData.HiRes ? 2f : 1f;
var uv = new Vector2(part.U, part.V) * hrFactor;
var wh = new Vector2(part.Width, part.Height) * hrFactor;
var partBegin = cursorScreenPos + uv;
var partEnd = cursorScreenPos + uv + wh;
var savePos = ImGui.GetCursorPos();
if (!reqHover || ImGui.IsMouseHoveringRect(partBegin, partEnd))
{
var adjustedOffsets = this.Offsets * hrFactor;
var ngBegin1 = partBegin with { X = partBegin.X + adjustedOffsets.Left };
var ngEnd1 = partEnd with { X = partEnd.X - adjustedOffsets.Right };
var ngBegin2 = partBegin with { Y = partBegin.Y + adjustedOffsets.Top };
var ngEnd2 = partEnd with { Y = partEnd.Y - adjustedOffsets.Bottom };
var ngCol = RgbaVector4ToUint(col with { W = 0.75f * col.W });
ImGui.GetWindowDrawList()
.AddRect(partBegin, partEnd, RgbaVector4ToUint(col));
ImGui.GetWindowDrawList().AddRect(ngBegin1, ngEnd1, ngCol);
ImGui.GetWindowDrawList().AddRect(ngBegin2, ngEnd2, ngCol);
ImGui.SetCursorPos(cursorLocalPos + uv + new Vector2(0, -20));
ImGui.TextColored(col, $"[#{partId}]\t{part.U}, {part.V}\t{part.Width}x{part.Height}");
}
ImGui.SetCursorPos(savePos);
}
/// <inheritdoc/>
private protected override void PrintNodeObject() => ShowStruct(this.NgNode);
/// <inheritdoc/>
private protected override void PrintFieldsForNodeType(bool isEditorOpen = false)
{
if (!isEditorOpen)
{
ImGui.Text("NineGrid Offsets:\t");
ImGui.SameLine();
this.Offsets.Print();
}
this.DrawTextureAndParts();
}
/// <summary>
/// A struct representing the four offsets of an <see cref="AtkNineGridNode"/>.
/// </summary>
internal struct NineGridOffsets
{
/// <summary>Top offset.</summary>
internal int Top;
/// <summary>Left offset.</summary>
internal int Left;
/// <summary>Right offset.</summary>
internal int Right;
/// <summary>Bottom offset.</summary>
internal int Bottom;
/// <summary>
/// Initializes a new instance of the <see cref="NineGridOffsets"/> struct.
/// </summary>
/// <param name="top">The top offset.</param>
/// <param name="right">The right offset.</param>
/// <param name="bottom">The bottom offset.</param>
/// <param name="left">The left offset.</param>
internal NineGridOffsets(int top, int right, int bottom, int left)
{
this.Top = top;
this.Right = right;
this.Left = left;
this.Bottom = bottom;
}
/// <summary>
/// Initializes a new instance of the <see cref="NineGridOffsets"/> struct.
/// </summary>
/// <param name="ngNode">The node using these offsets.</param>
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;
/// <summary>Prints the offsets in ImGui.</summary>
internal readonly void Print() => Gui.PrintFieldValuePairs(("Top", $"{this.Top}"), ("Bottom", $"{this.Bottom}"), ("Left", $"{this.Left}"), ("Right", $"{this.Right}"));
}
}