static bool TranslateNode(GraphBuilder builder, INodeModel nodeModel, out INode node, out Dictionary <string, uint> portToOffsetMapping, out uint?preAllocatedDataIndex) { Assert.IsNotNull(nodeModel); preAllocatedDataIndex = null; switch (nodeModel) { case SetVariableNodeModel setVariableNodeModel: { node = setVariableNodeModel.Node; portToOffsetMapping = setVariableNodeModel.PortToOffsetMapping; if (setVariableNodeModel.DeclarationModel == null) { return(false); } preAllocatedDataIndex = builder.GetVariableDataIndex(setVariableNodeModel.DeclarationModel).DataIndex; return(true); } case IEventNodeModel eventNodeModel: node = eventNodeModel.Node; ((IEventNode)node).EventId = TypeHash.CalculateStableTypeHash( eventNodeModel.TypeHandle.Resolve(nodeModel.GraphModel.Stencil)); portToOffsetMapping = eventNodeModel.PortToOffsetMapping; return(true); case SubgraphReferenceNodeModel subgraphReferenceNodeModel: node = subgraphReferenceNodeModel.Node; portToOffsetMapping = subgraphReferenceNodeModel.PortToOffsetMapping; return(true); case IDotsNodeModel dotsNodeModel: node = dotsNodeModel.Node; portToOffsetMapping = dotsNodeModel.PortToOffsetMapping; if (nodeModel is IReferenceComponentTypes referenceComponentTypes) { foreach (var typeReference in referenceComponentTypes.ReferencedTypes) { if (typeReference.TypeIndex != -1) { builder.AddReferencedComponent(typeReference); } } } return(true); case IConstantNodeModel constantNodeModel: HandleConstants(builder, out node, out portToOffsetMapping, constantNodeModel); return(true); case IVariableModel variableModel: return(HandleVariable(builder, out node, out portToOffsetMapping, out preAllocatedDataIndex, variableModel)); default: throw new NotImplementedException( $"Don't know how to translate a node of type {nodeModel.GetType()}: {nodeModel}"); } }
IEnumerable <StatementSyntax> ConvertNodesToSyntaxList(INodeModel node, IEnumerable <SyntaxNode> blocks, CompilationOptions options) { foreach (var block in blocks) { switch (block) { case StatementSyntax statementNode: foreach (var statementSyntax in Instrument(statementNode, node, options)) { yield return(statementSyntax); } break; case ExpressionSyntax expressionNode: foreach (var statementSyntax in Instrument(ExpressionStatement(expressionNode) .WithAdditionalAnnotations( new SyntaxAnnotation(Annotations.VSNodeMetadata, node.Guid.ToString())), node, options)) { yield return(statementSyntax); } break; default: throw new InvalidOperationException("Expected a statement or expression " + $"node, found a {node.GetType()} when building {block}"); } } }
void ProcessDependency(INodeModel nodeModel, Vector2 delta, Action <GraphElement, IDependency, Vector2, INodeModel> dependencyCallback) { Log($"ProcessDependency {nodeModel}"); if (!m_DependenciesByNode.TryGetValue(nodeModel.Guid, out Dictionary <GUID, IDependency> link)) { return; } foreach (KeyValuePair <GUID, IDependency> dependency in link) { if (m_ModelsToMove.Contains(dependency.Value.DependentNode)) { continue; } if (!m_TempMovedModels.Add(dependency.Value.DependentNode)) { Log($"Skip ProcessDependency {dependency.Value.DependentNode}"); continue; } if (m_VseGraphView.UIController.ModelsToNodeMapping.TryGetValue(dependency.Value.DependentNode, out var graphElement)) { dependencyCallback(graphElement, dependency.Value, delta, nodeModel); } else { Log($"Cannot find ui node for model: {dependency.Value.DependentNode} dependency from {nodeModel}"); } ProcessDependency(dependency.Value.DependentNode, delta, dependencyCallback); } }
protected virtual void VisitNode(INodeModel nodeModel, HashSet <INodeModel> visitedNodes) { if (nodeModel == null) { return; } visitedNodes.Add(nodeModel); if (nodeModel is IHasVariableDeclaration hasVariableDeclaration) { foreach (var variableDeclaration in hasVariableDeclaration.VariableDeclarations) { VisitVariableDeclaration(variableDeclaration); } } foreach (var inputPortModel in nodeModel.InputsByDisplayOrder) { if (inputPortModel.Connected) { foreach (var connectionPortModel in inputPortModel.ConnectionPortModels) { if (!visitedNodes.Contains(connectionPortModel.NodeModel)) { VisitNode(connectionPortModel.NodeModel, visitedNodes); } } } } }
static StackBaseModel FindConnectedStacksCommonDescendant(INodeModel statement, HashSet <IStackModel> visited) { var firstStack = GetConnectedStack((NodeModel)statement, 0); StackBaseModel desc = statement.OutputsByDisplayOrder.Aggregate(firstStack, (stack, nextPort) => { if (stack == null) { return(null); } if (nextPort.PortType != PortType.Execution) { return(firstStack); } var nextStack = GetConnectedStack(nextPort); if (nextStack == null) { return(null); } if (!visited.Add(nextStack)) { return(stack); } return(FindCommonDescendant(visited, stack, nextStack)); }); return(desc); }
public void AddStackedNode(INodeModel nodeModelInterface, int index) { if (!AcceptNode(nodeModelInterface.GetType())) { return; } var nodeModel = (NodeModel)nodeModelInterface; Utility.SaveAssetIntoObject(nodeModel.NodeAssetReference, (Object)AssetModel); nodeModel.GraphModel = GraphModel; nodeModel.ParentStackModel = this; if (index == -1) { m_NodeModels.Add(nodeModel.NodeAssetReference); } else { m_NodeModels.Insert(index, nodeModel.NodeAssetReference); } bool insertedLast = index == -1 || m_NodeModels.Count == 1 || index == m_NodeModels.Count; if (insertedLast && ModelDelegatesOutputs(nodeModelInterface)) { TransferConnections(GraphModel, m_OutputPorts, OutputPorts); } VSGraphModel vsGraphModel = (VSGraphModel)GraphModel; vsGraphModel.LastChanges.ChangedElements.Add(nodeModel); }
// static StatementSyntax StatementFromExitStrategy(StackExitStrategy stackExitStrategy, ExpressionSyntax returnValue) // { // StatementSyntax lastStatementSyntax; // switch (stackExitStrategy) // { // case StackExitStrategy.Return: // lastStatementSyntax = ReturnStatement(returnValue); // break; // case StackExitStrategy.Break: // lastStatementSyntax = BreakStatement(); // break; // case StackExitStrategy.None: // lastStatementSyntax = null; // break; // default: // lastStatementSyntax = ContinueStatement(); // break; // } // // return lastStatementSyntax; // } protected virtual IEnumerable <SyntaxNode> BuildNode(INodeModel statement, IPortModel portModel) { if (statement == null) { return(Enumerable.Empty <SyntaxNode>()); } Assert.IsTrue(portModel == null || portModel.NodeModel == statement, "If a Port is provided, it must be owned by the provided node"); var ext = ModelUtility.ExtensionMethodCache <RoslynTranslator> .GetExtensionMethod( statement.GetType(), mi => mi.ReturnType == typeof(IEnumerable <SyntaxNode>) && mi.GetParameters().Length == 3 && mi.GetParameters()[2].ParameterType == typeof(IPortModel), mi => mi.GetParameters()[1].ParameterType); if (ext != null) { var syntaxNode = (IEnumerable <SyntaxNode>)ext.Invoke(null, new object[] { this, statement, portModel }) ?? Enumerable.Empty <SyntaxNode>(); var annotatedNodes = new List <SyntaxNode>(); foreach (var node in syntaxNode) { var annotatedNode = node?.WithAdditionalAnnotations(new SyntaxAnnotation(Annotations.AnnotationKind, (statement.NodeAssetReference).GetInstanceID().ToString())); annotatedNodes.Add(annotatedNode); } return(annotatedNodes); } else { Debug.LogError("Roslyn Translator doesn't know how to create a node of type: " + statement.GetType()); } return(Enumerable.Empty <SyntaxNode>()); }
public static TracingStep Error(INodeModel nodeModel, string error) => new TracingStep { Type = TracingStepType.Error, NodeModel = nodeModel, ErrorMessage = error, };
void ProcessDependencyModel(INodeModel nodeModel, GraphViewStateComponent.StateUpdater graphUpdater, Action <IDependency, INodeModel, GraphViewStateComponent.StateUpdater> dependencyCallback) { Log($"ProcessDependencyModel {nodeModel}"); if (!m_DependenciesByNode.TryGetValue(nodeModel.Guid, out var link)) { return; } foreach (var dependency in link) { if (m_ModelsToMove.Contains(dependency.Value.DependentNode)) { continue; } if (!m_TempMovedModels.Add(dependency.Value.DependentNode)) { Log($"Skip ProcessDependency {dependency.Value.DependentNode}"); continue; } dependencyCallback(dependency.Value, nodeModel, graphUpdater); ProcessDependencyModel(dependency.Value.DependentNode, graphUpdater, dependencyCallback); } }
public void Remove(INodeModel parent, INodeModel child) { if (!m_DependenciesByNode.TryGetValue(parent, out Dictionary <INodeModel, IDependency> link)) { return; } if (!link.TryGetValue(child, out IDependency dependency)) { return; } if (dependency is LinkedNodesDependency linked) { linked.count--; if (linked.count <= 0) { link.Remove(child); } } else { link.Remove(child); } if (link.Count == 0) { m_DependenciesByNode.Remove(parent); } }
public Task <IActionResult> HeartBeat(NodeHeartBeatModel model) { return(this.ResultAsync(async() => { bool ret = false; if (model.IsModelValid()) { INodeModel node = null; if (!String.IsNullOrEmpty(model.Address)) { node = await this.Db.Nodes.GetBy(model.Address); if (null != node) { node.CopyPropertiesFrom(model); node.LastConnectionTime = DateTime.Now; var usage = NodeResourceUsages.Instance.Get(node.Address); usage.Add(node.CpuUsage, node.MemoryUsage); node.CpuUsage = usage.CpuUsage; node.MemoryUsage = usage.MemoryUsage; node.TotalBeatsCount = usage.TotalBeatsCount; await this.Db.Nodes.Save(node); ret = true; } } } return ret; })); }
void ProcessDependency(INodeModel nodeModel, Vector2 delta, Action <GraphElement, IDependency, Vector2, INodeModel> dependencyCallback) { Log($"ProcessDependency {nodeModel}"); if (!m_DependenciesByNode.TryGetValue(nodeModel.Guid, out var link)) { return; } foreach (var dependency in link) { if (m_ModelsToMove.Contains(dependency.Value.DependentNode)) { continue; } if (!m_TempMovedModels.Add(dependency.Value.DependentNode)) { Log($"Skip ProcessDependency {dependency.Value.DependentNode}"); continue; } var graphElement = dependency.Value.DependentNode.GetUI <Node>(m_GraphView); if (graphElement != null) { dependencyCallback(graphElement, dependency.Value, delta, nodeModel); } else { Log($"Cannot find ui node for model: {dependency.Value.DependentNode} dependency from {nodeModel}"); } ProcessDependency(dependency.Value.DependentNode, delta, dependencyCallback); } }
public void AddStackedNodeNoUndo(INodeModel nodeModelInterface, int index) { if (!AcceptNode(nodeModelInterface.GetType())) { return; } var nodeModel = (NodeModel)nodeModelInterface; Utility.SaveAssetIntoObject(nodeModel.NodeAssetReference, (Object)AssetModel); nodeModel.GraphModel = GraphModel; nodeModel.ParentStackModel = this; if (index == -1) { m_NodeModels.Add(nodeModel.NodeAssetReference); } else { m_NodeModels.Insert(index, nodeModel.NodeAssetReference); } VSGraphModel vsGraphModel = (VSGraphModel)GraphModel; vsGraphModel.LastChanges.ChangedElements.Add(nodeModel); }
protected bool ExposeProperty(IProperty property, ref ChangeTracker changeTracker, ref T pickedType) { bool justPicked = false; if (m_EditedModel == m_HighLevelNodeImguiVisitor.model && !m_Picked.Equals(InvalidValue)) { pickedType = m_Picked; justPicked = true; m_Picked = InvalidValue; m_EditedModel = null; changeTracker.MarkChanged(); } EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel(property.GetName()); if (GUILayout.Button(Title(pickedType))) { m_EditedModel = m_HighLevelNodeImguiVisitor.model; var mousePosition = Event.current.mousePosition; if (m_HighLevelNodeImguiVisitor.CurrentContainer != null) { mousePosition = m_HighLevelNodeImguiVisitor.CurrentContainer.LocalToWorld(mousePosition); } ShowSearcher(Stencil, mousePosition, property, pickedType); } EditorGUILayout.EndHorizontal(); return(justPicked); }
public IEnumerator SelectionIsRestoredWhenEnteringPlaymode_AddNodesBeforePersistence() { MarkGraphViewStateDirty(); yield return(null); GetNodesAndSetViewDataKey(out Node node1, out Node node2, out Node node3); CommandDispatcher.Dispatch(new SelectElementsCommand(SelectElementsCommand.SelectionMode.Add, node1Model, node3Model)); // Allow 1 frame to let the persistent data get saved yield return(null); // This will re-create the window, flushing all temporary state yield return(new EnterPlayMode()); node1Model = CreateNode(key1, new Vector2(200, 200)); node2Model = CreateNode(key2, new Vector2(400, 400)); node3Model = CreateNode(key3, new Vector2(600, 600)); MarkGraphViewStateDirty(); yield return(null); GetNodesAndSetViewDataKey(out node1, out node2, out node3); // Allow 1 frame to let the persistence be restored yield return(null); Assert.True(node1.IsSelected()); Assert.False(node2.IsSelected()); Assert.True(node3.IsSelected()); }
static LinkedNodesDependency CreateDependencyFromEdge(IEdgeModel model, out INodeModel parent) { LinkedNodesDependency dependency; if (model.InputPortModel.NodeModel is IStackModel && model.InputPortModel.PortType != PortType.Instance) { dependency = new LinkedNodesDependency { DependentPort = model.InputPortModel, ParentPort = model.OutputPortModel, count = 1, }; parent = model.OutputPortModel.NodeModel; } else { dependency = new LinkedNodesDependency { DependentPort = model.OutputPortModel, ParentPort = model.InputPortModel, }; parent = model.InputPortModel.NodeModel; } return(dependency); }
public void Add(INodeModel parent, IDependency child) { if (!m_DependenciesByNode.TryGetValue(parent.Guid, out Dictionary <GUID, IDependency> link)) { m_DependenciesByNode.Add(parent.Guid, new Dictionary <GUID, IDependency> { { child.DependentNode.Guid, child } }); } else { if (link.TryGetValue(child.DependentNode.Guid, out IDependency dependency)) { if (dependency is LinkedNodesDependency linked) { linked.count++; } else { Debug.LogWarning($"Dependency between nodes {parent} && {child.DependentNode} registered both as a {dependency.GetType().Name} and a {nameof(LinkedNodesDependency)}"); } } else { link.Add(child.DependentNode.Guid, child); } } }
public override void SetUp() { base.SetUp(); m_NodeModel1 = CreateNode("Node 1", new Vector2(0, 0)); m_NodeModel2 = CreateNode <NonDeletableNodeModel>("Node 2", new Vector2(200, 0)); }
// static StatementSyntax StatementFromExitStrategy(StackExitStrategy stackExitStrategy, ExpressionSyntax returnValue) // { // StatementSyntax lastStatementSyntax; // switch (stackExitStrategy) // { // case StackExitStrategy.Return: // lastStatementSyntax = ReturnStatement(returnValue); // break; // case StackExitStrategy.Break: // lastStatementSyntax = BreakStatement(); // break; // case StackExitStrategy.None: // lastStatementSyntax = null; // break; // default: // lastStatementSyntax = ContinueStatement(); // break; // } // // return lastStatementSyntax; // } protected virtual IEnumerable <SyntaxNode> BuildNode(INodeModel statement, IPortModel portModel) { if (statement == null) { return(Enumerable.Empty <SyntaxNode>()); } Assert.IsTrue(portModel == null || portModel.NodeModel == statement, "If a Port is provided, it must be owned by the provided node"); var ext = ModelUtility.ExtensionMethodCache <RoslynTranslator> .GetExtensionMethod( statement.GetType(), FilterMethods, KeySelector); if (ext != null) { var syntaxNode = (IEnumerable <SyntaxNode>)ext.Invoke(null, new object[] { this, statement, portModel }) ?? Enumerable.Empty <SyntaxNode>(); var annotatedNodes = new List <SyntaxNode>(); foreach (var node in syntaxNode) { var annotatedNode = node?.WithAdditionalAnnotations(new SyntaxAnnotation(Annotations.AnnotationKind, statement.Guid.ToString())); annotatedNodes.Add(annotatedNode); } return(annotatedNodes); } else { Debug.LogError("Roslyn Translator doesn't know how to create a node of type: " + statement.GetType()); } return(Enumerable.Empty <SyntaxNode>()); }
public NodeModel DuplicateNode(INodeModel copiedNode, Dictionary <INodeModel, NodeModel> mapping, StackBaseModel pastedNodeParentStack, Vector2 delta, int stackInsertionIndex, List <StackedNodesStruct> implicitStackedNodes = null) { var pastedNodeModel = (NodeModel)copiedNode.Clone(); // Set graphmodel BEFORE define node as it is commonly use during Define pastedNodeModel.AssetModel = AssetModel; pastedNodeModel.Title = copiedNode.Title; pastedNodeModel.AssignNewGuid(); pastedNodeModel.DefineNode(); pastedNodeModel.ReinstantiateInputConstants(); mapping.Add(copiedNode, pastedNodeModel); if (pastedNodeParentStack != null) { pastedNodeParentStack.AddStackedNode(pastedNodeModel, stackInsertionIndex); } else { AddNode(pastedNodeModel); pastedNodeModel.Position += delta; if (pastedNodeModel is StackBaseModel pastedStackModel) { DuplicateStackedNodes(copiedNode, mapping, delta, stackInsertionIndex, implicitStackedNodes, pastedStackModel); } } return(pastedNodeModel); }
public static TracingStep ExecutedNode(INodeModel nodeModel1, byte progress) => new TracingStep { Type = TracingStepType.ExecutedNode, NodeModel = nodeModel1, Progress = progress, };
static void CreateItemizedNode(State state, VSGraphModel graphModel, ref IPortModel outputPortModel) { ItemizeOptions currentItemizeOptions = state.Preferences.CurrentItemizeOptions; // automatically itemize, i.e. duplicate variables as they get connected if (!outputPortModel.Connected || currentItemizeOptions == ItemizeOptions.Nothing) { return; } INodeModel nodeToConnect = outputPortModel.NodeModel; bool itemizeContant = currentItemizeOptions.HasFlag(ItemizeOptions.Constants) && nodeToConnect is ConstantNodeModel; bool itemizeVariable = currentItemizeOptions.HasFlag(ItemizeOptions.Variables) && (nodeToConnect is VariableNodeModel || nodeToConnect is ThisNodeModel); bool itemizeSystemConstant = currentItemizeOptions.HasFlag(ItemizeOptions.SystemConstants) && nodeToConnect is SystemConstantNodeModel; if (itemizeContant || itemizeVariable || itemizeSystemConstant) { Vector2 offset = Vector2.up * k_NodeOffset; nodeToConnect = graphModel.DuplicateUnstackedNode(outputPortModel.NodeModel, new Dictionary <INodeModel, NodeModel>(), offset); outputPortModel = nodeToConnect.OutputsById[outputPortModel.UniqueId]; } }
public void Visit(INodeModel node) { if (node.Clusters.Count == this.NrOfClusters) { Console.WriteLine(node); } }
void CheckNodeList(IReadOnlyList <INodeModel> nodeModels, Dictionary <GUID, int> existingGuids = null) { if (existingGuids == null) { existingGuids = new Dictionary <GUID, int>(nodeModels.Count * 4); // wild guess of total number of nodes, including stacked nodes } for (var i = 0; i < nodeModels.Count; i++) { INodeModel node = nodeModels[i]; Assert.IsTrue(node.NodeAssetReference != null, $"Node asset {i} is null"); Assert.IsNotNull(node, $"Node {i} is null"); Assert.IsTrue(AssetModel.IsSameAsset(node.AssetModel), $"Node {i} asset is not matching its actual asset"); Assert.IsFalse(node.Guid.Empty(), $"Node {i} ({node.GetType()}) has an empty Guid"); Assert.IsFalse(existingGuids.TryGetValue(node.Guid, out var oldIndex), $"duplicate GUIDs: Node {i} ({node.GetType()}) and Node {oldIndex}"); existingGuids.Add(node.Guid, i); if (node.Destroyed) { continue; } CheckNodePorts(node.InputsById); CheckNodePorts(node.OutputsById); if (node is IStackModel stackModel) { CheckNodeList(stackModel.NodeModels, existingGuids); } } }
void ComputeNodeDependencies() { NodeDependencies.Clear(); m_DependenciesToMerge.Clear(); foreach (IEdgeModel edgeModel in GetSortedSelectedEdgeModels()) { INodeModel parentModel = edgeModel.ToPort.NodeModel; INodeModel childModel = edgeModel.FromPort.NodeModel; if (parentModel == childModel) { // Node is its own parent continue; } MergeNodeDependencies(parentModel, childModel); AddChildToParent(parentModel, childModel); } // Remove parents that were merged foreach (INodeModel parentToRemove in m_DependenciesToMerge.Keys) { NodeDependencies.Remove(parentToRemove); } }
public bool GetComponentFromEntityOrComponentPort( INodeModel model, IPortModel entityOrComponentPort, out ComponentQueryDeclarationModel query, out ExpressionSyntax setValue, AccessMode mode = AccessMode.Read) { setValue = null; var componentVariableType1 = entityOrComponentPort.DataType; IVariableDeclarationModel varNode = null; if (!entityOrComponentPort.Connected) // assume current iteration context entity variable { varNode = context.IterationContext.Query.ItemVariableDeclarationModel; } else { varNode = (entityOrComponentPort.ConnectionPortModels?.FirstOrDefault()?.NodeModel as VariableNodeModel)?.DeclarationModel; } if (varNode != null && varNode.DataType == typeof(Entity).GenerateTypeHandle(Stencil) && varNode.Owner is IIteratorStackModel iteratorStackModel) { query = iteratorStackModel.ComponentQueryDeclarationModel; if (query.Components.Any(x => x.Component.TypeHandle == componentVariableType1)) { context.RecordComponentAccess(context.IterationContext, componentVariableType1, mode); var componentVarName = context.GetComponentVariableName(iteratorStackModel, componentVariableType1); setValue = IdentifierName(componentVarName); } else { var componentName = componentVariableType1.Resolve(Stencil).FriendlyName(); var queryCopy = query; AddError(model, $"A component of type {componentName} is required, which the query {query.Name} doesn't specify", new CompilerQuickFix($"Add {componentName} to the query", s => s.Dispatch(new AddComponentToQueryAction( queryCopy, componentVariableType1, ComponentDefinitionFlags.None))) ); return(false); } } if (setValue == null) { context.RecordComponentAccess(context.IterationContext, componentVariableType1, mode); setValue = BuildPort(entityOrComponentPort).FirstOrDefault() as ExpressionSyntax; } query = null; return(true); }
public ChangeStackedNodeAction(INodeModel oldNodeModel, IStackModel stackModel, StackNodeModelSearcherItem selectedItem) { OldNodeModel = oldNodeModel; StackModel = stackModel; SelectedItem = selectedItem; }
public IEnumerable <SyntaxNode> BuildNode(INodeModel inputNode) { if (inputNode == null) { return(Enumerable.Empty <SyntaxNode>()); } return(BuildNode(inputNode, null)); }
protected override void Because_of() { var dto = new NodeDto <int> { ID = 1, Name = "Hi" }; _destination = Mapper.Map <INodeModel <int> >(dto); }
public RenamableNode(INodeModel model, Store store, GraphView graphView) : base(model, store, graphView) { if (model is IRenamableModel) { this.EnableRename(); } }
internal IDisplayNode CreateDisplayNode(INodeModel nodeModel) { Angle angle = nodeModel.DirectionAngle; IDisplayNode displayNode = m_Factory.Create(nodeModel.Id, nodeModel.X, nodeModel.Y, -angle.Degrees, DefaultRadius, DefaultFill, DefaultStroke, DefaultStrokeThickness); return displayNode; }
internal void Update(IEnumerable <int> trail) { IEnumerable <int> enumerable = trail as int[] ?? trail.ToArray(); if ( !enumerable.Any() ) { m_NodeModel = NodeModel.Unknown; } else { int nodeId = DetermineNodeId(enumerable); int lineId = Helper.NodeToLine(nodeId); m_NodeModel = m_NodeModelCreator.CreateNodeModel(lineId, nodeId); } SendMessage(); }