diff --git a/Scripts/Editor/NodeEditor.cs b/Scripts/Editor/NodeEditor.cs index 8b06c26..f38b510 100644 --- a/Scripts/Editor/NodeEditor.cs +++ b/Scripts/Editor/NodeEditor.cs @@ -81,6 +81,26 @@ namespace XNodeEditor { return NodeEditorResources.styles.nodeBody; } + /// Add items for the context menu when right-clicking this node. Override to add custom menu items. + public virtual void AddContextMenuItems(GenericMenu menu) { + // Actions if only one node is selected + if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) { + XNode.Node node = Selection.activeObject as XNode.Node; + menu.AddItem(new GUIContent("Move To Top"), false, () => NodeEditorWindow.current.MoveNodeToTop(node)); + menu.AddItem(new GUIContent("Rename"), false, NodeEditorWindow.current.RenameSelectedNode); + } + + // Add actions to any number of selected nodes + menu.AddItem(new GUIContent("Duplicate"), false, NodeEditorWindow.current.DuplicateSelectedNodes); + menu.AddItem(new GUIContent("Remove"), false, NodeEditorWindow.current.RemoveSelectedNodes); + + // Custom sctions if only one node is selected + if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) { + XNode.Node node = Selection.activeObject as XNode.Node; + NodeEditorWindow.AddCustomContextMenuItems(menu, node); + } + } + public void InitiateRename() { renaming = 1; } diff --git a/Scripts/Editor/NodeEditorAction.cs b/Scripts/Editor/NodeEditorAction.cs index b5315f8..d8d36cb 100644 --- a/Scripts/Editor/NodeEditorAction.cs +++ b/Scripts/Editor/NodeEditorAction.cs @@ -260,9 +260,13 @@ namespace XNodeEditor { ShowPortContextMenu(hoveredPort); } else if (IsHoveringNode && IsHoveringTitle(hoveredNode)) { if (!Selection.Contains(hoveredNode)) SelectNode(hoveredNode, false); - ShowNodeContextMenu(); + GenericMenu menu = new GenericMenu(); + NodeEditor.GetEditor(hoveredNode).AddContextMenuItems(menu); + menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero)); } else if (!IsHoveringNode) { - ShowGraphContextMenu(); + GenericMenu menu = new GenericMenu(); + graphEditor.AddContextMenuItems(menu); + menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero)); } } isPanning = false; @@ -323,15 +327,6 @@ namespace XNodeEditor { panOffset = Vector2.zero; } - public void CreateNode(Type type, Vector2 position) { - XNode.Node node = graph.AddNode(type); - node.position = position; - node.name = UnityEditor.ObjectNames.NicifyVariableName(type.Name); - AssetDatabase.AddObjectToAsset(node, graph); - if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets(); - Repaint(); - } - /// Remove nodes in the graph in Selection.objects public void RemoveSelectedNodes() { // We need to delete reroutes starting at the highest point index to avoid shifting indices diff --git a/Scripts/Editor/NodeEditorGUI.cs b/Scripts/Editor/NodeEditorGUI.cs index 8d7b95a..9f48f0e 100644 --- a/Scripts/Editor/NodeEditorGUI.cs +++ b/Scripts/Editor/NodeEditorGUI.cs @@ -116,60 +116,6 @@ namespace XNodeEditor { if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets(); } - /// Show right-click context menu for selected nodes - public void ShowNodeContextMenu() { - GenericMenu contextMenu = new GenericMenu(); - // If only one node is selected - if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) { - XNode.Node node = Selection.activeObject as XNode.Node; - contextMenu.AddItem(new GUIContent("Move To Top"), false, () => MoveNodeToTop(node)); - contextMenu.AddItem(new GUIContent("Rename"), false, RenameSelectedNode); - } - - contextMenu.AddItem(new GUIContent("Duplicate"), false, DuplicateSelectedNodes); - contextMenu.AddItem(new GUIContent("Remove"), false, RemoveSelectedNodes); - - // If only one node is selected - if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) { - XNode.Node node = Selection.activeObject as XNode.Node; - AddCustomContextMenuItems(contextMenu, node); - } - - contextMenu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero)); - } - - /// Show right-click context menu for current graph - void ShowGraphContextMenu() { - GenericMenu contextMenu = new GenericMenu(); - Vector2 pos = WindowToGridPosition(Event.current.mousePosition); - for (int i = 0; i < nodeTypes.Length; i++) { - Type type = nodeTypes[i]; - - //Get node context menu path - string path = graphEditor.GetNodeMenuName(type); - if (string.IsNullOrEmpty(path)) continue; - - contextMenu.AddItem(new GUIContent(path), false, () => { - CreateNode(type, pos); - }); - } - contextMenu.AddSeparator(""); - contextMenu.AddItem(new GUIContent("Preferences"), false, () => OpenPreferences()); - 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 42e583c..bfe8307 100644 --- a/Scripts/Editor/NodeEditorReflection.cs +++ b/Scripts/Editor/NodeEditorReflection.cs @@ -71,6 +71,17 @@ namespace XNodeEditor { return types.ToArray(); } + public static 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)); + } + } + } + public static KeyValuePair[] GetContextMenuMethods(object obj) { Type type = obj.GetType(); MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); diff --git a/Scripts/Editor/NodeGraphEditor.cs b/Scripts/Editor/NodeGraphEditor.cs index 1c32a6e..20f5657 100644 --- a/Scripts/Editor/NodeGraphEditor.cs +++ b/Scripts/Editor/NodeGraphEditor.cs @@ -38,10 +38,39 @@ namespace XNodeEditor { return ObjectNames.NicifyVariableName(type.ToString().Replace('.', '/')); } + /// Add items for the context menu when right-clicking this node. Override to add custom menu items. + public virtual void AddContextMenuItems(GenericMenu menu) { + Vector2 pos = NodeEditorWindow.current.WindowToGridPosition(Event.current.mousePosition); + for (int i = 0; i < NodeEditorWindow.nodeTypes.Length; i++) { + Type type = NodeEditorWindow.nodeTypes[i]; + + //Get node context menu path + string path = GetNodeMenuName(type); + if (string.IsNullOrEmpty(path)) continue; + + menu.AddItem(new GUIContent(path), false, () => { + CreateNode(type, pos); + }); + } + menu.AddSeparator(""); + menu.AddItem(new GUIContent("Preferences"), false, () => NodeEditorWindow.OpenPreferences()); + NodeEditorWindow.AddCustomContextMenuItems(menu, target); + } + public virtual Color GetTypeColor(Type type) { return NodeEditorPreferences.GetTypeColor(type); } + /// Create a node and save it in the graph asset + public virtual void CreateNode(Type type, Vector2 position) { + XNode.Node node = target.AddNode(type); + node.position = position; + node.name = UnityEditor.ObjectNames.NicifyVariableName(type.Name); + AssetDatabase.AddObjectToAsset(node, target); + if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets(); + NodeEditorWindow.RepaintAll(); + } + /// Creates a copy of the original node in the graph public XNode.Node CopyNode(XNode.Node original) { XNode.Node node = target.CopyNode(original);