Unity 编辑器篇|(二)GenericMenu自定义弹出式菜单

2024-01-09 10:58:38

1. 前言

  • GenericMenu 是 Unity 中的一个强大的类,用于创建和管理自定义上下文菜单(也称为弹出菜单)。可以使用 GenericMenu 来为编辑器中的不同场合或场景元素创建自定义右键单击菜单,以提供各种操作选项。
    1
方法描述
allowDuplicateNames允许菜单具有多个同名的菜单项。
AddDisabledItem向菜单添加已禁用的项。
AddItem向菜单添加一个项。
AddSeparator向菜单添加一个分隔符项。
DropDown在给定屏幕矩形中显示菜单。
GetItemCount获取菜单中的项数。
ShowAsContext右键单击时在鼠标下显示菜单。
MenuFunction回调函数,菜单项选中时调用。
MenuFunction2带有用户数据的回调函数,菜单项选中时调用。
 // 创建一个通用菜单
 GenericMenu menu = new GenericMenu();
 
 //添加一个不可用并且勾选的菜单项RGB/Blue
 menu.AddDisabledItem(new GUIContent("RGB/Blue"), true);
 
 //添加一个菜单项RGB/Red,并且传入一个有参回调
 menu.AddItem(new GUIContent("RGB/Red"), false, OnColorSelected, Color.red);
 
 //添加一个菜单项RGB/Green,并且传入一个无参回调
 menu.AddItem(new GUIContent("RGB/Green"), true, OnColorSelected);
 
//添加一个分割线
 menu.AddSeparator("");
 
 //允许重命名
 menu.allowDuplicateNames = true;
 
 //添加两个名称一样的菜单项
 menu.AddItem(new GUIContent("CMYK"), true, OnColorSelected);
 menu.AddItem(new GUIContent("CMYK"), true, OnColorSelected);
 
 // 以右键菜单的形式展示菜单
 menu.ShowAsContext();

using UnityEngine;
using UnityEditor;

public class GenericMenuExample : EditorWindow
{
    [MenuItem("Example/GUI Color")]
    static void Init()
    {
        EditorWindow window = GetWindow<GenericMenuExample>();
        window.position = new Rect(50f, 50f, 200f, 24f);
        window.Show();
    }

    [SerializeField]
    Color m_Color = Color.white;

    void OnEnable()
    {
        titleContent = new GUIContent("GUI Color");
    }

    void AddMenuItemForColor(GenericMenu menu, string menuPath, Color color)
    {
        menu.AddItem(new GUIContent(menuPath), m_Color.Equals(color), OnColorSelected, color);
    }

    void OnColorSelected(object color)
    {
        m_Color = (Color)color;
    }

    void OnGUI()
    {
        GUI.color = m_Color;

        if (GUILayout.Button("Select GUI Color"))
        {
            GenericMenu menu = new GenericMenu();

            AddMenuItemForColor(menu, "RGB/Red", Color.red);
            AddMenuItemForColor(menu, "RGB/Green", Color.green);
            AddMenuItemForColor(menu, "RGB/Blue", Color.blue);

            menu.AddSeparator("");

            AddMenuItemForColor(menu, "CMYK/Cyan", Color.cyan);
            AddMenuItemForColor(menu, "CMYK/Yellow", Color.yellow);
            AddMenuItemForColor(menu, "CMYK/Magenta", Color.magenta);
            menu.AddSeparator("CMYK/");
            AddMenuItemForColor(menu, "CMYK/Black", Color.black);

            menu.AddSeparator("");

            AddMenuItemForColor(menu, "White", Color.white);

            menu.ShowAsContext();
        }
    }
}

在这里插入图片描述

2. Scene视图添加自定义菜单

  • 通过 SceneView.duringSceneGui 注册了一个回调函数 OnSceneGUI。当在 Scene 视图中使用鼠标右键点击时,将触发 GenericMenu 的创建和显示,显示两个选项 “Option 1” 和 “Option 2”。这里使用了 ShowAsContext() 方法以上下文菜单的方式展示。
using UnityEditor;
using UnityEngine;

public class TestGenericMenu : MonoBehaviour
{
    [InitializeOnLoadMethod]
    private static void SceneViewExtensions()
    {
        // 注册 SceneView 的回调函数
        SceneView.duringSceneGui += OnSceneGUI;
    }

    private static void OnSceneGUI(SceneView sceneView)
    {
        // 在 Scene 视图中的鼠标位置创建 GenericMenu
        Event guiEvent = Event.current;
        Vector2 mousePosition = guiEvent.mousePosition;
        // 通过鼠标右键触发菜
        if (guiEvent.type == EventType.MouseDown && guiEvent.button == 1)
        {
            GenericMenu menu = new GenericMenu();
            menu.AddItem(new GUIContent("Option 1"), false, Option1Selected);
            menu.AddItem(new GUIContent("Option 2"), false, Option2Selected);

            menu.ShowAsContext(); // 以上下文菜单方式显示
            guiEvent.Use(); // 标记事件已被处理
        }
    }

    private static void Option1Selected()
    {
        Debug.Log("Option 1 selected!");
    }

    private static void Option2Selected()
    {
        Debug.Log("Option 2 selected!");
    }
}

2

3. Hierarchy视图添加自定义菜单

  • 通过EditorApplication.hierarchyWindowItemOnGUI 来注册 OnHierarchyGUI 方法作为 Hierarchy 视图中的每个项的 GUI 回调函数。当右键点击 Hierarchy 视图中的 GameObject 时,将创建一个包含 “Option 1” 和 “Option 2” 两个选项的 GenericMenu 菜单,并在点击时触发相应的方法。
using UnityEditor;
using UnityEngine;

public class TestGenericMenu : MonoBehaviour
{
    [InitializeOnLoadMethod]
    private static void SceneViewExtensions()
    {
        // 注册 hierarchyWindowItemOnGUI 的回调函数
        EditorApplication.hierarchyWindowItemOnGUI += OnHierarchyGUI;
    }

    private 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;
            if (selectedGameObject)
            {
                // 创建 GenericMenu
                GenericMenu menu = new GenericMenu();
                menu.AddItem(new GUIContent("Option 1"), false, Option1Selected, selectedGameObject);
                menu.AddItem(new GUIContent("Option 2"), false, Option2Selected, selectedGameObject);

                // 在鼠标位置显示菜单
                menu.ShowAsContext();
                Event.current.Use();
            }
        }
    }

    private static void Option1Selected(object obj)
    {
        GameObject selectedObject = obj as GameObject;
        Debug.Log("Option 1 selected for: " + selectedObject.name);
    }

    private static void Option2Selected(object obj)
    {
        GameObject selectedObject = obj as GameObject;
        Debug.Log("Option 2 selected for: " + selectedObject.name);
    }
}

3

4. Project视图添加自定义菜单

  • 通注册一个回调函数 OnProjectGUI 到 EditorApplication.projectWindowItemOnGUI 事件中。当在 Project 视图中右键点击资源项时,将检测鼠标事件类型是否为右键点击,并且鼠标位置是否在资源项区域内。如果是,则会获取当前资源的路径,并创建一个包含 “Option 1” 和 “Option 2” 两个选项的 GenericMenu 菜单。
using UnityEditor;
using UnityEngine;

public class TestGenericMenu : MonoBehaviour
{
    [InitializeOnLoadMethod]
    private static void SceneViewExtensions()
    {
        // 注册 projectWindowItemOnGUI 的回调函数
        EditorApplication.projectWindowItemOnGUI += OnProjectOnGUI;
    }

    private static void OnProjectOnGUI(string guid, Rect selectionRect)
    {
        if (Event.current != null && selectionRect.Contains(Event.current.mousePosition) && Event.current.type == EventType.ContextClick)
        {
            // 获取当前右键点击的资源路径
            string assetPath = AssetDatabase.GUIDToAssetPath(guid);
            // 创建 GenericMenu
            GenericMenu menu = new GenericMenu();
            menu.AddItem(new GUIContent("Option 1"), false, Resource1Selected, assetPath);
            menu.AddItem(new GUIContent("Option 2"), false, Resource2Selected, assetPath);

            // 在鼠标位置显示菜单
            menu.ShowAsContext();
            Event.current.Use();
        }
    }

    private static void Resource1Selected(object obj)
    {
        string assetPath = obj as string;
        Debug.Log("Option 1 selected for: " + assetPath);
    }

    private static void Resource2Selected(object obj)
    {
        string assetPath = obj as string;
        Debug.Log("Option 2 selected for: " + assetPath);
    }
}

3

5. Game视图添加自定义菜单

  • 通注册一个回调函数 OnProjectGUI 到 EditorApplication.projectWindowItemOnGUI 事件中。当在 Project 视图中右键点击资源项时,将检测鼠标事件类型是否为右键点击,并且鼠标位置是否在资源项区域内。如果是,则会获取当前资源的路径,并创建一个包含 “Option 1” 和 “Option 2” 两个选项的 GenericMenu 菜单。
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

#if UNITY_EDITOR
[ExecuteInEditMode]
public class TestGenericMenu : MonoBehaviour
{
    private void OnGUI()
    {
        // 在 Game 视图中的鼠标位置创建 GenericMenu
        if (Event.current != null && Event.current.type == EventType.ContextClick) // 通过鼠标右键触发菜单
        {
            Debug.Log("1");
            Vector2 mousePosition = Event.current.mousePosition;

            GenericMenu menu = new GenericMenu();
            menu.AddItem(new GUIContent("Option 1"), false, Option1Selected);
            menu.AddItem(new GUIContent("Option 2"), false, Option2Selected);

            menu.ShowAsContext(); // 以上下文菜单方式显示

            Event.current.Use(); // 标记事件已被处理
        }
    }

    private static void Option1Selected()
    {
        Debug.Log("Option 1 selected!");
    }

    private static void Option2Selected()
    {
        Debug.Log("Option 2 selected!");
    }
}
#endif

4

文章来源:https://blog.csdn.net/backlighting2015/article/details/135468478
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。