Beispiel #1
0
        private void DeleteButton_Click(object sender, RoutedEventArgs e)
        {
            GraphEditorViewModel graph = (GraphEditorViewModel)VisualEditor.DataContext;

            graph.VisualNodes.Clear();
            graph.Connections.Clear();
        }
Beispiel #2
0
        private void VisualNode_MouseDown(object sender, MouseButtonEventArgs e)
        {
            UserControl controlSender          = (UserControl)sender;
            VisualGraphComponentViewModel node = (VisualGraphComponentViewModel)controlSender.DataContext;

            GraphEditorViewModel graphViewModel = (GraphEditorViewModel)DataContext;

            node.ZIndex = graphViewModel.FindMaxZIndex() + 10;
        }
Beispiel #3
0
        private void Editor_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            // If we are creating a connection...
            if (IsCreatingConnection)
            {
                ConnectionBuilderViewModel connectionBuilder = (ConnectionBuilderViewModel)NewConnectionLine.DataContext;
                NodePinViewModel           connectionRootPin = (NodePinViewModel)connectionBuilder.OutputPin.DataContext;

                // Check if we are clicking from an input pin
                // If we are, try to automatically place a constant node connecting to the input pin
                if (connectionRootPin.IsOutputPin == false && connectionRootPin.IsExecutionPin == false)
                {
                    GraphEditorViewModel        viewModel        = (GraphEditorViewModel)this.DataContext;
                    VisualConstantNodeViewModel autoConstantNode = new VisualConstantNodeViewModel(connectionRootPin.DataType)
                    {
                        X = viewModel.MousePoint.X,
                        Y = viewModel.MousePoint.Y
                    };

                    viewModel.VisualNodes.Add(autoConstantNode);

                    // Generates the view for the NodePin in the constant node before we add it
                    Dispatcher.Invoke(new Action(() => { }), DispatcherPriority.ContextIdle, null);

                    viewModel.Connections.Add(new ConnectionViewModel(autoConstantNode.OutputPin.Pin, connectionRootPin.Pin));
                }

                IsCreatingConnection = false;
                return;
            }

            // If we aren't creating a connection just deselect any nodes
            foreach (VisualGraphComponentViewModel node in ((GraphEditorViewModel)DataContext).VisualNodes)
            {
                node.IsSelected = false;
            }
        }
Beispiel #4
0
        public static NodeGraphManager BuildGraph(GraphEditorViewModel graph)
        {
            List <VisualNodeViewModel> visualExecutionNodes = new List <VisualNodeViewModel>();

            foreach (var graphComponent in graph.VisualNodes)
            {
                VisualNodeViewModel visualNode = graphComponent as VisualNodeViewModel;
                if (visualNode != null && visualNode.ExecutionInputs.Count > 0)
                {
                    visualExecutionNodes.Add(visualNode);
                }
            }

            // Begin to build our graph
            NodeGraphManager graphManager = new NodeGraphManager();

            Dictionary <VisualNodeViewModel, GraphNode> functionNodes = new Dictionary <VisualNodeViewModel, GraphNode>();
            List <VisualConstantNodeViewModel>          constantNodes = new List <VisualConstantNodeViewModel>();

            foreach (dynamic visualNode in graph.VisualNodes)
            {
                if (visualNode is VisualNodeViewModel)
                {
                    functionNodes.Add(visualNode, new GraphNode(visualNode.NodeType, graphManager));
                }
                else if (visualNode is VisualConstantNodeViewModel)
                {
                    constantNodes.Add(visualNode as VisualConstantNodeViewModel);
                }
            }

            // Wire up constant nodes
            foreach (var constantNode in constantNodes)
            {
                List <ConnectionViewModel> connections = GetPinConnections(constantNode.OutputPin, graph);

                // Lookup each input pin that the constant node is connecting to and add it in our graph manager
                foreach (var connection in connections)
                {
                    foreach (var functionNode in functionNodes)
                    {
                        if (functionNode.Key.Inputs.Contains(connection.InputPin))
                        {
                            // Get pin index
                            int pindex = ((NodePinViewModel)connection.InputPin).Index;

                            IDataTypeContainer valueToSet;

                            // Get value to set
                            if (constantNode.OutputPin.DataType == typeof(DataTypes.Numeric))
                            {
                                valueToSet = new DataTypes.Numeric(Double.Parse(constantNode.Value));
                            }
                            else if (constantNode.OutputPin.DataType == typeof(DataTypes.Boolean))
                            {
                                valueToSet = new DataTypes.Boolean(Boolean.Parse(constantNode.Value));
                            }
                            else if (constantNode.OutputPin.DataType == typeof(DataTypes.String))
                            {
                                valueToSet = new DataTypes.String(constantNode.Value);
                            }
                            else
                            {
                                throw new Exception("Data type could not be determined.");
                            }

                            OutputPin pinConnection = new OutputPin(
                                ((NodePinViewModel)connection.InputPin).DataType, null)
                            {
                                OutputValue = valueToSet, OutputRealised = true
                            };


                            graphManager.AddConnection(pinConnection, functionNode.Value.NodeInputs[pindex]);
                        }
                    }
                }
            }

            // Wire up functional nodes
            foreach (var functionNode in functionNodes)
            {
                int outputPindex = 0;

                // Check each output pin on the node
                foreach (var output in functionNode.Key.Outputs)
                {
                    List <ConnectionViewModel> connections = GetPinConnections(output, graph);

                    foreach (var connection in connections)
                    {
                        // Wire up non-execution pins
                        foreach (var targetFunctionNode in functionNodes)
                        {
                            if (targetFunctionNode.Key.Inputs.Contains(connection.InputPin))
                            {
                                int pindex = ((NodePinViewModel)connection.InputPin).Index;

                                graphManager.AddConnection(
                                    functionNodes[functionNode.Key].NodeOutputs[outputPindex],
                                    targetFunctionNode.Value.NodeInputs[pindex]);
                            }
                        }
                    }
                }

                // Wire up execution pins
                foreach (var executionOutput in functionNode.Key.ExecutionOutputs)
                {
                    List <ConnectionViewModel> connections = GetPinConnections(executionOutput, graph);

                    if (connections.Count == 0)
                    {
                        graphManager.AddNode(functionNode.Value);
                    }

                    foreach (var connection in connections)
                    {
                        foreach (var targetFunctionNode in functionNodes)
                        {
                            if (targetFunctionNode.Key.ExecutionInputs.Contains(connection.InputPin))
                            {
                                int pindex = ((NodePinViewModel)connection.OutputPin).Index;
                                graphManager.AddConnection(functionNode.Value, pindex, targetFunctionNode.Value);
                            }
                        }
                    }
                }
            }

            graphManager.RealiseNodeOutputs();

            return(graphManager);
        }
Beispiel #5
0
        public static List <ConnectionViewModel> GetPinConnections(NodePinViewModel pin, GraphEditorViewModel graph)
        {
            List <ConnectionViewModel> pinConnections = new List <ConnectionViewModel>();

            foreach (var connection in graph.Connections)
            {
                NodePinViewModel inputPin  = connection.InputPin;
                NodePinViewModel outputPin = connection.OutputPin;

                if (pin == inputPin || pin == outputPin)
                {
                    pinConnections.Add(connection);
                }
            }

            return(pinConnections);
        }
Beispiel #6
0
 public async static Task <NodeGraphManager> BuildGraphAsync(GraphEditorViewModel graph)
 {
     return(await Task.Run(() => BuildGraph(graph)));
 }
Beispiel #7
0
        private void NodePin_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            DependencyObject parentObject = VisualTreeHelper.GetParent(this);

            // Find the visual editor
            while (!(parentObject is VisualEditor))
            {
                parentObject = VisualTreeHelper.GetParent(parentObject);

                if (parentObject == null)
                {
                    return;
                }
            }

            VisualEditor visualEditor = parentObject as VisualEditor;

            // Determine how to handle the click
            if (visualEditor.IsCreatingConnection)
            {
                // If we are creating a new connection then we have to validate and add a new one
                GraphEditorViewModel       graph             = ((GraphEditorViewModel)visualEditor.DataContext);
                ConnectionBuilderViewModel connectionBuilder = ((ConnectionBuilderViewModel)visualEditor.NewConnectionLine.DataContext);

                NodePinViewModel rootPin   = (NodePinViewModel)connectionBuilder.OutputPin.DataContext;
                NodePinViewModel targetPin = (NodePinViewModel)this.DataContext;

                // Validate the output and input pins
                // Reverse them if needed
                // TODO: More extensive validation. ie. Check for output -> output or input -> input connections.

                // Ensure datatypes are the same between pins
                if (rootPin.DataType != targetPin.DataType)
                {
                    // If the data types do not match try and add in an auto-conversion
                    foreach (var rule in graph.ConversionRules)
                    {
                        if (rule.Item1 == rootPin.DataType && rule.Item2 == targetPin.DataType)
                        {
                            // Conversion rule found!
                            // Add the conversion node at the midpoint between pins
                            Point rootPoint   = rootPin.Pin.Centre;
                            Point targetPoint = targetPin.Pin.Centre;

                            Point midPoint = new Point(
                                ((rootPoint.X + targetPoint.X) / 2),
                                (rootPoint.Y + targetPoint.Y) / 2);

                            VisualNodeViewModel conversionNode = new VisualNodeViewModel(rule.Item3)
                            {
                                X = midPoint.X,
                                Y = midPoint.Y
                            };

                            graph.VisualNodes.Add(conversionNode);

                            // Generate the conversion node's view so we can access its pins
                            Dispatcher.Invoke(new Action(() => { }), DispatcherPriority.ContextIdle, null);

                            // Add the new connections, but ensure it is an OutputPin -> InputPin connection
                            // Otherwise, we need to correct for that here
                            if (((NodePinViewModel)connectionBuilder.OutputPin.DataContext).IsOutputPin == false)
                            {
                                // Connections need flipping
                                graph.Connections.Add(new ConnectionViewModel(targetPin.Pin, conversionNode.Inputs[0].Pin));
                                graph.Connections.Add(new ConnectionViewModel(conversionNode.Outputs[0].Pin, rootPin.Pin));
                            }
                            else
                            {
                                // Connection is correct
                                graph.Connections.Add(new ConnectionViewModel(rootPin.Pin, conversionNode.Inputs[0].Pin));
                                graph.Connections.Add(new ConnectionViewModel(conversionNode.Outputs[0].Pin, targetPin.Pin));
                            }
                        }
                    }
                }
                // If datatypes are the same, we can just create a connection between the pins
                // Make sure the connection is added in an OutputPin -> InputPin order
                else
                {
                    if (((NodePinViewModel)connectionBuilder.OutputPin.DataContext).IsOutputPin == false)
                    {
                        graph.Connections.Add(new ConnectionViewModel(this, connectionBuilder.OutputPin));
                    }
                    else
                    {
                        graph.Connections.Add(new ConnectionViewModel(connectionBuilder.OutputPin, this));
                    }
                }

                visualEditor.IsCreatingConnection = false;
            }
            else
            {
                // We need to initialise the 'create a connection' mode
                visualEditor.IsCreatingConnection = true;

                // And set the root pin
                ConnectionBuilderViewModel newConnection = ((ConnectionBuilderViewModel)visualEditor.NewConnectionLine.DataContext);
                newConnection.OutputPin = this;
            }
        }