399 lines
16 KiB
C#
399 lines
16 KiB
C#
#nullable enable
|
|
using System.Text;
|
|
using ImGuiNET;
|
|
using T3.Core.DataTypes;
|
|
using T3.Editor.Gui.Input;
|
|
using T3.Editor.Gui.MagGraph.States;
|
|
using T3.Editor.Gui.Styling;
|
|
using T3.Editor.Gui.UiHelpers;
|
|
using T3.Editor.UiModel;
|
|
using T3.Editor.UiModel.Helpers;
|
|
using T3.Editor.UiModel.InputsAndTypes;
|
|
using T3.Editor.UiModel.ProjectHandling;
|
|
|
|
namespace T3.Editor.Gui.MagGraph.Interaction;
|
|
|
|
/// <summary>
|
|
/// Draws a curated overview of essential symbols structured by categories and namespaces
|
|
/// </summary>
|
|
internal static class SymbolBrowsing
|
|
{
|
|
internal static PlaceHolderUi.UiResults Draw(GraphUiContext context)
|
|
{
|
|
if (ProjectView.Focused == null)
|
|
return PlaceHolderUi.UiResults.None;
|
|
|
|
var uiResult = PlaceHolderUi.UiResults.None;
|
|
|
|
_libTree = UpdateLibPage(); // only required for hot code reloading
|
|
|
|
if (_path.Count == 0)
|
|
return PlaceHolderUi.UiResults.Cancel;
|
|
|
|
|
|
// Find active page
|
|
_activePage = _path[0];
|
|
|
|
for (var index = _path.Count - 1; index >= 0; index--)
|
|
{
|
|
var group = _path[index];
|
|
if (group.Variant == Variants.Page)
|
|
_activePage = group;
|
|
}
|
|
|
|
var lastCurrentGroup = _path[^1];
|
|
|
|
// Draw tip
|
|
if (lastCurrentGroup.Variant == Variants.Project)
|
|
{
|
|
Icon.Tip.DrawAtCursor(UiColors.TextMuted);
|
|
ImGui.SameLine(0, 5);
|
|
CustomComponents.HelpText("Explore essential ops below...");
|
|
}
|
|
|
|
ColumnLayout.StartLayout();
|
|
ImGui.Indent(5);
|
|
|
|
if (lastCurrentGroup.Variant == Variants.Page || lastCurrentGroup.Variant == Variants.Project)
|
|
{
|
|
_libTree = UpdateLibPage();
|
|
DrawItemTree(_path, _activePage);
|
|
}
|
|
else
|
|
{
|
|
var matchingSymbolUis = new List<SymbolUi>();
|
|
|
|
var activeNamespace = ActiveNamespaceString; // Outside of loop to away recomputing
|
|
foreach (var symbolUi in EditorSymbolPackage.AllSymbolUis)
|
|
{
|
|
if (symbolUi.Symbol.Namespace == activeNamespace)
|
|
matchingSymbolUis.Add(symbolUi);
|
|
}
|
|
|
|
var orderedEnumerable = matchingSymbolUis
|
|
.OrderByDescending(sui => SymbolFilter.ComputeRelevancy(sui,
|
|
string.Empty,
|
|
ProjectView.Focused.OpenedProject.Package,
|
|
context.CompositionInstance))
|
|
.ToList();
|
|
foreach (var symbolUi in orderedEnumerable)
|
|
{
|
|
uiResult |= PlaceHolderUi.DrawSymbolUiEntry(context, symbolUi, false);
|
|
WindowContentExtend.ExtendToLastItem();
|
|
}
|
|
}
|
|
|
|
return uiResult;
|
|
|
|
void DrawItemTree(List<Group> groupPath, Group group, int levelOnPage = 0)
|
|
{
|
|
switch (group.Variant)
|
|
{
|
|
case Variants.Project:
|
|
{
|
|
foreach (var subItem in group.Items)
|
|
{
|
|
DrawItemTree([group], subItem, levelOnPage + 1);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case Variants.Page when levelOnPage == 0:
|
|
{
|
|
foreach (var subItem in group.Items)
|
|
{
|
|
DrawItemTree([..groupPath], subItem, levelOnPage + 1);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case Variants.Page:
|
|
{
|
|
var color = ColorVariations.OperatorLabel.Apply(TypeUiRegistry.GetPropertiesForType(group.Type)
|
|
.Color);
|
|
ImGui.PushStyleColor(ImGuiCol.Text, color.Rgba);
|
|
ImGui.TextUnformatted($"{group.Name}...");
|
|
ImGui.PopStyleColor();
|
|
|
|
if (ImGui.IsItemHovered())
|
|
{
|
|
ImGui.GetWindowDrawList().AddRect(
|
|
ImGui.GetItemRectMin() - new Vector2(3, 1),
|
|
ImGui.GetItemRectMax() + new Vector2(3, 1),
|
|
UiColors.ForegroundFull.Fade(0.3f), 3);
|
|
}
|
|
|
|
if (ImGui.IsItemClicked())
|
|
{
|
|
_path.Clear();
|
|
_path.AddRange([..groupPath, group]);
|
|
ImGui.SetScrollY(0);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case Variants.Namespace when levelOnPage == 1:
|
|
{
|
|
var groupNamespace = GetNamespaceString([..groupPath, group]);
|
|
|
|
var matchingSymbolUis = new List<SymbolUi>();
|
|
foreach (var s in EditorSymbolPackage.AllSymbolUis)
|
|
{
|
|
if (s.Symbol.Namespace == groupNamespace && s.Tags.HasFlag(SymbolUi.SymbolTags.Essential))
|
|
matchingSymbolUis.Add(s);
|
|
}
|
|
|
|
if (matchingSymbolUis.Count == 0)
|
|
break;
|
|
|
|
var orderedEnumerable = matchingSymbolUis
|
|
.OrderByDescending(sui => SymbolFilter.ComputeRelevancy(sui,
|
|
string.Empty,
|
|
ProjectView.Focused!.OpenedProject.Package,
|
|
context.CompositionInstance))
|
|
.ToList();
|
|
|
|
ColumnLayout.StartGroupAndWrapIfRequired(orderedEnumerable.Count + 1);
|
|
|
|
DrawGroupHeader(group);
|
|
foreach (var symbolUi in orderedEnumerable)
|
|
{
|
|
ImGui.SetNextItemWidth(100);
|
|
uiResult |= PlaceHolderUi.DrawSymbolUiEntry(context, symbolUi, false);
|
|
WindowContentExtend.ExtendToLastItem();
|
|
ColumnLayout.ExtendWidth(ImGui.GetItemRectSize().X);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case Variants.Namespace:
|
|
{
|
|
var color = ColorVariations.OperatorLabel.Apply(TypeUiRegistry.GetPropertiesForType(group.Type)
|
|
.Color);
|
|
ImGui.PushStyleColor(ImGuiCol.Text, color.Rgba);
|
|
ImGui.TextUnformatted(group.Name + "/");
|
|
ImGui.PopStyleColor();
|
|
WindowContentExtend.ExtendToLastItem();
|
|
|
|
if (ImGui.IsItemHovered())
|
|
{
|
|
ImGui.GetWindowDrawList().AddRect(
|
|
ImGui.GetItemRectMin() - new Vector2(3, 1),
|
|
ImGui.GetItemRectMax() + new Vector2(3, 1),
|
|
UiColors.ForegroundFull.Fade(0.3f), 3);
|
|
}
|
|
|
|
if (ImGui.IsItemClicked())
|
|
{
|
|
_path.Clear();
|
|
_path.AddRange([..groupPath, group]);
|
|
ImGui.SetScrollY(0);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case Variants.Grouping:
|
|
case Variants.NamespaceCategory:
|
|
{
|
|
ColumnLayout.StartGroupAndWrapIfRequired(group.Items.Count + 1);
|
|
DrawGroupHeader(group);
|
|
foreach (var subItem in group.Items)
|
|
{
|
|
DrawItemTree([..groupPath, group], subItem, levelOnPage + 1);
|
|
WindowContentExtend.ExtendToLastItem();
|
|
ColumnLayout.ExtendWidth(ImGui.GetItemRectSize().X);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void Reset()
|
|
{
|
|
_path = [_libTree];
|
|
}
|
|
|
|
public static bool IsFilterActive => _path.Count > 1;
|
|
|
|
public static string FilterString => _path.Count <= 1
|
|
? string.Empty
|
|
: string.Join(".", _path[1..].Select(t => t.Name));
|
|
|
|
private static string GetNamespaceString(List<Group> groupPath)
|
|
{
|
|
_stringBuilder.Clear();
|
|
foreach (var g in groupPath)
|
|
{
|
|
if (g.Variant == Variants.Grouping)
|
|
continue;
|
|
|
|
if (_stringBuilder.Length > 0)
|
|
_stringBuilder.Append(".");
|
|
|
|
_stringBuilder.Append(g.Name);
|
|
}
|
|
|
|
return _stringBuilder.ToString();
|
|
}
|
|
|
|
private static void DrawGroupHeader(Group group)
|
|
{
|
|
ImGui.SetCursorPosY(ImGui.GetCursorPosY()+5);
|
|
ImGui.PushFont(Fonts.FontSmall);
|
|
ImGui.PushStyleColor(ImGuiCol.Text, UiColors.TextMuted.Rgba);
|
|
ImGui.TextUnformatted(group.Name + "...");
|
|
ImGui.PopStyleColor();
|
|
ImGui.PopFont();
|
|
|
|
WindowContentExtend.ExtendToLastItem();
|
|
}
|
|
|
|
private static Group UpdateLibPage()
|
|
{
|
|
return new Group(SymbolBrowsing.Variants.Project, "Lib",
|
|
[
|
|
new Group(Variants.NamespaceCategory, "numbers", [
|
|
new Group(Variants.Page, "anim", [
|
|
new Group(Variants.Namespace, "time"),
|
|
new Group(Variants.Namespace, "animators"),
|
|
new Group(Variants.Namespace, "vj"),
|
|
]),
|
|
new Group(Variants.Page, "float", [
|
|
new Group(Variants.Namespace, "basic"),
|
|
new Group(Variants.Namespace, "trigonometry"),
|
|
new Group(Variants.Namespace, "adjust"),
|
|
new Group(Variants.Namespace, "process"),
|
|
new Group(Variants.Namespace, "logic"),
|
|
new Group(Variants.Namespace, "random"),
|
|
]),
|
|
new Group(Variants.Namespace, "vec2"),
|
|
new Group(Variants.Namespace, "vec3"),
|
|
new Group(Variants.Namespace, "color"),
|
|
new Group(Variants.Namespace, "bool"),
|
|
new Group(Variants.Page, "int", [
|
|
new Group(Variants.Namespace, "basic"),
|
|
new Group(Variants.Namespace, "logic"),
|
|
new Group(Variants.Namespace, "process"),
|
|
])
|
|
]),
|
|
new Group(Variants.NamespaceCategory, "image", [
|
|
new Group(Variants.Page, "generate", [
|
|
new Group(Variants.Namespace, "load", type: typeof(Texture2D)),
|
|
new Group(Variants.Namespace, "basic", type: typeof(Texture2D)),
|
|
new Group(Variants.Namespace, "noise", type: typeof(Texture2D)),
|
|
new Group(Variants.Namespace, "pattern", type: typeof(Texture2D)),
|
|
], type: typeof(Texture2D)),
|
|
new Group(Variants.Page, "fx", [
|
|
new Group(Variants.Namespace, "blur", type: typeof(Texture2D)),
|
|
new Group(Variants.Namespace, "distort", type: typeof(Texture2D)),
|
|
new Group(Variants.Namespace, "stylize", type: typeof(Texture2D)),
|
|
new Group(Variants.Namespace, "glitch", type: typeof(Texture2D)),
|
|
], type: typeof(Texture2D)),
|
|
new Group(Variants.Namespace, "color", type: typeof(Texture2D)),
|
|
new Group(Variants.Namespace, "transform", type: typeof(Texture2D)),
|
|
new Group(Variants.Namespace, "analyze", type: typeof(Texture2D)),
|
|
new Group(Variants.Namespace, "use", type: typeof(Texture2D)),
|
|
]),
|
|
new Group(Variants.NamespaceCategory, "point", [
|
|
new Group(Variants.Namespace, "generate", type: typeof(BufferWithViews)),
|
|
new Group(Variants.Namespace, "transform", type: typeof(BufferWithViews)),
|
|
new Group(Variants.Namespace, "modify", type: typeof(BufferWithViews)),
|
|
new Group(Variants.Namespace, "draw", type: typeof(Command)),
|
|
]),
|
|
|
|
new Group(Variants.Grouping, "particles", [
|
|
new Group(Variants.Namespace, "particle", type: typeof(BufferWithViews)),
|
|
new Group(Variants.Page, "particle", [
|
|
new Group(Variants.Namespace, "force", type: typeof(BufferWithViews)),
|
|
], type: typeof(BufferWithViews)),
|
|
]),
|
|
new Group(Variants.NamespaceCategory, "render", [
|
|
new Group(Variants.Namespace, "basic", type: typeof(Command)),
|
|
new Group(Variants.Namespace, "camera", type: typeof(Command)),
|
|
new Group(Variants.Namespace, "transform", type: typeof(Command)),
|
|
new Group(Variants.Namespace, "shading", type: typeof(Command)),
|
|
new Group(Variants.Namespace, "postfx", type: typeof(Texture2D)),
|
|
new Group(Variants.Namespace, "gizmo", type: typeof(Command)),
|
|
new Group(Variants.Namespace, "utils", type: typeof(Command)),
|
|
]),
|
|
|
|
new Group(Variants.Grouping, "misc", [
|
|
new Group(Variants.Page, "field", [
|
|
//new Group(Variants.NamespaceCategory, "field", [
|
|
new Group(Variants.Namespace, "adjust", type: typeof(ShaderGraphNode)),
|
|
new Group(Variants.Namespace, "analyze", type: typeof(ShaderGraphNode)),
|
|
new Group(Variants.Namespace, "combine", type: typeof(ShaderGraphNode)),
|
|
new Group(Variants.Namespace, "generate.sdf", type: typeof(ShaderGraphNode)),
|
|
new Group(Variants.Namespace, "generate.texture", type: typeof(ShaderGraphNode)),
|
|
new Group(Variants.Namespace, "generate.vec3", type: typeof(ShaderGraphNode)),
|
|
new Group(Variants.Namespace, "render", type: typeof(ShaderGraphNode)),
|
|
new Group(Variants.Namespace, "space", type: typeof(ShaderGraphNode)),
|
|
new Group(Variants.Namespace, "use", type: typeof(ShaderGraphNode)),
|
|
], type: typeof(ShaderGraphNode)),
|
|
new Group(Variants.Page, "mesh", [
|
|
new Group(Variants.Namespace, "generate", type: typeof(MeshBuffers)),
|
|
new Group(Variants.Namespace, "modify", type: typeof(MeshBuffers)),
|
|
new Group(Variants.Namespace, "draw", type: typeof(Command)),
|
|
]),
|
|
new Group(Variants.Page, "string", [
|
|
new Group(Variants.Namespace, "combine", type: typeof(string)),
|
|
new Group(Variants.Namespace, "convert", type: typeof(string)),
|
|
new Group(Variants.Namespace, "search", type: typeof(string)),
|
|
new Group(Variants.Namespace, "logic", type: typeof(string)),
|
|
new Group(Variants.Namespace, "datetime", type: typeof(string)),
|
|
new Group(Variants.Namespace, "list", type: typeof(string)),
|
|
new Group(Variants.Namespace, "buffers", type: typeof(string)),
|
|
], type: typeof(string)),
|
|
new Group(Variants.Page, "io", [
|
|
new Group(Variants.Namespace, "audio"),
|
|
new Group(Variants.Namespace, "file"),
|
|
new Group(Variants.Namespace, "input"),
|
|
new Group(Variants.Namespace, "midi"),
|
|
new Group(Variants.Namespace, "osc"),
|
|
new Group(Variants.Namespace, "video"),
|
|
]),
|
|
new Group(Variants.Namespace, "flow", type: typeof(Command)),
|
|
]),
|
|
]);
|
|
}
|
|
|
|
private sealed class Group
|
|
{
|
|
internal Group(SymbolBrowsing.Variants variant, string name, List<Group>? items = null, Type? type = null)
|
|
{
|
|
Variant = variant;
|
|
Name = name;
|
|
Items = items ?? [];
|
|
Type = type;
|
|
}
|
|
|
|
internal readonly Variants Variant;
|
|
internal readonly string Name;
|
|
internal readonly List<Group> Items;
|
|
internal readonly Type? Type;
|
|
|
|
public override string ToString()
|
|
{
|
|
return $"{Variant} {Name} {Items.Count}";
|
|
}
|
|
}
|
|
|
|
private enum Variants
|
|
{
|
|
Project,
|
|
Page,
|
|
NamespaceCategory,
|
|
Namespace,
|
|
Grouping,
|
|
}
|
|
|
|
private static Group _libTree = UpdateLibPage();
|
|
private static Group? _activePage;
|
|
private static string ActiveNamespaceString => GetNamespaceString(_path);
|
|
private static readonly StringBuilder _stringBuilder = new();
|
|
private static List<Group> _path = [];
|
|
} |