/// <summary> /// Forms new connections from the external nodes to the Node To Code Node, /// based on the connectors passed as inputs. /// </summary> /// <param name="externalOutputConnections">List of connectors to remake, along with the port names of the new port</param> /// <param name="codeBlockNode">The new Node To Code created Code Block Node</param> private void ReConnectOutputConnections(Dictionary <ConnectorModel, string> externalOutputConnections, CodeBlockNodeModel codeBlockNode) { foreach (var kvp in externalOutputConnections) { var connector = kvp.Key; string variableName = kvp.Value; int startIndex = 0, endIndex = 0; //Get the start and end idex for the ports for the connection endIndex = connector.End.Owner.InPorts.IndexOf(connector.End); int i = 0; for (i = 0; i < codeBlockNode.OutPorts.Count; i++) { if (codeBlockNode.GetAstIdentifierForOutputIndex(i).Value == variableName) { break; } } var portModel = codeBlockNode.OutPorts[i]; startIndex = codeBlockNode.OutPorts.IndexOf(portModel); //Make the new connection and then record and add it var newConnector = ConnectorModel.Make(codeBlockNode, connector.End.Owner, startIndex, endIndex, PortType.INPUT); this.Connectors.Add(newConnector); UndoRecorder.RecordCreationForUndo(newConnector); } }
/// <summary> /// Forms new connections from the external nodes to the Node To Code Node, /// based on the connectors passed as inputs. /// </summary> /// <param name="externalInputConnections">List of connectors to remake, along with the port names of the new port</param> /// <param name="codeBlockNode">The new Node To Code created Code Block Node</param> private void ReConnectInputConnections(Dictionary <ConnectorModel, string> externalInputConnections, CodeBlockNodeModel codeBlockNode) { foreach (var kvp in externalInputConnections) { var connector = kvp.Key; string variableName = kvp.Value; int startIndex = 0, endIndex = 0; //Find the start and end index of the ports for the connection startIndex = connector.Start.Owner.OutPorts.IndexOf(connector.Start); endIndex = CodeBlockNodeModel.GetInportIndex(codeBlockNode, variableName); //For inputs, a single node can be an input to multiple nodes in the code block node selection //After conversion, all these connecetions should become only 1 connection and not many //Hence for inputs, it is required to make sure that a certain type of connection has not //been created already. if (Connectors.Where(x => (x.Start == connector.Start && x.End == codeBlockNode.InPorts[endIndex])).FirstOrDefault() == null) { //Make the new connection and then record and add it var newConnector = ConnectorModel.Make(connector.Start.Owner, codeBlockNode, startIndex, endIndex, PortType.INPUT); this.Connectors.Add(newConnector); UndoRecorder.RecordCreationForUndo(newConnector); } } }
internal void ConvertNodesToCodeInternal(Guid nodeId) { IEnumerable <NodeModel> nodes = DynamoSelection.Instance.Selection.OfType <NodeModel>().Where(n => n.IsConvertible); if (!nodes.Any()) { return; } Dictionary <string, string> variableNameMap; string code = dynSettings.Controller.EngineController.ConvertNodesToCode(nodes, out variableNameMap); //UndoRedo Action Group---------------------------------------------- UndoRecorder.BeginActionGroup(); #region Step I. Delete all nodes and their connections //Create two dictionarys to store the details of the external connections that have to //be recreated after the conversion var externalInputConnections = new Dictionary <ConnectorModel, string>(); var externalOutputConnections = new Dictionary <ConnectorModel, string>(); //Also collect the average X and Y co-ordinates of the different nodes var nodeList = nodes.ToList(); int nodeCount = nodeList.Count; double totalX = 0, totalY = 0; for (int i = 0; i < nodeList.Count; ++i) { var node = nodeList[i]; #region Step I.A. Delete the connections for the node var connectors = node.AllConnectors as IList <ConnectorModel>; if (null == connectors) { connectors = node.AllConnectors.ToList(); } for (int n = 0; n < connectors.Count(); ++n) { var connector = connectors[n]; if (!IsInternalNodeToCodeConnection(connector)) { //If the connector is an external connector, the save its details //for recreation later var startNode = connector.Start.Owner; int index = startNode.OutPorts.IndexOf(connector.Start); //We use the varibleName as the connection between the port of the old Node //to the port of the new node. var variableName = startNode.GetAstIdentifierForOutputIndex(index).Value; if (variableNameMap.ContainsKey(variableName)) { variableName = variableNameMap[variableName]; } //Store the data in the corresponding dictionary if (startNode == node) { externalOutputConnections.Add(connector, variableName); } else { externalInputConnections.Add(connector, variableName); } } //Delete the connector UndoRecorder.RecordDeletionForUndo(connector); connector.NotifyConnectedPortsOfDeletion(); Connectors.Remove(connector); } #endregion #region Step I.B. Delete the node totalX += node.X; totalY += node.Y; UndoRecorder.RecordDeletionForUndo(node); Nodes.Remove(node); #endregion } #endregion #region Step II. Create the new code block node var codeBlockNode = new CodeBlockNodeModel(code, nodeId, this, totalX / nodeCount, totalY / nodeCount); UndoRecorder.RecordCreationForUndo(codeBlockNode); Nodes.Add(codeBlockNode); #endregion #region Step III. Recreate the necessary connections ReConnectInputConnections(externalInputConnections, codeBlockNode); ReConnectOutputConnections(externalOutputConnections, codeBlockNode); #endregion UndoRecorder.EndActionGroup(); //End UndoRedo Action Group------------------------------------------ // select node var placedNode = dynSettings.Controller.DynamoViewModel.Model.Nodes.Find((node) => node.GUID == nodeId); if (placedNode != null) { DynamoSelection.Instance.ClearSelection(); DynamoSelection.Instance.Selection.Add(placedNode); } Modified(); }