Skip to content

Instantly share code, notes, and snippets.

@SolarianZ
Last active May 14, 2024 05:18
Show Gist options
  • Save SolarianZ/e20ee9aa0c0caaa2aff6ced6a07d7a00 to your computer and use it in GitHub Desktop.
Save SolarianZ/e20ee9aa0c0caaa2aff6ced6a07d7a00 to your computer and use it in GitHub Desktop.
{"category": "Unity Engine/Editor/Extensions", "keywords": "Unity, Editor, Dynamic, Modify, Menu Item, MenuItemAttribute"} Modify menu items dynamically, no need for MenuItemAttribute.
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
/// <summary>
/// Modify menu items dynamically, no need for MenuItemAttribute.
/// Some methods are not available in earlier versions of Unity.
/// </summary>
public static class DynamicMenuItem
{
private const BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Static;
public static event Action menuChanged
{
// Exeption thrown on using EventInfo.AddEventHandler and EventInfo.RemoveEventHandler:
// System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
// ---> System.InvalidOperationException: Cannot add the event handler since no public add method exists for the event.
add => typeof(Menu).GetEvent("menuChanged", bindingFlags)
.GetAddMethod(true).Invoke(null, new object[] { value });
remove => typeof(Menu).GetEvent("menuChanged", bindingFlags)
.GetRemoveMethod(true).Invoke(null, new object[] { value });
}
public static void AddMenuItem(string name, string shortcut, bool @checked, int priority, Action execute, Func<bool> validate)
{
typeof(Menu).GetMethod("AddMenuItem", bindingFlags)
.Invoke(null, new object[] { name, shortcut, @checked, priority, execute, validate });
}
public static void RemoveMenuItem(string name)
{
typeof(Menu).GetMethod("RemoveMenuItem", bindingFlags)
.Invoke(null, new object[] { name });
}
public static void AddSeparator(string name, int priority)
{
if (!name.EndsWith("/"))
{
name = name.Insert(name.Length, "/");
}
typeof(Menu).GetMethod("AddSeparator", bindingFlags)
.Invoke(null, new object[] { name, priority });
}
public static bool MenuItemExists(string menuPath)
{
bool menuItemExists = (bool)typeof(Menu).GetMethod("MenuItemExists", bindingFlags)
.Invoke(null, new object[] { menuPath });
return menuItemExists;
}
public static string[] ExtractSubmenus(string menuPath)
{
string[] submenus = (string[])typeof(Menu).GetMethod("ExtractSubmenus", bindingFlags)
.Invoke(null, new object[] { menuPath });
return submenus;
}
public static void SetChecked(string menuPath, bool isChecked) => Menu.SetChecked(menuPath, isChecked);
public static bool GetChecked(string menuPath) => Menu.GetChecked(menuPath);
public static bool GetEnabled(string menuPath) => Menu.GetEnabled(menuPath);
#if UNITY_2023_3_OR_NEWER
public static bool GetEnabledWithContext(string menuPath, UnityEngine.Object[] context)
{
bool enabledWithContext = (bool)typeof(Menu).GetMethod("GetEnabledWithContext", bindingFlags)
.Invoke(null, new object[] { menuPath, context });
return enabledWithContext;
}
public static void UpdateContextMenu(UnityEngine.Object[] context, int userData)
{
typeof(Menu).GetMethod("UpdateContextMenu", bindingFlags)
.Invoke(null, new object[] { context, userData });
}
public static string GetHotkey(string menuPath)
{
string hotkey = (string)typeof(Menu).GetMethod("GetHotkey", bindingFlags)
.Invoke(null, new object[] { menuPath });
return hotkey;
}
#endif
public static void SetHotkey(string menuPath, string hotkey)
{
typeof(Menu).GetMethod("SetHotkey", bindingFlags)
.Invoke(null, new object[] { menuPath, hotkey });
}
public static void GetMenuItemDefaultShortcuts(List<string> itemNames, List<string> outItemDefaultShortcuts)
{
typeof(Menu).GetMethod("GetMenuItemDefaultShortcuts", bindingFlags)
.Invoke(null, new object[] { itemNames, outItemDefaultShortcuts });
}
/// <summary>
/// Will clear all dynamic menus.
/// </summary>
public static void RebuildAllMenus()
{
typeof(Menu).GetMethod("RebuildAllMenus", bindingFlags)
.Invoke(null, null);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment