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 = this.graph.nodes.Count(x => x.GetType() == nodeType); if (typeCount >= disallowAttrib.max) { continue; } } xNode.Node newNode = this.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); } } } } EditorUtility.SetDirty(this.graph); // Select the new nodes Selection.objects = newNodes; }
/// <summary> Draws all connections </summary> public void DrawConnections() { Vector2 mousePos = Event.current.mousePosition; List <RerouteReference> selection = this.preBoxSelectionReroute != null ? new List <RerouteReference>(this.preBoxSelectionReroute) : new List <RerouteReference>(); this.hoveredReroute = new RerouteReference(); List <Vector2> gridPoints = new List <Vector2>(2); Color col = GUI.color; foreach (xNode.Node node in this.graph.nodes) { //If a null node is found, return. This can happen if the nodes associated script is deleted. It is currently not possible in Unity to delete a null asset. if (node == null) { continue; } // Draw full connections and output > reroute foreach (xNode.NodePort output in node.Outputs) { //Needs cleanup. Null checks are ugly if (!this._portConnectionPoints.TryGetValue(output, out var fromRect)) { continue; } Color portColor = this.graphEditor.GetPortColor(output); for (int k = 0; k < output.ConnectionCount; k++) { xNode.NodePort input = output.GetConnection(k); Gradient noodleGradient = this.graphEditor.GetNoodleGradient(output, input); float noodleThickness = this.graphEditor.GetNoodleThickness(output, input); NoodlePath noodlePath = this.graphEditor.GetNoodlePath(output, input); NoodleStroke noodleStroke = this.graphEditor.GetNoodleStroke(output, input); // Error handling if (input == null) { continue; //If a script has been updated and the port doesn't exist, it is removed and null is returned. If this happens, return. } if (!input.IsConnectedTo(output)) { input.Connect(output); } if (!this._portConnectionPoints.TryGetValue(input, out var toRect)) { continue; } List <Vector2> reroutePoints = output.GetReroutePoints(k); gridPoints.Clear(); gridPoints.Add(fromRect.center); gridPoints.AddRange(reroutePoints); gridPoints.Add(toRect.center); this.DrawNoodle(noodleGradient, noodlePath, noodleStroke, noodleThickness, gridPoints); // Loop through reroute points again and draw the points for (int i = 0; i < reroutePoints.Count; i++) { RerouteReference rerouteRef = new RerouteReference(output, k, i); // Draw reroute point at position Rect rect = new Rect(reroutePoints[i], new Vector2(12, 12)); rect.position = new Vector2(rect.position.x - 6, rect.position.y - 6); rect = this.GridToWindowRect(rect); // Draw selected reroute points with an outline if (this.selectedReroutes.Contains(rerouteRef)) { GUI.color = NodeEditorPreferences.GetSettings().highlightColor; GUI.DrawTexture(rect, NodeEditorResources.dotOuter); } GUI.color = portColor; GUI.DrawTexture(rect, NodeEditorResources.dot); if (rect.Overlaps(this.selectionBox)) { selection.Add(rerouteRef); } if (rect.Contains(mousePos)) { this.hoveredReroute = rerouteRef; } } } } } GUI.color = col; if (Event.current.type != EventType.Layout && currentActivity == NodeActivity.DragGrid) { this.selectedReroutes = selection; } }