diff --git a/Source/Editor/Options/InterfaceOptions.cs b/Source/Editor/Options/InterfaceOptions.cs
index f26506c74..f031ab383 100644
--- a/Source/Editor/Options/InterfaceOptions.cs
+++ b/Source/Editor/Options/InterfaceOptions.cs
@@ -159,7 +159,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
{
@@ -179,6 +179,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.
///
@@ -525,6 +541,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(DisabledHidden.Hidden)]
+ [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.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 41382e60c..9b92b380f 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;
@@ -154,11 +155,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. 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");
- _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
@@ -271,6 +273,42 @@ 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();
+
+ 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, 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)
{
var menu = new ContextMenu();