GenericMenu 允许您创建自定义上下文菜单和下拉菜单。
一、弹出式菜单前言
下面的示例打开了一个带有按钮的编辑器窗口。单击该按钮可显示上下文菜单,您可以通过该菜单更改应用于窗口中 GUI 的颜色。将示例的内容复制到名为 GenericMenuExample.cs 的脚本中,然后将其置于您项目中的 Editor 文件夹内。
using UnityEngine;
using UnityEditor;
public class GenericMenuExample : EditorWindow
{
// open the window from the menu item Example -> GUI Color
[MenuItem("Example/GUI Color")]
static void Init()
{
EditorWindow window = GetWindow<GenericMenuExample>();
window.position = new Rect(50f, 50f, 200f, 24f);
window.Show();
}
//serialize field on window so its value will be saved when Unity recompiles
[SerializeField]
Color m_Color = Color.white;
void OnEnable()
{
titleContent = new GUIContent("GUI Color");
}
//a method to simplify adding menu items
void AddMenuItemForColor(GenericMenu menu, string menuPath, Color color)
{
//the menu item is marked as selected if it matches
//the current value of m_Color
menu.AddItem(new GUIContent(menuPath), m_Color.Equals(color), OnColorSelected, color);
}
//the GenericMenu.MenuFunction2 event handler for when a menu item is selected
void OnColorSelected(object color)
{
m_Color = (Color)color;
}
void OnGUI()
{
//set the GUI to use the color stored in m_Color
GUI.color = m_Color;
//display the GenericMenu when pressing a button
if(GUILayout.Button("Select GUI Color"))
{
//create the menu and add items to it
GenericMenu menu = new GenericMenu();
//forward slashes nest menu items under submenus
AddMenuItemForColor(menu, "RGB/Red", Color.red);
AddMenuItemForColor(menu, "RGB/Green", Color.green);
AddMenuItemForColor(menu, "RGB/Blue", Color.blue);
//an empty string will create a separator at the top level
menu.AddSeparator("");
AddMenuItemForColor(menu, "CMYK/Cyan", Color.cyan);
AddMenuItemForColor(menu, "CMYK/Yellow", Color.yellow);
AddMenuItemForColor(menu, "CMYK/Magenta", Color.magenta);
//a trailing slash will nest a separator in a submenu
menu.AddSeparator("CMYK/");
AddMenuItemForColor(menu, "CMYK/Black", Color.black);
menu.AddSeparator("");
AddMenuItemForColor(menu, "White", Color.white);
// display the menu
menu.ShowAsContext();
}
}
}
二、GenericMenu菜单简介
GenericMenu 是 Unity 中的一个强大的类,用于创建和管理自定义上下文菜单(也称为弹出菜单)。可以使用 GenericMenu 来为编辑器中的不同场合或场景元素创建自定义右键单击菜单,以提供各种操作选项。
using UnityEngine;
namespace UnityEditor
{
//
//摘要:
//GenericMenu lets you create custom context menus and dropdown menus.
public sealed class GenericMenu
{
public GenericMenu();
//
//Allow the menu to have multiple items with the same name.
public bool allowDuplicateNames { get; set; }
//
//摘要:
// Add a disabled item to the menu.
//
//参数:
// content:
// The GUIContent to display as a disabled menu item.
public void AddDisabledItem(GUIContent content);
//
//摘要:
// Add a disabled item to the menu.
//
//参数:
// content:
// The GUIContent to display as a disabled menu item.
//
// on:
// Specifies whether to show that the item is currently activated
// (i.e. a tick next to the item in the menu).
public void AddDisabledItem(GUIContent content, bool on);
public void AddItem(GUIContent content, bool on, MenuFunction func);
public void AddItem(GUIContent content, bool on, MenuFunction2 func, object userData);
//
//摘要:
// Add a seperator item to the menu.
//
//参数:
// path:
// The path to the submenu, if adding a separator to a submenu.
// When adding a separator to the top level of a menu, use an empty
// string as the path.
public void AddSeparator(string path);
//
//摘要:
// Show the menu at the given screen rect.
//
//参数:
// position:
// The position at which to show the menu.
public void DropDown(Rect position);
//
//摘要:
// Get number of items in the menu.
//
//返回结果:
// The number of items in the menu.
public int GetItemCount();
//
//摘要:
// Show the menu under the mouse when right-clicked.
public void ShowAsContext();
//
//摘要:
// Callback function, called when a menu item is selected.
public delegate void MenuFunction();
//
//摘要:
// Callback function with user data, called when a menu item is selected.
//
//参数:
// userData:
// The data to pass through to the callback function.
public delegate void MenuFunction2(object userData);
}
}
方法 | 描述 |
---|
allowDuplicateNames | 允许菜单具有多个同名的菜单项。 |
AddDisabledItem | 向菜单添加已禁用的项。 |
AddItem | 向菜单添加一个项。 |
AddSeparator | 向菜单添加一个分隔符项。 |
DropDown | 在给定屏幕矩形中显示菜单。 |
GetItemCount | 获取菜单中的项数。 |
ShowAsContext | 右键单击时在鼠标下显示菜单。 |
MenuFunction | 回调函数,菜单项选中时调用。 |
MenuFunction2 | 带有用户数据的回调函数,菜单项选中时调用。 |
三、一个GenericMenu菜单例子
GenericMenu使用简介:
// 创建一个通用菜单
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();
一个GenericMenu菜单例子:
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();
}
}
}
四、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);
}
}
五、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);
}
}
六、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