diff --git a/Core/Resource/CollectionUtils.cs b/Core/Resource/CollectionUtils.cs
new file mode 100644
index 0000000000..2be941a2da
--- /dev/null
+++ b/Core/Resource/CollectionUtils.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Core.Resource
+{
+ public static class CollectionUtils
+ {
+ ///
+ /// A simple method to get a new index by "jumping" from a startIndex
+ /// When the jump would make the index exceed the valid range of the collection,
+ /// it will return an index that "wraps" around the other side
+ ///
+ /// Index to jump from
+ /// How far to jump (usually 1 or -1 for forward and backward respectively)
+ /// The collection whose Count (Length for arrays) will be referenced
+ /// If false, this will default to making every wrap result in the first or last index of the collection.
+ /// If true, it will be a "real" wrap, where if you jump in excess of X, you will wrap to the index X distance from the other side.
+ ///
+ public static int WrapIndex(int startIndex, int jumpAmount, System.Collections.IList collection, bool realWrap = false)
+ {
+ int index = startIndex + jumpAmount;
+ index %= collection.Count;
+
+ bool newIndexIsNegative = index < 0;
+ int negativeWrapIndex = realWrap ? collection.Count + index : collection.Count - 1;
+
+ return newIndexIsNegative ? negativeWrapIndex : index;
+ }
+ }
+}
diff --git a/Core/Resource/MathUtils.cs b/Core/Resource/MathUtils.cs
index 1cdcdbde11..b9507f1be3 100644
--- a/Core/Resource/MathUtils.cs
+++ b/Core/Resource/MathUtils.cs
@@ -1,7 +1,6 @@
using System;
using System.Numerics;
using T3.Core.Animation;
-using T3.Core.Operator;
namespace T3.Core
{
diff --git a/T3/Gui/Graph/Interaction/SymbolBrowser.cs b/T3/Gui/Graph/Interaction/SymbolBrowser.cs
index e5add61fab..abf37cfb0b 100644
--- a/T3/Gui/Graph/Interaction/SymbolBrowser.cs
+++ b/T3/Gui/Graph/Interaction/SymbolBrowser.cs
@@ -3,6 +3,8 @@
using System.Diagnostics;
using System.Linq;
using System.Numerics;
+using System.Threading.Tasks;
+using Core.Resource;
using ImGuiNET;
using T3.Core;
using T3.Core.IO;
@@ -51,20 +53,19 @@ public void Draw()
{
if (!IsOpen)
{
- if (!ImGui.IsWindowFocused() || !ImGui.IsKeyReleased((ImGuiKey)Key.Tab))
+ if (!ImGui.IsWindowFocused() || !ImGui.IsKeyReleased((ImGuiKey)Key.Tab) || !ImGui.IsWindowHovered())
return;
- if (NodeSelection.GetSelectedChildUis().Count() == 1)
+ if (NodeSelection.GetSelectedChildUis().Count() != 1)
{
- var childUi = NodeSelection.GetSelectedChildUis().ToList()[0];
- {
- var instance = NodeSelection.GetInstanceForSymbolChildUi(childUi);
- ConnectionMaker.OpenBrowserWithSingleSelection(this, childUi, instance);
- }
+ OpenAt(GraphCanvas.Current.InverseTransformPositionFloat(ImGui.GetIO().MousePos + new Vector2(-4, -20)), null, null, false, null);
+ return;
}
- else
+
+ var childUi = NodeSelection.GetSelectedChildUis().ToList()[0];
{
- OpenAt(GraphCanvas.Current.InverseTransformPositionFloat(ImGui.GetIO().MousePos + new Vector2(-4, -20)), null, null, false, null);
+ var instance = NodeSelection.GetInstanceForSymbolChildUi(childUi);
+ ConnectionMaker.OpenBrowserWithSingleSelection(this, childUi, instance);
}
return;
@@ -76,62 +77,60 @@ public void Draw()
ImGui.PushID(UiId);
{
- _posInWindow = GraphCanvas.Current.ChildPosFromCanvas(PosOnCanvas);
+ var posInWindow = GraphCanvas.Current.ChildPosFromCanvas(PosOnCanvas);
_posInScreen = GraphCanvas.Current.TransformPosition(PosOnCanvas);
_drawList = ImGui.GetWindowDrawList();
ImGui.SetNextWindowFocus();
- DrawMatchesList();
- DrawSearchInput();
+
+ Vector2 browserPositionInWindow = posInWindow + _browserPositionOffset;
+ Vector2 browserSize = _resultListSize;
+ ShiftPositionToFitOnCanvas(ref browserPositionInWindow, ref browserSize);
+
+ ImGui.SetCursorPos(browserPositionInWindow);
+
+ DrawResultsList(browserSize);
+
+ if (_symbolUiForDescription != null)
+ {
+ DrawDescriptionPanel(browserPositionInWindow, browserSize, _symbolUiForDescription);
+ }
+
+ DrawSearchInput(posInWindow, _posInScreen, _size);
}
+
ImGui.PopID();
}
#endregion
- private bool _selectedItemWasChanged;
-
#region internal implementation -----------------------------------------------------------
- private void DrawSearchInput()
- {
- ImGui.SetCursorPos(_posInWindow);
- ImGui.SetNextItemWidth(90);
+ private void DrawSearchInput(Vector2 posInWindow, Vector2 posInScreen, Vector2 size)
+ {
if (_focusInputNextTime)
{
ImGui.SetKeyboardFocusHere();
_focusInputNextTime = false;
}
- ImGui.SetCursorPos(_posInWindow + new Vector2(1, 1));
- ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, new Vector2(7, 6));
- ImGui.SetNextItemWidth(_size.X);
- ImGui.InputText("##filter", ref _filter.SearchString, 10);
- _drawList.AddRect(_posInScreen, _posInScreen + _size, Color.Gray);
+ ImGui.SetCursorPos(posInWindow);
+
+ var padding = new Vector2(7, 6);
+ ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, padding);
+ ImGui.SetNextItemWidth(size.X);
+
+ ImGui.InputText("##symbolbrowserfilter", ref _filter.SearchString, 10);
+
+ // Search input outline
+ _drawList.AddRect(posInScreen, posInScreen + size, Color.Gray);
if (ImGui.IsKeyReleased((ImGuiKey)Key.CursorDown))
{
- if (_filter.MatchingSymbolUis.Count > 0)
- {
- var index = _filter.MatchingSymbolUis.IndexOf(_selectedSymbolUi);
- index++;
- index %= _filter.MatchingSymbolUis.Count;
- _selectedSymbolUi = _filter.MatchingSymbolUis[index];
-
- _selectedItemWasChanged = true;
- }
+ SelectNextSymbolUi(_selectedSymbolUi);
}
else if (ImGui.IsKeyReleased((ImGuiKey)Key.CursorUp))
{
- if (_filter.MatchingSymbolUis.Count > 0)
- {
- var index = _filter.MatchingSymbolUis.IndexOf(_selectedSymbolUi);
- index--;
- if (index < 0)
- index = _filter.MatchingSymbolUis.Count - 1;
-
- _selectedSymbolUi = _filter.MatchingSymbolUis[index];
- _selectedItemWasChanged = true;
- }
+ SelectPreviousSymbol(_selectedSymbolUi);
}
else if (ImGui.IsKeyPressed((ImGuiKey)Key.Return))
{
@@ -150,26 +149,43 @@ private void DrawSearchInput()
}
var clickedOutside = ImGui.IsMouseClicked(ImGuiMouseButton.Left) && ImGui.IsWindowHovered();
- if (clickedOutside
+ var shouldCancelConnectionMaker = clickedOutside
|| ImGui.IsMouseClicked(ImGuiMouseButton.Right)
- || ImGui.IsKeyDown((ImGuiKey)Key.Esc))
+ || ImGui.IsKeyDown((ImGuiKey)Key.Esc);
+
+ if (shouldCancelConnectionMaker)
{
ConnectionMaker.Cancel();
- //Log.Debug("Closing...");
Cancel();
}
ImGui.PopStyleVar();
- if (ImGui.IsItemActive())
+ if (!ImGui.IsItemActive())
+ return;
+
+ if (ImGui.IsMouseDragging(ImGuiMouseButton.Left))
{
- if (ImGui.IsMouseDragging(ImGuiMouseButton.Left))
- {
- PosOnCanvas += GraphCanvas.Current.InverseTransformDirection(ImGui.GetIO().MouseDelta);
- }
+ PosOnCanvas += GraphCanvas.Current.InverseTransformDirection(ImGui.GetIO().MouseDelta);
}
}
+ private void SelectNextSymbolUi(SymbolUi selectedSymbolUi) => JumpThroughMatchingSymbolList(selectedSymbolUi, 1);
+ private void SelectPreviousSymbol(SymbolUi selectedSymbolUi) => JumpThroughMatchingSymbolList(selectedSymbolUi, -1);
+
+ private void JumpThroughMatchingSymbolList(SymbolUi currentSelectedSymbolUi, int jump)
+ {
+ if (_filter.MatchingSymbolUis.Count == 0)
+ {
+ return;
+ }
+
+ var index = _filter.MatchingSymbolUis.IndexOf(currentSelectedSymbolUi);
+ index = CollectionUtils.WrapIndex(index, jump, _filter.MatchingSymbolUis);
+ _selectedSymbolUi = _filter.MatchingSymbolUis[index];
+ _selectedItemWasChanged = true;
+ }
+
private void Cancel()
{
if (_prepareCommand != null)
@@ -184,50 +200,32 @@ private void Cancel()
private void Close()
{
THelpers.RestoreImGuiKeyboardNavigation();
- //T3Ui.OpenedPopUpName = null;
IsOpen = false;
var win = GraphWindow.GetPrimaryGraphWindow();
win?.Focus();
}
- private void DrawMatchesList()
+ private void DrawResultsList(Vector2 size)
{
- ImGui.SetCursorPos(_posInWindow + new Vector2(1, _size.Y + 1));
ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, new Vector2(5, 5));
ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(10, 10));
- SymbolUi itemForHelp = null;
+ var itemForHelpIsHovered = false;
- if (ImGui.BeginChildFrame(999, _resultListSize))
+ if (ImGui.BeginChildFrame(999, size))
{
- if (_filter.MatchingSymbolUis.Count > 0 && !_filter.MatchingSymbolUis.Contains(_selectedSymbolUi))
+ var gotAMatch = _filter.MatchingSymbolUis.Count > 0 && !_filter.MatchingSymbolUis.Contains(_selectedSymbolUi);
+ if (gotAMatch)
_selectedSymbolUi = _filter.MatchingSymbolUis[0];
if ((_selectedSymbolUi == null && SymbolUiRegistry.Entries.Values.Any()))
_selectedSymbolUi = SymbolUiRegistry.Entries.Values.FirstOrDefault();
- // Print type filter
- if (_filter.FilterInputType != null || _filter.FilterOutputType != null)
- {
- ImGui.PushFont(Fonts.FontSmall);
-
- var inputTypeName = _filter.FilterInputType != null
- ? TypeNameRegistry.Entries[_filter.FilterInputType]
- : string.Empty;
-
- var outputTypeName = _filter.FilterOutputType != null
- ? TypeNameRegistry.Entries[_filter.FilterOutputType]
- : string.Empty;
-
- var isMultiInput = _filter.OnlyMultiInputs ? "[..]" : "";
-
- var headerLabel = $"{inputTypeName}{isMultiInput} -> {outputTypeName}";
- ImGui.TextDisabled(headerLabel);
- ImGui.PopFont();
- }
+ PrintTypeFilter();
foreach (var symbolUi in _filter.MatchingSymbolUis)
{
- ImGui.PushID(symbolUi.Symbol.Id.GetHashCode());
+ var symbolHash = symbolUi.Symbol.Id.GetHashCode();
+ ImGui.PushID(symbolHash);
{
var color = symbolUi.Symbol.OutputDefinitions.Count > 0
? TypeUiRegistry.GetPropertiesForType(symbolUi.Symbol.OutputDefinitions[0]?.ValueType).Color
@@ -241,24 +239,22 @@ private void DrawMatchesList()
ImGui.PushStyleColor(ImGuiCol.Text, ColorVariations.OperatorLabel.Apply(color).Rgba);
var isSelected = symbolUi == _selectedSymbolUi;
- if (isSelected && _selectedItemWasChanged)
- {
- ScrollToMakeItemVisible();
- _selectedItemWasChanged = false;
- }
- if (itemForHelp == null && isSelected)
+ ImGui.Selectable($"##Selectable{symbolHash.ToString()}", isSelected);
+ bool selectionChangedToThis = isSelected && _selectedItemWasChanged;
+
+ if (!itemForHelpIsHovered)
{
- itemForHelp = symbolUi;
+ var isHovered = ImGui.IsItemHovered();
+ itemForHelpIsHovered = DetermineItemForHelp(isHovered, symbolUi, isSelected);
}
- ImGui.Selectable("", isSelected);
-
- if (ImGui.IsItemHovered())
+ if (selectionChangedToThis)
{
- itemForHelp = symbolUi;
+ ScrollToMakeItemVisible();
+ _selectedItemWasChanged = false;
}
-
+
if (ImGui.IsItemActivated())
{
CreateInstance(symbolUi.Symbol);
@@ -287,34 +283,117 @@ private void DrawMatchesList()
ImGui.EndChildFrame();
- DrawDescriptionPanel(itemForHelp);
-
ImGui.PopStyleVar(2);
}
- private static void DrawDescriptionPanel(SymbolUi itemForHelp)
+ private bool DetermineItemForHelp(bool isHovered, SymbolUi symbolUi, bool isSelected)
{
- if (itemForHelp == null)
+ if (isHovered)
+ {
+ _symbolUiForDescription = symbolUi;
+ _timeDescriptionSymbolUiLastHovered = DateTime.Now;
+ return true;
+ }
+
+ if (isSelected && !_descriptionPanelHovered)
+ {
+ if ((DateTime.Now - _timeDescriptionSymbolUiLastHovered).Milliseconds > 50)
+ {
+ _symbolUiForDescription = symbolUi;
+ _timeDescriptionSymbolUiLastHovered = DateTime.Now;
+ }
+ }
+
+ return false;
+ }
+
+ private void PrintTypeFilter()
+ {
+ if (_filter.FilterInputType == null && _filter.FilterOutputType == null)
return;
+ ImGui.PushFont(Fonts.FontSmall);
+
+ var inputTypeName = _filter.FilterInputType != null
+ ? TypeNameRegistry.Entries[_filter.FilterInputType]
+ : string.Empty;
+
+ var outputTypeName = _filter.FilterOutputType != null
+ ? TypeNameRegistry.Entries[_filter.FilterOutputType]
+ : string.Empty;
+
+ var isMultiInput = _filter.OnlyMultiInputs ? "[..]" : "";
+
+ var headerLabel = $"{inputTypeName}{isMultiInput} -> {outputTypeName}";
+ ImGui.TextDisabled(headerLabel);
+ ImGui.PopFont();
+ }
+
+
+ private void ShiftPositionToFitOnCanvas(ref Vector2 position, ref Vector2 size)
+ {
+ var maxXPos = position.X + size.X;
+ var maxYPos = position.Y + size.Y;
+
+ var windowSize = GraphCanvas.Current.WindowSize;
+
+ var shouldShiftLeft = maxXPos > windowSize.X;
+ var xPositionOffset = shouldShiftLeft ? windowSize.X - maxXPos : 0;
+
+ var yOverflow = maxYPos > windowSize.Y;
+ var yShrinkage = yOverflow ? windowSize.Y - maxYPos : 0;
+
+ position.X += xPositionOffset;
+ size.Y += yShrinkage;
+ }
+
+ private void DrawDescriptionPanel(Vector2 position, Vector2 size, SymbolUi itemForHelp)
+ {
+ if (itemForHelp == null)
+ return;
+
ExampleSymbolLinking.ExampleSymbols.TryGetValue(itemForHelp.Symbol.Id, out var examples2);
var hasExamples = examples2 is { Count: > 0 };
var hasDescription = !string.IsNullOrEmpty(itemForHelp.Description);
if (!hasExamples && !hasDescription)
return;
-
- ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, Vector2.One); // Padding between panels
- ImGui.SameLine();
- if (ImGui.GetContentRegionAvail().X < 250)
+ var maxXPos = position.X + size.X * 2;
+ bool overflow = maxXPos >= GraphCanvas.Current.WindowSize.X;
+
+ if (overflow && !UserSettings.Config.AlwaysShowDescriptionPanel)
{
- ImGui.PopStyleVar();
return;
}
-
-
- if (ImGui.BeginChildFrame(998, new Vector2(250, _resultListSize.Y)))
+
+ if (!overflow)
+ {
+ position.X += size.X;
+ }
+ else //if it's overflowing but AlwaysShowDescriptionPanel is true
+ {
+ position.X -= size.X;
+
+ //if it simply doesn't fit on screen, return
+ if (position.X <= 0)
+ return;
+ }
+
+ ImGui.SetCursorPos(position);
+ DrawDescriptionPanelImGui(itemForHelp, size, hasExamples);
+
+
+ _descriptionPanelHovered = ImGui.IsItemHovered();
+ if (_descriptionPanelHovered)
+ _timeDescriptionSymbolUiLastHovered = DateTime.Now;
+ }
+
+ private void DrawDescriptionPanelImGui(SymbolUi itemForHelp, Vector2 size, bool hasExamples)
+ {
+ ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, Vector2.One); // Padding between panels
+
+ if (ImGui.BeginChildFrame(998, size))
{
if (!string.IsNullOrEmpty(itemForHelp.Description))
{
@@ -326,7 +405,6 @@ private static void DrawDescriptionPanel(SymbolUi itemForHelp)
if (hasExamples)
{
ImGui.Dummy(new Vector2(10, 10));
-
ListExampleOperators(itemForHelp);
}
@@ -338,18 +416,18 @@ private static void DrawDescriptionPanel(SymbolUi itemForHelp)
public static void ListExampleOperators(SymbolUi itemForHelp)
{
- if (ExampleSymbolLinking.ExampleSymbols.TryGetValue(itemForHelp.Symbol.Id, out var examples))
+ if (!ExampleSymbolLinking.ExampleSymbols.TryGetValue(itemForHelp.Symbol.Id, out var examples))
+ return;
+
+ ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0.5f);
+ foreach (var guid in examples)
{
- ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0.5f);
- for (var index = 0; index < examples.Count; index++)
- {
- var label = "Example";
- var exampleId = examples[index];
- DrawExampleOperator(exampleId, label);
- }
-
- ImGui.PopStyleVar();
+ var label = "Example";
+ var exampleId = guid;
+ DrawExampleOperator(exampleId, label);
}
+
+ ImGui.PopStyleVar();
}
public static void DrawExampleOperator(Guid exampleId, string label)
@@ -384,6 +462,7 @@ private void ScrollToMakeItemVisible()
var scrollTarget = ImGui.GetCursorPos();
var windowSize = ImGui.GetWindowSize();
var scrollPos = ImGui.GetScrollY();
+
if (scrollTarget.Y < scrollPos)
{
ImGui.SetScrollY(scrollTarget.Y);
@@ -475,17 +554,21 @@ private void CreateInstance(Symbol symbol)
public bool IsOpen;
private readonly Vector2 _size = SymbolChildUi.DefaultOpSize;
+ private static Vector2 _browserPositionOffset => new Vector2(0, 40);
private bool _focusInputNextTime;
private Vector2 _posInScreen;
private ImDrawListPtr _drawList;
- private Vector2 _posInWindow;
+ private bool _selectedItemWasChanged;
private static readonly Vector2 _resultListSize = new Vector2(250, 300);
private readonly Vector4 _namespaceColor = new Color(1, 1, 1, 0.4f);
private SymbolUi _selectedSymbolUi;
+ private SymbolUi _symbolUiForDescription;
+ private bool _descriptionPanelHovered;
+ private DateTime _timeDescriptionSymbolUiLastHovered;
private static readonly int UiId = "DraftNode".GetHashCode();
}
}
\ No newline at end of file
diff --git a/T3/Gui/SettingsUi.cs b/T3/Gui/SettingsUi.cs
new file mode 100644
index 0000000000..003660abad
--- /dev/null
+++ b/T3/Gui/SettingsUi.cs
@@ -0,0 +1,101 @@
+using ImGuiNET;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+using System.Text;
+using System.Threading.Tasks;
+using T3.Gui.Windows;
+
+namespace t3.Gui
+{
+ public static class SettingsUi
+ {
+ ///
+ /// Draws a table of s
+ ///
+ /// Unique identifier for your table - will not be displayed
+ /// Settings to display
+ /// Returns true if a setting has been modified
+ public static bool DrawSettingsTable(string tableID, UIControlledSetting[] settings)
+ {
+ ImGui.NewLine();
+ bool changed = false;
+ if (ImGui.BeginTable(tableID, 2, ImGuiTableFlags.BordersInnerH | ImGuiTableFlags.SizingFixedSame | ImGuiTableFlags.PadOuterX))
+ {
+ foreach (UIControlledSetting setting in settings)
+ {
+ ImGui.TableNextRow();
+ ImGui.TableNextColumn();
+ ImGui.Indent();
+
+ if (setting.DrawOnLeft)
+ {
+ var valueChanged = setting.DrawGUIControl(true);
+ changed |= valueChanged;
+
+ ImGui.SameLine();
+ ImGui.Dummy(_leftCheckboxSpacing);
+ ImGui.SameLine();
+
+ ImGui.Text(setting.CleanLabel);
+ DrawTooltip(setting);
+
+ ImGui.Unindent();
+ }
+ else
+ {
+ ImGui.Text(setting.CleanLabel);
+ DrawTooltip(setting);
+ ImGui.Unindent();
+ ImGui.TableNextColumn();
+ var valueChanged = setting.DrawGUIControl(true);
+ changed |= valueChanged;
+ }
+
+ }
+ }
+
+ ImGui.EndTable();
+ ImGui.NewLine();
+
+ return changed;
+ }
+
+ ///
+ /// Draws a series of settings in order
+ ///
+ ///
+ ///
+ public static bool DrawSettings(UIControlledSetting[] settings)
+ {
+ ImGui.NewLine();
+
+ bool changed = false;
+
+ foreach (var setting in settings)
+ {
+ ImGui.Text(setting.CleanLabel);
+ DrawTooltip(setting);
+ ImGui.SameLine();
+ changed |= setting.DrawGUIControl(true);
+ }
+
+ ImGui.NewLine();
+ return changed;
+ }
+
+ private static void DrawTooltip(UIControlledSetting setting)
+ {
+ if (!string.IsNullOrEmpty(setting.Tooltip))
+ {
+ if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
+ {
+ ImGui.SetTooltip(setting.Tooltip);
+ }
+ }
+ }
+
+ private static readonly Vector2 _leftCheckboxSpacing = new Vector2(0f, 20f);
+ }
+}
diff --git a/T3/Gui/Styling/CustomComponents.cs b/T3/Gui/Styling/CustomComponents.cs
index 2a6e53d752..2aaf7f10fe 100644
--- a/T3/Gui/Styling/CustomComponents.cs
+++ b/T3/Gui/Styling/CustomComponents.cs
@@ -473,23 +473,22 @@ public static bool DrawSegmentedToggle(ref int currentIndex, List option
}
- public static bool FloatValueEdit(string label, ref float value, float min= float.NegativeInfinity, float max= float.PositiveInfinity, float scale= 0)
+ public static bool FloatValueEdit(string label, ref float value, float min = float.NegativeInfinity, float max = float.PositiveInfinity, float scale = 0.01f, bool clamp = false)
{
var labelSize = ImGui.CalcTextSize(label);
const float leftPadding = 200;
var p = ImGui.GetCursorPos();
- ImGui.SetCursorPosX( MathF.Max(leftPadding - labelSize.X,0)+10);
+ ImGui.SetCursorPosX(MathF.Max(leftPadding - labelSize.X, 0) + 10);
ImGui.AlignTextToFramePadding();
- ImGui.TextUnformatted(label);
+
+ string cleanedLabel = label.Split(_idSpecifier)[0];
+ ImGui.TextUnformatted(cleanedLabel);
ImGui.SetCursorPos(p);
-
+
ImGui.SameLine();
ImGui.SetCursorPosX(leftPadding + 20);
- var size = new Vector2(150, ImGui.GetFrameHeight());
- ImGui.PushID(label);
- var result = SingleValueEdit.Draw(ref value, size, min, max);
- var modified = (result & InputEditStateFlags.Modified) != InputEditStateFlags.Nothing;
- ImGui.PopID();
+ var modified = DrawSingleValueEdit(cleanedLabel, ref value, min, max, clamp, scale);
+
return modified;
}
@@ -500,17 +499,35 @@ public static bool IntValueEdit(string label, ref int value, int min = int.MinVa
var p = ImGui.GetCursorPos();
ImGui.SetCursorPosX(MathF.Max(leftPadding - labelSize.X, 0) + 10);
ImGui.AlignTextToFramePadding();
- ImGui.TextUnformatted(label);
+
+ string cleanedLabel = label.Split(_idSpecifier)[0];
+ ImGui.TextUnformatted(cleanedLabel);
+
ImGui.SetCursorPos(p);
ImGui.SameLine();
ImGui.SetCursorPosX(leftPadding + 20);
+
+ var modified = DrawSingleValueEdit(cleanedLabel, ref value, min, max, true, scale);
+ return modified;
+ }
+
+ public static bool DrawSingleValueEdit(string label, ref int value, int min = int.MinValue, int max = int.MaxValue, bool clamp = false, float scale = 1f)
+ {
+ ImGui.PushID(label);
var size = new Vector2(150, ImGui.GetFrameHeight());
+ var result = SingleValueEdit.Draw(ref value, size, min, max, clamp, scale);
+ ImGui.PopID();
+ return (result & InputEditStateFlags.Modified) != InputEditStateFlags.Nothing;
+ }
+
+ public static bool DrawSingleValueEdit(string label, ref float value, float min = float.MinValue, float max = float.MaxValue, bool clamp = false, float scale = 1f)
+ {
ImGui.PushID(label);
- var result = SingleValueEdit.Draw(ref value, size, min, max, true, scale);
- var modified = (result & InputEditStateFlags.Modified) != InputEditStateFlags.Nothing;
+ var size = new Vector2(150, ImGui.GetFrameHeight());
+ var result = SingleValueEdit.Draw(ref value, size, min, max, clamp, scale);
ImGui.PopID();
- return modified;
+ return (result & InputEditStateFlags.Modified) != InputEditStateFlags.Nothing;
}
public static bool StringValueEdit(string label, ref string value)
@@ -521,7 +538,10 @@ public static bool StringValueEdit(string label, ref string value)
var p = ImGui.GetCursorPos();
ImGui.SetCursorPosX( MathF.Max(leftPadding - labelSize.X,0)+10);
ImGui.AlignTextToFramePadding();
- ImGui.TextUnformatted(label);
+
+ string cleanedLabel = label.Split(_idSpecifier)[0];
+ ImGui.TextUnformatted(cleanedLabel);
+
ImGui.SetCursorPos(p);
ImGui.SameLine();
@@ -541,7 +561,10 @@ public static bool DrawEnumSelector(ref int index, string label)
var p = ImGui.GetCursorPos();
ImGui.SetCursorPosX(MathF.Max(200 - labelSize.X, 0) + 10);
ImGui.AlignTextToFramePadding();
- ImGui.TextUnformatted(label);
+
+ string cleanedLabel = label.Split(_idSpecifier)[0];
+ ImGui.TextUnformatted(cleanedLabel);
+
ImGui.SetCursorPos(p);
// Dropdown
@@ -567,6 +590,8 @@ public static bool DrawEnumSelector(ref int index, string label)
var modified = ImGui.Combo($"##dropDown{enumType}{label}", ref index, valueNames, valueNames.Length, valueNames.Length);
return modified;
}
+
+ private const string _idSpecifier = "##";
}
public static class InputWithTypeAheadSearch
@@ -665,6 +690,6 @@ public static bool Draw(string id, ref string text, IOrderedEnumerable i
private static List _lastResults = new List();
private static int _selectedResultIndex = 0;
- private static bool _isSearchResultWindowOpen;
+ private static bool _isSearchResultWindowOpen;
}
}
\ No newline at end of file
diff --git a/T3/Gui/UiHelpers/UIControlledSetting.cs b/T3/Gui/UiHelpers/UIControlledSetting.cs
new file mode 100644
index 0000000000..c1e6acdefe
--- /dev/null
+++ b/T3/Gui/UiHelpers/UIControlledSetting.cs
@@ -0,0 +1,84 @@
+using ImGuiNET;
+using System;
+using T3.Gui.UiHelpers;
+
+namespace T3.Gui.Windows
+{
+ public class UIControlledSetting
+ {
+ ///
+ /// The generated unique label
+ ///
+ private string _uniqueLabel;
+ private string _hiddenUniqueLabel;
+
+ ///
+ /// The label provided in the constructor
+ ///
+ public string CleanLabel { get; private set; }
+ public bool DrawOnLeft { get; private set; }
+
+ public string Tooltip { get; private set; }
+ private string _additionalNotes;
+ private Func _guiFunc;
+ private Action _OnValueChanged;
+
+ // Cheaper than GUIDs
+ // In case we want to have the same variable be changeable with different UI controls
+ // or if multiple settings have the same label
+ static ushort _countForUniqueID = ushort.MaxValue;
+
+ ///
+ /// For the sake of simple use of the optional parameters and populating/maintaining many settings, the recommended way to call this constructor is:
+ ///
+ /// new UIControlledSetting
+ /// (
+ /// label: "My Setting",
+ /// tooltip: "The global scale of all rendered UI in the application",
+ /// guiFunc: (string guiLabel) => CustomComponents.FloatValueEdit(guiLabel, ref UserSettings.Config.UiScaleFactor, 0.01f, 0.5f, 3f),
+ /// OnValueChanged: () => //your action
+ /// );
+ ///
+ ///
+ /// The label to display next to the gui control
+ /// The - based function that draws the setting control and
+ /// returns true if the control was changed. The input to this function see is a unique ID based on the label provided
+ /// Tooltip displayed when hovering over the control
+ /// Additional notes displayed alongside the tooltip [Not currently in use, but will be once T3 tooltips are integrated]
+ /// An action performed when the value is changed
+ public UIControlledSetting(string label, Func guiFunc, string tooltip = null, string additionalNotes = null, bool drawOnLeft = false, Action OnValueChanged = null)
+ {
+ CleanLabel = label;
+ _hiddenUniqueLabel = $"##{label}{_countForUniqueID--}";
+ _uniqueLabel = $"{label}##{_countForUniqueID--}";
+
+ _guiFunc = guiFunc;
+ Tooltip = tooltip;
+ _additionalNotes = additionalNotes;
+ _OnValueChanged = OnValueChanged;
+ DrawOnLeft = drawOnLeft;
+ }
+
+ ///
+ /// Draws the GUI for this setting using the Func provided in its constructor
+ ///
+ /// True if changed, false if unchanged.
+ /// If an Action was provided in constructor, it will be executed when value is changed.
+ public bool DrawGUIControl(bool hideLabel)
+ {
+ var changed = DrawCommand(hideLabel);
+
+ if (changed)
+ {
+ _OnValueChanged?.Invoke();
+ }
+
+ return changed;
+ }
+
+ bool DrawCommand(bool hideLabel)
+ {
+ return _guiFunc.Invoke(hideLabel ? _hiddenUniqueLabel : _uniqueLabel);
+ }
+ }
+}
\ No newline at end of file
diff --git a/T3/Gui/UiHelpers/UserSettings.cs b/T3/Gui/UiHelpers/UserSettings.cs
index 13bbf413ff..5e2cc9bed0 100644
--- a/T3/Gui/UiHelpers/UserSettings.cs
+++ b/T3/Gui/UiHelpers/UserSettings.cs
@@ -79,6 +79,9 @@ public class ConfigData
public float SpaceMouseMoveSpeedFactor = 1f;
public float SpaceMouseDamping = 0.5f;
+ // Symbol Browser
+ public bool AlwaysShowDescriptionPanel = false;
+
[JsonConverter(typeof(StringEnumConverter))]
public TimeFormat.TimeDisplayModes TimeDisplayMode = TimeFormat.TimeDisplayModes.Bars;
diff --git a/T3/Gui/Windows/SettingsInSettingsWindow.cs b/T3/Gui/Windows/SettingsInSettingsWindow.cs
new file mode 100644
index 0000000000..927af25de2
--- /dev/null
+++ b/T3/Gui/Windows/SettingsInSettingsWindow.cs
@@ -0,0 +1,231 @@
+using ImGuiNET;
+using System;
+using System.Numerics;
+using T3.Gui.Graph;
+using T3.Gui.UiHelpers;
+
+namespace T3.Gui.Windows
+{
+ public partial class SettingsWindow
+ {
+ static readonly UIControlledSetting[] userInterfaceSettings = new UIControlledSetting[]
+ {
+ new UIControlledSetting
+ (
+ label: "Warn before Lib modifications",
+ tooltip: "This warning pops up when you attempt to enter an Operator that ships with the application.\n" +
+ "If unsure, this is best left checked.",
+ guiFunc: (string guiLabel) => ImGui.Checkbox(guiLabel, ref UserSettings.Config.WarnBeforeLibEdit),
+ drawOnLeft: true
+ ),
+
+ new UIControlledSetting
+ (
+ label: "Use arc connections",
+ tooltip: "Affects the shape of the connections between your Operators",
+ guiFunc: (string guiLabel) => ImGui.Checkbox(guiLabel, ref UserSettings.Config.UseArcConnections),
+ drawOnLeft: true
+ ),
+
+ new UIControlledSetting
+ (
+ label: "Use Jog Dial Control",
+ guiFunc: (string guiLabel) => ImGui.Checkbox(guiLabel, ref UserSettings.Config.UseJogDialControl),
+ drawOnLeft: true
+ ),
+
+ new UIControlledSetting
+ (
+ label: "Show Graph thumbnails",
+ guiFunc: (string guiLabel) => ImGui.Checkbox(guiLabel, ref UserSettings.Config.ShowThumbnails),
+ drawOnLeft: true
+ ),
+
+ new UIControlledSetting
+ (
+ label: "Drag snapped nodes",
+ guiFunc: (string guiLabel) => ImGui.Checkbox(guiLabel, ref UserSettings.Config.SmartGroupDragging),
+ drawOnLeft: true
+ ),
+
+ new UIControlledSetting
+ (
+ label: "Fullscreen Window Swap",
+ tooltip: "Swap main and second windows when fullscreen",
+ guiFunc: (string guiLabel) => ImGui.Checkbox(guiLabel, ref UserSettings.Config.SwapMainAnd2ndWindowsWhenFullscreen),
+ drawOnLeft: true
+ ),
+
+ new UIControlledSetting
+ (
+ label: "UI Scale",
+ tooltip: "The global scale of all rendered UI in the application",
+ guiFunc: (string guiLabel) => CustomComponents.DrawSingleValueEdit(guiLabel, ref UserSettings.Config.UiScaleFactor, 0.1f, 5f, true, 0.01f)
+ ),
+
+ new UIControlledSetting
+ (
+ label: "Scroll smoothing",
+ guiFunc: (string guiLabel) => CustomComponents.DrawSingleValueEdit(guiLabel, ref UserSettings.Config.ScrollSmoothing, 0f, 0.2f, true, 0.01f)
+ ),
+
+ new UIControlledSetting
+ (
+ label: "Snap strength",
+ guiFunc: (string guiLabel) => CustomComponents.DrawSingleValueEdit(guiLabel, ref UserSettings.Config.SnapStrength)
+ ),
+
+ new UIControlledSetting
+ (
+ label: "Click threshold",
+ guiFunc: (string guiLabel) => CustomComponents.DrawSingleValueEdit(guiLabel, ref UserSettings.Config.ClickThreshold)
+
+ ),
+
+ new UIControlledSetting
+ (
+ label: "Timeline Raster Density",
+ guiFunc: (string guiLabel) => CustomComponents.DrawSingleValueEdit(guiLabel, ref UserSettings.Config.TimeRasterDensity)
+ ),
+ };
+
+ static readonly UIControlledSetting[] spaceMouseSettings = new UIControlledSetting[]
+ {
+ new UIControlledSetting
+ (
+ label: "Smoothing",
+ guiFunc: (string guiLabel) => CustomComponents.DrawSingleValueEdit(guiLabel, ref UserSettings.Config.SpaceMouseDamping, 0.01f, 1f)
+ ),
+
+ new UIControlledSetting
+ (
+ label: "Move Speed",
+ guiFunc: (string guiLabel) => CustomComponents.DrawSingleValueEdit(guiLabel, ref UserSettings.Config.SpaceMouseMoveSpeedFactor, 0, 10f)
+ ),
+
+ new UIControlledSetting
+ (
+ label: "Rotation Speed",
+ guiFunc: (string guiLabel) => CustomComponents.DrawSingleValueEdit(guiLabel, ref UserSettings.Config.SpaceMouseRotationSpeedFactor, 0, 10f)
+ )
+ };
+
+ static readonly UIControlledSetting[] additionalSettings = new UIControlledSetting[]
+ {
+ new UIControlledSetting
+ (
+ label: "Gizmo size",
+ guiFunc: (string guiLabel) => CustomComponents.DrawSingleValueEdit(guiLabel, ref UserSettings.Config.GizmoSize)
+ ),
+
+ new UIControlledSetting
+ (
+ label: "Tooltip delay",
+ guiFunc: (string guiLabel) => CustomComponents.DrawSingleValueEdit(guiLabel, ref UserSettings.Config.TooltipDelay)
+ ),
+
+
+ // These settings were laid out in the old UI, kept here for someone else to ultimately choose to yeet or unyeet them
+
+ //new UIControlledSetting
+ //(
+ // label: "Show Title",
+ // guiFunc: (string guiLabel) => ImGui.Checkbox(guiLabel, ref UserSettings.Config.ShowTitleAndDescription)
+ //),
+
+ //new UIControlledSetting
+ //(
+ // label: "Show Timeline",
+ // guiFunc: (string guiLabel) => ImGui.Checkbox(guiLabel, ref UserSettings.Config.ShowTimeline)
+ //)
+ };
+
+ static readonly UIControlledSetting[] debugSettings = new UIControlledSetting[]
+ {
+ new UIControlledSetting
+ (
+ label: "VSync",
+ guiFunc: (string guiLabel) => ImGui.Checkbox(guiLabel, ref UseVSync),
+ drawOnLeft: true
+ ),
+
+ new UIControlledSetting
+ (
+ label: "Show Window Regions",
+ guiFunc: (string guiLabel) => ImGui.Checkbox(guiLabel, ref WindowRegionsVisible),
+ drawOnLeft: true
+ ),
+
+ new UIControlledSetting
+ (
+ label: "Show Item Regions",
+ guiFunc: (string guiLabel) => ImGui.Checkbox(guiLabel, ref ItemRegionsVisible),
+ drawOnLeft: true
+ ),
+ };
+
+ static readonly UIControlledSetting[] t3UiStyleSettings = new UIControlledSetting[]
+ {
+ new UIControlledSetting
+ (
+ label: "Label position",
+ guiFunc: (string guiLabel) => ImGui.DragFloat2(guiLabel, ref GraphNode.LabelPos)
+ ),
+
+ new UIControlledSetting
+ (
+ label: "Height Connection Zone",
+ guiFunc: (string guiLabel) => CustomComponents.DrawSingleValueEdit(guiLabel, ref GraphNode.UsableSlotThickness)
+ ),
+
+ new UIControlledSetting
+ (
+ label: "Slot Gaps",
+ guiFunc: (string guiLabel) => CustomComponents.DrawSingleValueEdit(guiLabel, ref GraphNode.SlotGaps, 0, 10f)
+ ),
+
+ new UIControlledSetting
+ (
+ label: "Input Slot Margin Y",
+ guiFunc: (string guiLabel) => CustomComponents.DrawSingleValueEdit(guiLabel, ref GraphNode.InputSlotMargin, 0, 10f)
+ ),
+
+ new UIControlledSetting
+ (
+ label: "Input Slot Thickness",
+ guiFunc: (string guiLabel) => CustomComponents.DrawSingleValueEdit(guiLabel, ref GraphNode.InputSlotThickness, 0, 10f)
+ ),
+
+ new UIControlledSetting
+ (
+ label: "Output Slot Margin",
+ guiFunc: (string guiLabel) => CustomComponents.DrawSingleValueEdit(guiLabel, ref GraphNode.OutputSlotMargin, 0, 10f)
+ ),
+
+ new UIControlledSetting
+ (
+ label: "Value Label Color",
+ guiFunc: (string guiLabel) => ImGui.ColorEdit4(guiLabel, ref T3Style.Colors.ValueLabelColor.Rgba)
+ ),
+
+ new UIControlledSetting
+ (
+ label: "Value Label Color Hover",
+ guiFunc: (string guiLabel) => ImGui.ColorEdit4(guiLabel, ref T3Style.Colors.ValueLabelColorHover.Rgba)
+ ),
+ };
+
+ static readonly UIControlledSetting[] symbolBrowserSettings = new UIControlledSetting[]
+ {
+ new UIControlledSetting
+ (
+ label: "Always Show Description",
+ tooltip: "Shifts the Description panel to the left of the Symbol Browser when\n" +
+ "it is too close to the right edge of the screen to display it.",
+ guiFunc: (string guiLabel) => ImGui.Checkbox(guiLabel, ref UserSettings.Config.AlwaysShowDescriptionPanel),
+ drawOnLeft: true
+ ),
+ };
+
+ }
+}
\ No newline at end of file
diff --git a/T3/Gui/Windows/SettingsWindow.cs b/T3/Gui/Windows/SettingsWindow.cs
index b61e205435..b080e6d7e9 100644
--- a/T3/Gui/Windows/SettingsWindow.cs
+++ b/T3/Gui/Windows/SettingsWindow.cs
@@ -1,13 +1,17 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
+using System.Threading.Channels;
+using System.Windows.Forms;
using ImGuiNET;
using T3.Gui.Commands;
using T3.Gui.Graph;
using T3.Gui.TypeColors;
using T3.Gui.UiHelpers;
+using System.Numerics;
+using t3.Gui;
namespace T3.Gui.Windows
{
- public class SettingsWindow : Window
+ public partial class SettingsWindow : Window
{
public SettingsWindow()
{
@@ -22,57 +26,38 @@ public SettingsWindow()
protected override void DrawContent()
{
var changed = false;
+ ImGui.NewLine();
if (ImGui.TreeNode("User Interface"))
{
- if (ImGui.DragFloat("UI Scale", ref UserSettings.Config.UiScaleFactor, 0.01f, 0.5f, 3f))
- {
- changed = true;
- }
- changed |= ImGui.Checkbox("Warn before Lib modifications", ref UserSettings.Config.WarnBeforeLibEdit);
- changed |= ImGui.Checkbox("Use arc connections", ref UserSettings.Config.UseArcConnections);
- changed |= ImGui.Checkbox("Use Jog Dial Control", ref UserSettings.Config.UseJogDialControl);
- changed |= ImGui.DragFloat("Scroll smoothing", ref UserSettings.Config.ScrollSmoothing);
- changed |= ImGui.Checkbox("Show Graph thumbnails", ref UserSettings.Config.ShowThumbnails);
- changed |= ImGui.Checkbox("Drag snapped nodes", ref UserSettings.Config.SmartGroupDragging);
- ImGui.Separator();
- changed |= ImGui.DragFloat("Snap strength", ref UserSettings.Config.SnapStrength);
- changed |= ImGui.DragFloat("Click threshold", ref UserSettings.Config.ClickThreshold);
- changed |= ImGui.DragFloat("Keyboard scroll speed", ref UserSettings.Config.KeyboardScrollAcceleration);
-
- changed |= ImGui.DragFloat("Timeline Raster Density", ref UserSettings.Config.TimeRasterDensity, 0.01f);
-
- changed |= ImGui.Checkbox("Swap Main & 2nd windows when fullscreen", ref UserSettings.Config.SwapMainAnd2ndWindowsWhenFullscreen);
-
-
+ changed |= SettingsUi.DrawSettingsTable("##uisettingstable", userInterfaceSettings);
ImGui.TreePop();
}
if (ImGui.TreeNode("Space Mouse"))
{
- changed |= ImGui.DragFloat("Smoothing", ref UserSettings.Config.SpaceMouseDamping, 0.01f, 0.01f, 1f);
- changed |= ImGui.DragFloat("Move Speed", ref UserSettings.Config.SpaceMouseMoveSpeedFactor, 0.01f, 0, 10f);
- changed |= ImGui.DragFloat("Rotation Speed", ref UserSettings.Config.SpaceMouseRotationSpeedFactor, 0.01f, 0, 10f);
+ changed |= SettingsUi.DrawSettingsTable("##settingspacemousetable", spaceMouseSettings);
ImGui.TreePop();
}
-
- if (ImGui.TreeNode("Additional settings"))
+ if (ImGui.TreeNode("Additional Settings"))
{
- //ImGui.Checkbox("Show Timeline", ref UserSettings.Config.ShowTimeline);
- //ImGui.Checkbox("Show Title", ref UserSettings.Config.ShowTitleAndDescription);
- changed |= ImGui.DragFloat("Gizmo size", ref UserSettings.Config.GizmoSize);
- changed |= ImGui.DragFloat("Tooltip delay", ref UserSettings.Config.TooltipDelay);
+ changed |= SettingsUi.DrawSettingsTable("##additionalsettingstable", additionalSettings);
+
+ if(ImGui.TreeNode("Symbol Browser Settings"))
+ {
+ changed |= SettingsUi.DrawSettingsTable("##symbolbrowsersettingstable", symbolBrowserSettings);
+ }
+
ImGui.TreePop();
}
+#if DEBUG
if (ImGui.TreeNode("Debug Options"))
{
- ImGui.Checkbox("VSync", ref UseVSync);
- ImGui.Checkbox("Show Window Regions", ref WindowRegionsVisible);
- ImGui.Checkbox("Show Item Regions", ref ItemRegionsVisible);
-
+ SettingsUi.DrawSettings(debugSettings);
if (ImGui.TreeNode("Undo Queue"))
{
+ ImGui.Indent();
ImGui.TextUnformatted("Undo");
ImGui.Indent();
foreach (var c in UndoRedoStack.UndoStack)
@@ -89,10 +74,11 @@ protected override void DrawContent()
ImGui.Selectable(c.Name);
}
+ ImGui.Unindent();
ImGui.Unindent();
ImGui.TreePop();
}
-
+
if (ImGui.TreeNode("Modified Symbols"))
{
foreach (var symbolUi in UiModel.GetModifiedSymbolUis())
@@ -108,22 +94,16 @@ protected override void DrawContent()
ImGui.TreePop();
}
-
+
+#endif
+#if DEBUG
if (ImGui.TreeNode("Look (not saved)"))
{
ColorVariations.DrawSettingsUi();
if (ImGui.TreeNode("T3 Ui Style"))
{
- ImGui.DragFloat("Height Connection Zone", ref GraphNode.UsableSlotThickness);
- ImGui.DragFloat2("Label position", ref GraphNode.LabelPos);
- ImGui.DragFloat("Slot Gaps", ref GraphNode.SlotGaps, 0.1f, 0, 10f);
- ImGui.DragFloat("Input Slot Margin Y", ref GraphNode.InputSlotMargin, 0.1f, 0, 10f);
- ImGui.DragFloat("Input Slot Thickness", ref GraphNode.InputSlotThickness, 0.1f, 0, 10f);
- ImGui.DragFloat("Output Slot Margin", ref GraphNode.OutputSlotMargin, 0.1f, 0, 10f);
-
- ImGui.ColorEdit4("ValueLabelColor", ref T3Style.Colors.ValueLabelColor.Rgba);
- ImGui.ColorEdit4("ValueLabelColorHover", ref T3Style.Colors.ValueLabelColorHover.Rgba);
+ SettingsUi.DrawSettingsTable("##t3uistylesettings", t3UiStyleSettings);
}
if (ImGui.TreeNode("T3 Graph colors"))
@@ -133,12 +113,15 @@ protected override void DrawContent()
}
ImGui.TreePop();
}
-
- if(changed)
+#endif
+
+ if (changed)
UserSettings.Save();
-
+
+#if DEBUG
ImGui.Separator();
T3Metrics.Draw();
+#endif
}
public override List GetInstances()