From c91c8b66cee7bb9a8a99840dfa696a143bb8dee9 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 15 Jun 2021 16:39:15 +0200 Subject: [PATCH] Add `Category` attribute for types grouping in editor dialogs --- .../CustomEditors/Dedicated/ScriptsEditor.cs | 14 +--- .../Dedicated/UIControlEditor.cs | 15 +--- Source/Editor/GUI/ClickableLabel.cs | 1 + Source/Editor/GUI/ItemsListContextMenu.cs | 79 +++++++++++++++---- Source/Editor/GUI/Popups/TypeSearchPopup.cs | 15 ++++ Source/Editor/Surface/Archetypes/Particles.cs | 4 +- Source/Editor/Surface/VisjectSurfaceWindow.cs | 13 +-- .../Attributes/Editor/CategoryAttribute.cs | 27 +++++++ 8 files changed, 116 insertions(+), 52 deletions(-) create mode 100644 Source/Engine/Scripting/Attributes/Editor/CategoryAttribute.cs diff --git a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs index ffe4ce585..8a6ae54a9 100644 --- a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs @@ -68,19 +68,7 @@ namespace FlaxEditor.CustomEditors.Dedicated var cm = new ItemsListContextMenu(180); for (int i = 0; i < scripts.Count; i++) { - var scriptType = scripts[i]; - var item = new ItemsListContextMenu.Item(scriptType.Name, scriptType) - { - TooltipText = scriptType.TypeName, - }; - var attributes = scriptType.GetAttributes(false); - var tooltipAttribute = (TooltipAttribute)attributes.FirstOrDefault(x => x is TooltipAttribute); - if (tooltipAttribute != null) - { - item.TooltipText += '\n'; - item.TooltipText += tooltipAttribute.Text; - } - cm.AddItem(item); + cm.AddItem(new TypeSearchPopup.TypeItemView(scripts[i])); } cm.ItemClicked += item => AddScript((ScriptType)item.Tag); cm.SortChildren(); diff --git a/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs b/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs index b860d9826..d7a6f2617 100644 --- a/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs @@ -639,21 +639,8 @@ namespace FlaxEditor.CustomEditors.Dedicated var cm = new ItemsListContextMenu(180); for (int i = 0; i < controlTypes.Count; i++) { - var controlType = controlTypes[i]; - var item = new ItemsListContextMenu.Item(controlType.Name, controlType) - { - TooltipText = controlType.TypeName, - }; - var attributes = controlType.GetAttributes(false); - var tooltipAttribute = (TooltipAttribute)attributes.FirstOrDefault(x => x is TooltipAttribute); - if (tooltipAttribute != null) - { - item.TooltipText += '\n'; - item.TooltipText += tooltipAttribute.Text; - } - cm.AddItem(item); + cm.AddItem(new TypeSearchPopup.TypeItemView(controlTypes[i])); } - cm.ItemClicked += controlType => SetType((ScriptType)controlType.Tag); cm.SortChildren(); cm.Show(button.Parent, button.BottomLeft); diff --git a/Source/Editor/GUI/ClickableLabel.cs b/Source/Editor/GUI/ClickableLabel.cs index f8940e714..325d8822a 100644 --- a/Source/Editor/GUI/ClickableLabel.cs +++ b/Source/Editor/GUI/ClickableLabel.cs @@ -10,6 +10,7 @@ namespace FlaxEditor.GUI /// The label that contains events for mouse interaction. /// /// + [HideInEditor] public class ClickableLabel : Label { private bool _leftClick; diff --git a/Source/Editor/GUI/ItemsListContextMenu.cs b/Source/Editor/GUI/ItemsListContextMenu.cs index 8c4dd723d..4abe39f0b 100644 --- a/Source/Editor/GUI/ItemsListContextMenu.cs +++ b/Source/Editor/GUI/ItemsListContextMenu.cs @@ -32,9 +32,14 @@ namespace FlaxEditor.GUI protected List _highlights; /// - /// Gets or sets the name. + /// The item name. /// - public string Name { get; set; } + public string Name; + + /// + /// The item category name (optional). + /// + public string Category; /// /// Occurs when items gets clicked by the user. @@ -49,18 +54,6 @@ namespace FlaxEditor.GUI { } - /// - /// Initializes a new instance of the class. - /// - /// The item name. - /// The item tag object. - public Item(string name, object tag = null) - : base(0, 0, 120, 12) - { - Name = name; - Tag = tag; - } - /// /// Updates the filter. /// @@ -181,6 +174,7 @@ namespace FlaxEditor.GUI } private readonly TextBox _searchBox; + private List _categoryPanels; private bool _waitingForInput; /// @@ -242,6 +236,23 @@ namespace FlaxEditor.GUI if (items[i] is Item item) item.UpdateFilter(_searchBox.Text); } + if (_categoryPanels != null) + { + for (int i = 0; i < _categoryPanels.Count; i++) + { + var category = _categoryPanels[i]; + bool anyVisible = false; + for (int j = 0; j < category.Children.Count; j++) + { + if (category.Children[j] is Item item2) + { + item2.UpdateFilter(_searchBox.Text); + anyVisible |= item2.Visible; + } + } + category.Visible = anyVisible; + } + } UnlockChildrenRecursive(); PerformLayout(true); @@ -254,8 +265,33 @@ namespace FlaxEditor.GUI /// The item. public void AddItem(Item item) { - item.Parent = ItemsPanel; item.Clicked += OnClickItem; + ContainerControl parent = ItemsPanel; + if (!string.IsNullOrEmpty(item.Category)) + { + if (_categoryPanels == null) + _categoryPanels = new List(); + for (int i = 0; i < _categoryPanels.Count; i++) + { + if (string.Equals(_categoryPanels[i].HeaderText, item.Category, StringComparison.Ordinal)) + { + parent = _categoryPanels[i]; + break; + } + } + if (parent == ItemsPanel) + { + var categoryPanel = new DropPanel + { + HeaderText = item.Category, + Parent = parent, + }; + categoryPanel.Open(false); + _categoryPanels.Add(categoryPanel); + parent = categoryPanel; + } + } + item.Parent = parent; } /// @@ -281,6 +317,19 @@ namespace FlaxEditor.GUI if (items[i] is Item item) item.UpdateFilter(null); } + if (_categoryPanels != null) + { + for (int i = 0; i < _categoryPanels.Count; i++) + { + var category = _categoryPanels[i]; + for (int j = 0; j < category.Children.Count; j++) + { + if (category.Children[j] is Item item2) + item2.UpdateFilter(null); + } + category.Visible = true; + } + } _searchBox.Clear(); UnlockChildrenRecursive(); diff --git a/Source/Editor/GUI/Popups/TypeSearchPopup.cs b/Source/Editor/GUI/Popups/TypeSearchPopup.cs index a35b2a1c5..71a97ed05 100644 --- a/Source/Editor/GUI/Popups/TypeSearchPopup.cs +++ b/Source/Editor/GUI/Popups/TypeSearchPopup.cs @@ -27,6 +27,15 @@ namespace FlaxEditor.GUI /// public ScriptType Type => _type; + /// + /// Initializes a new instance of the class. + /// + /// The type. + public TypeItemView(ScriptType type) + : this(type, type.GetAttributes(false)) + { + } + /// /// Initializes a new instance of the class. /// @@ -38,12 +47,18 @@ namespace FlaxEditor.GUI Name = type.Name; TooltipText = type.TypeName; + Tag = type; var tooltipAttribute = (TooltipAttribute)attributes.FirstOrDefault(x => x is TooltipAttribute); if (tooltipAttribute != null) { TooltipText += '\n'; TooltipText += tooltipAttribute.Text; } + var categoryAttribute = (CategoryAttribute)attributes.FirstOrDefault(x => x is CategoryAttribute); + if (categoryAttribute != null) + { + Category = categoryAttribute.Name; + } } /// diff --git a/Source/Editor/Surface/Archetypes/Particles.cs b/Source/Editor/Surface/Archetypes/Particles.cs index 28d6dce6a..f6fd2d003 100644 --- a/Source/Editor/Surface/Archetypes/Particles.cs +++ b/Source/Editor/Surface/Archetypes/Particles.cs @@ -118,8 +118,10 @@ namespace FlaxEditor.Surface.Archetypes var cm = new ItemsListContextMenu(180); foreach (var module in modules) { - cm.AddItem(new ItemsListContextMenu.Item(module.Title, module.TypeID) + cm.AddItem(new ItemsListContextMenu.Item { + Name = module.Title, + Tag = module.TypeID, TooltipText = module.Description, }); } diff --git a/Source/Editor/Surface/VisjectSurfaceWindow.cs b/Source/Editor/Surface/VisjectSurfaceWindow.cs index 810f125ae..119c01c30 100644 --- a/Source/Editor/Surface/VisjectSurfaceWindow.cs +++ b/Source/Editor/Surface/VisjectSurfaceWindow.cs @@ -447,18 +447,13 @@ namespace FlaxEditor.Surface var cm = new ItemsListContextMenu(180); foreach (var newParameterType in newParameterTypes) { - var name = newParameterType.Type != null ? window.VisjectSurface.GetTypeName(newParameterType) : newParameterType.Name; - var item = new ItemsListContextMenu.Item(name, newParameterType) + var item = new TypeSearchPopup.TypeItemView(newParameterType) { + Tag = newParameterType, TooltipText = newParameterType.TypeName, }; - var attributes = newParameterType.GetAttributes(false); - var tooltipAttribute = (TooltipAttribute)attributes.FirstOrDefault(x => x is TooltipAttribute); - if (tooltipAttribute != null) - { - item.TooltipText += '\n'; - item.TooltipText += tooltipAttribute.Text; - } + if (newParameterType.Type != null) + item.Name = window.VisjectSurface.GetTypeName(newParameterType); cm.AddItem(item); } cm.ItemClicked += OnAddParameterItemClicked; diff --git a/Source/Engine/Scripting/Attributes/Editor/CategoryAttribute.cs b/Source/Engine/Scripting/Attributes/Editor/CategoryAttribute.cs new file mode 100644 index 000000000..e5f4f9794 --- /dev/null +++ b/Source/Engine/Scripting/Attributes/Editor/CategoryAttribute.cs @@ -0,0 +1,27 @@ +// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. + +using System; + +namespace FlaxEngine +{ + /// + /// Describes the category name for a type. + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] + public sealed class CategoryAttribute : Attribute + { + /// + /// The category name. + /// + public string Name; + + /// + /// Initializes a new instance of the class. + /// + /// The category name. + public CategoryAttribute(string name) + { + Name = name; + } + } +}