From ee5a7cf1effeaf83a663f57a92873022c643ea2c Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Mon, 16 Jan 2023 18:14:17 +0200 Subject: [PATCH 01/19] Update authors --- Source/Editor/Windows/AboutDialog.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Editor/Windows/AboutDialog.cs b/Source/Editor/Windows/AboutDialog.cs index 866c88128..6ef152e28 100644 --- a/Source/Editor/Windows/AboutDialog.cs +++ b/Source/Editor/Windows/AboutDialog.cs @@ -94,6 +94,7 @@ namespace FlaxEditor.Windows "Lukáš Jech", "Jean-Baptiste Perrier", "Chandler Cox", + "Ari Vuollet", }); authors.Sort(); var authorsLabel = new Label(4, topParentControl.Bottom + 20, Width - 8, 70) From e2e7facad0edc9399816a2d6dedcc8f6d6e62798 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Wed, 18 Jan 2023 11:53:30 +0100 Subject: [PATCH 02/19] Fix using dependency module from nested referenced build in C# --- .../Flax.Build/Build/DotNet/Builder.DotNet.cs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/Source/Tools/Flax.Build/Build/DotNet/Builder.DotNet.cs b/Source/Tools/Flax.Build/Build/DotNet/Builder.DotNet.cs index 091c26741..8ae2b831a 100644 --- a/Source/Tools/Flax.Build/Build/DotNet/Builder.DotNet.cs +++ b/Source/Tools/Flax.Build/Build/DotNet/Builder.DotNet.cs @@ -323,17 +323,11 @@ namespace Flax.Build // Reference module output binary fileReferences.Add(Path.Combine(outputPath, dependencyModule.BinaryModuleName + ".CSharp.dll")); } - foreach (var e in buildData.ReferenceBuilds) + var referencedBuild = buildData.FinReferenceBuildModule(dependencyModule.BinaryModuleName); + if (referencedBuild != null && !string.IsNullOrEmpty(referencedBuild.ManagedPath)) { - foreach (var q in e.Value.BuildInfo.BinaryModules) - { - if (q.Name == dependencyModule.BinaryModuleName && !string.IsNullOrEmpty(q.ManagedPath)) - { - // Reference binary module build build for referenced target - fileReferences.Add(q.ManagedPath); - break; - } - } + // Reference binary module build build for referenced target + fileReferences.Add(referencedBuild.ManagedPath); } } } From 15fd2e884e6c41df94f3978cf49e6bc7c99536ca Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Wed, 18 Jan 2023 13:04:10 +0100 Subject: [PATCH 03/19] Add printing exact source code location on networking bindings generation for C# types --- .../Build/Plugins/NetworkingPlugin.cs | 25 +++++---- .../Tools/Flax.Build/Utilities/MonoCecil.cs | 52 +++++++++++++++++++ 2 files changed, 67 insertions(+), 10 deletions(-) diff --git a/Source/Tools/Flax.Build/Build/Plugins/NetworkingPlugin.cs b/Source/Tools/Flax.Build/Build/Plugins/NetworkingPlugin.cs index 47be906d9..41ed23eab 100644 --- a/Source/Tools/Flax.Build/Build/Plugins/NetworkingPlugin.cs +++ b/Source/Tools/Flax.Build/Build/Plugins/NetworkingPlugin.cs @@ -805,13 +805,13 @@ namespace Flax.Build.Plugins { if (property.GetMethod == null) { - Log.Error($"Missing getter method for property '{property.Name}' of type {valueType.FullName} in {type.FullName} for automatic replication."); + MonoCecil.CompilationError($"Missing getter method for property '{property.Name}' of type {valueType.FullName} in {type.FullName} for automatic replication.", property); failed = true; return; } if (property.SetMethod == null) { - Log.Error($"Missing setter method for property '{property.Name}' of type {valueType.FullName} in {type.FullName} for automatic replication."); + MonoCecil.CompilationError($"Missing setter method for property '{property.Name}' of type {valueType.FullName} in {type.FullName} for automatic replication.", property); failed = true; return; } @@ -1090,7 +1090,12 @@ namespace Flax.Build.Plugins else { // Unknown type - Log.Error($"Not supported type '{valueType.FullName}' on {(field?.Name ?? property.Name)} in {type.FullName} for automatic replication."); + if (property != null) + MonoCecil.CompilationError($"Not supported type '{valueType.FullName}' on {property.Name} in {type.FullName} for automatic replication.", property); + else if (field != null) + MonoCecil.CompilationError($"Not supported type '{valueType.FullName}' on {field.Name} in {type.FullName} for automatic replication.", field.Resolve()); + else + MonoCecil.CompilationError($"Not supported type '{valueType.FullName}' for automatic replication."); failed = true; } } @@ -1212,13 +1217,13 @@ namespace Flax.Build.Plugins // Validate RPC usage if (method.IsAbstract) { - Log.Error($"Not supported abstract RPC method '{method.FullName}'."); + MonoCecil.CompilationError($"Not supported abstract RPC method '{method.FullName}'.", method); failed = true; return; } if (method.IsVirtual) { - Log.Error($"Not supported virtual RPC method '{method.FullName}'."); + MonoCecil.CompilationError($"Not supported virtual RPC method '{method.FullName}'.", method); failed = true; return; } @@ -1226,13 +1231,13 @@ namespace Flax.Build.Plugins var voidType = module.TypeSystem.Void; if (method.ReturnType != voidType) { - Log.Error($"Not supported non-void RPC method '{method.FullName}'."); + MonoCecil.CompilationError($"Not supported non-void RPC method '{method.FullName}'.", method); failed = true; return; } if (method.IsStatic) { - Log.Error($"Not supported static RPC method '{method.FullName}'."); + MonoCecil.CompilationError($"Not supported static RPC method '{method.FullName}'.", method); failed = true; return; } @@ -1243,13 +1248,13 @@ namespace Flax.Build.Plugins methodRPC.IsClient = (bool)attribute.GetFieldValue("Client", false); if (methodRPC.IsServer && methodRPC.IsClient) { - Log.Error($"Network RPC {method.Name} in {type.FullName} cannot be both Server and Client."); + MonoCecil.CompilationError($"Network RPC {method.Name} in {type.FullName} cannot be both Server and Client.", method); failed = true; return; } if (!methodRPC.IsServer && !methodRPC.IsClient) { - Log.Error($"Network RPC {method.Name} in {type.FullName} needs to have Server or Client specifier."); + MonoCecil.CompilationError($"Network RPC {method.Name} in {type.FullName} needs to have Server or Client specifier.", method); failed = true; return; } @@ -1289,7 +1294,7 @@ namespace Flax.Build.Plugins var parameter = method.Parameters[i]; if (parameter.IsOut) { - Log.Error($"Network RPC {method.Name} in {type.FullName} parameter {parameter.Name} cannot be 'out'."); + MonoCecil.CompilationError($"Network RPC {method.Name} in {type.FullName} parameter {parameter.Name} cannot be 'out'.", method); failed = true; return; } diff --git a/Source/Tools/Flax.Build/Utilities/MonoCecil.cs b/Source/Tools/Flax.Build/Utilities/MonoCecil.cs index 444cbf6ec..43c1de4ba 100644 --- a/Source/Tools/Flax.Build/Utilities/MonoCecil.cs +++ b/Source/Tools/Flax.Build/Utilities/MonoCecil.cs @@ -11,6 +11,58 @@ namespace Flax.Build /// internal static class MonoCecil { + public static void CompilationError(string message) + { + Log.Error(message); + } + + public static void CompilationError(string message, MethodDefinition method) + { + if (method != null && method.DebugInformation.HasSequencePoints) + { + var sp = method.DebugInformation.SequencePoints[0]; + message = $"{sp.Document.Url}({sp.StartLine},{sp.StartColumn},{sp.EndLine},{sp.EndColumn}): error: {message}"; + } + Log.Error(message); + } + + public static void CompilationError(string message, PropertyDefinition property) + { + if (property != null) + { + if (property.GetMethod != null) + { + CompilationError(message, property.GetMethod); + return; + } + else if (property.SetMethod != null) + { + CompilationError(message, property.SetMethod); + return; + } + } + Log.Error(message); + } + + public static void CompilationError(string message, FieldDefinition field) + { + if (field != null && field.DeclaringType != null) + { + // Just include potential filename + var methods = field.DeclaringType.Methods; + if (methods != null && methods.Count != 0) + { + var method = methods[0]; + if (method != null && method.DebugInformation.HasSequencePoints) + { + var sp = method.DebugInformation.SequencePoints[0]; + message = $"{sp.Document.Url}({0},{0},{0},{0}): error: {message}"; + } + } + } + Log.Error(message); + } + public static bool HasAttribute(this ICustomAttributeProvider type, string fullName) { return type.CustomAttributes.Any(x => x.AttributeType.FullName == fullName); From df997c8e3c62d2142582197ac1867330f38fcb8a Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Wed, 18 Jan 2023 13:04:38 +0100 Subject: [PATCH 04/19] Fix invalid RPC properties gather when using attribute constructor arguments --- Source/Tools/Flax.Build/Build/Plugins/NetworkingPlugin.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Source/Tools/Flax.Build/Build/Plugins/NetworkingPlugin.cs b/Source/Tools/Flax.Build/Build/Plugins/NetworkingPlugin.cs index 41ed23eab..63c9bacfa 100644 --- a/Source/Tools/Flax.Build/Build/Plugins/NetworkingPlugin.cs +++ b/Source/Tools/Flax.Build/Build/Plugins/NetworkingPlugin.cs @@ -1246,6 +1246,13 @@ namespace Flax.Build.Plugins methodRPC.Method = method; methodRPC.IsServer = (bool)attribute.GetFieldValue("Server", false); methodRPC.IsClient = (bool)attribute.GetFieldValue("Client", false); + methodRPC.Channel = (int)attribute.GetFieldValue("Channel", 4); // int as NetworkChannelType (default is ReliableOrdered=4) + if (attribute.HasConstructorArguments && attribute.ConstructorArguments.Count >= 3) + { + methodRPC.IsServer = (bool)attribute.ConstructorArguments[0].Value; + methodRPC.IsClient = (bool)attribute.ConstructorArguments[1].Value; + methodRPC.Channel = (int)attribute.ConstructorArguments[2].Value; + } if (methodRPC.IsServer && methodRPC.IsClient) { MonoCecil.CompilationError($"Network RPC {method.Name} in {type.FullName} cannot be both Server and Client.", method); @@ -1258,7 +1265,6 @@ namespace Flax.Build.Plugins failed = true; return; } - methodRPC.Channel = (int)attribute.GetFieldValue("Channel", 4); // int as NetworkChannelType (default is ReliableOrdered=4) module.GetType("System.IntPtr", out var intPtrType); module.GetType("FlaxEngine.Object", out var scriptingObjectType); var fromUnmanagedPtr = scriptingObjectType.Resolve().GetMethod("FromUnmanagedPtr"); From ec2bdb74377960a3852b405a89b1fc28158c2d4a Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Wed, 18 Jan 2023 13:20:24 +0100 Subject: [PATCH 05/19] Fix crash when copying empty span of data into `DataContainer` --- Source/Engine/Core/Types/DataContainer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Engine/Core/Types/DataContainer.h b/Source/Engine/Core/Types/DataContainer.h index 5c29a5f3c..be63dd034 100644 --- a/Source/Engine/Core/Types/DataContainer.h +++ b/Source/Engine/Core/Types/DataContainer.h @@ -231,7 +231,7 @@ public: /// Data to copy. void Copy(const DataContainer& data) { - if (data.IsValid()) + if (data.Length() != 0) Copy(data.Get(), data.Length()); else Release(); @@ -243,7 +243,7 @@ public: /// Data to copy. void Copy(const Span& data) { - if (data.IsValid()) + if (data.Length() != 0) Copy(data.Get(), data.Length()); else Release(); From 04727cf2bc58bb8c4d5d6ec85d26b800ef1c9c30 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Wed, 18 Jan 2023 13:38:18 +0100 Subject: [PATCH 06/19] Add error log if the RPC is invoked on non-networked object --- Source/Engine/Networking/NetworkReplicator.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Source/Engine/Networking/NetworkReplicator.cpp b/Source/Engine/Networking/NetworkReplicator.cpp index 4c99defda..15116777b 100644 --- a/Source/Engine/Networking/NetworkReplicator.cpp +++ b/Source/Engine/Networking/NetworkReplicator.cpp @@ -897,6 +897,13 @@ void NetworkReplicator::EndInvokeRPC(ScriptingObject* obj, const ScriptingTypeHa rpc.Info = *info; const Span argsData(argsStream->GetBuffer(), argsStream->GetPosition()); rpc.ArgsData.Copy(argsData); +#if USE_EDITOR || !BUILD_RELEASE + auto it = Objects.Find(obj->GetID()); + if (it == Objects.End()) + { + LOG(Error, "Cannot invoke RPC method '{0}.{1}' on object '{2}' that is not registered in networking (use 'NetworkReplicator.AddObject').", type.ToString(), String(name), obj->GetID()); + } +#endif ObjectsLock.Unlock(); } From 689a042e889f5bd4c91813fe290832e080c4568c Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Wed, 18 Jan 2023 13:39:51 +0100 Subject: [PATCH 07/19] Fix sending client RPC from host that is both server and client --- Source/Engine/Networking/NetworkReplicator.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Engine/Networking/NetworkReplicator.cpp b/Source/Engine/Networking/NetworkReplicator.cpp index 15116777b..0ac792239 100644 --- a/Source/Engine/Networking/NetworkReplicator.cpp +++ b/Source/Engine/Networking/NetworkReplicator.cpp @@ -987,6 +987,7 @@ void NetworkInternal::NetworkReplicatorUpdate() CachedWriteStream = New(); const bool isClient = NetworkManager::IsClient(); const bool isServer = NetworkManager::IsServer(); + const bool isHost = NetworkManager::IsHost(); NetworkStream* stream = CachedWriteStream; NetworkPeer* peer = NetworkManager::Peer; @@ -1286,7 +1287,7 @@ void NetworkInternal::NetworkReplicatorUpdate() // Client -> Server peer->EndSendMessage(channel, msg); } - else if (e.Info.Client && isServer) + else if (e.Info.Client && (isServer || isHost)) { // Server -> Client(s) BuildCachedTargets(item); From eaa63e679ead5c5c49257444c1098b34b4dc35da Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 18 Jan 2023 15:36:42 +0100 Subject: [PATCH 08/19] Fix selected UI control outline when using custom Game viewport aspect #897 --- Source/Editor/Windows/GameWindow.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Source/Editor/Windows/GameWindow.cs b/Source/Editor/Windows/GameWindow.cs index f17deb4bd..aaed484a1 100644 --- a/Source/Editor/Windows/GameWindow.cs +++ b/Source/Editor/Windows/GameWindow.cs @@ -816,15 +816,23 @@ namespace FlaxEditor.Windows } // Selected UI controls outline + bool drawAnySelectedControl = false; for (var i = 0; i < Editor.Instance.SceneEditing.Selection.Count; i++) { if (Editor.Instance.SceneEditing.Selection[i].EditableObject is UIControl controlActor && controlActor && controlActor.Control != null) { + if (!drawAnySelectedControl) + { + drawAnySelectedControl = true; + Render2D.PushTransform(ref _viewport._cachedTransform); + } var control = controlActor.Control; var bounds = Rectangle.FromPoints(control.PointToParent(_viewport, Float2.Zero), control.PointToParent(_viewport, control.Size)); Render2D.DrawRectangle(bounds, Editor.Instance.Options.Options.Visual.SelectionOutlineColor0, Editor.Instance.Options.Options.Visual.UISelectionOutlineSize); } } + if (drawAnySelectedControl) + Render2D.PopTransform(); // Play mode hints and overlay if (Editor.StateMachine.IsPlayMode) From c1c1f5d60e3556e7224146deda07650c9e66d6e0 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Thu, 19 Jan 2023 14:47:20 +0100 Subject: [PATCH 09/19] Fix sending client RPC to all clients (including the owner) --- Source/Engine/Networking/NetworkReplicator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/Networking/NetworkReplicator.cpp b/Source/Engine/Networking/NetworkReplicator.cpp index 0ac792239..c914e7ff1 100644 --- a/Source/Engine/Networking/NetworkReplicator.cpp +++ b/Source/Engine/Networking/NetworkReplicator.cpp @@ -1290,7 +1290,7 @@ void NetworkInternal::NetworkReplicatorUpdate() else if (e.Info.Client && (isServer || isHost)) { // Server -> Client(s) - BuildCachedTargets(item); + BuildCachedTargets(NetworkManager::Clients, item.TargetClientIds, NetworkManager::LocalClientId); peer->EndSendMessage(channel, msg, CachedTargets); } } From fb12e63bb13540c424e1c95a7ddc04189d6e7a1b Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Thu, 19 Jan 2023 15:57:51 -0600 Subject: [PATCH 10/19] Fixed editor not saving added tags #885 --- Source/Editor/CustomEditors/Editors/TagEditor.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Editor/CustomEditors/Editors/TagEditor.cs b/Source/Editor/CustomEditors/Editors/TagEditor.cs index b95f9e722..5b65ffad3 100644 --- a/Source/Editor/CustomEditors/Editors/TagEditor.cs +++ b/Source/Editor/CustomEditors/Editors/TagEditor.cs @@ -260,6 +260,8 @@ namespace FlaxEditor.CustomEditors.Editors // Reload editor window to reflect new tag assetWindow?.RefreshAsset(); + assetWindow?.MarkAsEdited(); + assetWindow?.Save(); } }; dialog.Closed += popup => From f110926288778ae9016208085db355dc3bf7851d Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Thu, 19 Jan 2023 16:10:17 -0600 Subject: [PATCH 11/19] Moved into function in Asset Window. --- Source/Editor/CustomEditors/Editors/TagEditor.cs | 2 -- Source/Editor/Windows/Assets/AssetEditorWindow.cs | 9 ++++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Source/Editor/CustomEditors/Editors/TagEditor.cs b/Source/Editor/CustomEditors/Editors/TagEditor.cs index 5b65ffad3..b95f9e722 100644 --- a/Source/Editor/CustomEditors/Editors/TagEditor.cs +++ b/Source/Editor/CustomEditors/Editors/TagEditor.cs @@ -260,8 +260,6 @@ namespace FlaxEditor.CustomEditors.Editors // Reload editor window to reflect new tag assetWindow?.RefreshAsset(); - assetWindow?.MarkAsEdited(); - assetWindow?.Save(); } }; dialog.Closed += popup => diff --git a/Source/Editor/Windows/Assets/AssetEditorWindow.cs b/Source/Editor/Windows/Assets/AssetEditorWindow.cs index 05a9151c2..9d06359ad 100644 --- a/Source/Editor/Windows/Assets/AssetEditorWindow.cs +++ b/Source/Editor/Windows/Assets/AssetEditorWindow.cs @@ -313,7 +313,14 @@ namespace FlaxEditor.Windows.Assets /// public void RefreshAsset() { - _isWaitingForLoaded = true; + if (_asset == null) + return; + if (!_asset.IsLoaded) + return; + + OnAssetLoaded(); + MarkAsEdited(); + Save(); } /// From 85df496657fde22462a32f36a9267cabc755e338 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 20 Jan 2023 00:51:46 -0600 Subject: [PATCH 12/19] Better tag picker --- .../Editor/CustomEditors/Editors/TagEditor.cs | 366 +++++++++++++----- 1 file changed, 271 insertions(+), 95 deletions(-) diff --git a/Source/Editor/CustomEditors/Editors/TagEditor.cs b/Source/Editor/CustomEditors/Editors/TagEditor.cs index b95f9e722..3f425d845 100644 --- a/Source/Editor/CustomEditors/Editors/TagEditor.cs +++ b/Source/Editor/CustomEditors/Editors/TagEditor.cs @@ -156,88 +156,119 @@ namespace FlaxEditor.CustomEditors.Editors pickerData.IsEditing = false; } - - private static void OnAddButtonClicked(Tree tree, TreeNode parentNode, PickerData pickerData) + private static void OnAddTagButtonClicked(string input, Tree tree, TextBox textBox, DropPanel dropPanel, PickerData pickerData) { - // Create new node - var nodeIndent = 16.0f; - var indentation = 0; - var parentTag = string.Empty; - if (parentNode.CustomArrowRect.HasValue) - { - indentation = (int)((parentNode.CustomArrowRect.Value.Location.X - 18) / nodeIndent) + 1; - var parentTagValue = (Tag)parentNode.Tag; - parentTag = parentTagValue.ToString(); - } - var node = new TreeNodeWithAddons - { - ChildrenIndent = nodeIndent, - CullChildren = false, - ClipChildren = false, - TextMargin = new Margin(22.0f, 2.0f, 2.0f, 2.0f), - CustomArrowRect = new Rectangle(18 + indentation * nodeIndent, 2, 12, 12), - BackgroundColorSelected = Color.Transparent, - BackgroundColorHighlighted = parentNode.BackgroundColorHighlighted, - }; - var checkbox = new CheckBox(32.0f + indentation * nodeIndent, 0) - { - Height = 16.0f, - IsScrollable = false, - Parent = node, - }; - node.Addons.Add(checkbox); - checkbox.StateChanged += c => OnCheckboxEdited(node, c, pickerData); - var addButton = new Button(tree.Width - 16, 0, 14, 14) - { - Text = "+", - TooltipText = "Add subtag within this tag namespace", - IsScrollable = false, - BorderColor = Color.Transparent, - BackgroundColor = Color.Transparent, - Parent = node, - AnchorPreset = AnchorPresets.TopRight, - }; - node.Addons.Add(addButton); - addButton.ButtonClicked += button => OnAddButtonClicked(tree, node, pickerData); + if (string.IsNullOrEmpty(input)) + return; + + // Ensure that name is unique + if (Tags.List.Contains(input)) + return; - // Link - node.Parent = parentNode; - node.IndexInParent = 0; - parentNode.Expand(true); - ((Panel)tree.Parent.Parent).ScrollViewTo(node); + var subInputs = input.Split('.'); + string tagString = string.Empty; + string lastTagString = string.Empty; - // Start renaming the tag - var prefix = parentTag.Length != 0 ? parentTag + '.' : string.Empty; - var renameArea = node.HeaderRect; - if (renameArea.Location.X < nodeIndent) + TreeNode parentNode = tree.GetChild(); // Start at root + int parentCount = 0; + for (int i = 0; i < subInputs.Length; i++) { - // Fix root node's child renaming - renameArea.Location.X += nodeIndent; - renameArea.Size.X -= nodeIndent; - } - var dialog = RenamePopup.Show(node, renameArea, prefix, false); - var cursor = dialog.InputField.TextLength; - dialog.InputField.SelectionRange = new TextRange(cursor, cursor); - dialog.Validate = (popup, value) => - { - // Ensure that name is unique - if (Tags.List.Contains(value)) - return false; - - // Ensure user entered direct subtag of the parent node - if (value.StartsWith(popup.InitialValue)) + if (string.IsNullOrEmpty(subInputs[i])) { - var name = value.Substring(popup.InitialValue.Length); - if (name.Length > 0 && name.IndexOf('.') == -1) - return true; + lastTagString = tagString; + tagString = string.Empty; + continue; } - return false; - }; - dialog.Renamed += popup => - { + + // Check all entered subtags and create any that dont exist + for (int j = 0; j <= i; j++) + { + if (j == 0) + { + tagString += subInputs[j]; + } + else + { + tagString += "." + subInputs[j]; + } + } + + if (string.IsNullOrEmpty(tagString)) + { + tagString = string.Empty; + continue; + } + + if (Tags.List.Contains(tagString)) + { + // Find next parent node + foreach (var child in parentNode.Children) + { + if (!(child is TreeNode childNode)) + continue; + + var tagValue = (Tag)childNode.Tag; + if (!string.Equals(tagValue.ToString(), tagString)) + continue; + + parentNode = childNode; + parentCount += 1; + } + lastTagString = tagString; + tagString = string.Empty; + continue; + } + + // Create new node + var nodeIndent = 16.0f; + var indentation = 0; + var parentTag = lastTagString; + if (parentNode.CustomArrowRect.HasValue) + { + indentation = (int)((parentNode.CustomArrowRect.Value.Location.X - 18) / nodeIndent) + 1; + var parentTagValue = (Tag)parentNode.Tag; + parentTag = parentTagValue.ToString(); + } + var node = new TreeNodeWithAddons + { + ChildrenIndent = nodeIndent, + CullChildren = false, + ClipChildren = false, + TextMargin = new Margin(22.0f, 2.0f, 2.0f, 2.0f), + CustomArrowRect = new Rectangle(18 + indentation * nodeIndent, 2, 12, 12), + BackgroundColorSelected = Color.Transparent, + BackgroundColorHighlighted = parentNode.BackgroundColorHighlighted, + }; + var checkbox = new CheckBox(32.0f + indentation * nodeIndent, 0) + { + Height = 16.0f, + IsScrollable = false, + Parent = node, + }; + node.Addons.Add(checkbox); + checkbox.StateChanged += c => OnCheckboxEdited(node, c, pickerData); + var addButton = new Button(tree.Width - 16, 0, 14, 14) + { + Text = "+", + TooltipText = "Add subtag within this tag namespace", + IsScrollable = false, + BorderColor = Color.Transparent, + BackgroundColor = Color.Transparent, + Parent = node, + AnchorPreset = AnchorPresets.TopRight, + }; + node.Addons.Add(addButton); + addButton.ButtonClicked += button => OnAddSubTagButtonClicked(((Tag)node.Tag).ToString(), textBox, dropPanel); + + // Link + node.Parent = parentNode; + node.IndexInParent = 0; + parentNode.Expand(true); + ((Panel)tree.Parent.Parent).ScrollViewTo(node); + // Get tag name - var tagName = popup.Text; - var tagShortName = tagName.Substring(popup.InitialValue.Length); + var tagName = tagString; + var tagShortName = tagName.Substring(parentCount == 0 ? lastTagString.Length : lastTagString.Length + 1); if (tagShortName.Length == 0) return; @@ -261,19 +292,129 @@ namespace FlaxEditor.CustomEditors.Editors // Reload editor window to reflect new tag assetWindow?.RefreshAsset(); } - }; - dialog.Closed += popup => + + textBox.Text = string.Empty; + lastTagString = tagString; + tagString = string.Empty; + parentNode = tree.GetChild(); // return to root + parentCount = 0; + } + } + + private static void OnAddSubTagButtonClicked(string parentTag, TextBox textBox, DropPanel dropPanel) + { + if (textBox == null || dropPanel == null || string.IsNullOrEmpty(parentTag)) { - // Remove temporary node if renaming was canceled - if (popup.InitialValue == popup.Text || popup.Text.Length == 0) - node.Dispose(); - }; + return; + } + dropPanel.Open(); + textBox.Text = string.Empty; + textBox.Text += parentTag + "."; + textBox.Focus(); + textBox.SelectionRange = new TextRange(textBox.Text.Length, textBox.Text.Length); } internal static ContextMenuBase CreatePicker(Tag value, Tag[] values, PickerData pickerData) { // Initialize search popup - var menu = Utilities.Utils.CreateSearchPopup(out var searchBox, out var tree, 20.0f); + var menu = Utilities.Utils.CreateSearchPopup(out var searchBox, out var tree, 40.0f); + + // Add tag drop panel + var addTagDropPanel = new DropPanel + { + HeaderText = "Add Tag", + EnableDropDownIcon = true, + ArrowImageOpened = new SpriteBrush(FlaxEngine.GUI.Style.Current.ArrowDown), + ArrowImageClosed = new SpriteBrush(FlaxEngine.GUI.Style.Current.ArrowRight), + Parent = menu, + HeaderTextMargin = new Margin(2.0f), + AnchorPreset = AnchorPresets.TopLeft, + Bounds = new Rectangle(2, 2, menu.Width - 4, 30), + IsClosed = true, + ItemsMargin = new Margin(2.0f), + CloseAnimationTime = 0, + }; + var tagNamePanel = new HorizontalPanel + { + Parent = addTagDropPanel, + AutoSize = false, + Bounds = new Rectangle(0, 0, addTagDropPanel.Width, 20.0f), + }; + var nameLabel = new Label + { + Size = new Float2(addTagDropPanel.Width / 4, 0), + Parent = tagNamePanel, + Text = "Tag Name:", + }; + var nameTextBox = new TextBox + { + IsMultiline = false, + WatermarkText = "X.Y.Z", + Size = new Float2(addTagDropPanel.Width * 0.7f, 0), + Parent = tagNamePanel, + }; + + bool uniqueText = true; + nameTextBox.TextChanged += () => + { + // Ensure that name is unique + if (Tags.List.Contains(nameTextBox.Text)) + uniqueText = false; + else + uniqueText = true; + + var currentStyle = FlaxEngine.GUI.Style.Current; + if (uniqueText) + { + nameTextBox.BorderColor = Color.Transparent; + nameTextBox.BorderSelectedColor = currentStyle.BackgroundSelected; + } + else + { + var color = new Color(1.0f, 0.0f, 0.02745f, 1.0f); + nameTextBox.BorderColor = Color.Lerp(color, currentStyle.TextBoxBackground, 0.6f); + nameTextBox.BorderSelectedColor = color; + } + }; + + nameTextBox.EditEnd += () => + { + if (!uniqueText) + return; + + if (!nameTextBox.IsFocused) + { + nameTextBox.BorderColor = Color.Transparent; + nameTextBox.BorderSelectedColor = FlaxEngine.GUI.Style.Current.BackgroundSelected; + return; + } + + OnAddTagButtonClicked(nameTextBox.Text, tree, nameTextBox, addTagDropPanel, pickerData); + }; + + var addButtonPanel = new HorizontalPanel + { + Parent = addTagDropPanel, + AutoSize = false, + Bounds = new Rectangle(0, 0, addTagDropPanel.Width, 30.0f), + }; + var buttonAddTag = new Button + { + Parent = addButtonPanel, + Size = new Float2(100, 20), + Text = "Add Tag", + AnchorPreset = AnchorPresets.MiddleCenter, + }; + buttonAddTag.Clicked += () => + { + if (!uniqueText) + return; + + OnAddTagButtonClicked(nameTextBox.Text, tree, nameTextBox, addTagDropPanel, pickerData); + }; + + // Used for how far everything should drop when the drop down panel is opened + var dropPanelOpenHeight = tagNamePanel.Height + addButtonPanel.Height + 4; // Create tree with tags hierarchy tree.Margin = new Margin(-16.0f, 0.0f, -16.0f, -0.0f); // Hide root node @@ -339,7 +480,7 @@ namespace FlaxEditor.CustomEditors.Editors AnchorPreset = AnchorPresets.TopRight, }; node.Addons.Add(addButton); - addButton.ButtonClicked += button => OnAddButtonClicked(tree, node, pickerData); + addButton.ButtonClicked += button => OnAddSubTagButtonClicked(((Tag)node.Tag).ToString(), nameTextBox, addTagDropPanel); // Link to parent { @@ -360,10 +501,13 @@ namespace FlaxEditor.CustomEditors.Editors { Margin = new Margin(1.0f), AutoSize = false, - Bounds = new Rectangle(0, 0, menu.Width, 20.0f), + Bounds = new Rectangle(0, 0, menu.Width - 4, 20.0f), Parent = menu, }; - var buttonsSize = new Float2((menu.Width - buttonsPanel.Margin.Width) / 4.0f - buttonsPanel.Spacing, 18.0f); + buttonsPanel.Y += addTagDropPanel.HeaderHeight + 4; + buttonsPanel.X += 2; + + var buttonsSize = new Float2((menu.Width - 2 - buttonsPanel.Margin.Width) / 3.0f - buttonsPanel.Spacing, 18.0f); var buttonExpandAll = new Button { Size = buttonsSize, @@ -382,20 +526,13 @@ namespace FlaxEditor.CustomEditors.Editors root.CollapseAll(true); root.Expand(true); }; - var buttonAddTag = new Button + var buttonClearAll = new Button { Size = buttonsSize, Parent = buttonsPanel, - Text = "Add Tag", + Text = "Clear All", }; - buttonAddTag.Clicked += () => OnAddButtonClicked(tree, root, pickerData); - var buttonReset = new Button - { - Size = buttonsSize, - Parent = buttonsPanel, - Text = "Reset", - }; - buttonReset.Clicked += () => + buttonClearAll.Clicked += () => { pickerData.IsEditing = true; UncheckAll(root); @@ -404,6 +541,45 @@ namespace FlaxEditor.CustomEditors.Editors pickerData.SetValues?.Invoke(null); }; + // Move menu children to location when drop panel is opened and closed + addTagDropPanel.IsClosedChanged += panel => + { + if (panel.IsClosed) + { + foreach (var child in menu.Children) + { + if (child == panel) + continue; + + // Expand panels so scrollbars work + if (child is Panel) + { + child.Bounds = new Rectangle(child.Bounds.X, child.Bounds.Y - dropPanelOpenHeight, child.Width, child.Height + dropPanelOpenHeight); + continue; + } + child.Y -= dropPanelOpenHeight; + nameTextBox.Text = String.Empty; + } + } + else + { + foreach (var child in menu.Children) + { + if (child == panel) + continue; + + // Shrink panels so scrollbars work + if (child is Panel) + { + child.Bounds = new Rectangle(child.Bounds.X, child.Bounds.Y + dropPanelOpenHeight, child.Width, child.Height - dropPanelOpenHeight); + continue; + } + child.Y += dropPanelOpenHeight; + nameTextBox.Text = String.Empty; + } + } + }; + // Setup search filter searchBox.TextChanged += delegate { From efe11d0105b57d66211ab79fe9c1a26028862b8b Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 20 Jan 2023 00:55:54 -0600 Subject: [PATCH 13/19] Added selecting text box when tag add drop panel open --- Source/Editor/CustomEditors/Editors/TagEditor.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Source/Editor/CustomEditors/Editors/TagEditor.cs b/Source/Editor/CustomEditors/Editors/TagEditor.cs index 3f425d845..56ffdbaba 100644 --- a/Source/Editor/CustomEditors/Editors/TagEditor.cs +++ b/Source/Editor/CustomEditors/Editors/TagEditor.cs @@ -546,6 +546,7 @@ namespace FlaxEditor.CustomEditors.Editors { if (panel.IsClosed) { + // Resize/ Move UI to fit space with drop down foreach (var child in menu.Children) { if (child == panel) @@ -563,6 +564,7 @@ namespace FlaxEditor.CustomEditors.Editors } else { + // Resize/ Move UI to fit space with drop down foreach (var child in menu.Children) { if (child == panel) @@ -577,6 +579,9 @@ namespace FlaxEditor.CustomEditors.Editors child.Y += dropPanelOpenHeight; nameTextBox.Text = String.Empty; } + // Select tag name box on open + nameTextBox.Focus(); + nameTextBox.SelectionRange = new TextRange(nameTextBox.Text.Length, nameTextBox.Text.Length); } }; From 6c1ce82e5cb73eb00e1d1087fe16ac4057f6fe8b Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 20 Jan 2023 00:56:46 -0600 Subject: [PATCH 14/19] Small cleanup --- Source/Editor/CustomEditors/Editors/TagEditor.cs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/Source/Editor/CustomEditors/Editors/TagEditor.cs b/Source/Editor/CustomEditors/Editors/TagEditor.cs index 56ffdbaba..d1cdf8cfc 100644 --- a/Source/Editor/CustomEditors/Editors/TagEditor.cs +++ b/Source/Editor/CustomEditors/Editors/TagEditor.cs @@ -183,14 +183,7 @@ namespace FlaxEditor.CustomEditors.Editors // Check all entered subtags and create any that dont exist for (int j = 0; j <= i; j++) { - if (j == 0) - { - tagString += subInputs[j]; - } - else - { - tagString += "." + subInputs[j]; - } + tagString += j == 0 ? subInputs[j] : "." + subInputs[j]; } if (string.IsNullOrEmpty(tagString)) From 64dcfa21b8b2187167f6f1123103d3324a81ca01 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 20 Jan 2023 01:22:36 -0600 Subject: [PATCH 15/19] small fixes --- .../Editor/CustomEditors/Editors/TagEditor.cs | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Source/Editor/CustomEditors/Editors/TagEditor.cs b/Source/Editor/CustomEditors/Editors/TagEditor.cs index d1cdf8cfc..9d538cbce 100644 --- a/Source/Editor/CustomEditors/Editors/TagEditor.cs +++ b/Source/Editor/CustomEditors/Editors/TagEditor.cs @@ -194,6 +194,8 @@ namespace FlaxEditor.CustomEditors.Editors if (Tags.List.Contains(tagString)) { + parentNode = tree.GetChild(); // return to root + parentCount = 0; // Find next parent node foreach (var child in parentNode.Children) { @@ -284,13 +286,13 @@ namespace FlaxEditor.CustomEditors.Editors // Reload editor window to reflect new tag assetWindow?.RefreshAsset(); + assetWindow?.MarkAsEdited(); + assetWindow?.Save(); } textBox.Text = string.Empty; lastTagString = tagString; tagString = string.Empty; - parentNode = tree.GetChild(); // return to root - parentCount = 0; } } @@ -301,8 +303,7 @@ namespace FlaxEditor.CustomEditors.Editors return; } dropPanel.Open(); - textBox.Text = string.Empty; - textBox.Text += parentTag + "."; + textBox.Text = parentTag + "."; textBox.Focus(); textBox.SelectionRange = new TextRange(textBox.Text.Length, textBox.Text.Length); } @@ -345,6 +346,7 @@ namespace FlaxEditor.CustomEditors.Editors WatermarkText = "X.Y.Z", Size = new Float2(addTagDropPanel.Width * 0.7f, 0), Parent = tagNamePanel, + EndEditOnClick = false, }; bool uniqueText = true; @@ -375,8 +377,9 @@ namespace FlaxEditor.CustomEditors.Editors if (!uniqueText) return; - if (!nameTextBox.IsFocused) + if (addTagDropPanel.IsClosed) { + Debug.Log("Hit"); nameTextBox.BorderColor = Color.Transparent; nameTextBox.BorderSelectedColor = FlaxEngine.GUI.Style.Current.BackgroundSelected; return; @@ -552,7 +555,8 @@ namespace FlaxEditor.CustomEditors.Editors continue; } child.Y -= dropPanelOpenHeight; - nameTextBox.Text = String.Empty; + nameTextBox.Text = string.Empty; + nameTextBox.Defocus(); } } else @@ -570,11 +574,8 @@ namespace FlaxEditor.CustomEditors.Editors continue; } child.Y += dropPanelOpenHeight; - nameTextBox.Text = String.Empty; + nameTextBox.Text = string.Empty; } - // Select tag name box on open - nameTextBox.Focus(); - nameTextBox.SelectionRange = new TextRange(nameTextBox.Text.Length, nameTextBox.Text.Length); } }; From 56c9be6f8cd8724c28edec51d6ead44c1d0eb741 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 20 Jan 2023 01:55:09 -0600 Subject: [PATCH 16/19] fixes --- .../Editor/CustomEditors/Editors/TagEditor.cs | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/Source/Editor/CustomEditors/Editors/TagEditor.cs b/Source/Editor/CustomEditors/Editors/TagEditor.cs index 9d538cbce..c6fd4a9a4 100644 --- a/Source/Editor/CustomEditors/Editors/TagEditor.cs +++ b/Source/Editor/CustomEditors/Editors/TagEditor.cs @@ -175,8 +175,6 @@ namespace FlaxEditor.CustomEditors.Editors { if (string.IsNullOrEmpty(subInputs[i])) { - lastTagString = tagString; - tagString = string.Empty; continue; } @@ -194,8 +192,6 @@ namespace FlaxEditor.CustomEditors.Editors if (Tags.List.Contains(tagString)) { - parentNode = tree.GetChild(); // return to root - parentCount = 0; // Find next parent node foreach (var child in parentNode.Children) { @@ -213,11 +209,27 @@ namespace FlaxEditor.CustomEditors.Editors tagString = string.Empty; continue; } + else if (subInputs.Length > 1) + { + // Find next parent node + foreach (var child in parentNode.Children) + { + if (!(child is TreeNode childNode)) + continue; + + var tagValue = (Tag)childNode.Tag; + if (!string.Equals(tagValue.ToString(), lastTagString)) + continue; + + parentNode = childNode; + parentCount += 1; + } + } // Create new node var nodeIndent = 16.0f; var indentation = 0; - var parentTag = lastTagString; + var parentTag = string.Empty; if (parentNode.CustomArrowRect.HasValue) { indentation = (int)((parentNode.CustomArrowRect.Value.Location.X - 18) / nodeIndent) + 1; @@ -282,18 +294,17 @@ namespace FlaxEditor.CustomEditors.Editors // Update asset var settingsObj = (LayersAndTagsSettings)settingsAsset.Instance; settingsObj.Tags.Add(tagName); + settingsObj.Tags.Sort(); settingsAsset.SetInstance(settingsObj); // Reload editor window to reflect new tag assetWindow?.RefreshAsset(); - assetWindow?.MarkAsEdited(); - assetWindow?.Save(); } - textBox.Text = string.Empty; lastTagString = tagString; tagString = string.Empty; } + textBox.Text = string.Empty; } private static void OnAddSubTagButtonClicked(string parentTag, TextBox textBox, DropPanel dropPanel) From 5d601621cf4ea3d9c0a55ed5f718bc83bd542144 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 20 Jan 2023 02:14:05 -0600 Subject: [PATCH 17/19] small fix --- Source/Editor/CustomEditors/Editors/TagEditor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/CustomEditors/Editors/TagEditor.cs b/Source/Editor/CustomEditors/Editors/TagEditor.cs index c6fd4a9a4..8f330da29 100644 --- a/Source/Editor/CustomEditors/Editors/TagEditor.cs +++ b/Source/Editor/CustomEditors/Editors/TagEditor.cs @@ -537,7 +537,7 @@ namespace FlaxEditor.CustomEditors.Editors { Size = buttonsSize, Parent = buttonsPanel, - Text = "Clear All", + Text = "Clear all", }; buttonClearAll.Clicked += () => { From 31e27e84a9517aae0c2eee8918616a17ed6a2f5d Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Fri, 20 Jan 2023 11:48:53 +0100 Subject: [PATCH 18/19] Minor fix --- Source/Editor/Windows/Assets/AssetEditorWindow.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Source/Editor/Windows/Assets/AssetEditorWindow.cs b/Source/Editor/Windows/Assets/AssetEditorWindow.cs index 9d06359ad..0d244479c 100644 --- a/Source/Editor/Windows/Assets/AssetEditorWindow.cs +++ b/Source/Editor/Windows/Assets/AssetEditorWindow.cs @@ -313,9 +313,7 @@ namespace FlaxEditor.Windows.Assets /// public void RefreshAsset() { - if (_asset == null) - return; - if (!_asset.IsLoaded) + if (_asset == null || _asset.WaitForLoaded()) return; OnAssetLoaded(); From 66d5850a763c47462f4df62d0023805020338d6b Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Fri, 20 Jan 2023 12:02:40 +0100 Subject: [PATCH 19/19] Asset update --- Content/Shaders/GI/DDGI.flax | 4 +-- Content/Shaders/GI/GlobalSurfaceAtlas.flax | 4 +-- Content/Shaders/TAA.flax | 4 +-- Content/Shaders/VolumetricFog.flax | 4 +-- .../Editor/CustomEditors/Editors/TagEditor.cs | 30 +++++++++---------- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Content/Shaders/GI/DDGI.flax b/Content/Shaders/GI/DDGI.flax index c8f8eee9d..daaac6317 100644 --- a/Content/Shaders/GI/DDGI.flax +++ b/Content/Shaders/GI/DDGI.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6b00a1519c9fe2303a05c10ae4061649c4073a3f65a3bd8c2af848cdc7bf5e53 -size 23702 +oid sha256:da77e6d9cfc596990d6286fe5b3a7976357cccd95cb0e7ed6a3fdcc23695d212 +size 24284 diff --git a/Content/Shaders/GI/GlobalSurfaceAtlas.flax b/Content/Shaders/GI/GlobalSurfaceAtlas.flax index f74572140..a90a8c5ab 100644 --- a/Content/Shaders/GI/GlobalSurfaceAtlas.flax +++ b/Content/Shaders/GI/GlobalSurfaceAtlas.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b69d6b93baa29702789073f911dbe784dc65ccd66a43cef837a217959d24d13 -size 12612 +oid sha256:32bf53278f501fbdcb61ba7da32dd1a37e6f87608401be4a256b9cc9bf687d7f +size 12952 diff --git a/Content/Shaders/TAA.flax b/Content/Shaders/TAA.flax index e9575793e..b57642b07 100644 --- a/Content/Shaders/TAA.flax +++ b/Content/Shaders/TAA.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26cf20668dc0d93fdffa3ea715130b618e9c491e73dc8be779c1d182e73b255b -size 3257 +oid sha256:8d22fd7b1f4008b56a9f95e0c6263f8f66a26244bb40437c724344633a4ea4bc +size 3343 diff --git a/Content/Shaders/VolumetricFog.flax b/Content/Shaders/VolumetricFog.flax index 18eddae16..8de7291ce 100644 --- a/Content/Shaders/VolumetricFog.flax +++ b/Content/Shaders/VolumetricFog.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:72415ba69a685e9a739d1a08d08c6eb9efd3cab31d8cc0c949cb187a9bad19a5 -size 13841 +oid sha256:d25529ed77efff338892f54c103d007e98102328382497a5bb0ca5b047ef6acb +size 14255 diff --git a/Source/Editor/CustomEditors/Editors/TagEditor.cs b/Source/Editor/CustomEditors/Editors/TagEditor.cs index 8f330da29..e9bcd97a9 100644 --- a/Source/Editor/CustomEditors/Editors/TagEditor.cs +++ b/Source/Editor/CustomEditors/Editors/TagEditor.cs @@ -160,7 +160,7 @@ namespace FlaxEditor.CustomEditors.Editors { if (string.IsNullOrEmpty(input)) return; - + // Ensure that name is unique if (Tags.List.Contains(input)) return; @@ -177,7 +177,7 @@ namespace FlaxEditor.CustomEditors.Editors { continue; } - + // Check all entered subtags and create any that dont exist for (int j = 0; j <= i; j++) { @@ -189,7 +189,7 @@ namespace FlaxEditor.CustomEditors.Editors tagString = string.Empty; continue; } - + if (Tags.List.Contains(tagString)) { // Find next parent node @@ -197,11 +197,11 @@ namespace FlaxEditor.CustomEditors.Editors { if (!(child is TreeNode childNode)) continue; - + var tagValue = (Tag)childNode.Tag; if (!string.Equals(tagValue.ToString(), tagString)) continue; - + parentNode = childNode; parentCount += 1; } @@ -216,11 +216,11 @@ namespace FlaxEditor.CustomEditors.Editors { if (!(child is TreeNode childNode)) continue; - + var tagValue = (Tag)childNode.Tag; if (!string.Equals(tagValue.ToString(), lastTagString)) continue; - + parentNode = childNode; parentCount += 1; } @@ -266,13 +266,13 @@ namespace FlaxEditor.CustomEditors.Editors }; node.Addons.Add(addButton); addButton.ButtonClicked += button => OnAddSubTagButtonClicked(((Tag)node.Tag).ToString(), textBox, dropPanel); - + // Link node.Parent = parentNode; node.IndexInParent = 0; parentNode.Expand(true); ((Panel)tree.Parent.Parent).ScrollViewTo(node); - + // Get tag name var tagName = tagString; var tagShortName = tagName.Substring(parentCount == 0 ? lastTagString.Length : lastTagString.Length + 1); @@ -355,7 +355,7 @@ namespace FlaxEditor.CustomEditors.Editors { IsMultiline = false, WatermarkText = "X.Y.Z", - Size = new Float2(addTagDropPanel.Width * 0.7f, 0), + Size = new Float2(addTagDropPanel.Width * 0.7f, 0), Parent = tagNamePanel, EndEditOnClick = false, }; @@ -395,7 +395,7 @@ namespace FlaxEditor.CustomEditors.Editors nameTextBox.BorderSelectedColor = FlaxEngine.GUI.Style.Current.BackgroundSelected; return; } - + OnAddTagButtonClicked(nameTextBox.Text, tree, nameTextBox, addTagDropPanel, pickerData); }; @@ -416,10 +416,10 @@ namespace FlaxEditor.CustomEditors.Editors { if (!uniqueText) return; - + OnAddTagButtonClicked(nameTextBox.Text, tree, nameTextBox, addTagDropPanel, pickerData); }; - + // Used for how far everything should drop when the drop down panel is opened var dropPanelOpenHeight = tagNamePanel.Height + addButtonPanel.Height + 4; @@ -454,7 +454,7 @@ namespace FlaxEditor.CustomEditors.Editors tagShortName = tagName.Substring(lastDotIndex + 1); tagParentName = tagName.Substring(0, lastDotIndex); } - + // Create node var node = new TreeNodeWithAddons { @@ -513,7 +513,7 @@ namespace FlaxEditor.CustomEditors.Editors }; buttonsPanel.Y += addTagDropPanel.HeaderHeight + 4; buttonsPanel.X += 2; - + var buttonsSize = new Float2((menu.Width - 2 - buttonsPanel.Margin.Width) / 3.0f - buttonsPanel.Spacing, 18.0f); var buttonExpandAll = new Button {