I can create MenuItem using the attribute on a static method; I was wondering, is it possible to add menu items in editor code?
Eg. Run through all types of certain basetype through reflection, add creation menuitem for every non-abstract type
I can create MenuItem using the attribute on a static method; I was wondering, is it possible to add menu items in editor code?
Eg. Run through all types of certain basetype through reflection, add creation menuitem for every non-abstract type
So I made a boo macro that does what I needed. Not exactly adding menuItems in runtime, but at least dynamically during compilation; Since C# doesn’t support any kind of macros, here’s my example class written in BOO. It has to be placed in Editor folder (so the runtime assemblies are already loaded and can be looked into)
This particular case creates a MenuItem creation method for every class that derives from Framework.Entity and isn’t abstract.
namespace Framework.Editor
macro GenerateMenuItems:
for assembly in System.AppDomain.CurrentDomain.GetAssemblies():
try:
types = assembly.GetTypes();
except e:
continue
for type in types:
baseType = Framework.Entity
if type.IsAbstract: continue
if baseType.IsAssignableFrom(type):
typeName = type.Name;
methodName = "MenuItem_$(typeName)"
menuPath = "GameObject/Entity/$typeName"
yield [|
[UnityEditor.MenuItem($menuPath)]
public static def $methodName():
Framework.Entity.CreateEntity_Editor[of $type]()
return
|]
class EntityCreationMenu:
GenerateMenuItems
After the compilation, the class (decompiled using ILSpy) looks like this:
[Serializable]
public class EntityCreationMenu
{
[MenuItem("GameObject/Entity/Entity")]
public static void MenuItem_Entity()
{
Entity.CreateEntity_Editor<Entity>();
}
[MenuItem("GameObject/Entity/TriggerDelay")]
public static void MenuItem_TriggerDelay()
{
Entity.CreateEntity_Editor<TriggerDelay>();
}
[MenuItem("GameObject/Entity/TriggerIsDead")]
public static void MenuItem_TriggerIsDead()
{
Entity.CreateEntity_Editor<TriggerIsDead>();
}
[MenuItem("GameObject/Entity/TriggerOnEnter")]
public static void MenuItem_TriggerOnEnter()
{
Entity.CreateEntity_Editor<TriggerOnEnter>();
}
//...................... and so on
No that’s not possible. Attributes are part of the compiled code. They are simply metadata stored directly in the compiled code, So you can’t add MenuItems dynamically. Even if it would be possible since they are just metadata they don’t do anything on their own. The Unity editor is searching for the attributes when the code has finished compilation and build the menus based on that metadata. This is only done once after the code has been compiled or a an asset import as been completed.
For such a feature Unity would need to add an API to the editor to query, delete and add menu items dynamically which unfortunately doesn’t exist (yet).
You can’t add an arbitrary number of menu items AFAIK, and I’d like to be wrong about that. This, BTW, seems like basic stuff the Editor should have supported from Day 1. Anyway, those strings in the MenuItem attribute don’t have to be baked in. They can be static string vars, you can change them programatically. So if you know how many you’ll have, you can fill them in on the fly.