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

355 lines
14 KiB
C#

using ImGuiNET;
using T3.Core.DataTypes.Vector;
using T3.Editor.Gui.Input;
using T3.Editor.Gui.Styling;
using T3.Editor.Gui.UiHelpers;
using T3.Editor.UiModel;
using T3.Editor.UiModel.Commands;
using T3.Editor.UiModel.Commands.Graph;
using T3.Editor.UiModel.InputsAndTypes;
using T3.Editor.UiModel.Modification;
using T3.Editor.UiModel.Selection;
namespace T3.Editor.Gui.Windows;
[HelpUiID("OperatorSettings")]
public sealed class ParameterSettings
{
public bool DrawToggleIcon(SymbolUi symbolUi, ref bool isEnabled)
{
var modified = false;
IsActive = isEnabled;
ImGui.SameLine();
var w = ImGui.GetFrameHeight();
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + 2);
ImGui.PushStyleColor(ImGuiCol.Button, Color.Transparent.Rgba);
if (CustomComponents.IconButton(
Icon.ViewList,
new Vector2(w, w),
IsActive
? CustomComponents.ButtonStates.Activated
: CustomComponents.ButtonStates.Default
))
{
IsActive = !IsActive;
modified = true;
isEnabled = IsActive;
}
ImGui.PopStyleColor();
return modified;
}
internal bool DrawContent(SymbolUi symbolUi, NodeSelection nodeSelection)
{
var modified = false;
using (new ChildWindowScope("wrapper",
new Vector2(0, 0),
ImGuiWindowFlags.None,
UiColors.BackgroundInputField))
{
FormInputs.AddVerticalSpace(5);
var selectedInputUi = DrawSelectionArea(symbolUi, nodeSelection);
ImGui.SameLine(0, 0);
modified = DrawSettingsForParameter(selectedInputUi);
}
return modified;
}
private bool _isDraggingParameterOrder;
private static bool _wasDraggingParameterOrder;
private List<IInputUi> _symbolUisWhileDragging = [];
private IInputUi DrawSelectionArea(SymbolUi symbolUi, NodeSelection nodeSelection)
{
IInputUi selectedInputUi = null;
using (new ChildWindowScope("selector",
new Vector2(SelectionWidth * T3Ui.UiScaleFactor, 0),
ImGuiWindowFlags.NoBackground,
Color.Transparent,
0))
{
var dl = ImGui.GetWindowDrawList();
var symbol = symbolUi.Symbol;
ImGui.PushStyleVar(ImGuiStyleVar.ButtonTextAlign, new Vector2(0, 0.5f));
var inputUis = _isDraggingParameterOrder ? _symbolUisWhileDragging : symbolUi.InputUis.Values.ToList();
var dragCompleted = false;
for (var index = 0; index < inputUis.Count; index++)
{
var inputUi = inputUis[index];
var isSelected = inputUi.InputDefinition.Id == SelectedInputId;
if (isSelected)
selectedInputUi = inputUi;
var padding = inputUi.AddPadding ? 4 : 0f;
if (!string.IsNullOrEmpty(inputUi.GroupTitle))
padding = 13;
var size = new Vector2(SelectionWidth * T3Ui.UiScaleFactor, padding + ImGui.GetFrameHeight());
var clicked = ImGui.InvisibleButton(inputUi.InputDefinition.Name, size);
var typeColor = TypeUiRegistry.GetPropertiesForType(inputUi.Type).Color;
var textColor = isSelected ? ColorVariations.OperatorLabel.Apply(typeColor) : typeColor.Fade(0.9f);
var backgroundColor = isSelected ? UiColors.WindowBackground : Color.Transparent;
if ((ImGui.IsItemHovered() || ImGui.IsItemActive()) && !isSelected)
{
backgroundColor = UiColors.WindowBackground.Fade(0.5f);
}
// Handle dragging
var itemMin = ImGui.GetItemRectMin();
var itemMax = ImGui.GetItemRectMax();
if (!_isDraggingParameterOrder && ImGui.IsItemActive() && ImGui.IsMouseDragging(ImGuiMouseButton.Left))
{
_isDraggingParameterOrder = true;
_symbolUisWhileDragging = symbolUi.InputUis.Values.ToList();
}
else if (_isDraggingParameterOrder)
{
//if (ImGui.IsItemActive() && !ImGui.IsItemHovered())
if (ImGui.IsItemActive())
{
var mouseY = ImGui.GetMousePos().Y;
var halfHeight = ImGui.GetItemRectSize().Y / 2;
var indexDelta = 0;
if (mouseY < itemMin.Y - halfHeight && index > 0)
{
indexDelta = -1;
}
else if (mouseY > itemMax.Y + halfHeight && index < symbolUi.InputUis.Count - 1)
{
indexDelta = 1;
}
if (indexDelta != 0)
{
(_symbolUisWhileDragging[index + indexDelta], _symbolUisWhileDragging[index])
= (_symbolUisWhileDragging[index], _symbolUisWhileDragging[index + indexDelta]);
_wasDraggingParameterOrder = true;
}
}
}
dl.AddRectFilled(itemMin, ImGui.GetItemRectMax(), backgroundColor, 7, ImDrawFlags.RoundCornersLeft);
// Draw group title
if (!string.IsNullOrEmpty(inputUi.GroupTitle))
{
dl.AddText(Fonts.FontSmall, Fonts.FontSmall.FontSize,
itemMin
+ new Vector2(6, 0),
UiColors.TextMuted.Fade(0.5f),
inputUi.GroupTitle);
}
// Draw name
var font = isSelected ? Fonts.FontBold : Fonts.FontNormal;
dl.AddText(font, font.FontSize,
itemMin
+ new Vector2(8, padding + 2),
textColor,
inputUi.InputDefinition.Name.AddSpacesForImGuiOutput());
// Drag handle
if (ImGui.IsItemActive() || (!ImGui.IsAnyItemActive() && ImGui.IsItemHovered()))
{
for (int i = 0; i < 3; i++)
{
var pos = new Vector2(itemMin.X + 2, itemMin.Y + i * 5 + size.Y / 2 - 6);
dl.AddRectFilled(pos, pos + new Vector2(3, 2), UiColors.ForegroundFull.Fade(0.2f), 0);
}
}
// Handle click
if (clicked && !_wasDraggingParameterOrder)
{
SelectedInputId = inputUi.InputDefinition.Id;
selectedInputUi = inputUi;
var selectedInstance = nodeSelection.GetFirstSelectedInstance();
if (selectedInstance == null)
nodeSelection.SetSelection(inputUi);
}
if (ImGui.IsItemDeactivated())
{
dragCompleted = true;
}
}
ImGui.PopStyleVar();
if (selectedInputUi == null && symbolUi.InputUis.Count > 0)
{
SelectedInputId = symbolUi.InputUis.Values.First().InputDefinition.Id;
}
if (dragCompleted && _wasDraggingParameterOrder)
{
_isDraggingParameterOrder = false;
var oldOrder = symbol.InputDefinitions.Select(def => def.Id).ToList();
var newOrder = _symbolUisWhileDragging.Select(inputUi => inputUi.InputDefinition.Id).ToList();
_symbolUisWhileDragging.Clear();
_wasDraggingParameterOrder = false;
if (!oldOrder.SequenceEqual(newOrder))
{
UndoRedoStack.AddAndExecute(new ChangeInputOrderCommand(symbol.Id, oldOrder, newOrder));
}
}
}
return selectedInputUi;
}
private static bool DrawSettingsForParameter(IInputUi selectedInputUi)
{
var modified = false;
using (new ChildWindowScope("settings",
new Vector2(0, 0), ImGuiWindowFlags.None,
UiColors.WindowBackground.Rgba,
10,
5))
{
if (selectedInputUi != null)
{
FormInputs.AddSectionHeaderParam(selectedInputUi.InputDefinition.Name);
ImGui.PushStyleColor(ImGuiCol.Text, UiColors.TextMuted.Rgba);
ImGui.TextUnformatted(selectedInputUi.Type.Name);
ImGui.PopStyleColor();
FormInputs.AddVerticalSpace(5);
var style = ParameterListStyles.Default;
if (selectedInputUi.AddPadding)
{
style = ParameterListStyles.WithPadding;
}
else if (selectedInputUi.GroupTitle != null)
{
style = ParameterListStyles.WithGroup;
}
FormInputs.DrawFieldSetHeader("Show parameter as");
if (FormInputs.AddEnumDropdown(ref style, null))
{
switch (style)
{
case ParameterListStyles.Default:
selectedInputUi.AddPadding = false;
selectedInputUi.GroupTitle = null;
break;
case ParameterListStyles.WithPadding:
selectedInputUi.AddPadding = true;
selectedInputUi.GroupTitle = null;
break;
case ParameterListStyles.WithGroup:
selectedInputUi.AddPadding = false;
selectedInputUi.GroupTitle = "";
break;
}
modified = true;
}
if (style == ParameterListStyles.WithGroup)
{
var groupTitle = selectedInputUi.GroupTitle;
if (FormInputs.AddStringInput("##groupTitle", ref groupTitle,
"Group Title",
null,
"""
Group title shown above parameter
Group will be collapsed by default if name ends with '...' (three dots).
"""))
{
selectedInputUi.GroupTitle = groupTitle;
modified = true;
}
}
{
FormInputs.DrawFieldSetHeader("Relevancy in Graph");
var tmpForRef = selectedInputUi.Relevancy;
if (FormInputs.AddEnumDropdown(ref tmpForRef, null, defaultValue: Relevancy.Optional))
{
selectedInputUi.Relevancy = tmpForRef;
modified = true;
}
}
{
FormInputs.AddVerticalSpace();
FormInputs.SetIndentToLeft();
var tmp = selectedInputUi.ExcludedFromPresets;
if (FormInputs.AddCheckBox("Excluded from presets",
ref tmp,
"""
Saving certain parameters in presets might not be useful or expected. E.g. for Text rendering, the actual string should not be part of the text style.
This setting does also apply to Snapshots.
""",
false))
{
selectedInputUi.ExcludedFromPresets = tmp;
modified = true;
}
FormInputs.SetIndentToParameters();
}
// Draw additional settings for input types like Vector2, Vector3, etc.
modified |= selectedInputUi.DrawSettings();
FormInputs.AddVerticalSpace();
FormInputs.DrawFieldSetHeader("Documentation");
var width = ImGui.GetContentRegionAvail().X;
var description = string.IsNullOrEmpty(selectedInputUi.Description) ? string.Empty : selectedInputUi.Description;
ImGui.PushStyleVar(ImGuiStyleVar.FrameRounding, 5);
if (ImGui.InputTextMultiline("##parameterDescription", ref description, 16000, new Vector2(width, 0)))
{
selectedInputUi.Description = string.IsNullOrEmpty(description) ? null : description;
modified = true;
}
ImGui.PopStyleVar();
}
else
{
CustomComponents.EmptyWindowMessage("no input selected...");
}
}
return modified;
}
private const float SelectionWidth = 150;
private enum ParameterListStyles
{
Default,
WithPadding,
WithGroup,
}
internal Guid SelectedInputId { get; set; }
public bool IsActive { get; private set; } = false;
public void SelectInput(Guid inputUiId)
{
SelectedInputId = inputUiId;
}
}