Exemple #1
0
        private static IEnumerable <Command> ScanAttributes()
        {
            var commands = new List <Command>();

            foreach (var mi in TypeCache.GetMethodsWithAttribute <CommandHandlerAttribute>())
            {
                if (!(Delegate.CreateDelegate(typeof(CommandHandler), mi) is CommandHandler callback))
                {
                    continue;
                }

                foreach (var attr in mi.GetCustomAttributes <CommandHandlerAttribute>())
                {
                    if (commands.Any(c => c.id == attr.id))
                    {
                        Debug.LogWarning($"There is already a command with the ID {attr.id}. " +
                                         "Commands need to have a unique ID, i.e. \"Unity/Category/Command_42\".");
                        continue;
                    }

                    commands.Add(new Command {
                        id = attr.id, label = attr.label ?? attr.id, hint = attr.hint, handler = callback, managed = true
                    });
                }
            }

            return(commands);
        }
        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();
        }
        static MethodInfo GetCustomSelectorHandlerForAttribute(Attribute attribute)
        {
            var methodsWithHandler = TypeCache.GetMethodsWithAttribute(typeof(ObjectSelectorHandlerAttribute));

            foreach (var methodWithHandler in methodsWithHandler)
            {
                var selectorHandlerAttributes = methodWithHandler.GetCustomAttributes(typeof(ObjectSelectorHandlerAttribute), false).OfType <ObjectSelectorHandlerAttribute>();
                foreach (var selectorHandlerAttribute in selectorHandlerAttributes)
                {
                    if (selectorHandlerAttribute.attributeType == attribute.GetType())
                    {
                        return(methodWithHandler);
                    }
                }
            }

            return(null);
        }
        private static void ProcessInitializeOnLoadMethodAttributes()
        {
            bool reportTimes = (bool)Debug.GetDiagnosticSwitch("EnableDomainReloadTimings").value;

            foreach (var method in TypeCache.GetMethodsWithAttribute <InitializeOnLoadMethodAttribute>())
            {
                using (new EditorPerformanceMarker($"InitializeOnLoad {method.DeclaringType?.Name}.{method.Name}", method.DeclaringType).Auto())
                    using (_profilerMarkerProcessInitializeOnLoadMethodAttributes.Auto(reportTimes, () => $"{method.DeclaringType?.FullName}::{method.Name}"))
                    {
                        try
                        {
                            method.Invoke(null, null);
                        }
                        catch (Exception x)
                        {
                            Debug.LogError(x);
                        }
                    }
            }
        }
        // Invokes the menu item in the specified path.
        public static bool ExecuteMenuItem(string menuItemPath)
        {
            var sanitizedPath = MenuService.SanitizeMenuItemName(menuItemPath);
            var isDefaultMode = ModeService.currentId == ModeService.k_DefaultModeId;
            var result        = ExecuteMenuItemInternal(sanitizedPath, isDefaultMode);

            if (result)
            {
                return(result);
            }

            if (!isDefaultMode)
            {
                var menuItems = TypeCache.GetMethodsWithAttribute <MenuItem>();
                foreach (var item in menuItems)
                {
                    MenuItem itemData = (MenuItem)item.GetCustomAttributes(typeof(MenuItem), false)[0];
                    if (!itemData.validate && itemData.menuItem == sanitizedPath)
                    {
                        if (item.GetParameters().Length == 0)
                        {
                            item.Invoke(null, new object[0]);
                            return(true);
                        }
                        else if (item.GetParameters()[0].ParameterType == typeof(MenuCommand))
                        {
                            item.Invoke(null, new[] { new MenuCommand(null) });
                            return(true);
                        }
                        break;
                    }
                }

                Debug.LogError($"ExecuteMenuItem failed because there is no menu named '{menuItemPath}'");
            }

            return(false);
        }
Exemple #6
0
        internal static void DrawHint(Rect hintTriggerRect, Vector2 mousePosition, AssetReference assetReference)
        {
            if (!hintTriggerRect.Contains(mousePosition) || !GUIClip.visibleRect.Contains(mousePosition))
            {
                return;
            }

            string assetPath = AssetDatabase.GUIDToAssetPath(assetReference.guid);
            var    assetType = AssetDatabase.GetMainAssetTypeAtPath(assetPath);

            if (assetType == null) //this means the object or its base script has been deleted and is "Missing"
            {
                return;
            }

            var hintGenerators = TypeCache.GetMethodsWithAttribute <DynamicHintGeneratorAttribute>();

            if (assetType.IsSubclassOf(typeof(ScriptableObject)))
            {
                DynamicHintContent hint = GetDynamicHintContentOf(hintGenerators, assetType, assetPath);
                if (hint != null)
                {
                    DrawMouseTooltip(hint, hintTriggerRect);
                }
                return;
            }

            if (assetType == typeof(GameObject))
            {
                /* GameObjects can have multiple components with custom tooltips
                 * so for now we'll just display the first one.
                 * If needed, we could:
                 * 1) Implement a "priority system" (like OrderedCallbacks)
                 * 2) Display one big tooltip made up with all elements from custom tooltip
                 */

                GameObject assetGameObject = (GetLoadedObjectFromInstanceID(assetReference.instanceID) as GameObject);
                if (!assetGameObject)
                {
                    /* this seems to happen non-deterministically at project startup depending of what the user is hovering when the editor opens,
                     * or while the user is scrolling a list of objects and hovers one of them casually, even if the object hovered is actually a
                     * GameObject.
                     * */
                    return;
                }

                foreach (var component in assetGameObject.GetComponents <Component>())
                {
                    if (component == null)
                    {
                        continue;
                    }                                    //this means its script has been deleted and is "Missing"

                    DynamicHintContent hint = GetDynamicHintContentOf(hintGenerators, component.GetType(), string.Empty, component);
                    if (hint == null)
                    {
                        continue;
                    }

                    DrawMouseTooltip(hint, hintTriggerRect);
                    return;
                }
            }
        }