diff --git a/Source/Editor/Content/Proxy/AnimationGraphFunctionProxy.cs b/Source/Editor/Content/Proxy/AnimationGraphFunctionProxy.cs
index c4ea2e09a..a8092a162 100644
--- a/Source/Editor/Content/Proxy/AnimationGraphFunctionProxy.cs
+++ b/Source/Editor/Content/Proxy/AnimationGraphFunctionProxy.cs
@@ -11,6 +11,7 @@ namespace FlaxEditor.Content
/// A asset proxy object.
///
///
+ [ContentContextMenu("New/Animation/Animation Graph Function")]
public class AnimationGraphFunctionProxy : BinaryAssetProxy
{
///
diff --git a/Source/Editor/Content/Proxy/AnimationGraphProxy.cs b/Source/Editor/Content/Proxy/AnimationGraphProxy.cs
index 3c445c104..7f43b8c7b 100644
--- a/Source/Editor/Content/Proxy/AnimationGraphProxy.cs
+++ b/Source/Editor/Content/Proxy/AnimationGraphProxy.cs
@@ -11,6 +11,7 @@ namespace FlaxEditor.Content
/// A asset proxy object.
///
///
+ [ContentContextMenu("New/Animation/Animation Graph")]
public class AnimationGraphProxy : BinaryAssetProxy
{
///
diff --git a/Source/Editor/Content/Proxy/AnimationProxy.cs b/Source/Editor/Content/Proxy/AnimationProxy.cs
index bda0fa98d..eb8c892ab 100644
--- a/Source/Editor/Content/Proxy/AnimationProxy.cs
+++ b/Source/Editor/Content/Proxy/AnimationProxy.cs
@@ -14,6 +14,7 @@ namespace FlaxEditor.Content
/// A asset proxy object.
///
///
+ [ContentContextMenu("New/Animation/Animation")]
public class AnimationProxy : BinaryAssetProxy
{
///
diff --git a/Source/Editor/Content/Proxy/CSharpScriptProxy.cs b/Source/Editor/Content/Proxy/CSharpScriptProxy.cs
index 332695695..a871d0589 100644
--- a/Source/Editor/Content/Proxy/CSharpScriptProxy.cs
+++ b/Source/Editor/Content/Proxy/CSharpScriptProxy.cs
@@ -12,6 +12,7 @@ namespace FlaxEditor.Content
/// Context proxy object for C# script files.
///
///
+ [ContentContextMenu("New/C# Script")]
public class CSharpScriptProxy : ScriptProxy
{
///
diff --git a/Source/Editor/Content/Proxy/CollisionDataProxy.cs b/Source/Editor/Content/Proxy/CollisionDataProxy.cs
index cca8a8192..b6ff2e75f 100644
--- a/Source/Editor/Content/Proxy/CollisionDataProxy.cs
+++ b/Source/Editor/Content/Proxy/CollisionDataProxy.cs
@@ -38,6 +38,7 @@ namespace FlaxEditor.Content
/// A asset proxy object.
///
///
+ [ContentContextMenu("New/Physics/Collision Data")]
class CollisionDataProxy : BinaryAssetProxy
{
///
diff --git a/Source/Editor/Content/Proxy/CppProxy.cs b/Source/Editor/Content/Proxy/CppProxy.cs
index d975b8778..6581dccd2 100644
--- a/Source/Editor/Content/Proxy/CppProxy.cs
+++ b/Source/Editor/Content/Proxy/CppProxy.cs
@@ -75,6 +75,7 @@ namespace FlaxEditor.Content
/// Context proxy object for C++ script files.
///
///
+ [ContentContextMenu("New/C++/C++ Script")]
public class CppScriptProxy : CppProxy
{
///
@@ -98,6 +99,7 @@ namespace FlaxEditor.Content
/// Context proxy object for C++ Json Asset files.
///
///
+ [ContentContextMenu("New/C++/C++ Function Library")]
public class CppStaticClassProxy : CppProxy
{
///
@@ -115,6 +117,7 @@ namespace FlaxEditor.Content
/// Context proxy object for C++ Json Asset files.
///
///
+ [ContentContextMenu("New/C++/C++ Json Asset")]
public class CppAssetProxy : CppProxy
{
///
diff --git a/Source/Editor/Content/Proxy/GameplayGlobalsProxy.cs b/Source/Editor/Content/Proxy/GameplayGlobalsProxy.cs
index 7c8a7268d..af391a8c4 100644
--- a/Source/Editor/Content/Proxy/GameplayGlobalsProxy.cs
+++ b/Source/Editor/Content/Proxy/GameplayGlobalsProxy.cs
@@ -11,6 +11,7 @@ namespace FlaxEditor.Content
/// A asset proxy object.
///
///
+ [ContentContextMenu("New/Gameplay Globals")]
public class GameplayGlobalsProxy : BinaryAssetProxy
{
///
diff --git a/Source/Editor/Content/Proxy/JsonAssetProxy.cs b/Source/Editor/Content/Proxy/JsonAssetProxy.cs
index 3f2863f74..8bfaae384 100644
--- a/Source/Editor/Content/Proxy/JsonAssetProxy.cs
+++ b/Source/Editor/Content/Proxy/JsonAssetProxy.cs
@@ -22,6 +22,7 @@ namespace FlaxEditor.Content
/// Json assets proxy.
///
///
+ [ContentContextMenu("New/Json Asset")]
public abstract class JsonAssetProxy : JsonAssetBaseProxy
{
///
diff --git a/Source/Editor/Content/Proxy/MaterialFunctionProxy.cs b/Source/Editor/Content/Proxy/MaterialFunctionProxy.cs
index 702f04706..f8c868cb5 100644
--- a/Source/Editor/Content/Proxy/MaterialFunctionProxy.cs
+++ b/Source/Editor/Content/Proxy/MaterialFunctionProxy.cs
@@ -11,6 +11,7 @@ namespace FlaxEditor.Content
/// A asset proxy object.
///
///
+ [ContentContextMenu("New/Material/Material Function")]
public class MaterialFunctionProxy : BinaryAssetProxy
{
///
diff --git a/Source/Editor/Content/Proxy/MaterialInstanceProxy.cs b/Source/Editor/Content/Proxy/MaterialInstanceProxy.cs
index 663c191ef..60ff9bc51 100644
--- a/Source/Editor/Content/Proxy/MaterialInstanceProxy.cs
+++ b/Source/Editor/Content/Proxy/MaterialInstanceProxy.cs
@@ -14,6 +14,7 @@ namespace FlaxEditor.Content
/// A asset proxy object.
///
///
+ [ContentContextMenu("New/Material/Material Instance")]
public class MaterialInstanceProxy : BinaryAssetProxy
{
private MaterialPreview _preview;
diff --git a/Source/Editor/Content/Proxy/MaterialProxy.cs b/Source/Editor/Content/Proxy/MaterialProxy.cs
index e2e74eb14..68c9c81b7 100644
--- a/Source/Editor/Content/Proxy/MaterialProxy.cs
+++ b/Source/Editor/Content/Proxy/MaterialProxy.cs
@@ -15,6 +15,7 @@ namespace FlaxEditor.Content
/// A asset proxy object.
///
///
+ [ContentContextMenu("New/Material/Material")]
public class MaterialProxy : BinaryAssetProxy
{
private MaterialPreview _preview;
diff --git a/Source/Editor/Content/Proxy/ParticleEmitterFunctionProxy.cs b/Source/Editor/Content/Proxy/ParticleEmitterFunctionProxy.cs
index 24cc22690..b508bb818 100644
--- a/Source/Editor/Content/Proxy/ParticleEmitterFunctionProxy.cs
+++ b/Source/Editor/Content/Proxy/ParticleEmitterFunctionProxy.cs
@@ -11,6 +11,7 @@ namespace FlaxEditor.Content
/// A asset proxy object.
///
///
+ [ContentContextMenu("New/Particles/Particle Emitter Function")]
public class ParticleEmitterFunctionProxy : BinaryAssetProxy
{
///
diff --git a/Source/Editor/Content/Proxy/ParticleEmitterProxy.cs b/Source/Editor/Content/Proxy/ParticleEmitterProxy.cs
index 089c614da..be07720d2 100644
--- a/Source/Editor/Content/Proxy/ParticleEmitterProxy.cs
+++ b/Source/Editor/Content/Proxy/ParticleEmitterProxy.cs
@@ -15,6 +15,7 @@ namespace FlaxEditor.Content
/// A asset proxy object.
///
///
+ [ContentContextMenu("New/Particles/Particle Emitter")]
public class ParticleEmitterProxy : BinaryAssetProxy
{
private ParticleEmitterPreview _preview;
diff --git a/Source/Editor/Content/Proxy/ParticleSystemProxy.cs b/Source/Editor/Content/Proxy/ParticleSystemProxy.cs
index c19e84a78..38301afdf 100644
--- a/Source/Editor/Content/Proxy/ParticleSystemProxy.cs
+++ b/Source/Editor/Content/Proxy/ParticleSystemProxy.cs
@@ -39,6 +39,7 @@ namespace FlaxEditor.Content
/// A asset proxy object.
///
///
+ [ContentContextMenu("New/Particles/Particle System")]
public class ParticleSystemProxy : BinaryAssetProxy
{
private ParticleSystemPreview _preview;
diff --git a/Source/Editor/Content/Proxy/PrefabProxy.cs b/Source/Editor/Content/Proxy/PrefabProxy.cs
index 64eb1d9f1..a4610b25a 100644
--- a/Source/Editor/Content/Proxy/PrefabProxy.cs
+++ b/Source/Editor/Content/Proxy/PrefabProxy.cs
@@ -15,6 +15,7 @@ namespace FlaxEditor.Content
/// Content proxy for .
///
///
+ [ContentContextMenu("New/Prefab")]
public sealed class PrefabProxy : JsonAssetBaseProxy
{
private PrefabPreview _preview;
diff --git a/Source/Editor/Content/Proxy/SceneProxy.cs b/Source/Editor/Content/Proxy/SceneProxy.cs
index 7856fa064..cecd825a1 100644
--- a/Source/Editor/Content/Proxy/SceneProxy.cs
+++ b/Source/Editor/Content/Proxy/SceneProxy.cs
@@ -10,6 +10,7 @@ namespace FlaxEditor.Content
/// Content proxy for .
///
///
+ [ContentContextMenu("New/Scene")]
public sealed class SceneProxy : JsonAssetBaseProxy
{
///
diff --git a/Source/Editor/Content/Proxy/SettingsProxy.cs b/Source/Editor/Content/Proxy/SettingsProxy.cs
index 0bbd2830f..651ba62d2 100644
--- a/Source/Editor/Content/Proxy/SettingsProxy.cs
+++ b/Source/Editor/Content/Proxy/SettingsProxy.cs
@@ -11,6 +11,7 @@ namespace FlaxEditor.Content
/// Content proxy for json settings assets (e.g or ).
///
///
+ [ContentContextMenu("New/Settings")]
public class SettingsProxy : JsonAssetProxy
{
private readonly Type _type;
diff --git a/Source/Editor/Content/Proxy/ShaderSourceProxy.cs b/Source/Editor/Content/Proxy/ShaderSourceProxy.cs
index 86020c997..9b2ec22d5 100644
--- a/Source/Editor/Content/Proxy/ShaderSourceProxy.cs
+++ b/Source/Editor/Content/Proxy/ShaderSourceProxy.cs
@@ -13,6 +13,7 @@ namespace FlaxEditor.Content
/// Context proxy object for shader source files (represented by ).
///
///
+ [ContentContextMenu("New/Shader Source")]
public class ShaderSourceProxy : ContentProxy
{
///
diff --git a/Source/Editor/Content/Proxy/SkeletonMaskProxy.cs b/Source/Editor/Content/Proxy/SkeletonMaskProxy.cs
index 2a90820b0..ab78a1e09 100644
--- a/Source/Editor/Content/Proxy/SkeletonMaskProxy.cs
+++ b/Source/Editor/Content/Proxy/SkeletonMaskProxy.cs
@@ -11,6 +11,7 @@ namespace FlaxEditor.Content
/// A asset proxy object.
///
///
+ [ContentContextMenu("New/Animation/Skeleton Mask")]
public class SkeletonMaskProxy : BinaryAssetProxy
{
///
diff --git a/Source/Editor/Content/Proxy/VisualScriptProxy.cs b/Source/Editor/Content/Proxy/VisualScriptProxy.cs
index b065a4fcd..afd105131 100644
--- a/Source/Editor/Content/Proxy/VisualScriptProxy.cs
+++ b/Source/Editor/Content/Proxy/VisualScriptProxy.cs
@@ -15,6 +15,7 @@ namespace FlaxEditor.Content
/// A asset proxy object.
///
///
+ [ContentContextMenu("New/Visual Script")]
public class VisualScriptProxy : BinaryAssetProxy, IScriptTypesContainer
{
internal VisualScriptProxy()
diff --git a/Source/Editor/Windows/ContentWindow.ContextMenu.cs b/Source/Editor/Windows/ContentWindow.ContextMenu.cs
index 7368c4efd..56cba9b9e 100644
--- a/Source/Editor/Windows/ContentWindow.ContextMenu.cs
+++ b/Source/Editor/Windows/ContentWindow.ContextMenu.cs
@@ -39,7 +39,6 @@ namespace FlaxEditor.Windows
// Create context menu
ContextMenuButton b;
- ContextMenuChildMenu c;
ContextMenu cm = new ContextMenu
{
Tag = item
@@ -149,22 +148,77 @@ namespace FlaxEditor.Windows
{
cm.AddButton("New folder", NewFolder);
}
-
- c = cm.AddChildMenu("New");
- c.ContextMenu.Tag = item;
- c.ContextMenu.AutoSort = true;
- int newItems = 0;
- for (int i = 0; i < Editor.ContentDatabase.Proxy.Count; i++)
+
+ // loop through each proxy and user defined json type and add them to the context menu
+ foreach (var type in Editor.CodeEditing.All.Get())
{
- var p = Editor.ContentDatabase.Proxy[i];
+ if (type.IsAbstract || !type.HasAttribute(typeof(ContentContextMenuAttribute), true) || Editor.CodeEditing.Actors.Get().Contains(type) || Editor.CodeEditing.Scripts.Get().Contains(type))
+ continue;
+
+ ContentContextMenuAttribute attribute = null;
+ foreach (var typeAttribute in type.GetAttributes(true))
+ {
+ if (typeAttribute is ContentContextMenuAttribute contentContextMenuAttribute)
+ {
+ attribute = contentContextMenuAttribute;
+ break;
+ }
+ }
+
+ ContentProxy p;
+ if (type.Type.IsSubclassOf(typeof(ContentProxy)))
+ {
+ p = Editor.ContentDatabase.Proxy.Find(T => T.GetType() == type.Type);
+ }
+ else
+ {
+ // user can use attribute to put their own assets into the content context menu
+ var generic = typeof(SpawnableJsonAssetProxy<>).MakeGenericType(type.Type);
+ var instance = Activator.CreateInstance(generic);
+ p = instance as AssetProxy;
+ }
+
+ if (p == null)
+ continue;
+
+ // create menus
if (p.CanCreate(folder))
{
- c.ContextMenu.AddButton(p.Name, () => NewItem(p));
- newItems++;
+ var splitPath = attribute.Path.Split('/');
+ ContextMenuChildMenu childCM = null;
+ bool mainCM = true;
+ for (int i = 0; i < splitPath?.Length; i++)
+ {
+ if (i == splitPath.Length - 1)
+ {
+ if (mainCM)
+ {
+ cm.AddButton(splitPath[i].Trim(), () => NewItem(p));
+ mainCM = false;
+ }
+ else
+ {
+ childCM?.ContextMenu.AddButton(splitPath[i].Trim(), () => NewItem(p));
+ childCM.ContextMenu.AutoSort = true;
+ }
+ }
+ else
+ {
+ if (mainCM)
+ {
+ childCM = cm.GetOrAddChildMenu(splitPath[i].Trim());
+ mainCM = false;
+ }
+ else
+ {
+ childCM = childCM?.ContextMenu.GetOrAddChildMenu(splitPath[i].Trim());
+ }
+ childCM.ContextMenu.AutoSort = true;
+ }
+ }
}
}
- c.Enabled = newItems > 0;
-
+
if (folder.CanHaveAssets)
{
cm.AddButton("Import file", () =>
diff --git a/Source/Engine/Physics/PhysicalMaterial.h b/Source/Engine/Physics/PhysicalMaterial.h
index 0d8356546..b46c1a294 100644
--- a/Source/Engine/Physics/PhysicalMaterial.h
+++ b/Source/Engine/Physics/PhysicalMaterial.h
@@ -8,7 +8,7 @@
///
/// Physical materials are used to define the response of a physical object when interacting dynamically with the world.
///
-API_CLASS() class FLAXENGINE_API PhysicalMaterial final : public ISerializable
+API_CLASS(Attributes = "ContentContextMenu(\"New/Physics/Physical Material\")") class FLAXENGINE_API PhysicalMaterial final : public ISerializable
{
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_MINIMAL(PhysicalMaterial);
diff --git a/Source/Engine/Scripting/Attributes/Editor/ContentContextMenu.cs b/Source/Engine/Scripting/Attributes/Editor/ContentContextMenu.cs
new file mode 100644
index 000000000..ee9956ede
--- /dev/null
+++ b/Source/Engine/Scripting/Attributes/Editor/ContentContextMenu.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace FlaxEngine
+{
+ ///
+ /// This attribute is used to show content items that can be created in the content browser context menu. Separate the subcontext menus with a /.
+ ///
+ [Serializable]
+ [AttributeUsage(AttributeTargets.Class)]
+ public class ContentContextMenuAttribute : Attribute
+ {
+ ///
+ /// The path to be used in the context menu
+ ///
+ public string Path;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The path to use to create the context menu
+ public ContentContextMenuAttribute(string path)
+ {
+ Path = path;
+ }
+ }
+}