It's possible to create MenuItems with out attributes?

Hi,

I want to know if it’s possible to create a Menu Item without using it’s attribute. For example, I want to know if there is a possible way to make it for example by calling a method:

EditorMenu.CreateNewMenu(const string menu_name, Action method_to_execute);

I’m saying it, in a theoretical way, but I don’t know really if this is possible. And the Unity Docs doesn’t say anything.

Thanks in advance!

Sorry for necroing, but this is first article in google on this topic.

Actually its possible and quite easy, unity doing this trough internal class UnityEditor.Menu.
image

It has methods to both add and remove menu items
image

However since its internal class you can access it trough reflections or by creating *.asmref file to make your scripts part of the unity assembly. In assembly reference file you should reference some unity editor assembly, for example UnityEditor.UI

You can create public wrapper to access these internal methods:

using System;
using UnityEditor;

public static class _Menu
{
    public static void RemoveMenuItem(string name) => Menu.RemoveMenuItem(name);
    public static bool MenuItemExists(string menuPath) => Menu.MenuItemExists(menuPath);

    public static void AddMenuItem(string name, string shortcut, bool @checked, int priority, 
        Action execute, Func<bool> validate)
    {
        Menu.AddMenuItem(name, shortcut, @checked, priority, execute, validate);
    }
}

Then to dynamically add/remove menu you can do something like this:

private const string MENU_PATH = "Asset/SubMenu/Etc";
private static bool MENU_SHOULD_EXIST = true;
        
[InitializeOnLoadMethod]
private static void Init()
{
    EditorApplication.delayCall += VerifyCreateMenu;
}
        
public static void VerifyMenu()
{
    var menuExist = _Menu.MenuItemExists(MENU_PATH);
    var menuShouldExist = MENU_SHOULD_EXIST; // Here check your preferences is menu should or should not exist.
    
    // Menu is removed but should be added
    if (!menuExist && menuShouldExist)
    {
        _Menu.AddMenuItem(PATH, "", false, 15,
            () =>
            {
                // Menu execute callback
            }, () => true);
    }
    // Menu exist but should be removed
    else if (menuExist && !menuShouldExist)
    {
        _Menu.RemoveMenuItem(PATH);
    }
}

Usage of EditorApplication.delayCall += VerifyCreateMenu; is required to let unity finish all its native menu population process, else your new menu can get lost.

No, because Unity doesn’t support adding / removing menu items dynamically at the moment. So the only way currently is to use the MenuItem attribute. The menu items will be “created” / “removed” when the scripting environment is reloaded which happens after each recompile.

edit
I just saw that question again and thought i should add some more information ^^.

While adding / removing native menu items is not supported by the editor, you could of course create your own “submenu” using an EditorWindow. You can show it borderless as tool window or popup. Simply close it when it looses focus. So you would have a static menuitem which just opens your “custom menu”.

Another solution could be to use a GenericMenu which you open when you click on a static MenuItem.

The biggest problems with both approaches would be to determine where your menu should be positioned. However here some WinAPI magic could help a bit.

However, just using WinAPI to “inject” custom menus is going to be quite difficult. You most likely should be able to use the Menu API of windows to access and change / add a menu item. However the main problem is to actually get the window messages when an item is clicked. It should theoretically be possible to just change an existing menuitem with that API. To actually handle completely custom menu items you would need to hook into the message queue of the Unity application window. Installing hooks is a topic of it’s own. It has to be done using a native DLL with the same architecture as the target application (32 / 64 bit).

I think thats a bit too much just to “add some menu items” into the main menu. It could also break or confuse the Unity application itself if you tamper with it’s menu. I wouldn’t recommend this. Using an EditorWindow or a GenericMenu is much safer and is cross-platform (in case someone uses mac or linux)

Ps: in case you want to play with the win API, here’s how the unity editor window structure looks like. The output here is
WindowClassName(#HWND) - Window title.

Note that the “UnityContainerWndClass” is the windowclass for both, the main window as well as all other floating container windows (when you undock a tab). So finding the main window using FindWindow would not work very well. EnumWindows is usually the better solution.