From fccd43502bb3153632cdf3fbc6d0ad331074c952 Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Sun, 4 May 2025 21:14:10 +0200 Subject: [PATCH 1/5] add create file Content Panel toolstrip button --- .../Windows/ContentWindow.ContextMenu.cs | 86 +++++++++++++------ Source/Editor/Windows/ContentWindow.cs | 26 +++++- 2 files changed, 81 insertions(+), 31 deletions(-) diff --git a/Source/Editor/Windows/ContentWindow.ContextMenu.cs b/Source/Editor/Windows/ContentWindow.ContextMenu.cs index 1ad225997..40dd9131b 100644 --- a/Source/Editor/Windows/ContentWindow.ContextMenu.cs +++ b/Source/Editor/Windows/ContentWindow.ContextMenu.cs @@ -39,8 +39,7 @@ namespace FlaxEditor.Windows folder = CurrentViewFolder; } Assert.IsNotNull(folder); - bool isRootFolder = CurrentViewFolder == _root.Folder; - + // Create context menu ContextMenuButton b; ContextMenu cm = new ContextMenu @@ -78,7 +77,7 @@ namespace FlaxEditor.Windows cm.AddButton(Utilities.Constants.ShowInExplorer, () => FileSystem.ShowFileExplorer(System.IO.Path.GetDirectoryName(item.Path))); if (!String.IsNullOrEmpty(Editor.Instance.Windows.ContentWin._itemsSearchBox.Text)) - { + { cm.AddButton("Show in Content Panel", () => { Editor.Instance.Windows.ContentWin.ClearItemsSearch(); @@ -178,19 +177,61 @@ namespace FlaxEditor.Windows cm.AddSeparator(); + CreateNewModuleMenu(cm, folder); + CreateNewFolderMenu(cm, folder, false, item); + CreateNewContentItemMenu(cm, folder); + + if (folder.CanHaveAssets) + { + cm.AddButton("Import file", () => + { + _view.ClearSelection(); + Editor.ContentImporting.ShowImportFileDialog(CurrentViewFolder); + }); + } + + // Remove any leftover separator + if (cm.ItemsContainer.Children.LastOrDefault() is ContextMenuSeparator) + cm.ItemsContainer.Children.Last().Dispose(); + + // Show it + cm.Show(this, location); + } + + private void CreateNewModuleMenu(ContextMenu menu, ContentFolder folder, bool disableUncreatable = false) + { // Check if is source folder to add new module if (folder?.ParentFolder?.Node is ProjectTreeNode parentFolderNode && folder.Node == parentFolderNode.Source) { - var button = cm.AddButton("New module"); + var button = menu.AddButton("New module"); button.CloseMenuOnClick = false; button.Clicked += () => NewModule(button, parentFolderNode.Source.Path); } - - if (!isRootFolder && !(item is ContentFolder projectFolder && projectFolder.Node is ProjectTreeNode)) + else if (disableUncreatable) { - cm.AddButton("New folder", NewFolder); + var button = menu.AddButton("New module"); + button.Enabled = false; } + } + private bool CanCreateFolder(ContentItem item = null) + { + bool canCreateFolder = CurrentViewFolder != _root.Folder && !(item is ContentFolder projectFolder && projectFolder.Node is ProjectTreeNode); + return canCreateFolder; + } + + private void CreateNewFolderMenu(ContextMenu menu, ContentFolder folder, bool disableUncreatable = false, ContentItem item = null) + { + bool canCreateFolder = CanCreateFolder(item); + if (canCreateFolder || disableUncreatable) + { + var b = menu.AddButton("New folder", NewFolder); + b.Enabled = canCreateFolder; + } + } + + private void CreateNewContentItemMenu(ContextMenu menu, ContentFolder folder, bool showNew = true, bool disableUncreatable = false) + { // Loop through each proxy and user defined json type and add them to the context menu var actorType = new ScriptType(typeof(Actor)); var scriptType = new ScriptType(typeof(Script)); @@ -230,7 +271,8 @@ namespace FlaxEditor.Windows if (p == null) continue; - if (p.CanCreate(folder)) + bool canCreate = p.CanCreate(folder); + if (canCreate || disableUncreatable) { var parts = attribute.Path.Split('/'); ContextMenuChildMenu childCM = null; @@ -238,16 +280,20 @@ namespace FlaxEditor.Windows for (int i = 0; i < parts?.Length; i++) { var part = parts[i].Trim(); + if (part == "New" && !showNew) + continue; if (i == parts.Length - 1) { if (mainCM) { - cm.AddButton(part, () => NewItem(p)); + var b = menu.AddButton(part, () => NewItem(p)); + b.Enabled = canCreate; mainCM = false; } else if (childCM != null) { - childCM.ContextMenu.AddButton(part, () => NewItem(p)); + var b = childCM.ContextMenu.AddButton(part, () => NewItem(p)); + b.Enabled = canCreate; childCM.ContextMenu.AutoSort = true; } } @@ -255,35 +301,21 @@ namespace FlaxEditor.Windows { if (mainCM) { - childCM = cm.GetOrAddChildMenu(part); + childCM = menu.GetOrAddChildMenu(part); childCM.ContextMenu.AutoSort = true; + childCM.Enabled = canCreate; mainCM = false; } else if (childCM != null) { childCM = childCM.ContextMenu.GetOrAddChildMenu(part); childCM.ContextMenu.AutoSort = true; + childCM.Enabled = canCreate; } } } } } - - if (folder.CanHaveAssets) - { - cm.AddButton("Import file", () => - { - _view.ClearSelection(); - Editor.ContentImporting.ShowImportFileDialog(CurrentViewFolder); - }); - } - - // Remove any leftover separator - if (cm.ItemsContainer.Children.LastOrDefault() is ContextMenuSeparator) - cm.ItemsContainer.Children.Last().Dispose(); - - // Show it - cm.Show(this, location); } private void OnExpandAllClicked(ContextMenuButton button) diff --git a/Source/Editor/Windows/ContentWindow.cs b/Source/Editor/Windows/ContentWindow.cs index f63db04bd..c87550b26 100644 --- a/Source/Editor/Windows/ContentWindow.cs +++ b/Source/Editor/Windows/ContentWindow.cs @@ -37,6 +37,7 @@ namespace FlaxEditor.Windows private readonly ToolStrip _toolStrip; private readonly ToolStripButton _importButton; + private readonly ToolStripButton _createNewButton; private readonly ToolStripButton _navigateBackwardButton; private readonly ToolStripButton _navigateForwardButton; private readonly ToolStripButton _navigateUpButton; @@ -153,11 +154,12 @@ namespace FlaxEditor.Windows { Parent = this, }; - _importButton = (ToolStripButton)_toolStrip.AddButton(Editor.Icons.Import64, () => Editor.ContentImporting.ShowImportFileDialog(CurrentViewFolder)).LinkTooltip("Import content"); + _importButton = (ToolStripButton)_toolStrip.AddButton(Editor.Icons.Import64, () => Editor.ContentImporting.ShowImportFileDialog(CurrentViewFolder)).LinkTooltip("Import content."); + _createNewButton = (ToolStripButton)_toolStrip.AddButton(Editor.Icons.Add64, OnCreateNewItemButtonClicked).LinkTooltip("Create a new asset."); _toolStrip.AddSeparator(); - _navigateBackwardButton = (ToolStripButton)_toolStrip.AddButton(Editor.Icons.Left64, NavigateBackward).LinkTooltip("Navigate backward"); - _navigateForwardButton = (ToolStripButton)_toolStrip.AddButton(Editor.Icons.Right64, NavigateForward).LinkTooltip("Navigate forward"); - _navigateUpButton = (ToolStripButton)_toolStrip.AddButton(Editor.Icons.Up64, NavigateUp).LinkTooltip("Navigate up"); + _navigateBackwardButton = (ToolStripButton)_toolStrip.AddButton(Editor.Icons.Left64, NavigateBackward).LinkTooltip("Navigate backward."); + _navigateForwardButton = (ToolStripButton)_toolStrip.AddButton(Editor.Icons.Right64, NavigateForward).LinkTooltip("Navigate forward."); + _navigateUpButton = (ToolStripButton)_toolStrip.AddButton(Editor.Icons.Up64, NavigateUp).LinkTooltip("Navigate up."); _toolStrip.AddSeparator(); // Navigation bar @@ -267,6 +269,22 @@ namespace FlaxEditor.Windows InputActions.Add(options => options.Search, () => _itemsSearchBox.Focus()); } + private void OnCreateNewItemButtonClicked() + { + if (Input.GetKey(KeyboardKeys.Shift) && CanCreateFolder()) + { + NewFolder(); + return; + } + + var menu = new ContextMenu(); + CreateNewFolderMenu(menu, CurrentViewFolder, true); + CreateNewModuleMenu(menu, CurrentViewFolder, true); + menu.AddSeparator(); + CreateNewContentItemMenu(menu, CurrentViewFolder, false, true); + menu.Show(this, new Float2(1, _createNewButton.Bottom)); + } + private ContextMenu OnViewDropdownPopupCreate(ComboBox comboBox) { var menu = new ContextMenu(); From c45cba18a6321cd0783e26299019de481386f6e0 Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Sun, 4 May 2025 21:18:00 +0200 Subject: [PATCH 2/5] fix menu positioning --- Source/Editor/Windows/ContentWindow.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/Windows/ContentWindow.cs b/Source/Editor/Windows/ContentWindow.cs index c87550b26..318bf5231 100644 --- a/Source/Editor/Windows/ContentWindow.cs +++ b/Source/Editor/Windows/ContentWindow.cs @@ -282,7 +282,7 @@ namespace FlaxEditor.Windows CreateNewModuleMenu(menu, CurrentViewFolder, true); menu.AddSeparator(); CreateNewContentItemMenu(menu, CurrentViewFolder, false, true); - menu.Show(this, new Float2(1, _createNewButton.Bottom)); + menu.Show(this, _createNewButton.UpperLeft, ContextMenuDirection.RightUp); } private ContextMenu OnViewDropdownPopupCreate(ComboBox comboBox) From b43ed886b9a6e71585bb774b4f360649f1f0f992 Mon Sep 17 00:00:00 2001 From: Saas Date: Sun, 12 Oct 2025 19:52:18 +0200 Subject: [PATCH 3/5] add option for what happens with unavailable entries and fix menu positioning --- Source/Editor/Options/InterfaceOptions.cs | 25 +++++++++++++++++++- Source/Editor/Windows/ContentWindow.cs | 28 +++++++++++++++++++---- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/Source/Editor/Options/InterfaceOptions.cs b/Source/Editor/Options/InterfaceOptions.cs index 617c1c3de..897ad91b8 100644 --- a/Source/Editor/Options/InterfaceOptions.cs +++ b/Source/Editor/Options/InterfaceOptions.cs @@ -140,7 +140,7 @@ namespace FlaxEditor.Options } /// - /// Options focus Game Window behaviour when play mode is entered. + /// Options for focus Game Window behaviour when play mode is entered. /// public enum PlayModeFocus { @@ -160,6 +160,22 @@ namespace FlaxEditor.Options GameWindowThenRestore, } + /// + /// Generic options for a disabled or hidden state. Used for example in create content button. + /// + public enum DisabledHidden + { + /// + /// Disabled state. + /// + Disabled, + + /// + /// Hidden state. + /// + Hidden, + } + /// /// Gets or sets the Editor User Interface scale. Applied to all UI elements, windows and text. Can be used to scale the interface up on a bigger display. Editor restart required. /// @@ -456,6 +472,13 @@ namespace FlaxEditor.Options [EditorDisplay("Visject", "Warn when deleting used parameter"), EditorOrder(552)] public bool WarnOnDeletingUsedVisjectParameter { get; set; } = true; + /// + /// Gets or sets a value indicating what should happen to unavaliable options in the content create menu. + /// + [DefaultValue(true)] + [EditorDisplay("Content"), EditorOrder(600)] + public DisabledHidden UnavaliableContentCreateOptions { get; set; } = DisabledHidden.Hidden; + private static FontAsset DefaultFont => FlaxEngine.Content.LoadAsyncInternal(EditorAssets.PrimaryFont); private static FontAsset ConsoleFont => FlaxEngine.Content.LoadAsyncInternal(EditorAssets.InconsolataRegularFont); diff --git a/Source/Editor/Windows/ContentWindow.cs b/Source/Editor/Windows/ContentWindow.cs index 318bf5231..a53de0900 100644 --- a/Source/Editor/Windows/ContentWindow.cs +++ b/Source/Editor/Windows/ContentWindow.cs @@ -278,11 +278,31 @@ namespace FlaxEditor.Windows } var menu = new ContextMenu(); - CreateNewFolderMenu(menu, CurrentViewFolder, true); - CreateNewModuleMenu(menu, CurrentViewFolder, true); + + InterfaceOptions interfaceOptions = Editor.Instance.Options.Options.Interface; + bool disableUnavaliable = interfaceOptions.UnavaliableContentCreateOptions == InterfaceOptions.DisabledHidden.Disabled; + + CreateNewFolderMenu(menu, CurrentViewFolder, disableUnavaliable); + CreateNewModuleMenu(menu, CurrentViewFolder, disableUnavaliable); menu.AddSeparator(); - CreateNewContentItemMenu(menu, CurrentViewFolder, false, true); - menu.Show(this, _createNewButton.UpperLeft, ContextMenuDirection.RightUp); + CreateNewContentItemMenu(menu, CurrentViewFolder, false, disableUnavaliable); + // Hack: Show the menu once to get the direction, then show it above or below the button depending on the direction. + menu.Show(this, _createNewButton.UpperLeft); + var direction = menu.Direction; + menu.Hide(); + bool below = false; + switch (direction) + { + case ContextMenuDirection.RightDown: + case ContextMenuDirection.LeftDown: + below = true; + break; + case ContextMenuDirection.RightUp: + case ContextMenuDirection.LeftUp: + below = false; + break; + } + menu.Show(this, below ? _createNewButton.BottomLeft : _createNewButton.UpperLeft, direction); } private ContextMenu OnViewDropdownPopupCreate(ComboBox comboBox) From 69a7e1f25cfb2f50440a5b4982f3c6c43fcf7e90 Mon Sep 17 00:00:00 2001 From: Saas Date: Sun, 12 Oct 2025 19:57:05 +0200 Subject: [PATCH 4/5] expand tooltip to hint at being able to create a new folder on shift + left click --- Source/Editor/Windows/ContentWindow.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/Windows/ContentWindow.cs b/Source/Editor/Windows/ContentWindow.cs index a53de0900..892d6184d 100644 --- a/Source/Editor/Windows/ContentWindow.cs +++ b/Source/Editor/Windows/ContentWindow.cs @@ -155,7 +155,7 @@ namespace FlaxEditor.Windows Parent = this, }; _importButton = (ToolStripButton)_toolStrip.AddButton(Editor.Icons.Import64, () => Editor.ContentImporting.ShowImportFileDialog(CurrentViewFolder)).LinkTooltip("Import content."); - _createNewButton = (ToolStripButton)_toolStrip.AddButton(Editor.Icons.Add64, OnCreateNewItemButtonClicked).LinkTooltip("Create a new asset."); + _createNewButton = (ToolStripButton)_toolStrip.AddButton(Editor.Icons.Add64, OnCreateNewItemButtonClicked).LinkTooltip("Create a new asset. Shift + left click to create a new folder."); _toolStrip.AddSeparator(); _navigateBackwardButton = (ToolStripButton)_toolStrip.AddButton(Editor.Icons.Left64, NavigateBackward).LinkTooltip("Navigate backward."); _navigateForwardButton = (ToolStripButton)_toolStrip.AddButton(Editor.Icons.Right64, NavigateForward).LinkTooltip("Navigate forward."); From 5dd9171316d7999441a67f887ae4f05e781c39a5 Mon Sep 17 00:00:00 2001 From: Saas Date: Fri, 17 Oct 2025 21:58:55 +0200 Subject: [PATCH 5/5] fix default value --- Source/Editor/Options/InterfaceOptions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/Options/InterfaceOptions.cs b/Source/Editor/Options/InterfaceOptions.cs index 897ad91b8..2a466b8ad 100644 --- a/Source/Editor/Options/InterfaceOptions.cs +++ b/Source/Editor/Options/InterfaceOptions.cs @@ -475,7 +475,7 @@ namespace FlaxEditor.Options /// /// Gets or sets a value indicating what should happen to unavaliable options in the content create menu. /// - [DefaultValue(true)] + [DefaultValue(DisabledHidden.Hidden)] [EditorDisplay("Content"), EditorOrder(600)] public DisabledHidden UnavaliableContentCreateOptions { get; set; } = DisabledHidden.Hidden;