From ff64fdb503e7d27a91da8d41628f83c2ca3f0621 Mon Sep 17 00:00:00 2001 From: Nils Hausfeld Date: Thu, 26 Oct 2023 20:33:07 +0200 Subject: [PATCH 1/7] - Test environment and first tests --- Source/Editor/Surface/Archetypes/Math.cs | 14 +++++++++++--- Source/Editor/Surface/ContextMenu/VisjectCMItem.cs | 4 +--- Source/Editor/Utilities/QueryFilterHelper.cs | 9 ++++----- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/Source/Editor/Surface/Archetypes/Math.cs b/Source/Editor/Surface/Archetypes/Math.cs index fe2f1e044..7f4afa6a6 100644 --- a/Source/Editor/Surface/Archetypes/Math.cs +++ b/Source/Editor/Surface/Archetypes/Math.cs @@ -13,6 +13,11 @@ namespace FlaxEditor.Surface.Archetypes public static class Math { private static NodeArchetype Op1(ushort id, string title, string desc, ConnectionsHint hints = ConnectionsHint.Numeric, Type type = null) + { + return Op1(id, title, desc, null, hints, type); + } + + private static NodeArchetype Op1(ushort id, string title, string desc, string[] altTitles, ConnectionsHint hints = ConnectionsHint.Numeric, Type type = null) { return new NodeArchetype { @@ -20,6 +25,7 @@ namespace FlaxEditor.Surface.Archetypes Title = title, Description = desc, Flags = NodeFlags.AllGraphs, + AlternativeTitles = altTitles, Size = new Float2(110, 20), DefaultType = new ScriptType(type), ConnectionsHints = hints, @@ -92,6 +98,7 @@ namespace FlaxEditor.Surface.Archetypes { TypeID = 11, Title = "Length", + AlternativeTitles = new[] { "Magnitude", "Mag" }, Description = "Returns the length of A vector", Flags = NodeFlags.AllGraphs, Size = new Float2(110, 20), @@ -107,10 +114,10 @@ namespace FlaxEditor.Surface.Archetypes Op1(13, "Round", "Rounds A to the nearest integer"), Op1(14, "Saturate", "Clamps A to the range [0, 1]"), Op1(15, "Sine", "Returns sine of A"), - Op1(16, "Sqrt", "Returns square root of A"), + Op1(16, "Sqrt", "Returns square root of A", new [] { "Square Root", "Square", "Root" }), Op1(17, "Tangent", "Returns tangent of A"), Op2(18, "Cross", "Returns the cross product of A and B", ConnectionsHint.None, typeof(Float3)), - Op2(19, "Distance", "Returns a distance scalar between A and B", ConnectionsHint.Vector, null, typeof(float), false), + Op2(19, "Distance", "Returns a distance scalar between A and B", new [] { "Magnitude", "Mag", "Length" }, ConnectionsHint.Vector, null, typeof(float), false), Op2(20, "Dot", "Returns the dot product of A and B", ConnectionsHint.Vector, null, typeof(float), false), Op2(21, "Max", "Selects the greater of A and B"), Op2(22, "Min", "Selects the lesser of A and B"), @@ -185,7 +192,7 @@ namespace FlaxEditor.Surface.Archetypes } }, // - Op1(27, "Negate", "Returns opposite value"), + Op1(27, "Negate", "Returns opposite value", new [] { "Invert" }), Op1(28, "One Minus", "Returns 1 - value"), // new NodeArchetype @@ -225,6 +232,7 @@ namespace FlaxEditor.Surface.Archetypes { TypeID = 31, Title = "Mad", + AlternativeTitles = new [] { "Multiply", "Add", "*+" }, Description = "Performs value multiplication and addition at once", Flags = NodeFlags.AllGraphs, Size = new Float2(160, 60), diff --git a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs index 37da7d74d..2694d7e53 100644 --- a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs +++ b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs @@ -72,9 +72,7 @@ namespace FlaxEditor.Surface.ContextMenu public void UpdateScore(Box selectedBox) { SortScore = 0; - - if (!(_highlights?.Count > 0)) - return; + if (!Visible) return; diff --git a/Source/Editor/Utilities/QueryFilterHelper.cs b/Source/Editor/Utilities/QueryFilterHelper.cs index e9e5e9ccb..f2db81009 100644 --- a/Source/Editor/Utilities/QueryFilterHelper.cs +++ b/Source/Editor/Utilities/QueryFilterHelper.cs @@ -140,8 +140,7 @@ namespace FlaxEditor.Utilities // Check if start the matching sequence if (matchStartPos == -1) { - if (ranges == null) - ranges = new List(); + ranges ??= new List(); matchStartPos = textPos; } } @@ -152,7 +151,7 @@ namespace FlaxEditor.Utilities { var length = textPos - matchStartPos; if (length >= MinLength) - ranges.Add(new Range(matchStartPos, length)); + ranges!.Add(new Range(matchStartPos, length)); textPos = matchStartPos + length; matchStartPos = -1; } @@ -165,13 +164,13 @@ namespace FlaxEditor.Utilities { var length = endPos - matchStartPos; if (length >= MinLength) - ranges.Add(new Range(matchStartPos, length)); + ranges!.Add(new Range(matchStartPos, length)); textPos = matchStartPos + length; } } // Check if has any range - if (ranges != null && ranges.Count > 0) + if (ranges is { Count: > 0 }) { matches = ranges.ToArray(); return true; From 0acf352d40ae4eb767359adcba5d506a4adebecb Mon Sep 17 00:00:00 2001 From: Nils Hausfeld Date: Thu, 26 Oct 2023 21:13:06 +0200 Subject: [PATCH 2/7] - Alternative titles now use QueryFilterHelper Match function as well - Cleaned up some code and using early outs now - Added some comments --- .../Surface/ContextMenu/VisjectCMItem.cs | 136 ++++++++++-------- 1 file changed, 76 insertions(+), 60 deletions(-) diff --git a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs index 2694d7e53..41821c2aa 100644 --- a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs +++ b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs @@ -166,6 +166,7 @@ namespace FlaxEditor.Surface.ContextMenu /// True if item's group header got a filter match and item should stay visible. public void UpdateFilter(string filterText, Box selectedBox, bool groupHeaderMatches = false) { + // When dragging connection out of a box, validate if the box is compatible with this item's type if (selectedBox != null) { Visible = CanConnectTo(selectedBox); @@ -182,72 +183,87 @@ namespace FlaxEditor.Surface.ContextMenu // Clear filter _highlights?.Clear(); Visible = true; + return; } - else + + GetTextRectangle(out var textRect); + + // Check archetype title + if (QueryFilterHelper.Match(filterText, _archetype.Title, out var ranges)) { - GetTextRectangle(out var textRect); - if (QueryFilterHelper.Match(filterText, _archetype.Title, out var ranges)) + // Update highlights + if (_highlights == null) + _highlights = new List(ranges.Length); + else + _highlights.Clear(); + var style = Style.Current; + var font = style.FontSmall; + for (int i = 0; i < ranges.Length; i++) { - // Update highlights - if (_highlights == null) - _highlights = new List(ranges.Length); - else - _highlights.Clear(); - var style = Style.Current; - var font = style.FontSmall; - for (int i = 0; i < ranges.Length; i++) + var start = font.GetCharPosition(_archetype.Title, ranges[i].StartIndex); + var end = font.GetCharPosition(_archetype.Title, ranges[i].EndIndex); + _highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height)); + + if (ranges[i].StartIndex <= 0) { - var start = font.GetCharPosition(_archetype.Title, ranges[i].StartIndex); - var end = font.GetCharPosition(_archetype.Title, ranges[i].EndIndex); - _highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height)); - - if (ranges[i].StartIndex <= 0) - { - _isStartsWithMatch = true; - if (ranges[i].Length == _archetype.Title.Length) - _isFullMatch = true; - } + _isStartsWithMatch = true; + if (ranges[i].Length == _archetype.Title.Length) + _isFullMatch = true; } - Visible = true; - } - else if (_archetype.AlternativeTitles?.Any(altTitle => string.Equals(filterText, altTitle, StringComparison.CurrentCultureIgnoreCase)) == true) - { - // Update highlights - if (_highlights == null) - _highlights = new List(1); - else - _highlights.Clear(); - var style = Style.Current; - var font = style.FontSmall; - var start = font.GetCharPosition(_archetype.Title, 0); - var end = font.GetCharPosition(_archetype.Title, _archetype.Title.Length - 1); - _highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height)); - _isFullMatch = true; - Visible = true; - } - else if (NodeArchetype.TryParseText != null && NodeArchetype.TryParseText(filterText, out var data)) - { - // Update highlights - if (_highlights == null) - _highlights = new List(1); - else - _highlights.Clear(); - var style = Style.Current; - var font = style.FontSmall; - var start = font.GetCharPosition(_archetype.Title, 0); - var end = font.GetCharPosition(_archetype.Title, _archetype.Title.Length - 1); - _highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height)); - Visible = true; - - Data = data; - } - else if (!groupHeaderMatches) - { - // Hide - _highlights?.Clear(); - Visible = false; } + Visible = true; + return; } + + // Check archetype synonyms + if (_archetype.AlternativeTitles!= null && _archetype.AlternativeTitles.Any(altTitle => QueryFilterHelper.Match(filterText, altTitle, out ranges))) + { + // Update highlights + if (_highlights == null) + _highlights = new List(1); + else + _highlights.Clear(); + var style = Style.Current; + var font = style.FontSmall; + var start = font.GetCharPosition(_archetype.Title, 0); + var end = font.GetCharPosition(_archetype.Title, _archetype.Title.Length - 1); + _highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height)); + for (int i = 0; i < ranges.Length; i++) + { + if (ranges[i].StartIndex <= 0) + { + _isStartsWithMatch = true; + } + } + Visible = true; + return; + } + + // Check archetype data (if it exists) + if (NodeArchetype.TryParseText != null && NodeArchetype.TryParseText(filterText, out var data)) + { + // Update highlights + if (_highlights == null) + _highlights = new List(1); + else + _highlights.Clear(); + var style = Style.Current; + var font = style.FontSmall; + var start = font.GetCharPosition(_archetype.Title, 0); + var end = font.GetCharPosition(_archetype.Title, _archetype.Title.Length - 1); + _highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height)); + Visible = true; + + Data = data; + return; + } + + if (groupHeaderMatches) + return; + + // Hide + _highlights?.Clear(); + Visible = false; } /// @@ -280,7 +296,7 @@ namespace FlaxEditor.Surface.ContextMenu } // Draw name - Render2D.DrawText(style.FontSmall, _archetype.Title, textRect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center); + Render2D.DrawText(style.FontSmall, _archetype.Title + "(" + SortScore + ")", textRect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center); if (_archetype.SubTitle != null) { var titleLength = style.FontSmall.MeasureText(_archetype.Title).X; From 8cc7c5d3d905270308e58ce0da2bfa0db979a5ee Mon Sep 17 00:00:00 2001 From: Nils Hausfeld Date: Thu, 26 Oct 2023 21:47:32 +0200 Subject: [PATCH 3/7] - Highlights get cleared now when there is no match - Highlights now give points, since it means there is a substring match - Cleanup --- .../Surface/ContextMenu/VisjectCMItem.cs | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs index 41821c2aa..c6288f327 100644 --- a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs +++ b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs @@ -80,6 +80,8 @@ namespace FlaxEditor.Surface.ContextMenu SortScore += 1; if (Data != null) SortScore += 1; + if (_highlights is { Count: > 0 }) + SortScore += 1; if (_isStartsWithMatch) SortScore += 2; if (_isFullMatch) @@ -185,9 +187,9 @@ namespace FlaxEditor.Surface.ContextMenu Visible = true; return; } - + GetTextRectangle(out var textRect); - + // Check archetype title if (QueryFilterHelper.Match(filterText, _archetype.Title, out var ranges)) { @@ -214,7 +216,7 @@ namespace FlaxEditor.Surface.ContextMenu Visible = true; return; } - + // Check archetype synonyms if (_archetype.AlternativeTitles!= null && _archetype.AlternativeTitles.Any(altTitle => QueryFilterHelper.Match(filterText, altTitle, out ranges))) { @@ -238,7 +240,7 @@ namespace FlaxEditor.Surface.ContextMenu Visible = true; return; } - + // Check archetype data (if it exists) if (NodeArchetype.TryParseText != null && NodeArchetype.TryParseText(filterText, out var data)) { @@ -257,13 +259,12 @@ namespace FlaxEditor.Surface.ContextMenu Data = data; return; } - - if (groupHeaderMatches) - return; - - // Hide + _highlights?.Clear(); - Visible = false; + + // Hide + if (!groupHeaderMatches) + Visible = false; } /// @@ -296,7 +297,7 @@ namespace FlaxEditor.Surface.ContextMenu } // Draw name - Render2D.DrawText(style.FontSmall, _archetype.Title + "(" + SortScore + ")", textRect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center); + Render2D.DrawText(style.FontSmall, _archetype.Title, textRect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center); if (_archetype.SubTitle != null) { var titleLength = style.FontSmall.MeasureText(_archetype.Title).X; From e55cdd91d5c11052c9e54e3c4867230e4979b4a8 Mon Sep 17 00:00:00 2001 From: Nils Hausfeld Date: Thu, 26 Oct 2023 22:23:55 +0200 Subject: [PATCH 4/7] - Reverted match class from more alternative titles PR --- Source/Editor/Surface/Archetypes/Math.cs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/Source/Editor/Surface/Archetypes/Math.cs b/Source/Editor/Surface/Archetypes/Math.cs index 7f4afa6a6..fe2f1e044 100644 --- a/Source/Editor/Surface/Archetypes/Math.cs +++ b/Source/Editor/Surface/Archetypes/Math.cs @@ -13,11 +13,6 @@ namespace FlaxEditor.Surface.Archetypes public static class Math { private static NodeArchetype Op1(ushort id, string title, string desc, ConnectionsHint hints = ConnectionsHint.Numeric, Type type = null) - { - return Op1(id, title, desc, null, hints, type); - } - - private static NodeArchetype Op1(ushort id, string title, string desc, string[] altTitles, ConnectionsHint hints = ConnectionsHint.Numeric, Type type = null) { return new NodeArchetype { @@ -25,7 +20,6 @@ namespace FlaxEditor.Surface.Archetypes Title = title, Description = desc, Flags = NodeFlags.AllGraphs, - AlternativeTitles = altTitles, Size = new Float2(110, 20), DefaultType = new ScriptType(type), ConnectionsHints = hints, @@ -98,7 +92,6 @@ namespace FlaxEditor.Surface.Archetypes { TypeID = 11, Title = "Length", - AlternativeTitles = new[] { "Magnitude", "Mag" }, Description = "Returns the length of A vector", Flags = NodeFlags.AllGraphs, Size = new Float2(110, 20), @@ -114,10 +107,10 @@ namespace FlaxEditor.Surface.Archetypes Op1(13, "Round", "Rounds A to the nearest integer"), Op1(14, "Saturate", "Clamps A to the range [0, 1]"), Op1(15, "Sine", "Returns sine of A"), - Op1(16, "Sqrt", "Returns square root of A", new [] { "Square Root", "Square", "Root" }), + Op1(16, "Sqrt", "Returns square root of A"), Op1(17, "Tangent", "Returns tangent of A"), Op2(18, "Cross", "Returns the cross product of A and B", ConnectionsHint.None, typeof(Float3)), - Op2(19, "Distance", "Returns a distance scalar between A and B", new [] { "Magnitude", "Mag", "Length" }, ConnectionsHint.Vector, null, typeof(float), false), + Op2(19, "Distance", "Returns a distance scalar between A and B", ConnectionsHint.Vector, null, typeof(float), false), Op2(20, "Dot", "Returns the dot product of A and B", ConnectionsHint.Vector, null, typeof(float), false), Op2(21, "Max", "Selects the greater of A and B"), Op2(22, "Min", "Selects the lesser of A and B"), @@ -192,7 +185,7 @@ namespace FlaxEditor.Surface.Archetypes } }, // - Op1(27, "Negate", "Returns opposite value", new [] { "Invert" }), + Op1(27, "Negate", "Returns opposite value"), Op1(28, "One Minus", "Returns 1 - value"), // new NodeArchetype @@ -232,7 +225,6 @@ namespace FlaxEditor.Surface.Archetypes { TypeID = 31, Title = "Mad", - AlternativeTitles = new [] { "Multiply", "Add", "*+" }, Description = "Performs value multiplication and addition at once", Flags = NodeFlags.AllGraphs, Size = new Float2(160, 60), From 95735035f3989a6a4c40b67ffe8586fa44735ff6 Mon Sep 17 00:00:00 2001 From: Nils Hausfeld Date: Sat, 28 Oct 2023 16:51:56 +0200 Subject: [PATCH 5/7] - Tab key now also spawns node --- Source/Editor/Surface/ContextMenu/VisjectCM.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/Surface/ContextMenu/VisjectCM.cs b/Source/Editor/Surface/ContextMenu/VisjectCM.cs index 930741807..8e5e4defd 100644 --- a/Source/Editor/Surface/ContextMenu/VisjectCM.cs +++ b/Source/Editor/Surface/ContextMenu/VisjectCM.cs @@ -704,7 +704,7 @@ namespace FlaxEditor.Surface.ContextMenu Hide(); return true; } - else if (key == KeyboardKeys.Return) + else if (key == KeyboardKeys.Return || key == KeyboardKeys.Tab) { if (SelectedItem != null) OnClickItem(SelectedItem); From b88233a65d012903faff04bd776324d41cfc01c6 Mon Sep 17 00:00:00 2001 From: Nils Hausfeld Date: Sat, 28 Oct 2023 16:58:37 +0200 Subject: [PATCH 6/7] - Always select first valid item when updating filters --- Source/Editor/Surface/ContextMenu/VisjectCM.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/Editor/Surface/ContextMenu/VisjectCM.cs b/Source/Editor/Surface/ContextMenu/VisjectCM.cs index 8e5e4defd..ad4bf8372 100644 --- a/Source/Editor/Surface/ContextMenu/VisjectCM.cs +++ b/Source/Editor/Surface/ContextMenu/VisjectCM.cs @@ -492,8 +492,7 @@ namespace FlaxEditor.Surface.ContextMenu // If no item is selected (or it's not visible anymore), select the top one Profiler.BeginEvent("VisjectCM.Layout"); - if (SelectedItem == null || !SelectedItem.VisibleInHierarchy) - SelectedItem = _groups.Find(g => g.Visible)?.Children.Find(c => c.Visible && c is VisjectCMItem) as VisjectCMItem; + SelectedItem = _groups.Find(g => g.Visible)?.Children.Find(c => c.Visible && c is VisjectCMItem) as VisjectCMItem; PerformLayout(); if (SelectedItem != null) _panel1.ScrollViewTo(SelectedItem); From 0fea7aad9295755113f817c95e6556e208d49b88 Mon Sep 17 00:00:00 2001 From: Nils Hausfeld Date: Sat, 28 Oct 2023 17:11:03 +0200 Subject: [PATCH 7/7] - Minor cleanup --- Source/Editor/Surface/ContextMenu/VisjectCMItem.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs index c6288f327..d1bcec377 100644 --- a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs +++ b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs @@ -72,7 +72,7 @@ namespace FlaxEditor.Surface.ContextMenu public void UpdateScore(Box selectedBox) { SortScore = 0; - + if (!Visible) return; @@ -230,6 +230,7 @@ namespace FlaxEditor.Surface.ContextMenu var start = font.GetCharPosition(_archetype.Title, 0); var end = font.GetCharPosition(_archetype.Title, _archetype.Title.Length - 1); _highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height)); + for (int i = 0; i < ranges.Length; i++) { if (ranges[i].StartIndex <= 0) @@ -237,6 +238,7 @@ namespace FlaxEditor.Surface.ContextMenu _isStartsWithMatch = true; } } + Visible = true; return; } @@ -255,7 +257,6 @@ namespace FlaxEditor.Surface.ContextMenu var end = font.GetCharPosition(_archetype.Title, _archetype.Title.Length - 1); _highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height)); Visible = true; - Data = data; return; }