目录
1. 前言 2. Scene视图添加自定义菜单 3. Hierarchy视图添加自定义菜单 4. Project视图添加自定义菜单 5. Game视图添加自定义菜单
1. 前言
GenericMenu 是 Unity 中的一个强大的类,用于创建和管理自定义上下文菜单(也称为弹出菜单)。可以使用 GenericMenu 来为编辑器中的不同场合或场景元素创建自定义右键单击菜单,以提供各种操作选项。
方法 描述 allowDuplicateNames 允许菜单具有多个同名的菜单项。 AddDisabledItem 向菜单添加已禁用的项。 AddItem 向菜单添加一个项。 AddSeparator 向菜单添加一个分隔符项。 DropDown 在给定屏幕矩形中显示菜单。 GetItemCount 获取菜单中的项数。 ShowAsContext 右键单击时在鼠标下显示菜单。 MenuFunction 回调函数,菜单项选中时调用。 MenuFunction2 带有用户数据的回调函数,菜单项选中时调用。
GenericMenu menu = new GenericMenu ( ) ;
menu. AddDisabledItem ( new GUIContent ( "RGB/Blue" ) , true ) ;
menu. AddItem ( new GUIContent ( "RGB/Red" ) , false , OnColorSelected, Color. red) ;
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. duringSceneGui += OnSceneGUI;
}
private static void OnSceneGUI ( SceneView sceneView)
{
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!" ) ;
}
}
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 ( )
{
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 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) ;
}
}
4. Project视图添加自定义菜单
通注册一个回调函数 OnProjectGUI 到 EditorApplication.projectWindowItemOnGUI 事件中。当在 Project 视图中右键点击资源项时,将检测鼠标事件类型是否为右键点击,并且鼠标位置是否在资源项区域内。如果是,则会获取当前资源的路径,并创建一个包含 “Option 1” 和 “Option 2” 两个选项的 GenericMenu 菜单。
using UnityEditor ;
using UnityEngine ;
public class TestGenericMenu : MonoBehaviour
{
[ InitializeOnLoadMethod ]
private static void SceneViewExtensions ( )
{
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 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) ;
}
}
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 ( )
{
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