Dalamud/Dalamud/Interface/Internal/UiDebug2/Browsing/NodeTree.Editor.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

386 lines
12 KiB
C#

using System.Collections.Generic;
using System.Numerics;
using Dalamud.Interface.Components;
using Dalamud.Interface.Internal.UiDebug2.Utility;
using Dalamud.Interface.Utility.Raii;
using FFXIVClientStructs.FFXIV.Component.GUI;
using ImGuiNET;
using static Dalamud.Interface.ColorHelpers;
using static Dalamud.Interface.FontAwesomeIcon;
using static Dalamud.Interface.Internal.UiDebug2.Utility.Gui;
using static Dalamud.Interface.Utility.ImGuiHelpers;
using static ImGuiNET.ImGuiColorEditFlags;
using static ImGuiNET.ImGuiInputTextFlags;
using static ImGuiNET.ImGuiTableColumnFlags;
using static ImGuiNET.ImGuiTableFlags;
namespace Dalamud.Interface.Internal.UiDebug2.Browsing;
/// <inheritdoc cref="ResNodeTree"/>
internal unsafe partial class ResNodeTree
{
/// <summary>
/// Sets up the table for the node editor, if the "Edit" checkbox is ticked.
/// </summary>
private protected void DrawNodeEditorTable()
{
using var tbl = ImRaii.Table($"###Editor{(nint)this.Node}", 2, SizingStretchProp | NoHostExtendX);
if (tbl.Success)
{
this.DrawEditorRows();
}
}
/// <summary>
/// Draws each row in the node editor table.
/// </summary>
private protected virtual void DrawEditorRows()
{
var pos = new Vector2(this.Node->X, this.Node->Y);
var size = new Vector2(this.Node->Width, this.Node->Height);
var scale = new Vector2(this.Node->ScaleX, this.Node->ScaleY);
var origin = new Vector2(this.Node->OriginX, this.Node->OriginY);
var angle = (float)((this.Node->Rotation * (180 / Math.PI)) + 360);
var rgba = RgbaUintToVector4(this.Node->Color.RGBA);
var mult = new Vector3(this.Node->MultiplyRed, this.Node->MultiplyGreen, this.Node->MultiplyBlue) / 255f;
var add = new Vector3(this.Node->AddRed, this.Node->AddGreen, this.Node->AddBlue);
var hov = false;
ImGui.TableSetupColumn("Labels", WidthFixed);
ImGui.TableSetupColumn("Editors", WidthFixed);
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.Text("Position:");
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(150);
if (ImGui.DragFloat2($"##{(nint)this.Node:X}position", ref pos, 1, default, default, "%.0f"))
{
this.Node->X = pos.X;
this.Node->Y = pos.Y;
this.Node->DrawFlags |= 0xD;
}
hov |= SplitTooltip("X", "Y") || ImGui.IsItemActive();
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.Text("Size:");
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(150);
if (ImGui.DragFloat2($"##{(nint)this.Node:X}size", ref size, 1, 0, default, "%.0f"))
{
this.Node->Width = (ushort)Math.Max(size.X, 0);
this.Node->Height = (ushort)Math.Max(size.Y, 0);
this.Node->DrawFlags |= 0xD;
}
hov |= SplitTooltip("Width", "Height") || ImGui.IsItemActive();
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.Text("Scale:");
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(150);
if (ImGui.DragFloat2($"##{(nint)this.Node:X}scale", ref scale, 0.05f))
{
this.Node->ScaleX = scale.X;
this.Node->ScaleY = scale.Y;
this.Node->DrawFlags |= 0xD;
}
hov |= SplitTooltip("ScaleX", "ScaleY") || ImGui.IsItemActive();
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.Text("Origin:");
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(150);
if (ImGui.DragFloat2($"##{(nint)this.Node:X}origin", ref origin, 1, default, default, "%.0f"))
{
this.Node->OriginX = origin.X;
this.Node->OriginY = origin.Y;
this.Node->DrawFlags |= 0xD;
}
hov |= SplitTooltip("OriginX", "OriginY") || ImGui.IsItemActive();
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.Text("Rotation:");
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(150);
while (angle > 180)
{
angle -= 360;
}
if (ImGui.DragFloat($"##{(nint)this.Node:X}rotation", ref angle, 0.05f, default, default, "%.2f°"))
{
this.Node->Rotation = (float)(angle / (180 / Math.PI));
this.Node->DrawFlags |= 0xD;
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Rotation (deg)");
hov = true;
}
hov |= ImGui.IsItemActive();
if (hov)
{
Vector4 brightYellow = new(1, 1, 0.5f, 0.8f);
new NodeBounds(this.Node).Draw(brightYellow);
new NodeBounds(origin, this.Node).Draw(brightYellow);
}
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.Text("RGBA:");
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(150);
if (ImGui.ColorEdit4($"##{(nint)this.Node:X}RGBA", ref rgba, DisplayHex))
{
this.Node->Color = new() { RGBA = RgbaVector4ToUint(rgba) };
}
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.Text("Multiply:");
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(150);
if (ImGui.ColorEdit3($"##{(nint)this.Node:X}multiplyRGB", ref mult, DisplayHex))
{
this.Node->MultiplyRed = (byte)(mult.X * 255);
this.Node->MultiplyGreen = (byte)(mult.Y * 255);
this.Node->MultiplyBlue = (byte)(mult.Z * 255);
}
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.Text("Add:");
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(124);
if (ImGui.DragFloat3($"##{(nint)this.Node:X}addRGB", ref add, 1, -255, 255, "%.0f"))
{
this.Node->AddRed = (short)add.X;
this.Node->AddGreen = (short)add.Y;
this.Node->AddBlue = (short)add.Z;
}
SplitTooltip("+/- Red", "+/- Green", "+/- Blue");
var addTransformed = (add / 510f) + new Vector3(0.5f);
ImGui.SameLine();
ImGui.SetCursorPosX(ImGui.GetCursorPosX() - (4 * GlobalScale));
if (ImGui.ColorEdit3($"##{(nint)this.Node:X}addRGBPicker", ref addTransformed, NoAlpha | NoInputs))
{
this.Node->AddRed = (short)Math.Floor((addTransformed.X * 510f) - 255f);
this.Node->AddGreen = (short)Math.Floor((addTransformed.Y * 510f) - 255f);
this.Node->AddBlue = (short)Math.Floor((addTransformed.Z * 510f) - 255f);
}
}
}
/// <inheritdoc cref="CounterNodeTree"/>
internal unsafe partial class CounterNodeTree
{
/// <inheritdoc/>
private protected override void DrawEditorRows()
{
base.DrawEditorRows();
var str = this.CntNode->NodeText.ToString();
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.Text("Counter:");
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(150);
if (ImGui.InputText($"##{(nint)this.Node:X}counterEdit", ref str, 512, EnterReturnsTrue))
{
this.CntNode->SetText(str);
}
}
}
/// <inheritdoc cref="ImageNodeTree"/>
internal unsafe partial class ImageNodeTree
{
private static int TexDisplayStyle { get; set; }
/// <inheritdoc/>
private protected override void DrawEditorRows()
{
base.DrawEditorRows();
var partId = (int)this.PartId;
var partcount = this.ImgNode->PartsList->PartCount;
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.Text("Part Id:");
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(150);
if (ImGui.InputInt($"##partId{(nint)this.Node:X}", ref partId, 1, 1))
{
if (partId < 0)
{
partId = 0;
}
if (partId >= partcount)
{
partId = (int)(partcount - 1);
}
this.ImgNode->PartId = (ushort)partId;
}
}
}
/// <inheritdoc cref="NineGridNodeTree"/>
internal unsafe partial class NineGridNodeTree
{
/// <inheritdoc/>
private protected override void DrawEditorRows()
{
base.DrawEditorRows();
var lr = new Vector2(this.Offsets.Left, this.Offsets.Right);
var tb = new Vector2(this.Offsets.Top, this.Offsets.Bottom);
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.Text("Ninegrid Offsets:");
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(150);
if (ImGui.DragFloat2($"##{(nint)this.Node:X}ngOffsetLR", ref lr, 1, 0))
{
this.NgNode->LeftOffset = (short)Math.Max(0, lr.X);
this.NgNode->RightOffset = (short)Math.Max(0, lr.Y);
}
SplitTooltip("Left", "Right");
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(150);
if (ImGui.DragFloat2($"##{(nint)this.Node:X}ngOffsetTB", ref tb, 1, 0))
{
this.NgNode->TopOffset = (short)Math.Max(0, tb.X);
this.NgNode->BottomOffset = (short)Math.Max(0, tb.Y);
}
SplitTooltip("Top", "Bottom");
}
}
/// <inheritdoc cref="TextNodeTree"/>
internal unsafe partial class TextNodeTree
{
private static readonly List<FontType> FontList = [.. Enum.GetValues<FontType>()];
private static readonly string[] FontNames = Enum.GetNames<FontType>();
/// <inheritdoc/>
private protected override void DrawEditorRows()
{
base.DrawEditorRows();
var text = this.TxtNode->NodeText.ToString();
var fontIndex = FontList.IndexOf(this.TxtNode->FontType);
int fontSize = this.TxtNode->FontSize;
var alignment = this.TxtNode->AlignmentType;
var textColor = RgbaUintToVector4(this.TxtNode->TextColor.RGBA);
var edgeColor = RgbaUintToVector4(this.TxtNode->EdgeColor.RGBA);
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.Text("Text:");
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(Math.Max(ImGui.GetWindowContentRegionMax().X - ImGui.GetCursorPosX() - 50f, 150));
if (ImGui.InputText($"##{(nint)this.Node:X}textEdit", ref text, 512, EnterReturnsTrue))
{
this.TxtNode->SetText(text);
}
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.Text("Font:");
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(150);
if (ImGui.Combo($"##{(nint)this.Node:X}fontType", ref fontIndex, FontNames, FontList.Count))
{
this.TxtNode->FontType = FontList[fontIndex];
}
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.Text("Font Size:");
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(150);
if (ImGui.InputInt($"##{(nint)this.Node:X}fontSize", ref fontSize, 1, 10))
{
this.TxtNode->FontSize = (byte)fontSize;
}
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.Text("Alignment:");
ImGui.TableNextColumn();
if (InputAlignment($"##{(nint)this.Node:X}alignment", ref alignment))
{
this.TxtNode->AlignmentType = alignment;
}
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.Text("Text Color:");
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(150);
if (ImGui.ColorEdit4($"##{(nint)this.Node:X}TextRGB", ref textColor, DisplayHex))
{
this.TxtNode->TextColor = new() { RGBA = RgbaVector4ToUint(textColor) };
}
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.Text("Edge Color:");
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(150);
if (ImGui.ColorEdit4($"##{(nint)this.Node:X}EdgeRGB", ref edgeColor, DisplayHex))
{
this.TxtNode->EdgeColor = new() { RGBA = RgbaVector4ToUint(edgeColor) };
}
}
private static bool InputAlignment(string label, ref AlignmentType alignment)
{
var hAlign = (int)alignment % 3;
var vAlign = ((int)alignment - hAlign) / 3;
var hAlignInput = ImGuiComponents.IconButtonSelect($"{label}H", ref hAlign, [AlignLeft, AlignCenter, AlignRight], [0, 1, 2], 3u, new(25, 0));
var vAlignInput = ImGuiComponents.IconButtonSelect($"{label}V", ref vAlign, [ArrowsUpToLine, GripLines, ArrowsDownToLine], [0, 1, 2], 3u, new(25, 0));
if (hAlignInput || vAlignInput)
{
alignment = (AlignmentType)((vAlign * 3) + hAlign);
return true;
}
return false;
}
}