/// <summary> /// Create a node and add it to the view-model. /// </summary> public NodeViewModel CreateNode(ModuleBase moduleBase, Point nodeLocation, bool centerNode) { System.Windows.Media.Brush generatorBrush = new LinearGradientBrush(Colors.White, Colors.Orange, 90.0); System.Windows.Media.Brush operatorBrush = new LinearGradientBrush(Colors.White, Colors.PowderBlue, 90.0); System.Windows.Media.Brush finalBrush = new LinearGradientBrush(Colors.White, Colors.YellowGreen, 90.0); NodeViewModel node = new NodeViewModel(new LibnoiseNode(moduleBase)); node.Module.ID = moduleBase.GetType().Name + "_" + (Network.Nodes.Count(n => n.Module.ModuleType.Equals(moduleBase.GetType().Name)) + 1); node.X = nodeLocation.X; node.Y = nodeLocation.Y; node.StrokeBrush = System.Windows.Media.Brushes.Black; // this can be simplified, for sure, but I left in the giant ugly switch // in the event I want to do something unique by type, such as any additional // colouring or whatever. It's a little gross to look at, but it does the job switch (moduleBase.GetType().Name) { // Generators should not have any input values case "Billow": node.FillBrush = generatorBrush; break; case "Checker": node.FillBrush = generatorBrush; break; case "Const": node.FillBrush = generatorBrush; break; case "Cylinders": node.FillBrush = generatorBrush; break; case "Perlin": node.FillBrush = generatorBrush; break; case "RidgedMultifractal": node.FillBrush = generatorBrush; break; case "Spheres": node.FillBrush = generatorBrush; break; case "Voronoi": node.FillBrush = generatorBrush; break; case "Abs": node.FillBrush = operatorBrush; node.InputConnectors.Add(new ConnectorViewModel("Input")); break; case "Add": node.FillBrush = operatorBrush; node.InputConnectors.Add(new ConnectorViewModel("Left")); node.InputConnectors.Add(new ConnectorViewModel("Right")); break; case "Blend": node.FillBrush = operatorBrush; node.InputConnectors.Add(new ConnectorViewModel("Left")); node.InputConnectors.Add(new ConnectorViewModel("Right")); node.InputConnectors.Add(new ConnectorViewModel("Operator")); break; case "Cache": node.FillBrush = operatorBrush; node.InputConnectors.Add(new ConnectorViewModel("Input")); break; case "Clamp": node.FillBrush = operatorBrush; node.InputConnectors.Add(new ConnectorViewModel("Input")); break; case "Curve": node.FillBrush = operatorBrush; node.InputConnectors.Add(new ConnectorViewModel("Input")); break; case "Displace": node.FillBrush = operatorBrush; node.InputConnectors.Add(new ConnectorViewModel("Primary")); node.InputConnectors.Add(new ConnectorViewModel("X")); node.InputConnectors.Add(new ConnectorViewModel("Y")); node.InputConnectors.Add(new ConnectorViewModel("Z")); break; case "Exponent": node.FillBrush = operatorBrush; node.InputConnectors.Add(new ConnectorViewModel("Input")); break; case "Invert": node.FillBrush = operatorBrush; node.InputConnectors.Add(new ConnectorViewModel("Input")); break; case "Max": node.FillBrush = operatorBrush; node.InputConnectors.Add(new ConnectorViewModel("Left")); node.InputConnectors.Add(new ConnectorViewModel("Right")); break; case "Min": node.FillBrush = operatorBrush; node.InputConnectors.Add(new ConnectorViewModel("Left")); node.InputConnectors.Add(new ConnectorViewModel("Right")); break; case "Multiply": node.FillBrush = operatorBrush; node.InputConnectors.Add(new ConnectorViewModel("Left")); node.InputConnectors.Add(new ConnectorViewModel("Right")); break; case "Power": node.FillBrush = operatorBrush; node.InputConnectors.Add(new ConnectorViewModel("Left")); node.InputConnectors.Add(new ConnectorViewModel("Right")); break; case "Rotate": node.FillBrush = operatorBrush; node.InputConnectors.Add(new ConnectorViewModel("Input")); break; case "Scale": node.FillBrush = operatorBrush; node.InputConnectors.Add(new ConnectorViewModel("Input")); break; case "ScaleBias": node.FillBrush = operatorBrush; node.InputConnectors.Add(new ConnectorViewModel("Input")); break; case "Select": node.FillBrush = operatorBrush; node.InputConnectors.Add(new ConnectorViewModel("Primary")); node.InputConnectors.Add(new ConnectorViewModel("Secondary")); node.InputConnectors.Add(new ConnectorViewModel("Controller")); break; case "Subtract": node.FillBrush = operatorBrush; node.InputConnectors.Add(new ConnectorViewModel("Left")); node.InputConnectors.Add(new ConnectorViewModel("Right")); break; case "Terrace": node.FillBrush = operatorBrush; node.InputConnectors.Add(new ConnectorViewModel("Input")); break; case "Translate": node.FillBrush = operatorBrush; node.InputConnectors.Add(new ConnectorViewModel("Input")); break; case "Turbulence": node.FillBrush = operatorBrush; node.InputConnectors.Add(new ConnectorViewModel("Input")); break; case "Final": node.FillBrush = finalBrush; node.InputConnectors.Add(new ConnectorViewModel("Input")); break; default: break; } // for the 'Final' node, don't add any outputs. if (!moduleBase.GetType().Name.Equals("Final")) { node.OutputConnectors.Add(new ConnectorViewModel("Output")); } if (centerNode) { // // We want to center the node. // // For this to happen we need to wait until the UI has determined the // size based on the node's data-template. // // So we define an anonymous method to handle the SizeChanged event for a node. // // Note: If you don't declare sizeChangedEventHandler before initializing it you will get // an error when you try and unsubscribe the event from within the event handler. // EventHandler<EventArgs> sizeChangedEventHandler = null; sizeChangedEventHandler = delegate(object sender, EventArgs e) { // // This event handler will be called after the size of the node has been determined. // So we can now use the size of the node to modify its position. // node.X -= node.Size.Width / 2; node.Y -= node.Size.Height / 2; // // Don't forget to unhook the event, after the initial centering of the node // we don't need to be notified again of any size changes. // node.SizeChanged -= sizeChangedEventHandler; }; // // Now we hook the SizeChanged event so the anonymous method is called later // when the size of the node has actually been determined. // node.SizeChanged += sizeChangedEventHandler; } // // Add the node to the view-model. // this.Network.Nodes.Add(node); return node; }
/// <summary> /// Delete the node from the view-model. /// Also deletes any connections to or from the node. /// </summary> public void DeleteNode(NodeViewModel node, bool purge) { if (!node.Module.LibnoiseModule.GetType().Name.Equals("Final") || purge) { foreach (ConnectionViewModel cvm in node.AttachedConnections) { DeleteConnection(cvm); } // // Remove all connections attached to the node. - not used because we need to ensure each node is also cleared of the dest/source modules // //this.Network.Connections.RemoveRange(node.AttachedConnections); // // Remove the node from the network. // this.Network.Nodes.Remove(node); } else { MessageBox.Show("You cannot delete the final node"); } }
/// <summary> /// /// </summary> /// <param name="node_"></param> public void Load(XmlNode node_) { try { int version = int.Parse(node_.Attributes["version"].Value); int graphId = int.Parse(node_.Attributes["id"].Value); Sequence = GraphDataManager.Instance.GetByID(graphId); foreach (SequenceNode node in Sequence.Nodes) { XmlNode nodeNode = node_.SelectSingleNode("NodeList/Node[@id='" + node.Id + "']"); int versionNode = int.Parse(nodeNode.Attributes["version"].Value); if (nodeNode != null) { NodeViewModel nodeVM = new NodeViewModel(node); nodeVM.X = double.Parse(nodeNode.Attributes["x"].Value); nodeVM.Y = double.Parse(nodeNode.Attributes["y"].Value); nodeVM.ZIndex = int.Parse(nodeNode.Attributes["z"].Value); Network.Nodes.Add(nodeVM); } else { throw new InvalidOperationException("Can't find node from xml " + string.Format("id={0}", nodeNode.Attributes["id"].Value)); } } foreach (XmlNode linkNode in node_.SelectNodes("ConnectionList/Connection")) { int versionLink = int.Parse(linkNode.Attributes["version"].Value); ConnectionViewModel cvm = new ConnectionViewModel(); NodeViewModel srcNode = GetNodeVMBySequenceID(int.Parse(linkNode.Attributes["srcNodeID"].Value)); NodeViewModel destNode = GetNodeVMBySequenceID(int.Parse(linkNode.Attributes["destNodeID"].Value)); cvm.SourceConnector = srcNode.GetConnectorFromSlotId(int.Parse(linkNode.Attributes["srcNodeSlotID"].Value)); cvm.DestConnector = destNode.GetConnectorFromSlotId(int.Parse(linkNode.Attributes["destNodeSlotID"].Value)); Network.Connections.Add(cvm); } m_XmlNodeLoaded = node_; } catch (System.Exception ex) { LogManager.Instance.WriteException(ex); } }
/// <summary> /// /// </summary> internal void InitialNodeFromNewFunction() { // Function already contains nodes when it is created // so we need to create the corresponding NodeViewModel for each node if (Sequence is SequenceFunction && Network.Nodes.Count == 0) { IEnumerator<SequenceNode> it = Sequence.Nodes.GetEnumerator(); int i = 0; while (it.MoveNext() == true) { NodeViewModel nodeVM = new NodeViewModel(it.Current); nodeVM.X = 50 + i * 150; nodeVM.Y = 50; Network.Nodes.Add(nodeVM); i++; } } }
/// <summary> /// Create a node and add it to the view-model. /// </summary> public NodeViewModel CreateNode(SequenceNode node_, Point nodeLocation, bool centerNode) { NodeViewModel node = new NodeViewModel(node_); node.X = nodeLocation.X; node.Y = nodeLocation.Y; if (centerNode) { // // We want to center the node. // // For this to happen we need to wait until the UI has determined the // size based on the node's data-template. // // So we define an anonymous method to handle the SizeChanged event for a node. // // Note: If you don't declare sizeChangedEventHandler before initializing it you will get // an error when you try and unsubscribe the event from within the event handler. // EventHandler<EventArgs> sizeChangedEventHandler = null; sizeChangedEventHandler = delegate(object sender, EventArgs e) { // // This event handler will be called after the size of the node has been determined. // So we can now use the size of the node to modify its position. // node.X -= node.Size.Width / 2; node.Y -= node.Size.Height / 2; // // Don't forget to unhook the event, after the initial centering of the node // we don't need to be notified again of any size changes. // node.SizeChanged -= sizeChangedEventHandler; }; // // Now we hook the SizeChanged event so the anonymous method is called later // when the size of the node has actually been determined. // node.SizeChanged += sizeChangedEventHandler; } AddNode(node, true); return node; }
/// <summary> /// Delete the node from the view-model. /// Also deletes any connections to or from the node. /// </summary> public void DeleteNode(NodeViewModel node, bool saveUndo_ = false) { if (saveUndo_ == true) { m_UndoManager.Add(new DeleteNodeUndoCommand(this, node)); } this.Network.Connections.RemoveRange(node.AttachedConnections); this.Network.Nodes.Remove(node); }
/// <summary> /// add a node to the view-model. /// </summary> public void AddNode(NodeViewModel node_, bool saveUndo_ = false) { if (saveUndo_ == true) { m_UndoManager.Add(new CreateNodeUndoCommand(this, node_)); } this.Network.Nodes.Add(node_); }
/// <summary> /// /// </summary> public DeleteNodeUndoCommand(FlowGraphControlViewModel fgvm_, NodeViewModel nodeVM_) { m_FlowGraphVM = fgvm_; m_NodeVM = nodeVM_; CopyConnections(m_NodeVM.AttachedConnections); }
/// <summary> /// /// </summary> public CreateNodeUndoCommand(FlowGraphControlViewModel fgvm_, NodeViewModel nodeVM_) { m_FlowGraphVM = fgvm_; m_NodeVM = nodeVM_; }
// simple recursive method to trace the path from the selected node // to the final node. Each node on the trace will be selected. // eventually, it would be ideal to highlight the connectors as well... private void TraceConnectionPath(NodeViewModel nvm) { foreach (ConnectorViewModel cvm in nvm.OutputConnectors) { ConnectorViewModel destConnector = cvm.AttachedConnections.First().DestConnector; NodeViewModel destNode = destConnector.ParentNode; cvm.AttachedConnections.First().IsSelected = true; destConnector.IsSelected = true; TraceConnectionPath(destNode); } }
/// <summary> /// /// </summary> /// <param name="copyConnections_"></param> /// <returns></returns> public NodeViewModel Copy(bool copyConnections_ = false) { NodeViewModel node = new NodeViewModel(SeqNode.Copy()); node.name = name; node.x = x; node.y = y; node.zIndex = zIndex; node.size = size; node.isSelected = this.isSelected; if (copyConnections_ == true) { throw new NotImplementedException("NodeViewModel.Copy()"); } return node; }