diff --git a/Scripts/Editor/NodeEditorGUI.cs b/Scripts/Editor/NodeEditorGUI.cs index 0590e7e..476153d 100644 --- a/Scripts/Editor/NodeEditorGUI.cs +++ b/Scripts/Editor/NodeEditorGUI.cs @@ -74,8 +74,8 @@ namespace XNodeEditor { /// Show right-click context menu for a node public void ShowNodeContextMenu(Node node) { GenericMenu contextMenu = new GenericMenu(); - Vector2 pos = WindowToGridPosition(Event.current.mousePosition); contextMenu.AddItem(new GUIContent("Remove"), false, () => graph.RemoveNode(node)); + AddCustomContextMenuItems(contextMenu, node); contextMenu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero)); } @@ -85,7 +85,6 @@ namespace XNodeEditor { Vector2 pos = WindowToGridPosition(Event.current.mousePosition); for (int i = 0; i < nodeTypes.Length; i++) { Type type = nodeTypes[i]; - string name = nodeTypes[i].ToString().Replace('.', '/'); Node.CreateNodeMenuAttribute attrib; if (NodeEditorUtilities.GetAttrib(type, out attrib)) { @@ -95,9 +94,21 @@ namespace XNodeEditor { CreateNode(type, pos); }); } + AddCustomContextMenuItems(contextMenu, graph); contextMenu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero)); } + void AddCustomContextMenuItems(GenericMenu contextMenu, object obj) { + KeyValuePair[] items = GetContextMenuMethods(obj); + if (items.Length != 0) { + contextMenu.AddSeparator(""); + for (int i = 0; i < items.Length; i++) { + KeyValuePair kvp = items[i]; + contextMenu.AddItem(new GUIContent(kvp.Key.menuItem), false, () => kvp.Value.Invoke(obj, null)); + } + } + } + /// Draw a bezier from startpoint to endpoint, both in grid coordinates public void DrawConnection(Vector2 startPoint, Vector2 endPoint, Color col) { startPoint = GridToWindowPosition(startPoint); diff --git a/Scripts/Editor/NodeEditorReflection.cs b/Scripts/Editor/NodeEditorReflection.cs index 861c764..ecd158a 100644 --- a/Scripts/Editor/NodeEditorReflection.cs +++ b/Scripts/Editor/NodeEditorReflection.cs @@ -71,5 +71,30 @@ namespace XNodeEditor { FieldInfo fieldInfo = type.GetField(fieldName); return fieldInfo.GetValue(obj); } + + public static KeyValuePair[] GetContextMenuMethods(object obj) { + Type type = obj.GetType(); + MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); + List> kvp = new List>(); + for (int i = 0; i < methods.Length; i++) { + ContextMenu[] attribs = methods[i].GetCustomAttributes(typeof(ContextMenu), true).Select(x => x as ContextMenu).ToArray(); + if (attribs == null || attribs.Length == 0) continue; + if (methods[i].GetParameters().Length != 0) { + Debug.LogWarning("Method " + methods[i].DeclaringType.Name + "." + methods[i].Name + " has parameters and cannot be used for context menu commands."); + continue; + } + if (methods[i].IsStatic) { + Debug.LogWarning("Method " + methods[i].DeclaringType.Name + "." + methods[i].Name + " is static and cannot be used for context menu commands."); + continue; + } + + for (int k = 0; k < attribs.Length; k++) { + kvp.Add(new KeyValuePair(attribs[k], methods[i])); + } + } + //Sort menu items + kvp.Sort((x, y) => x.Key.priority.CompareTo(y.Key.priority)); + return kvp.ToArray(); + } } } \ No newline at end of file