internal void CleanUp() { for (int i = 0; i < m_Children.Count;) { if (m_Children[i].m_Children.Count > 0 || (m_Children[i].m_Children.Count == 0 && m_Children[i].value == null)) // CleanUp intermediate menu { m_Children[i].CleanUp(); if (m_Children[i].m_Children.Count == 0) // If clean up removed every children of that child we need to remove that child { m_Children.RemoveAt(i); continue; } } else { MenuItemScriptCommand menuItem = m_Children[i].value as MenuItemScriptCommand; if (menuItem != null && menuItem.IsNotValid) { m_Children.RemoveAt(i); continue; } } ++i; } }
// Find menus from command id private static void LoadMenuFromCommandId(IList menus, Dictionary <string, MenuItemScriptCommand> menuItems, string prefix = "") { if (menus == null || menuItems == null) { return; } foreach (var menuData in menus) { if (menuData != null) { var menu = menuData as JSONObject; if (menu == null) { continue; } var isInternal = JsonUtils.JsonReadBoolean(menu, k_MenuKeyInternal); if (isInternal && !Unsupported.IsDeveloperMode()) { continue; } var menuName = JsonUtils.JsonReadString(menu, k_MenuKeyName); var fullMenuName = prefix + menuName; var platform = JsonUtils.JsonReadString(menu, k_MenuKeyPlatform); // Check the menu item platform if (!string.IsNullOrEmpty(platform) && !Application.platform.ToString().ToLowerInvariant().StartsWith(platform.ToLowerInvariant())) { continue; } // Check if we are a submenu if (menu.Contains(k_MenuKeyChildren)) { if (menu[k_MenuKeyChildren] is IList children) { LoadMenuFromCommandId(children, menuItems, fullMenuName + "/"); } } else { var commandId = JsonUtils.JsonReadString(menu, k_MenuKeyCommandId); if (!string.IsNullOrEmpty(commandId) && CommandService.Exists(commandId)) { // Create a new menu item pointing to a command handler var shortcut = JsonUtils.JsonReadString(menu, k_MenuKeyShortcut); var @checked = JsonUtils.JsonReadBoolean(menu, k_MenuKeyChecked); var validateCommandId = JsonUtils.JsonReadString(menu, k_MenuKeyValidateCommandId); var commandMenuItem = MenuItemScriptCommand.InitializeFromCommand(fullMenuName, 100, commandId, validateCommandId); commandMenuItem.@checked = @checked; commandMenuItem.shortcut = shortcut; menuItems[fullMenuName] = commandMenuItem; } } } } }
private static void ExtractMenuItemsFromAttributes() { s_MenuItemsPerMode = new Dictionary <string, MenuItemsTree <MenuItemScriptCommand> >(); s_MenuItemsDefaultMode = new Dictionary <string, MenuItemScriptCommand>(); var menuItems = TypeCache.GetMethodsWithAttribute <MenuItem>(); // Order the menu items to start with Unity menus before projects menus. That way if there is a duplicate, the project one is flagged as duplicate foreach (var methodInfo in menuItems.OrderBy(m => !Utility.FastStartsWith(m.DeclaringType.Assembly.FullName, "UnityEditor", "unityeditor"))) { if (!ValidateMethodForMenuCommand(methodInfo)) { continue; } foreach (var attribute in methodInfo.GetCustomAttributes(typeof(MenuItem), false)) { string menuName = SanitizeMenuItemName(((MenuItem)attribute).menuItem); string[] editorModes = ((MenuItem)attribute).editorModes; foreach (var editorMode in editorModes) { if (editorMode == k_DefaultModeId) { if (s_MenuItemsDefaultMode.TryGetValue(menuName, out var menuItem)) { menuItem.Update((MenuItem)attribute, methodInfo); } else { s_MenuItemsDefaultMode.Add(menuName, MenuItemScriptCommand.Initialize(menuName, (MenuItem)attribute, methodInfo)); } } else { if (s_MenuItemsPerMode.TryGetValue(editorMode, out var menuItemsPerMode)) { MenuItemScriptCommand menuItem = menuItemsPerMode.FindItem(menuName); if (menuItem == null) { menuItemsPerMode.AddChildSearch(MenuItemScriptCommand.Initialize(menuName, (MenuItem)attribute, methodInfo)); } else { menuItem.Update((MenuItem)attribute, methodInfo); } } else { var newMenusPerMode = new MenuItemsTree <MenuItemScriptCommand>(); newMenusPerMode.AddChildSearch(MenuItemScriptCommand.Initialize(menuName, (MenuItem)attribute, methodInfo)); s_MenuItemsPerMode.Add(editorMode, newMenusPerMode); } } } } } CleanUpInvalidMenuItems(); }
internal static MenuItemScriptCommand InitializeFromCommand(string fullMenuName, int priority, string commandId, string validateCommandId) { var menuItem = new MenuItemScriptCommand() { name = fullMenuName, priority = priority, commandExecute = new Action(() => CommandService.Execute(commandId, CommandHint.Menu)) }; if (!string.IsNullOrEmpty(validateCommandId)) { menuItem.commandValidate = new Func <bool>(() => (bool)CommandService.Execute(commandId, CommandHint.Menu | CommandHint.Validate)); } return(menuItem); }