[Unity Editor] Expand the Hierarchy View

Table of contents

1. Expand the menu

2. Expand the layout

3. Rewrite the menu


1. Expand the menu

Click the Create button in the Hierarchy view, the pop-up menu My Create->Cube is the custom expansion menu

using UnityEngine;
using UnityEditor;

public class S2_拓展菜单 : MonoBehaviour
{
    [MenuItem("GameObject/My Create/Cube" , false , 0)]
    static void CreateCube()
    {
        GameObject.CreatePrimitive(PrimitiveType.Cube);
    }
}

The menu already contains some default menu items of the system. The principle of our expansion is to rewrite the custom path of MenuItem. The menu items under the Create button are all under the GameObject path, so as long as the beginning is GameObject/xx/xx, they can be freely expanded.

2. Expand the layout

After selecting a different game object, a group of buttons can be expanded on the right according to the EditorGUI. After clicking the Unity icon, enter the game object in the Console window.

The working principle is to listen to the EditorApplication.hierarchyWindowItemOnGUI rendering callback

using UnityEditor;
using UnityEngine;

public class S2_拓展布局 : MonoBehaviour
{
    [InitializeOnLoadMethod]
    static void InitializeOnLoadMethod()
    {
        EditorApplication.hierarchyWindowItemOnGUI = delegate (int instanceID, Rect selectionRect)
        {
            //在Hierarchy视图中选择一个资源
            if (Selection.activeObject && instanceID == Selection.activeObject.GetInstanceID())
            {
                //设置拓展按钮区域
                float width = 40f;
                float height = 20f;
                selectionRect.x += (selectionRect.width - width);
                selectionRect.width = width;
                selectionRect.height = height;

                //点击事件
                if (GUI.Button(selectionRect, AssetDatabase.LoadAssetAtPath<Texture>("Assets/unity.png")))
                {
                    Debug.LogFormat("click:{0}", Selection.activeObject.name);
                }
            }
        };
    }
}

Implement the EditorApplication.hierarchyWindowItemOnGUI delegate in the code to rewrite the Hierarchy view.

Here GUI.Button is used to draw a custom button, and click the button to listen to the event.

3. Rewrite the menu

Completely rewrite the menu

How it works: Listen to click events and open a new menu window

Use Event.current to get the current event. When the mouse-up event is detected and the selected state of the game object is satisfied, the custom event is executed.

EditorUtility.DisplayPopupMenu is used to pop up a custom menu, and the meaning of Event.current.Use() is to no longer perform the original operation, so the rewriting menu is realized.

using UnityEngine;
using UnityEditor;
using GluonGui.WorkspaceWindow.Views.WorkspaceExplorer.Explorer;

public class S2_重写菜单
{
    [MenuItem("Window/Test/自定义工具")]
    static void Test()
    {

    }

    [MenuItem("Window/Test/自定义2")]
    static void Test1()
    {

    }

    [MenuItem("Window/Test/自定义3/MOMO")]
    static void Test2()
    {

    }

    [InitializeOnLoadMethod]
    static void StartInitializeOnLoadMethod()
    {
        EditorApplication.hierarchyWindowItemOnGUI += OnHierarchyGUI;
    }

    static void OnHierarchyGUI(int instanceID , Rect selectionRect)
    {
        if(Event.current != null && selectionRect.Contains(Event.current.mousePosition) && Event.current.button == 1 && Event.current.type <= EventType.MouseUp) {
            GameObject selectedGameObject = EditorUtility.InstanceIDToObject(instanceID) as GameObject;

            //这里可以判断selectedGameObject的条件
            if (selectedGameObject)
            {
                Vector2 mousePosition = Event.current.mousePosition;

                EditorUtility.DisplayPopupMenu(new Rect(mousePosition.x, mousePosition.y, 0, 0), "Window/Test", null);	//用于弹出自定义菜单
                Event.current.Use();	//不再执行原有操作,所以实现了重写
            }
        }
    }
}

In addition, the Hierarchy view can also override the menu behavior that comes with the system. For example: I think the Image component is not easy to use, and its behavior can be overridden.

When creating an Image component, RaycastTarget is automatically checked. If the image does not need to handle click events, this will cause additional overhead.

The following is the logic of rewriting the Image component, so that RaycastTarget is not checked by default

using UnityEngine;
using UnityEditor;
using UnityEngine.UI;

public class S2_重写组件设置
{
    [MenuItem("GameObject/UI/Image")]
    static void CreatImage()
    {
        if (Selection.activeTransform)
        {
            if(Selection.activeTransform.GetComponentInParent<Canvas>())
            {
                Image image = new GameObject("image").AddComponent<Image>();    
                image.raycastTarget = false;
                image.transform.SetParent(Selection.activeTransform , false);
                
                //设置选中状态
                Selection.activeTransform = image.transform;
            }
        }
    }
}

Since the menu is rewritten, the Image object and components need to be created by using scripts. Then, get the image component object and directly set its raycastTarget property.

Guess you like

Origin blog.csdn.net/weixin_60154963/article/details/130495043