Example #1
0
 public Node FindNodeFromId(HyperGraph.IGraphModel graph, UInt64 id)
 {
     foreach (Node n in graph.Nodes)
     {
         if (n.Tag is ShaderFragmentNodeTag &&
             ((ShaderFragmentNodeTag)n.Tag).Id == (UInt64)id)
         {
             return(n);
         }
     }
     return(null);
 }
Example #2
0
        //
        //      Convert from the "ViewModel" to the "Model"
        //
        //      We don't maintain the ShaderPatcherLayer.NodeGraph representation
        //      permanently... But we need this for serialization and shader
        //      generation operations
        //
        //      So, let's just build it from the graph control object.
        //
        public ShaderPatcherLayer.NodeGraph ToShaderPatcherLayer(HyperGraph.IGraphModel graph)
        {
            ShaderPatcherLayer.NodeGraph nodeGraph          = new ShaderPatcherLayer.NodeGraph();
            Dictionary <Node, int>       nodeToVisualNodeId = new Dictionary <Node, int>();

            foreach (Node n in graph.Nodes)
            {
                var nTag = n.Tag as ShaderFragmentNodeTag;
                if (nTag == null)
                {
                    continue;
                }

                // Create a "visual node" (unless it already exists)
                //      --  this contains information that only affects the rendered
                //          graphs, not the output shader
                int visualNodeId;
                if (nodeToVisualNodeId.ContainsKey(n))
                {
                    visualNodeId = nodeToVisualNodeId[n];
                }
                else
                {
                    visualNodeId = nodeGraph.VisualNodes.Count();
                    nodeToVisualNodeId.Add(n, visualNodeId);
                    nodeGraph.VisualNodes.Add(
                        new ShaderPatcherLayer.VisualNode()
                    {
                        Location = n.Location,
                        State    = (n.Collapsed) ? ShaderPatcherLayer.VisualNode.StateType.Collapsed : ShaderPatcherLayer.VisualNode.StateType.Normal
                    });
                }

                // Potentially build a "node" in the patcher layer. This is only required
                // if we're referencing some object in the shader fragments archive
                if (!string.IsNullOrEmpty(nTag.ArchiveName))
                {
                    ShaderPatcherLayer.Node resultNode = new ShaderPatcherLayer.Node()
                    {
                        FragmentArchiveName = nTag.ArchiveName, NodeId = nTag.Id,
                        VisualNodeId        = visualNodeId
                    };

                    if (n.Tag is ShaderParameterNodeTag)
                    {
                        //  This is a hack... But there should be a drop down list that
                        //  can tell us the type of this parameter struct box.
                        foreach (var i in n.Items)
                        {
                            if (i is HyperGraph.Items.NodeDropDownItem)
                            {
                                var dropDown        = (HyperGraph.Items.NodeDropDownItem)i;
                                var stringForm      = dropDown.Items[dropDown.SelectedIndex];
                                var parameterSource = ShaderFragmentNodeCreator.AsEnumValue <ShaderFragmentArchive.Parameter.SourceType>(stringForm, ShaderFragmentNodeCreator.ParamSourceTypeNames);
                                resultNode.NodeType = AsNodeType(parameterSource);
                            }
                        }
                    }
                    else
                    {
                        resultNode.NodeType = ShaderPatcherLayer.Node.Type.Procedure;
                    }

                    nodeGraph.Nodes.Add(resultNode);
                }

                // Build connections...
                foreach (NodeConnection connection in n.Connections)
                {
                    if (connection.To != null)
                    {
                        var dstNode = connection.To.Node.Tag as ShaderFragmentNodeTag;
                        if (dstNode == null)
                        {
                            continue;
                        }

                        var dstItem = connection.To.Item as ShaderFragmentNodeItem;
                        if (dstItem == null)
                        {
                            continue;
                        }

                        if (connection.From == null && connection.To.Node == n)
                        {
                            // this is a direct constant connection. It connects the value either to a constant value, or some named variable
                            nodeGraph.ConstantConnections.Add(
                                new ShaderPatcherLayer.ConstantConnection()
                            {
                                Value        = connection.Name,
                                OutputNodeID = dstNode.Id, OutputParameterName = dstItem.Name
                            });
                        }
                        else if (connection.To.Node == n && connection.To.Item is ShaderFragmentInterfaceParameterItem)
                        {
                            // this is an output parameter. This is the only case where we creating the connection
                            // while processing the node on the "out" side
                            var outputParam      = (ShaderFragmentInterfaceParameterItem)connection.To.Item;
                            var resultConnection = new ShaderPatcherLayer.OutputParameterConnection
                            {
                                VisualNodeId = visualNodeId,        // (visual node for the output box)
                                Type         = outputParam.Type,
                                Name         = outputParam.Name,
                                Semantic     = outputParam.Semantic
                            };
                            if (connection.From.Item is ShaderFragmentNodeItem)
                            {
                                var tag = connection.From.Item.Node.Tag as ShaderFragmentNodeTag;
                                if (tag != null)
                                {
                                    resultConnection.InputNodeID = tag.Id;
                                }
                                resultConnection.InputParameterName = ((ShaderFragmentNodeItem)connection.From.Item).Name;
                            }
                            nodeGraph.OutputParameterConnections.Add(resultConnection);
                        }
                        else if (connection.From.Node == n)
                        {
                            if (connection.From.Item is ShaderFragmentInterfaceParameterItem)
                            {
                                // it's an input parameter... we just need type, name, semantic
                                var inputParam = (ShaderFragmentInterfaceParameterItem)connection.From.Item;
                                nodeGraph.InputParameterConnections.Add(
                                    new ShaderPatcherLayer.InputParameterConnection
                                {
                                    OutputNodeID        = dstNode.Id,
                                    OutputParameterName = dstItem.Name,
                                    VisualNodeId        = visualNodeId,
                                    Type     = inputParam.Type,
                                    Name     = inputParam.Name,
                                    Semantic = inputParam.Semantic,
                                    Default  = inputParam.Default
                                });
                            }
                            else if (connection.To.Item is ShaderFragmentInterfaceParameterItem)
                            {
                                // it's an output parameter...
                                // this will be handled when processing the node on the out side
                            }
                            else
                            {
                                // This is an output to the next node
                                var resultConnection = new ShaderPatcherLayer.NodeConnection()
                                {
                                    InputNodeID         = nTag.Id,
                                    OutputNodeID        = dstNode.Id,
                                    OutputParameterName = dstItem.Name,
                                    OutputType          = TypeFromNodeItem(dstItem)
                                };

                                if (connection.From.Item is ShaderFragmentNodeItem)
                                {
                                    var sourceItem = (ShaderFragmentNodeItem)connection.From.Item;
                                    resultConnection.InputParameterName = sourceItem.Name;
                                    resultConnection.InputType          = TypeFromNodeItem(sourceItem);
                                }
                                nodeGraph.NodeConnections.Add(resultConnection);
                            }
                        }
                    }
                    else if (connection.From != null && connection.From.Node == n)
                    {
                        // when connection.To is null, it could be an attached output connection
                        var resultConnection = new ShaderPatcherLayer.OutputParameterConnection()
                        {
                            Name        = connection.Name,
                            InputNodeID = nTag.Id
                        };

                        if (connection.From.Item is ShaderFragmentNodeItem)
                        {
                            var sourceItem = (ShaderFragmentNodeItem)connection.From.Item;
                            resultConnection.InputParameterName = sourceItem.Name;
                            resultConnection.Type = TypeFromNodeItem(sourceItem);
                        }
                        nodeGraph.OutputParameterConnections.Add(resultConnection);
                    }
                }

                // build the preview settings objects
                foreach (var i in n.Items)
                {
                    var preview = i as ShaderFragmentPreviewItem;
                    if (preview == null)
                    {
                        continue;
                    }

                    var settings = preview.PreviewSettings;
                    settings.VisualNodeId = visualNodeId;
                    nodeGraph.PreviewSettingsObjects.Add(settings);
                }
            }

            return(nodeGraph);
        }
Example #3
0
        public void AddToHyperGraph(ShaderPatcherLayer.NodeGraph nodeGraph, HyperGraph.IGraphModel graph)
        {
            //
            //      Convert from the "ShaderPatcherLayer" representation back to
            //      our graph control nodes.
            //
            //      This is required for robust serialisation. We can't easily
            //      serialise in and out the graph control objects directly, because
            //      it risks problems if the rendering code or shader fragment objects
            //      change. That is, it's not very version-robust.
            //
            //      It's better to serialise a slightly higher level representation
            //      that just contains the node names and connections. That way, we
            //      can adapt to changes in the tool and data.
            //
            {
                // --------< Basic Nodes >--------
                var newNodes            = new Dictionary <int, Node>();
                var nodeIdToControlNode = new Dictionary <UInt64, Node>();
                foreach (var n in nodeGraph.Nodes)
                {
                    if (!newNodes.ContainsKey(n.VisualNodeId))
                    {
                        var visualNode = nodeGraph.VisualNodes[n.VisualNodeId];

                        // also look for preview settings...
                        var  previewSettings = nodeGraph.PreviewSettingsObjects.Where(x => x.VisualNodeId == n.VisualNodeId).FirstOrDefault();
                        Node newNode         = null;
                        if (n.NodeType == ShaderPatcherLayer.Node.Type.Procedure)
                        {
                            var fn = _shaderFragments.GetFunction(n.FragmentArchiveName);
                            newNode = _nodeCreator.CreateNode(fn, n.FragmentArchiveName, previewSettings);
                        }
                        else
                        {
                            var ps = _shaderFragments.GetParameterStruct(n.FragmentArchiveName);
                            newNode = _nodeCreator.CreateParameterNode(ps, n.FragmentArchiveName, AsSourceType(n.NodeType));
                        }

                        if (newNode != null)
                        {
                            MatchVisualNode(newNode, visualNode);
                            newNodes[n.VisualNodeId]      = newNode;
                            nodeIdToControlNode[n.NodeId] = newNode;
                        }
                    }
                }

                graph.AddNodes(newNodes.Values);

                // --------< Node Connections >--------
                foreach (var c in nodeGraph.NodeConnections)
                {
                    if (nodeIdToControlNode.ContainsKey(c.InputNodeID) && nodeIdToControlNode.ContainsKey(c.OutputNodeID))
                    {
                        var inputItem = FindOrCreateNodeItem(nodeIdToControlNode[c.InputNodeID],
                                                             (item) => (item.Output != null && item.Output.Enabled && item is ShaderFragmentNodeItem && ((ShaderFragmentNodeItem)item).Name.Equals(c.InputParameterName)),
                                                             () => new ShaderFragmentNodeItem(c.InputParameterName, c.InputType, null, false, true));

                        var outputItem = FindOrCreateNodeItem(nodeIdToControlNode[c.OutputNodeID],
                                                              (item) => (item.Input != null && item.Input.Enabled && item is ShaderFragmentNodeItem && ((ShaderFragmentNodeItem)item).Name.Equals(c.OutputParameterName)),
                                                              () => new ShaderFragmentNodeItem(c.OutputParameterName, c.OutputType, null, true, false));

                        graph.Connect(inputItem.Output, outputItem.Input);
                    }
                }

                // --------< Constant Connections >--------
                foreach (var c in nodeGraph.ConstantConnections)
                {
                    if (nodeIdToControlNode.ContainsKey(c.OutputNodeID))
                    {
                        var node       = nodeIdToControlNode[c.OutputNodeID];
                        var outputItem = FindOrCreateNodeItem(node,
                                                              (item) => (item.Input != null && item.Input.Enabled && item is ShaderFragmentNodeItem && ((ShaderFragmentNodeItem)item).Name.Equals(c.OutputParameterName)),
                                                              () => new ShaderFragmentNodeItem(c.OutputParameterName, "float", null, true, false));

                        var connection = new NodeConnection();
                        connection.To   = outputItem.Input;
                        connection.Name = c.Value;
                        node.AddConnection(connection);
                    }
                }

                // --------< Input Parameter Connections >--------
                foreach (var c in nodeGraph.InputParameterConnections)
                {
                    if (!nodeIdToControlNode.ContainsKey(c.OutputNodeID))
                    {
                        continue;
                    }

                    var dstItem = FindOrCreateNodeItem(
                        nodeIdToControlNode[c.OutputNodeID],
                        (item) => (item.Input != null && item.Input.Enabled && item is ShaderFragmentNodeItem && ((ShaderFragmentNodeItem)item).Name.Equals(c.OutputParameterName)),
                        () => new ShaderFragmentNodeItem(c.OutputParameterName, c.Type, null, true, false));

                    Node srcNode;
                    if (!newNodes.ContainsKey(c.VisualNodeId))
                    {
                        srcNode = _nodeCreator.CreateInterfaceNode("Inputs", InterfaceDirection.In);
                        MatchVisualNode(srcNode, nodeGraph.VisualNodes[c.VisualNodeId]);
                        newNodes[c.VisualNodeId] = srcNode;
                        graph.AddNode(srcNode);
                    }
                    else
                    {
                        srcNode = newNodes[c.VisualNodeId];
                    }

                    var srcItem = FindOrCreateNodeItem(
                        srcNode,
                        (item) => {
                        var i = item as ShaderFragmentInterfaceParameterItem;
                        if (i == null)
                        {
                            return(false);
                        }
                        return(i.Name.Equals(c.Name) && i.Type.Equals(c.Type) && i.Semantic.Equals(c.Semantic));
                    },
                        () => new ShaderFragmentInterfaceParameterItem(c.Name, c.Type, InterfaceDirection.In)
                    {
                        Semantic = c.Semantic, Default = c.Default
                    });

                    graph.Connect(srcItem.Output, dstItem.Input);
                }

                // --------< Output Parameter Connections >--------
                foreach (var c in nodeGraph.OutputParameterConnections)
                {
                    if (!nodeIdToControlNode.ContainsKey(c.InputNodeID))
                    {
                        continue;
                    }

                    var srcItem = FindOrCreateNodeItem(
                        nodeIdToControlNode[c.InputNodeID],
                        (item) => (item.Output != null && item.Output.Enabled && item is ShaderFragmentNodeItem && ((ShaderFragmentNodeItem)item).Name.Equals(c.InputParameterName)),
                        () => new ShaderFragmentNodeItem(c.InputParameterName, c.Type, null, false, true));

                    Node dstNode;
                    if (!newNodes.ContainsKey(c.VisualNodeId))
                    {
                        dstNode = _nodeCreator.CreateInterfaceNode("Outputs", InterfaceDirection.Out);
                        MatchVisualNode(dstNode, nodeGraph.VisualNodes[c.VisualNodeId]);
                        newNodes[c.VisualNodeId] = dstNode;
                        graph.AddNode(dstNode);
                    }
                    else
                    {
                        dstNode = newNodes[c.VisualNodeId];
                    }

                    var dstItem = FindOrCreateNodeItem(
                        dstNode,
                        (item) =>
                    {
                        var i = item as ShaderFragmentInterfaceParameterItem;
                        if (i == null)
                        {
                            return(false);
                        }
                        return(i.Name.Equals(c.Name) && i.Type.Equals(c.Type) && i.Semantic.Equals(c.Semantic));
                    },
                        () => new ShaderFragmentInterfaceParameterItem(c.Name, c.Type, InterfaceDirection.Out)
                    {
                        Semantic = c.Semantic
                    });

                    graph.Connect(srcItem.Output, dstItem.Input);
                }
            }
        }