Files
2026-07-13 13:13:17 +08:00

231 lines
8.9 KiB
C#

using System.Reflection;
using ImGuiNET;
using T3.Core.DataTypes;
using T3.Editor.Gui.Styling;
namespace T3.Editor.Gui.TableView;
public static class TableList
{
public static bool Draw(StructuredList list)
{
return Draw(list, Vector2.Zero);
}
public static Dictionary<Type, string[]> TypeComponents = new()
{
{ typeof(Vector2), new[] { ".x", ".y" } },
{ typeof(Vector3), new[] { ".x", ".y", ".z" } },
{ typeof(Vector4), new[] { ".R", ".G", ".B", ".A" } },
{ typeof(Quaternion), new[] { ".x", ".y", ".z", ".w" } },
};
public static bool Draw(StructuredList list, Vector2 size)
{
ImGui.BeginChild("child", size);
ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, new Vector2(2, 2));
var valueColumnWidth = 50 * T3Ui.UiScaleFactor;
var lineNumberWidth = 40 * T3Ui.UiScaleFactor;
var headerHeight = 30 * T3Ui.UiScaleFactor;
var listModified = false;
ImGui.PushFont(Fonts.FontSmall);
{
FieldInfo[] members = list.Type.GetFields();
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted($"[{list.NumElements}]");
ImGui.SameLine(lineNumberWidth);
// List Header
for (var fieldIndex = 0; fieldIndex < members.Length; fieldIndex++)
{
var fi = members[fieldIndex];
if (TypeComponents.TryGetValue(fi.FieldType, out var components))
{
bool isFirst = true;
foreach (var c in components)
{
ImGui.PushID(fi.Name + c);
ImGui.Selectable((isFirst ? " " + fi.Name : "_") + "\n" + c,
false,
ImGuiSelectableFlags.None,
new Vector2(valueColumnWidth, headerHeight));
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip(fieldIndex + ": " +fi.Name + c );
}
ImGui.PopID();
ImGui.SameLine();
isFirst = false;
}
}
else
{
ImGui.Selectable(" " + fi.Name,
false, ImGuiSelectableFlags.None,
new Vector2(valueColumnWidth,
headerHeight));
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip(fieldIndex + ": " +fi.Name);
}
}
ImGui.SameLine();
}
ImGui.NewLine();
// Values
for (var objectIndex = 0; objectIndex < Math.Min(list.NumElements, 9999); objectIndex++)
{
var cursorScreenPos = ImGui.GetCursorScreenPos();
var isLineVisible = ImGui.IsRectVisible(cursorScreenPos,
cursorScreenPos + new Vector2(1000, ImGui.GetFrameHeight()));
if (!isLineVisible)
{
ImGui.Dummy(new Vector2(1, ImGui.GetFrameHeight()));
continue;
}
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(objectIndex + ".");
ImGui.SameLine(lineNumberWidth);
ImGui.PushID(objectIndex);
var obj = list[objectIndex];
var objModified = false;
for (var fieldIndex = 0; fieldIndex < members.Length; fieldIndex++)
{
FieldInfo fi = members[fieldIndex];
var o = fi.GetValue(obj);
if (o is float f)
{
if (DrawFloatManipulation(ref f, objectIndex* 1000+ fieldIndex))
{
fi.SetValue(obj, f);
objModified = true;
}
}
else if (fi.FieldType == typeof(string))
{
if (!(o is string s))
s = string.Empty;
ImGui.PushID(fi.Name);
ImGui.SetNextItemWidth(valueColumnWidth);
if (ImGui.InputText("##sdf", ref s, 256))
{
fi.SetValue(obj, s);
objModified = true;
}
ImGui.SameLine();
ImGui.PopID();
}
else if (o is Vector2 vector2)
{
if (DrawFloatManipulation(ref vector2.X, fieldIndex, 0)
| DrawFloatManipulation(ref vector2.Y, fieldIndex, 1))
{
fi.SetValue(obj, vector2);
objModified = true;
}
}
else if (o is Vector3 vector3)
{
if (DrawFloatManipulation(ref vector3.X, fieldIndex, 0)
| DrawFloatManipulation(ref vector3.Y, fieldIndex, 1)
| DrawFloatManipulation(ref vector3.Z, fieldIndex, 2))
{
fi.SetValue(obj, vector3);
objModified = true;
}
}
else if (o is Vector4 vector4)
{
if (DrawFloatManipulation(ref vector4.X, fieldIndex, 0)
| DrawFloatManipulation(ref vector4.Y, fieldIndex, 1)
| DrawFloatManipulation(ref vector4.Z, fieldIndex, 2)
| DrawFloatManipulation(ref vector4.W, fieldIndex, 3))
{
fi.SetValue(obj, vector4);
objModified = true;
}
}
else if (o is Quaternion q)
{
if (DrawFloatManipulation(ref q.X, fieldIndex, 0)
| DrawFloatManipulation(ref q.Y, fieldIndex, 1)
| DrawFloatManipulation(ref q.Z, fieldIndex, 2)
| DrawFloatManipulation(ref q.W, fieldIndex, 3))
{
fi.SetValue(obj, q);
objModified = true;
}
}
else
{
ImGui.SetNextItemWidth(valueColumnWidth);
ImGui.TextUnformatted("?");
ImGui.SameLine();
}
}
if (objModified)
{
list[objectIndex] = obj;
listModified = true;
}
if (ImGui.Button("+"))
{
list.Insert(objectIndex, obj);
}
ImGui.SameLine();
if (ImGui.Button("-"))
{
list.Remove(objectIndex);
}
ImGui.PopID();
}
}
ImGui.PopFont();
ImGui.PopStyleVar(); // FramePadding
ImGui.EndChild();
return listModified;
bool DrawFloatManipulation(ref float f, int fieldIndex, int componentIndex = 0)
{
ImGui.PushID(fieldIndex * 1000 + componentIndex);
ImGui.SetNextItemWidth(valueColumnWidth);
var grayedOut = (Math.Abs(f) < 0.0001f);
if (grayedOut)
{
ImGui.PushStyleColor(ImGuiCol.Text, UiColors.BackgroundFull.Rgba);
}
var fieldModified = ImGui.DragFloat("##sdf", ref f, 0.01f);
if (grayedOut)
{
ImGui.PopStyleColor();
}
ImGui.SameLine();
ImGui.PopID();
return fieldModified;
}
}
}