public void CreateNode(NodeReflectionData data, Vector2 screenPosition, PortView connectedPort = null) { var windowRoot = m_EditorWindow.rootVisualElement; var windowMousePosition = m_EditorWindow.rootVisualElement.ChangeCoordinatesTo( windowRoot.parent, screenPosition - m_EditorWindow.position.position ); var graphMousePosition = contentViewContainer.WorldToLocal(windowMousePosition); var node = data.CreateInstance(); node.graphPosition = graphMousePosition; m_Graph.AddNode(node); // Add a node to the visual graph var editorType = NodeReflection.GetNodeEditorType(data.type); var element = Activator.CreateInstance(editorType) as NodeView; element.Initialize(node, m_EdgeListener); AddElement(element); AssetDatabase.AddObjectToAsset(node, m_Graph); AssetDatabase.SaveAssets(); // If there was a provided existing port to connect to, find the best // candidate port on the new node and connect. if (connectedPort != null) { var edge = new Edge(); if (connectedPort.direction == Direction.Input) { edge.input = connectedPort; edge.output = element.GetCompatibleOutputPort(connectedPort); } else { edge.output = connectedPort; edge.input = element.GetCompatibleInputPort(connectedPort); } ConnectNodes(edge); } Dirty(element); }
/// <summary> /// Append views for nodes from a Graph /// </summary> private void AddNodes(List <AbstractNode> nodes, bool selectOnceAdded = false, bool centerOnMouse = false) { // Add views of each node from the graph Dictionary <AbstractNode, NodeView> nodeMap = new Dictionary <AbstractNode, NodeView>(); foreach (var node in nodes) { var editorType = NodeReflection.GetNodeEditorType(node.GetType()); var element = Activator.CreateInstance(editorType) as NodeView; if (node == null) { Debug.LogError("Null node"); } element.Initialize(node, m_EdgeListener); AddElement(element); nodeMap.Add(node, element); Dirty(element); if (selectOnceAdded) { AddToSelection(element); } } if (centerOnMouse) { Rect bounds = GetBounds(nodeMap.Values); Vector2 worldPosition = contentViewContainer.WorldToLocal(m_LastMousePosition); Vector2 delta = worldPosition - bounds.center; foreach (var node in nodeMap) { node.Value.SetPosition(new Rect(node.Key.graphPosition + delta, Vector2.one)); } } // Sync edges on the graph with our graph's connections // TODO: Deal with trash connections from bad imports foreach (var node in nodeMap) { foreach (var port in node.Key.ports) { if (!port.isInput) { continue; } foreach (var conn in port.connections) { if (conn.node == null) { Debug.LogError( $"Could not connect `{node.Value.title}:{port.portName}`: " + $"Connected node no longer exists." ); continue; } // Only add if the linked node is in the collection if (nodeMap.ContainsKey(conn.node)) { var inPort = node.Value.GetInputPort(port.portName); var outPort = nodeMap[conn.node].GetOutputPort(conn.portName); if (inPort == null) { Debug.LogError( $"Could not connect `{node.Value.title}:{port.portName}` -> `{conn.node.name}:{conn.portName}`. " + $"Input port `{port.portName}` no longer exists.", node.Key ); } else if (outPort == null) { Debug.LogError( $"Could not connect `{conn.node.name}:{conn.portName}` to `{node.Value.name}:{port.portName}`. " + $"Output port `{conn.portName}` no longer exists.", conn.node ); } else { var edge = inPort.ConnectTo(outPort); AddElement(edge); } } } } } }