/// <summary> Show right-click context menu </summary> public void ShowContextMenu() { GenericMenu contextMenu = new GenericMenu(); Vector2 pos = WindowToGridPosition(Event.current.mousePosition); if (hoveredNode != null) { Node node = hoveredNode; contextMenu.AddItem(new GUIContent("Remove"), false, () => graph.RemoveNode(node)); } else { 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)) { name = attrib.menuName; } contextMenu.AddItem(new GUIContent(name), false, () => { CreateNode(type, pos); }); } } contextMenu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero)); }
/// <summary> The order by which the menu items are displayed. </summary> public virtual int GetNodeMenuOrder(Type type) { //Check if type has the CreateNodeMenuAttribute XNode.Node.CreateNodeMenuAttribute attrib; if (NodeEditorUtilities.GetAttrib(type, out attrib)) // Return custom path return attrib.order; else return 0; }
/// <summary> Returns context node menu path. Null or empty strings for hidden nodes. </summary> public virtual string GetNodeMenuName(Type type) { //Check if type has the CreateNodeMenuAttribute XNode.Node.CreateNodeMenuAttribute attrib; if (NodeEditorUtilities.GetAttrib(type, out attrib)) // Return custom path return attrib.menuName; else // Return generated path return NodeEditorUtilities.NodeDefaultPath(type); }
/// <summary> Add items for the context menu when right-clicking this node. Override to add custom menu items. </summary> public virtual void AddContextMenuItems(GenericMenu menu) { Vector2 pos = NodeEditorWindow.current.WindowToGridPosition(Event.current.mousePosition); var nodeTypes = NodeEditorReflection.nodeTypes.OrderBy(type => GetNodeMenuOrder(type)).ToArray(); for (int i = 0; i < nodeTypes.Length; i++) { Type type = nodeTypes[i]; //Get node context menu path string path = GetNodeMenuName(type); if (string.IsNullOrEmpty(path)) { continue; } // Check if user is allowed to add more of given node type XNode.Node.DisallowMultipleNodesAttribute disallowAttrib; bool disallowed = false; if (NodeEditorUtilities.GetAttrib(type, out disallowAttrib)) { int typeCount = target.nodes.Count(x => x.GetType() == type); if (typeCount >= disallowAttrib.max) { disallowed = true; } } if (window.graph is DialogGraph) { } // Add node entry to context menu if (disallowed) { menu.AddItem(new GUIContent(path), false, null); } else { menu.AddItem(new GUIContent(path), false, () => { XNode.Node node = CreateNode(type, pos); NodeEditorWindow.current.AutoConnect(node); }); } } menu.AddSeparator(""); if (NodeEditorWindow.copyBuffer != null && NodeEditorWindow.copyBuffer.Length > 0) { menu.AddItem(new GUIContent("Paste"), false, () => NodeEditorWindow.current.PasteNodes(pos)); } else { menu.AddDisabledItem(new GUIContent("Paste")); } menu.AddItem(new GUIContent("Preferences"), false, () => NodeEditorReflection.OpenPreferences()); menu.AddCustomContextMenuItems(target); }
public virtual bool IsExcludeContextMenuNode(Type type) { //Check if type has the CreateNodeMenuAttribute XNode.Node.CreateNodeMenuAttribute attrib; if (NodeEditorUtilities.GetAttrib(type, out attrib)) // Return custom path { return(attrib.exclude); } return(false); }
public static string[] GetNodeMenuTags(Type type) { //Check if type has the CreateNodeMenuAttribute XNode.CreateNodeMenuAttribute attrib; if (NodeEditorUtilities.GetAttrib(type, out attrib)) // Return custom path { return(attrib.Tags); } return(new string[0]); }
/// <summary> Returns context node menu path. Null or empty strings for hidden nodes. </summary> public virtual string GetNodeMenuName(Type type) { //Check if type has the CreateNodeMenuAttribute XNode.Node.CreateNodeMenuAttribute attrib; if (NodeEditorUtilities.GetAttrib(type, out attrib)) // Return custom path { return(attrib.menuName); } else // Return generated path { return(ObjectNames.NicifyVariableName(type.ToString().Replace('.', '/'))); } }
/// <summary> Show right-click context menu for current graph </summary> void ShowGraphContextMenu() { GenericMenu contextMenu = new GenericMenu(); 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)) { name = attrib.menuName; } contextMenu.AddItem(new GUIContent(name), 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)); }
/// <summary> Make a field for a serialized property. Manual node port override. </summary> public static void PropertyField(SerializedProperty property, GUIContent label, Siccity.XNode.NodePort port, bool includeChildren = true, params GUILayoutOption[] options) { if (property == null) { throw new NullReferenceException(); } // If property is not a port, display a regular property field if (port == null) { EditorGUILayout.PropertyField(property, label, includeChildren, GUILayout.MinWidth(30)); } else { Rect rect = new Rect(); // If property is an input, display a regular property field and put a port handle on the left side if (port.direction == Siccity.XNode.NodePort.IO.Input) { // Get data from [Input] attribute Siccity.XNode.Node.ShowBackingValue showBacking = Siccity.XNode.Node.ShowBackingValue.Unconnected; Siccity.XNode.Node.InputAttribute inputAttribute; if (NodeEditorUtilities.GetAttrib(port.node.GetType(), property.name, out inputAttribute)) { showBacking = inputAttribute.backingValue; } switch (showBacking) { case Siccity.XNode.Node.ShowBackingValue.Unconnected: // Display a label if port is connected if (port.IsConnected) { EditorGUILayout.LabelField(label != null ? label : new GUIContent(property.displayName)); } // Display an editable property field if port is not connected else { EditorGUILayout.PropertyField(property, label, includeChildren, GUILayout.MinWidth(30)); } break; case Siccity.XNode.Node.ShowBackingValue.Never: // Display a label EditorGUILayout.LabelField(label != null ? label : new GUIContent(property.displayName)); break; case Siccity.XNode.Node.ShowBackingValue.Always: // Display an editable property field EditorGUILayout.PropertyField(property, label, includeChildren, GUILayout.MinWidth(30)); break; } rect = GUILayoutUtility.GetLastRect(); rect.position = rect.position - new Vector2(16, 0); // If property is an output, display a text label and put a port handle on the right side } else if (port.direction == Siccity.XNode.NodePort.IO.Output) { // Get data from [Output] attribute Siccity.XNode.Node.ShowBackingValue showBacking = Siccity.XNode.Node.ShowBackingValue.Unconnected; Siccity.XNode.Node.OutputAttribute outputAttribute; if (NodeEditorUtilities.GetAttrib(port.node.GetType(), property.name, out outputAttribute)) { showBacking = outputAttribute.backingValue; } switch (showBacking) { case Siccity.XNode.Node.ShowBackingValue.Unconnected: // Display a label if port is connected if (port.IsConnected) { EditorGUILayout.LabelField(label != null ? label : new GUIContent(property.displayName), NodeEditorResources.OutputPort, GUILayout.MinWidth(30)); } // Display an editable property field if port is not connected else { EditorGUILayout.PropertyField(property, label, includeChildren, GUILayout.MinWidth(30)); } break; case Siccity.XNode.Node.ShowBackingValue.Never: // Display a label EditorGUILayout.LabelField(label != null ? label : new GUIContent(property.displayName), NodeEditorResources.OutputPort, GUILayout.MinWidth(30)); break; case Siccity.XNode.Node.ShowBackingValue.Always: // Display an editable property field EditorGUILayout.PropertyField(property, label, includeChildren, GUILayout.MinWidth(30)); break; } rect = GUILayoutUtility.GetLastRect(); rect.position = rect.position + new Vector2(rect.width, 0); } rect.size = new Vector2(16, 16); Color backgroundColor = new Color32(90, 97, 105, 255); if (NodeEditorWindow.nodeTint.ContainsKey(port.node.GetType())) { backgroundColor *= NodeEditorWindow.nodeTint[port.node.GetType()]; } Color col = NodeEditorWindow.current.graphEditor.GetTypeColor(port.ValueType); DrawPortHandle(rect, backgroundColor, col); // Register the handle position Vector2 portPos = rect.center; if (NodeEditor.portPositions.ContainsKey(port)) { NodeEditor.portPositions[port] = portPos; } else { NodeEditor.portPositions.Add(port, portPos); } } }
private void InsertDuplicateNodes(XNode.Node[] nodes, Vector2 topLeft) { if (nodes == null || nodes.Length == 0) { return; } // Get top-left node Vector2 topLeftNode = nodes.Select(x => x.position).Aggregate((x, y) => new Vector2(Mathf.Min(x.x, y.x), Mathf.Min(x.y, y.y))); Vector2 offset = topLeft - topLeftNode; UnityEngine.Object[] newNodes = new UnityEngine.Object[nodes.Length]; Dictionary <XNode.Node, XNode.Node> substitutes = new Dictionary <XNode.Node, XNode.Node>(); for (int i = 0; i < nodes.Length; i++) { XNode.Node srcNode = nodes[i]; if (srcNode == null) { continue; } // Check if user is allowed to add more of given node type XNode.Node.DisallowMultipleNodesAttribute disallowAttrib; Type nodeType = srcNode.GetType(); if (NodeEditorUtilities.GetAttrib(nodeType, out disallowAttrib)) { int typeCount = graph.nodes.Count(x => x.GetType() == nodeType); if (typeCount >= disallowAttrib.max) { continue; } } XNode.Node newNode = graphEditor.CopyNode(srcNode); substitutes.Add(srcNode, newNode); newNode.position = srcNode.position + offset; newNodes[i] = newNode; } // Walk through the selected nodes again, recreate connections, using the new nodes for (int i = 0; i < nodes.Length; i++) { XNode.Node srcNode = nodes[i]; if (srcNode == null) { continue; } foreach (XNode.NodePort port in srcNode.Ports) { for (int c = 0; c < port.ConnectionCount; c++) { XNode.NodePort inputPort = port.direction == XNode.NodePort.IO.Input ? port : port.GetConnection(c); XNode.NodePort outputPort = port.direction == XNode.NodePort.IO.Output ? port : port.GetConnection(c); XNode.Node newNodeIn, newNodeOut; if (substitutes.TryGetValue(inputPort.node, out newNodeIn) && substitutes.TryGetValue(outputPort.node, out newNodeOut)) { newNodeIn.UpdatePorts(); newNodeOut.UpdatePorts(); inputPort = newNodeIn.GetInputPort(inputPort.fieldName); outputPort = newNodeOut.GetOutputPort(outputPort.fieldName); } if (!inputPort.IsConnectedTo(outputPort)) { inputPort.Connect(outputPort); } } } } // Select the new nodes Selection.objects = newNodes; }