Пример #1
0
        public override GraphicsPath MakePath()
        {
            GraphicsPath path1  = base.MakePath();
            SubGraphNode graph1 = base.Parent as SubGraphNode;

            if (graph1 != null)
            {
                RectangleF ef1 = this.Bounds;
                if (graph1.Collapsible)
                {
                    float single1 = ef1.Y + (ef1.Height / 2f);
                    path1.StartFigure();
                    path1.AddLine((float)(ef1.X + (ef1.Width / 4f)), single1, (float)(ef1.X + ((ef1.Width * 3f) / 4f)), single1);
                    if (!graph1.IsExpanded)
                    {
                        float single2 = ef1.X + (ef1.Width / 2f);
                        path1.StartFigure();
                        path1.AddLine(single2, (float)(ef1.Y + (ef1.Height / 4f)), single2, (float)(ef1.Y + ((ef1.Height * 3f) / 4f)));
                    }
                    return(path1);
                }
                path1.AddEllipse((float)(ef1.X + (ef1.Width / 4f)), (float)(ef1.Y + (ef1.Height / 4f)), (float)(ef1.Width / 2f), (float)(ef1.Height / 2f));
            }
            return(path1);
        }
        void OpenSubGraph(DropdownMenuAction action)
        {
            SubGraphNode subgraphNode = selection.OfType<MaterialNodeView>().First().node as SubGraphNode;

            var path = AssetDatabase.GetAssetPath(subgraphNode.subGraphAsset);
            ShaderGraphImporterEditor.ShowGraphEditWindow(path);
        }
Пример #3
0
        public override bool OnSingleClick(InputEventArgs evt, DiagramView view)
        {
            SubGraphNode graph1 = base.Parent as SubGraphNode;

            if ((graph1 == null) || !graph1.Collapsible)
            {
                return(false);
            }
            if (view != null)
            {
                view.StartTransaction();
            }
            string text1 = null;

            if (graph1.IsExpanded)
            {
                graph1.Collapse();
                text1 = "Collapsed SubGraph";
            }
            else if (evt.Control)
            {
                graph1.ExpandAll();
                text1 = "Expanded All SubGraphs";
            }
            else
            {
                graph1.Expand();
                text1 = "Expanded SubGraph";
            }
            if (view != null)
            {
                view.FinishTransaction(text1);
            }
            return(true);
        }
Пример #4
0
    public static SubGraphNode CreateInstance(GameObject go, GameObject parent, Vector3 pos, string text, bool showMesh = false)
    {
        SubGraphNode sgn = CreateInstance <SubGraphNode>();

        sgn.Init(go, parent, pos, text, showMesh);

        return(sgn);
    }
Пример #5
0
    public static SubGraphNode CreateInstance(GameObject go, Vector3 pos, string text, bool hide = false)
    {
        SubGraphNode sgn = CreateInstance <SubGraphNode>();

        sgn.Init(go, pos, text, hide);

        return(sgn);
    }
Пример #6
0
 public GraphTab(Graph graph, SubGraphNode subGraphNode, float zoom, Vector2 panOffset, List <Node> selectedNodes, List <Node> deletedNodes)
 {
     IsRootTab     = false;
     Graph         = graph;
     SubGraphNode  = subGraphNode;
     Zoom          = zoom;
     PanOffset     = panOffset;
     SelectedNodes = new List <Node>(selectedNodes);
     DeletedNodes  = new List <Node>(deletedNodes);
 }
        void OnSubGraphDoubleClick(MouseDownEvent evt)
        {
            if (evt.clickCount == 2 && evt.button == 0)
            {
                SubGraphNode subgraphNode = node as SubGraphNode;

                var path = AssetDatabase.GUIDToAssetPath(subgraphNode.subGraphGuid);
                ShaderGraphImporterEditor.ShowGraphEditWindow(path);
            }
        }
Пример #8
0
    public void InitSubNodes(string[] subs, GameObject go)
    {
        // it would be improper to call this function to add sub nodes
        // this is only for initial creation
        subNodes = new SubGraphNode[subs.Length];
        int i = 0;

        foreach (string str in subs)
        {
            SubGraphNode sgn = SubGraphNode.CreateInstance(go, Vector3.zero, str);
            sgn.getObject().transform.parent = thisObject.transform;
            subNodes[i++] = sgn;
        }
        positionSubNodes();
    }
Пример #9
0
        public void OpenSubGraph(SubGraphNode subGraphNode)
        {
            if (subGraphNode == null || subGraphNode.SubGraph == null)
            {
                return;
            }

            GraphTab currentTab = GraphTabs[GraphTabs.Count - 1];

            currentTab.Zoom          = CurrentZoom;
            currentTab.PanOffset     = CurrentPanOffset;
            currentTab.SelectedNodes = new List <Node>(SelectedNodes);
            var newTab = new GraphTab(CurrentGraph, subGraphNode, CurrentZoom, CurrentPanOffset, SelectedNodes, DeletedNodes);

            OpenGraph(subGraphNode.SubGraph, true, false, true);
            GraphTabs.Add(newTab);
        }
Пример #10
0
        public virtual IDiagramShapeCollection AddCollection(IDiagramShapeCollection coll, bool reparentLinks)
        {
            foreach (DiagramShape obj1 in coll)
            {
                if (!base.IsChildOf(obj1) && (this != obj1))
                {
                    continue;
                }
                throw new ArgumentException("Cannot add a group to itself or to one of its own children.");
            }
            DiagramShapeCollection collection1 = new DiagramShapeCollection();

            foreach (DiagramShape obj2 in coll)
            {
                collection1.Add(obj2);
            }
            CollectionEnumerator enumerator2 = collection1.GetEnumerator();

            while (enumerator2.MoveNext())
            {
                DiagramShape obj3  = enumerator2.Current;
                bool         flag1 = obj3.Layer != null;
                if (flag1)
                {
                    GroupShape.setAllNoClear(obj3, true);
                    obj3.Remove();
                }
                this.Add(obj3);
                if (flag1)
                {
                    GroupShape.setAllNoClear(obj3, false);
                }
            }
            if (reparentLinks && base.IsInDocument)
            {
                SubGraphNode.ReparentAllLinksToSubGraphs(collection1, true, base.Document.LinksLayer);
            }
            return(collection1);
        }
Пример #11
0
        protected virtual void PaintHandle(Graphics g, DiagramView view)
        {
            SubGraphNode graph1 = base.Parent as SubGraphNode;

            if (graph1 != null)
            {
                RectangleF ef1 = this.Bounds;
                if (graph1.Collapsible)
                {
                    float single1 = ef1.Y + (ef1.Height / 2f);
                    DiagramGraph.DrawLine(g, view, this.Pen, ef1.X + (ef1.Width / 4f), single1, ef1.X + ((ef1.Width * 3f) / 4f), single1);
                    if (graph1.IsExpanded)
                    {
                        return;
                    }
                    float single2 = ef1.X + (ef1.Width / 2f);
                    DiagramGraph.DrawLine(g, view, this.Pen, single2, ef1.Y + (ef1.Height / 4f), single2, ef1.Y + ((ef1.Height * 3f) / 4f));
                }
                else
                {
                    DiagramGraph.DrawEllipse(g, view, this.Pen, null, ef1.X + (ef1.Width / 4f), ef1.Y + (ef1.Height / 4f), ef1.Width / 2f, ef1.Height / 2f);
                }
            }
        }
        public void ToSubGraph()
        {
            var path = EditorUtility.SaveFilePanelInProject("Save Sub Graph", "New Shader Sub Graph", ShaderSubGraphImporter.Extension, "");

            path = path.Replace(Application.dataPath, "Assets");
            if (path.Length == 0)
            {
                return;
            }

            graphObject.RegisterCompleteObjectUndo("Convert To Subgraph");
            var graphView = graphEditorView.graphView;

            var nodes  = graphView.selection.OfType <IShaderNodeView>().Where(x => !(x.node is PropertyNode)).Select(x => x.node as AbstractMaterialNode).ToArray();
            var bounds = Rect.MinMaxRect(float.PositiveInfinity, float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity);

            foreach (var node in nodes)
            {
                var center = node.drawState.position.center;
                bounds = Rect.MinMaxRect(
                    Mathf.Min(bounds.xMin, center.x),
                    Mathf.Min(bounds.yMin, center.y),
                    Mathf.Max(bounds.xMax, center.x),
                    Mathf.Max(bounds.yMax, center.y));
            }
            var middle = bounds.center;

            bounds.center = Vector2.zero;

            // Collect the property nodes and get the corresponding properties
            var propertyNodeGuids = graphView.selection.OfType <IShaderNodeView>().Where(x => (x.node is PropertyNode)).Select(x => ((PropertyNode)x.node).propertyGuid);
            var metaProperties    = graphView.graph.properties.Where(x => propertyNodeGuids.Contains(x.guid));

            var copyPasteGraph = new CopyPasteGraph(
                graphView.graph.guid,
                graphView.selection.OfType <ShaderGroup>().Select(x => x.userData),
                graphView.selection.OfType <IShaderNodeView>().Where(x => !(x.node is PropertyNode)).Select(x => x.node as AbstractMaterialNode),
                graphView.selection.OfType <Edge>().Select(x => x.userData as IEdge),
                graphView.selection.OfType <BlackboardField>().Select(x => x.userData as AbstractShaderProperty),
                metaProperties);

            var deserialized = CopyPasteGraph.FromJson(JsonUtility.ToJson(copyPasteGraph, false));

            if (deserialized == null)
            {
                return;
            }

            var subGraph = new GraphData {
                isSubGraph = true
            };

            subGraph.path = "Sub Graphs";
            var subGraphOutputNode = new SubGraphOutputNode();

            {
                var drawState = subGraphOutputNode.drawState;
                drawState.position           = new Rect(new Vector2(bounds.xMax + 200f, 0f), drawState.position.size);
                subGraphOutputNode.drawState = drawState;
            }
            subGraph.AddNode(subGraphOutputNode);

            var nodeGuidMap = new Dictionary <Guid, Guid>();

            foreach (var node in deserialized.GetNodes <AbstractMaterialNode>())
            {
                var oldGuid = node.guid;
                var newGuid = node.RewriteGuid();
                nodeGuidMap[oldGuid] = newGuid;
                var drawState = node.drawState;
                drawState.position = new Rect(drawState.position.position - middle, drawState.position.size);
                node.drawState     = drawState;
                subGraph.AddNode(node);
            }

            // figure out what needs remapping
            var externalOutputSlots = new List <IEdge>();
            var externalInputSlots  = new List <IEdge>();

            foreach (var edge in deserialized.edges)
            {
                var outputSlot = edge.outputSlot;
                var inputSlot  = edge.inputSlot;

                Guid remappedOutputNodeGuid;
                Guid remappedInputNodeGuid;
                var  outputSlotExistsInSubgraph = nodeGuidMap.TryGetValue(outputSlot.nodeGuid, out remappedOutputNodeGuid);
                var  inputSlotExistsInSubgraph  = nodeGuidMap.TryGetValue(inputSlot.nodeGuid, out remappedInputNodeGuid);

                // pasting nice internal links!
                if (outputSlotExistsInSubgraph && inputSlotExistsInSubgraph)
                {
                    var outputSlotRef = new SlotReference(remappedOutputNodeGuid, outputSlot.slotId);
                    var inputSlotRef  = new SlotReference(remappedInputNodeGuid, inputSlot.slotId);
                    subGraph.Connect(outputSlotRef, inputSlotRef);
                }
                // one edge needs to go to outside world
                else if (outputSlotExistsInSubgraph)
                {
                    externalInputSlots.Add(edge);
                }
                else if (inputSlotExistsInSubgraph)
                {
                    externalOutputSlots.Add(edge);
                }
            }

            // Find the unique edges coming INTO the graph
            var uniqueIncomingEdges = externalOutputSlots.GroupBy(
                edge => edge.outputSlot,
                edge => edge,
                (key, edges) => new { slotRef = key, edges = edges.ToList() });

            var externalInputNeedingConnection = new List <KeyValuePair <IEdge, AbstractShaderProperty> >();

            foreach (var group in uniqueIncomingEdges)
            {
                var sr       = group.slotRef;
                var fromNode = graphObject.graph.GetNodeFromGuid(sr.nodeGuid);
                var fromSlot = fromNode.FindOutputSlot <MaterialSlot>(sr.slotId);

                AbstractShaderProperty prop;
                switch (fromSlot.concreteValueType)
                {
                case ConcreteSlotValueType.Texture2D:
                    prop = new TextureShaderProperty();
                    break;

                case ConcreteSlotValueType.Texture2DArray:
                    prop = new Texture2DArrayShaderProperty();
                    break;

                case ConcreteSlotValueType.Texture3D:
                    prop = new Texture3DShaderProperty();
                    break;

                case ConcreteSlotValueType.Cubemap:
                    prop = new CubemapShaderProperty();
                    break;

                case ConcreteSlotValueType.Vector4:
                    prop = new Vector4ShaderProperty();
                    break;

                case ConcreteSlotValueType.Vector3:
                    prop = new Vector3ShaderProperty();
                    break;

                case ConcreteSlotValueType.Vector2:
                    prop = new Vector2ShaderProperty();
                    break;

                case ConcreteSlotValueType.Vector1:
                    prop = new Vector1ShaderProperty();
                    break;

                case ConcreteSlotValueType.Boolean:
                    prop = new BooleanShaderProperty();
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                if (prop != null)
                {
                    var materialGraph    = (GraphData)graphObject.graph;
                    var fromPropertyNode = fromNode as PropertyNode;
                    var fromProperty     = fromPropertyNode != null?materialGraph.properties.FirstOrDefault(p => p.guid == fromPropertyNode.propertyGuid) : null;

                    prop.displayName = fromProperty != null ? fromProperty.displayName : fromSlot.concreteValueType.ToString();

                    subGraph.AddShaderProperty(prop);
                    var propNode = new PropertyNode();
                    {
                        var drawState = propNode.drawState;
                        drawState.position = new Rect(new Vector2(bounds.xMin - 300f, 0f), drawState.position.size);
                        propNode.drawState = drawState;
                    }
                    subGraph.AddNode(propNode);
                    propNode.propertyGuid = prop.guid;

                    foreach (var edge in group.edges)
                    {
                        subGraph.Connect(
                            new SlotReference(propNode.guid, PropertyNode.OutputSlotId),
                            new SlotReference(nodeGuidMap[edge.inputSlot.nodeGuid], edge.inputSlot.slotId));
                        externalInputNeedingConnection.Add(new KeyValuePair <IEdge, AbstractShaderProperty>(edge, prop));
                    }
                }
            }

            var uniqueOutgoingEdges = externalInputSlots.GroupBy(
                edge => edge.inputSlot,
                edge => edge,
                (key, edges) => new { slot = key, edges = edges.ToList() });

            var externalOutputsNeedingConnection = new List <KeyValuePair <IEdge, IEdge> >();

            foreach (var group in uniqueOutgoingEdges)
            {
                var outputNode = subGraph.outputNode as SubGraphOutputNode;

                AbstractMaterialNode node = graphView.graph.GetNodeFromGuid(group.edges[0].outputSlot.nodeGuid);
                MaterialSlot         slot = node.FindSlot <MaterialSlot>(group.edges[0].outputSlot.slotId);
                var slotId = outputNode.AddSlot(slot.concreteValueType);

                var inputSlotRef = new SlotReference(outputNode.guid, slotId);

                foreach (var edge in group.edges)
                {
                    var newEdge = subGraph.Connect(new SlotReference(nodeGuidMap[edge.outputSlot.nodeGuid], edge.outputSlot.slotId), inputSlotRef);
                    externalOutputsNeedingConnection.Add(new KeyValuePair <IEdge, IEdge>(edge, newEdge));
                }
            }

            File.WriteAllText(path, EditorJsonUtility.ToJson(subGraph));
            AssetDatabase.ImportAsset(path);

            var loadedSubGraph = AssetDatabase.LoadAssetAtPath(path, typeof(MaterialSubGraphAsset)) as MaterialSubGraphAsset;

            if (loadedSubGraph == null)
            {
                return;
            }

            var subGraphNode = new SubGraphNode();
            var ds           = subGraphNode.drawState;

            ds.position            = new Rect(middle - new Vector2(100f, 150f), Vector2.zero);
            subGraphNode.drawState = ds;
            graphObject.graph.AddNode(subGraphNode);
            subGraphNode.subGraphAsset = loadedSubGraph;

            foreach (var edgeMap in externalInputNeedingConnection)
            {
                graphObject.graph.Connect(edgeMap.Key.outputSlot, new SlotReference(subGraphNode.guid, edgeMap.Value.guid.GetHashCode()));
            }

            foreach (var edgeMap in externalOutputsNeedingConnection)
            {
                graphObject.graph.Connect(new SlotReference(subGraphNode.guid, edgeMap.Value.inputSlot.slotId), edgeMap.Key.inputSlot);
            }

            graphObject.graph.RemoveElements(
                graphView.selection.OfType <IShaderNodeView>().Select(x => x.node as AbstractMaterialNode),
                Enumerable.Empty <IEdge>(),
                Enumerable.Empty <GroupData>());
            graphObject.graph.ValidateGraph();
        }
Пример #13
0
        public List <SearchTreeEntry> CreateSearchTree(SearchWindowContext context)
        {
            // First build up temporary data structure containing group & title as an array of strings (the last one is the actual title) and associated node type.
            var nodeEntries = new List <NodeEntry>();

            foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                foreach (var type in assembly.GetTypesOrNothing())
                {
                    if (type.IsClass && !type.IsAbstract && (type.IsSubclassOf(typeof(AbstractMaterialNode))) &&
                        type != typeof(PropertyNode) &&
                        type != typeof(SubGraphNode))
                    {
                        var attrs = type.GetCustomAttributes(typeof(TitleAttribute), false) as TitleAttribute[];
                        if (attrs != null && attrs.Length > 0)
                        {
                            var node = (AbstractMaterialNode)Activator.CreateInstance(type);
                            AddEntries(node, attrs[0].title, nodeEntries);
                        }
                    }
                }
            }

            foreach (var guid in AssetDatabase.FindAssets(string.Format("t:{0}", typeof(SubGraphAsset))))
            {
                var asset = AssetDatabase.LoadAssetAtPath <SubGraphAsset>(AssetDatabase.GUIDToAssetPath(guid));
                var node  = new SubGraphNode {
                    asset = asset
                };
                var title = asset.path.Split('/').ToList();

                if (asset.descendents.Contains(m_Graph.assetGuid) || asset.assetGuid == m_Graph.assetGuid)
                {
                    continue;
                }

                if (string.IsNullOrEmpty(asset.path))
                {
                    AddEntries(node, new string[1] {
                        asset.name
                    }, nodeEntries);
                }

                else if (title[0] != k_HiddenFolderName)
                {
                    title.Add(asset.name);
                    AddEntries(node, title.ToArray(), nodeEntries);
                }
            }

            foreach (var property in m_Graph.properties)
            {
                var node = new PropertyNode();
                node.owner        = m_Graph;
                node.propertyGuid = property.guid;
                node.owner        = null;
                AddEntries(node, new[] { "Properties", "Property: " + property.displayName }, nodeEntries);
            }

            // Sort the entries lexicographically by group then title with the requirement that items always comes before sub-groups in the same group.
            // Example result:
            // - Art/BlendMode
            // - Art/Adjustments/ColorBalance
            // - Art/Adjustments/Contrast
            nodeEntries.Sort((entry1, entry2) =>
            {
                for (var i = 0; i < entry1.title.Length; i++)
                {
                    if (i >= entry2.title.Length)
                    {
                        return(1);
                    }
                    var value = entry1.title[i].CompareTo(entry2.title[i]);
                    if (value != 0)
                    {
                        // Make sure that leaves go before nodes
                        if (entry1.title.Length != entry2.title.Length && (i == entry1.title.Length - 1 || i == entry2.title.Length - 1))
                        {
                            return(entry1.title.Length < entry2.title.Length ? -1 : 1);
                        }
                        return(value);
                    }
                }
                return(0);
            });

            //* Build up the data structure needed by SearchWindow.

            // `groups` contains the current group path we're in.
            var groups = new List <string>();

            // First item in the tree is the title of the window.
            var tree = new List <SearchTreeEntry>
            {
                new SearchTreeGroupEntry(new GUIContent("Create Node"), 0),
            };

            foreach (var nodeEntry in nodeEntries)
            {
                // `createIndex` represents from where we should add new group entries from the current entry's group path.
                var createIndex = int.MaxValue;

                // Compare the group path of the current entry to the current group path.
                for (var i = 0; i < nodeEntry.title.Length - 1; i++)
                {
                    var group = nodeEntry.title[i];
                    if (i >= groups.Count)
                    {
                        // The current group path matches a prefix of the current entry's group path, so we add the
                        // rest of the group path from the currrent entry.
                        createIndex = i;
                        break;
                    }
                    if (groups[i] != group)
                    {
                        // A prefix of the current group path matches a prefix of the current entry's group path,
                        // so we remove everyfrom from the point where it doesn't match anymore, and then add the rest
                        // of the group path from the current entry.
                        groups.RemoveRange(i, groups.Count - i);
                        createIndex = i;
                        break;
                    }
                }

                // Create new group entries as needed.
                // If we don't need to modify the group path, `createIndex` will be `int.MaxValue` and thus the loop won't run.
                for (var i = createIndex; i < nodeEntry.title.Length - 1; i++)
                {
                    var group = nodeEntry.title[i];
                    groups.Add(group);
                    tree.Add(new SearchTreeGroupEntry(new GUIContent(group))
                    {
                        level = i + 1
                    });
                }

                // Finally, add the actual entry.
                tree.Add(new SearchTreeEntry(new GUIContent(nodeEntry.title.Last(), m_Icon))
                {
                    level = nodeEntry.title.Length, userData = nodeEntry
                });
            }

            return(tree);
        }
Пример #14
0
        public void ToSubGraph()
        {
            var graphView = graphEditorView.graphView;

            string path;
            string sessionStateResult = SessionState.GetString(k_PrevSubGraphPathKey, k_PrevSubGraphPathDefaultValue);
            string pathToOriginSG     = Path.GetDirectoryName(AssetDatabase.GUIDToAssetPath(selectedGuid));

            if (!sessionStateResult.Equals(k_PrevSubGraphPathDefaultValue))
            {
                path = sessionStateResult;
            }
            else
            {
                path = pathToOriginSG;
            }

            path = EditorUtility.SaveFilePanelInProject("Save Sub Graph", "New Shader Sub Graph", ShaderSubGraphImporter.Extension, "", path);
            path = path.Replace(Application.dataPath, "Assets");
            if (path.Length == 0)
            {
                return;
            }

            graphObject.RegisterCompleteObjectUndo("Convert To Subgraph");

            var nodes  = graphView.selection.OfType <IShaderNodeView>().Where(x => !(x.node is PropertyNode || x.node is SubGraphOutputNode)).Select(x => x.node).Where(x => x.allowedInSubGraph).ToArray();
            var bounds = Rect.MinMaxRect(float.PositiveInfinity, float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity);

            foreach (var node in nodes)
            {
                var center = node.drawState.position.center;
                bounds = Rect.MinMaxRect(
                    Mathf.Min(bounds.xMin, center.x),
                    Mathf.Min(bounds.yMin, center.y),
                    Mathf.Max(bounds.xMax, center.x),
                    Mathf.Max(bounds.yMax, center.y));
            }
            var middle = bounds.center;

            bounds.center = Vector2.zero;

            // Collect graph inputs
            var graphInputs = graphView.selection.OfType <BlackboardField>().Select(x => x.userData as ShaderInput);

            // Collect the property nodes and get the corresponding properties
            var propertyNodes  = graphView.selection.OfType <IShaderNodeView>().Where(x => (x.node is PropertyNode)).Select(x => ((PropertyNode)x.node).property);
            var metaProperties = graphView.graph.properties.Where(x => propertyNodes.Contains(x));

            // Collect the keyword nodes and get the corresponding keywords
            var keywordNodes = graphView.selection.OfType <IShaderNodeView>().Where(x => (x.node is KeywordNode)).Select(x => ((KeywordNode)x.node).keyword);
            var metaKeywords = graphView.graph.keywords.Where(x => keywordNodes.Contains(x));

            var copyPasteGraph = new CopyPasteGraph(graphView.selection.OfType <ShaderGroup>().Select(x => x.userData),
                                                    graphView.selection.OfType <IShaderNodeView>().Where(x => !(x.node is PropertyNode || x.node is SubGraphOutputNode)).Select(x => x.node).Where(x => x.allowedInSubGraph).ToArray(),
                                                    graphView.selection.OfType <Edge>().Select(x => x.userData as Graphing.Edge),
                                                    graphInputs,
                                                    metaProperties,
                                                    metaKeywords,
                                                    graphView.selection.OfType <StickyNote>().Select(x => x.userData),
                                                    true);

            // why do we serialize and deserialize only to make copies of everything in the steps below?
            // is this just to clear out all non-serialized data?
            var deserialized = CopyPasteGraph.FromJson(MultiJson.Serialize(copyPasteGraph), graphView.graph);

            if (deserialized == null)
            {
                return;
            }

            var subGraph = new GraphData {
                isSubGraph = true, path = "Sub Graphs"
            };
            var subGraphOutputNode = new SubGraphOutputNode();

            {
                var drawState = subGraphOutputNode.drawState;
                drawState.position           = new Rect(new Vector2(bounds.xMax + 200f, 0f), drawState.position.size);
                subGraphOutputNode.drawState = drawState;
            }
            subGraph.AddNode(subGraphOutputNode);
            subGraph.outputNode = subGraphOutputNode;

            // Always copy deserialized keyword inputs
            foreach (ShaderKeyword keyword in deserialized.metaKeywords)
            {
                var copiedInput = (ShaderKeyword)keyword.Copy();
                subGraph.SanitizeGraphInputName(copiedInput);
                subGraph.SanitizeGraphInputReferenceName(copiedInput, keyword.overrideReferenceName);
                subGraph.AddGraphInput(copiedInput);

                // Update the keyword nodes that depends on the copied keyword
                var dependentKeywordNodes = deserialized.GetNodes <KeywordNode>().Where(x => x.keyword == keyword);
                foreach (var node in dependentKeywordNodes)
                {
                    node.owner   = graphView.graph;
                    node.keyword = copiedInput;
                }
            }

            foreach (GroupData groupData in deserialized.groups)
            {
                subGraph.CreateGroup(groupData);
            }

            foreach (var node in deserialized.GetNodes <AbstractMaterialNode>())
            {
                var drawState = node.drawState;
                drawState.position = new Rect(drawState.position.position - middle, drawState.position.size);
                node.drawState     = drawState;

                // Checking if the group guid is also being copied.
                // If not then nullify that guid
                if (node.group != null && !subGraph.groups.Contains(node.group))
                {
                    node.group = null;
                }

                subGraph.AddNode(node);
            }

            foreach (var note in deserialized.stickyNotes)
            {
                if (note.group != null && !subGraph.groups.Contains(note.group))
                {
                    note.group = null;
                }

                subGraph.AddStickyNote(note);
            }

            // figure out what needs remapping
            var externalOutputSlots = new List <Graphing.Edge>();
            var externalInputSlots  = new List <Graphing.Edge>();

            foreach (var edge in deserialized.edges)
            {
                var outputSlot = edge.outputSlot;
                var inputSlot  = edge.inputSlot;

                var outputSlotExistsInSubgraph = subGraph.ContainsNode(outputSlot.node);
                var inputSlotExistsInSubgraph  = subGraph.ContainsNode(inputSlot.node);

                // pasting nice internal links!
                if (outputSlotExistsInSubgraph && inputSlotExistsInSubgraph)
                {
                    subGraph.Connect(outputSlot, inputSlot);
                }
                // one edge needs to go to outside world
                else if (outputSlotExistsInSubgraph)
                {
                    externalInputSlots.Add(edge);
                }
                else if (inputSlotExistsInSubgraph)
                {
                    externalOutputSlots.Add(edge);
                }
            }

            // Find the unique edges coming INTO the graph
            var uniqueIncomingEdges = externalOutputSlots.GroupBy(
                edge => edge.outputSlot,
                edge => edge,
                (key, edges) => new { slotRef = key, edges = edges.ToList() });

            var externalInputNeedingConnection = new List <KeyValuePair <IEdge, AbstractShaderProperty> >();

            var       amountOfProps  = uniqueIncomingEdges.Count();
            const int height         = 40;
            const int subtractHeight = 20;
            var       propPos        = new Vector2(0, -((amountOfProps / 2) + height) - subtractHeight);

            foreach (var group in uniqueIncomingEdges)
            {
                var sr       = group.slotRef;
                var fromNode = sr.node;
                var fromSlot = sr.slot;

                var materialGraph = graphObject.graph;
                var fromProperty  = fromNode is PropertyNode fromPropertyNode
                    ? materialGraph.properties.FirstOrDefault(p => p == fromPropertyNode.property)
                    : null;

                AbstractShaderProperty prop;
                switch (fromSlot.concreteValueType)
                {
                case ConcreteSlotValueType.Texture2D:
                    prop = new Texture2DShaderProperty();
                    break;

                case ConcreteSlotValueType.Texture2DArray:
                    prop = new Texture2DArrayShaderProperty();
                    break;

                case ConcreteSlotValueType.Texture3D:
                    prop = new Texture3DShaderProperty();
                    break;

                case ConcreteSlotValueType.Cubemap:
                    prop = new CubemapShaderProperty();
                    break;

                case ConcreteSlotValueType.Vector4:
                    prop = new Vector4ShaderProperty();
                    break;

                case ConcreteSlotValueType.Vector3:
                    prop = new Vector3ShaderProperty();
                    break;

                case ConcreteSlotValueType.Vector2:
                    prop = new Vector2ShaderProperty();
                    break;

                case ConcreteSlotValueType.Vector1:
                    prop = new Vector1ShaderProperty();
                    break;

                case ConcreteSlotValueType.Boolean:
                    prop = new BooleanShaderProperty();
                    break;

                case ConcreteSlotValueType.Matrix2:
                    prop = new Matrix2ShaderProperty();
                    break;

                case ConcreteSlotValueType.Matrix3:
                    prop = new Matrix3ShaderProperty();
                    break;

                case ConcreteSlotValueType.Matrix4:
                    prop = new Matrix4ShaderProperty();
                    break;

                case ConcreteSlotValueType.SamplerState:
                    prop = new SamplerStateShaderProperty();
                    break;

                case ConcreteSlotValueType.Gradient:
                    prop = new GradientShaderProperty();
                    break;

                case ConcreteSlotValueType.VirtualTexture:
                    prop = new VirtualTextureShaderProperty()
                    {
                        // also copy the VT settings over from the original property (if there is one)
                        value = (fromProperty as VirtualTextureShaderProperty)?.value ?? new SerializableVirtualTexture()
                    };
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                prop.displayName = fromProperty != null
                    ? fromProperty.displayName
                    : fromSlot.concreteValueType.ToString();
                prop.displayName = GraphUtil.SanitizeName(subGraph.addedInputs.Select(p => p.displayName), "{0} ({1})",
                                                          prop.displayName);

                subGraph.AddGraphInput(prop);
                var propNode = new PropertyNode();
                {
                    var drawState = propNode.drawState;
                    drawState.position = new Rect(new Vector2(bounds.xMin - 300f, 0f) + propPos,
                                                  drawState.position.size);
                    propPos           += new Vector2(0, height);
                    propNode.drawState = drawState;
                }
                subGraph.AddNode(propNode);
                propNode.property = prop;

                foreach (var edge in group.edges)
                {
                    subGraph.Connect(
                        new SlotReference(propNode, PropertyNode.OutputSlotId),
                        edge.inputSlot);
                    externalInputNeedingConnection.Add(new KeyValuePair <IEdge, AbstractShaderProperty>(edge, prop));
                }
            }

            var uniqueOutgoingEdges = externalInputSlots.GroupBy(
                edge => edge.outputSlot,
                edge => edge,
                (key, edges) => new { slot = key, edges = edges.ToList() });

            var externalOutputsNeedingConnection = new List <KeyValuePair <IEdge, IEdge> >();

            foreach (var group in uniqueOutgoingEdges)
            {
                var outputNode = subGraph.outputNode as SubGraphOutputNode;

                AbstractMaterialNode node = group.edges[0].outputSlot.node;
                MaterialSlot         slot = node.FindSlot <MaterialSlot>(group.edges[0].outputSlot.slotId);
                var slotId = outputNode.AddSlot(slot.concreteValueType);

                var inputSlotRef = new SlotReference(outputNode, slotId);

                foreach (var edge in group.edges)
                {
                    var newEdge = subGraph.Connect(edge.outputSlot, inputSlotRef);
                    externalOutputsNeedingConnection.Add(new KeyValuePair <IEdge, IEdge>(edge, newEdge));
                }
            }

            if (FileUtilities.WriteShaderGraphToDisk(path, subGraph))
            {
                AssetDatabase.ImportAsset(path);
            }

            // Store path for next time
            if (!pathToOriginSG.Equals(Path.GetDirectoryName(path)))
            {
                SessionState.SetString(k_PrevSubGraphPathKey, Path.GetDirectoryName(path));
            }
            else
            {
                // Or continue to make it so that next time it will open up in the converted-from SG's directory
                SessionState.EraseString(k_PrevSubGraphPathKey);
            }

            var loadedSubGraph = AssetDatabase.LoadAssetAtPath(path, typeof(SubGraphAsset)) as SubGraphAsset;

            if (loadedSubGraph == null)
            {
                return;
            }

            var subGraphNode = new SubGraphNode();
            var ds           = subGraphNode.drawState;

            ds.position            = new Rect(middle - new Vector2(100f, 150f), Vector2.zero);
            subGraphNode.drawState = ds;

            // Add the subgraph into the group if the nodes was all in the same group group
            var firstNode = copyPasteGraph.GetNodes <AbstractMaterialNode>().FirstOrDefault();

            if (firstNode != null && copyPasteGraph.GetNodes <AbstractMaterialNode>().All(x => x.group == firstNode.group))
            {
                subGraphNode.group = firstNode.group;
            }

            subGraphNode.asset = loadedSubGraph;
            graphObject.graph.AddNode(subGraphNode);

            foreach (var edgeMap in externalInputNeedingConnection)
            {
                graphObject.graph.Connect(edgeMap.Key.outputSlot, new SlotReference(subGraphNode, edgeMap.Value.guid.GetHashCode()));
            }

            foreach (var edgeMap in externalOutputsNeedingConnection)
            {
                graphObject.graph.Connect(new SlotReference(subGraphNode, edgeMap.Value.inputSlot.slotId), edgeMap.Key.inputSlot);
            }

            graphObject.graph.RemoveElements(
                graphView.selection.OfType <IShaderNodeView>().Select(x => x.node).Where(x => x.allowedInSubGraph).ToArray(),
                new IEdge[] {},
                new GroupData[] {},
                graphView.selection.OfType <StickyNote>().Select(x => x.userData).ToArray());
            graphObject.graph.ValidateGraph();
        }
Пример #15
0
        public void GenerateNodeEntries()
        {
            Profiler.BeginSample("SearchWindowProvider.GenerateNodeEntries");
            // First build up temporary data structure containing group & title as an array of strings (the last one is the actual title) and associated node type.
            List <NodeEntry> nodeEntries = new List <NodeEntry>();

            bool hideCustomInterpolators = m_Graph.activeTargets.All(at => at.ignoreCustomInterpolators);

            if (target is ContextView contextView)
            {
                // Iterate all BlockFieldDescriptors currently cached on GraphData
                foreach (var field in m_Graph.blockFieldDescriptors)
                {
                    if (field.isHidden)
                    {
                        continue;
                    }

                    // Test stage
                    if (field.shaderStage != contextView.contextData.shaderStage)
                    {
                        continue;
                    }

                    // Create title
                    List <string> title = ListPool <string> .Get();

                    if (!string.IsNullOrEmpty(field.path))
                    {
                        var path = field.path.Split('/').ToList();
                        title.AddRange(path);
                    }
                    title.Add(field.displayName);

                    // Create and initialize BlockNode instance then add entry
                    var node = (BlockNode)Activator.CreateInstance(typeof(BlockNode));
                    node.Init(field);
                    AddEntries(node, title.ToArray(), nodeEntries);
                }

                SortEntries(nodeEntries);

                if (contextView.contextData.shaderStage == ShaderStage.Vertex && !hideCustomInterpolators)
                {
                    var customBlockNodeStub = (BlockNode)Activator.CreateInstance(typeof(BlockNode));
                    customBlockNodeStub.InitCustomDefault();
                    AddEntries(customBlockNodeStub, new string[] { "Custom Interpolator" }, nodeEntries);
                }

                currentNodeEntries = nodeEntries;
                return;
            }


            Profiler.BeginSample("SearchWindowProvider.GenerateNodeEntries.IterateKnowNodes");
            foreach (var type in NodeClassCache.knownNodeTypes)
            {
                if ((!type.IsClass || type.IsAbstract) ||
                    type == typeof(PropertyNode) ||
                    type == typeof(KeywordNode) ||
                    type == typeof(DropdownNode) ||
                    type == typeof(SubGraphNode))
                {
                    continue;
                }

                TitleAttribute titleAttribute = NodeClassCache.GetAttributeOnNodeType <TitleAttribute>(type);
                if (titleAttribute != null)
                {
                    var node = (AbstractMaterialNode)Activator.CreateInstance(type);
                    if (!node.ExposeToSearcher)
                    {
                        continue;
                    }

                    if (ShaderGraphPreferences.allowDeprecatedBehaviors && node.latestVersion > 0)
                    {
                        var  versions = node.allowedNodeVersions ?? Enumerable.Range(0, node.latestVersion + 1);
                        bool multiple = (versions.Count() > 1);
                        foreach (int i in versions)
                        {
                            var depNode = (AbstractMaterialNode)Activator.CreateInstance(type);
                            depNode.ChangeVersion(i);
                            if (multiple)
                            {
                                AddEntries(depNode, titleAttribute.title.Append($"v{i}").ToArray(), nodeEntries);
                            }
                            else
                            {
                                AddEntries(depNode, titleAttribute.title, nodeEntries);
                            }
                        }
                    }
                    else
                    {
                        AddEntries(node, titleAttribute.title, nodeEntries);
                    }
                }
            }
            Profiler.EndSample();


            Profiler.BeginSample("SearchWindowProvider.GenerateNodeEntries.IterateSubgraphAssets");
            foreach (var asset in NodeClassCache.knownSubGraphAssets)
            {
                if (asset == null)
                {
                    continue;
                }

                var node = new SubGraphNode {
                    asset = asset
                };
                var title = asset.path.Split('/').ToList();

                if (asset.descendents.Contains(m_Graph.assetGuid) || asset.assetGuid == m_Graph.assetGuid)
                {
                    continue;
                }

                if (string.IsNullOrEmpty(asset.path))
                {
                    AddEntries(node, new string[1] {
                        asset.name
                    }, nodeEntries);
                }
                else if (title[0] != k_HiddenFolderName)
                {
                    title.Add(asset.name);
                    AddEntries(node, title.ToArray(), nodeEntries);
                }
            }
            Profiler.EndSample();


            Profiler.BeginSample("SearchWindowProvider.GenerateNodeEntries.IterateGraphInputs");
            foreach (var property in m_Graph.properties)
            {
                if (property is Serialization.MultiJsonInternal.UnknownShaderPropertyType)
                {
                    continue;
                }

                var node = new PropertyNode();
                node.property = property;
                AddEntries(node, new[] { "Properties", "Property: " + property.displayName }, nodeEntries);
            }
            foreach (var keyword in m_Graph.keywords)
            {
                var node = new KeywordNode();
                node.keyword = keyword;
                AddEntries(node, new[] { "Keywords", "Keyword: " + keyword.displayName }, nodeEntries);
            }
            foreach (var dropdown in m_Graph.dropdowns)
            {
                var node = new DropdownNode();
                node.dropdown = dropdown;
                AddEntries(node, new[] { "Dropdowns", "dropdown: " + dropdown.displayName }, nodeEntries);
            }
            if (!hideCustomInterpolators)
            {
                foreach (var cibnode in m_Graph.vertexContext.blocks.Where(b => b.value.isCustomBlock))
                {
                    var node = Activator.CreateInstance <CustomInterpolatorNode>();
                    node.ConnectToCustomBlock(cibnode.value);
                    AddEntries(node, new[] { "Custom Interpolator", cibnode.value.customName }, nodeEntries);
                }
            }
            Profiler.EndSample();

            SortEntries(nodeEntries);
            currentNodeEntries = nodeEntries;
            Profiler.EndSample();
        }
Пример #16
0
        public IEnumerator MoveDirectoryTests()
        {
            yield return(null);

            // rename the directory
            AssetDatabase.MoveAsset(targetUnityDirectoryPath, targetUnityDirectoryPath2);

            yield return(null);

            yield return(null);

            yield return(null);

            yield return(null);

            yield return(null);

            yield return(null);

            yield return(null);

            yield return(null);

            var graphPath = targetUnityDirectoryPath2 + "/ShaderGraph.shadergraph";

            OpenGraphWindow(graphPath);

            yield return(null);

            yield return(null);

            yield return(null);

            yield return(null);

            yield return(null);

            yield return(null);

            yield return(null);

            yield return(null);

            // try adding the subgraph node -- see if the asset still works after the files have been moved
            m_Graph = m_Window.graphObject.graph as GraphData;
            var subgraph = AssetDatabase.LoadAssetAtPath <SubGraphAsset>(graphPath);
            var node     = new SubGraphNode {
                asset = subgraph
            };

            m_Graph.AddNode(node);

            yield return(null);

            yield return(null);

            yield return(null);

            yield return(null);

            yield return(null);

            yield return(null);

            yield return(null);

            yield return(null);

            CloseGraphWindow();
        }
Пример #17
0
        public void GenerateNodeEntries()
        {
            // First build up temporary data structure containing group & title as an array of strings (the last one is the actual title) and associated node type.
            List <NodeEntry> nodeEntries = new List <NodeEntry>();

            foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                foreach (var type in assembly.GetTypesOrNothing())
                {
                    if (type.IsClass && !type.IsAbstract && (type.IsSubclassOf(typeof(AbstractMaterialNode))) &&
                        type != typeof(PropertyNode) &&
                        type != typeof(KeywordNode) &&
                        type != typeof(SubGraphNode))
                    {
                        var attrs = type.GetCustomAttributes(typeof(TitleAttribute), false) as TitleAttribute[];
                        if (attrs != null && attrs.Length > 0)
                        {
                            var node = (AbstractMaterialNode)Activator.CreateInstance(type);
                            AddEntries(node, attrs[0].title, nodeEntries);
                        }
                    }
                }
            }

            foreach (var guid in AssetDatabase.FindAssets(string.Format("t:{0}", typeof(SubGraphAsset))))
            {
                var asset = AssetDatabase.LoadAssetAtPath <SubGraphAsset>(AssetDatabase.GUIDToAssetPath(guid));
                var node  = new SubGraphNode {
                    asset = asset
                };
                var title = asset.path.Split('/').ToList();

                if (asset.descendents.Contains(m_Graph.assetGuid) || asset.assetGuid == m_Graph.assetGuid)
                {
                    continue;
                }

                if (string.IsNullOrEmpty(asset.path))
                {
                    AddEntries(node, new string[1] {
                        asset.name
                    }, nodeEntries);
                }

                else if (title[0] != k_HiddenFolderName)
                {
                    title.Add(asset.name);
                    AddEntries(node, title.ToArray(), nodeEntries);
                }
            }

            foreach (var property in m_Graph.properties)
            {
                var node = new PropertyNode();
                node.owner        = m_Graph;
                node.propertyGuid = property.guid;
                node.owner        = null;
                AddEntries(node, new[] { "Properties", "Property: " + property.displayName }, nodeEntries);
            }
            foreach (var keyword in m_Graph.keywords)
            {
                var node = new KeywordNode();
                node.owner       = m_Graph;
                node.keywordGuid = keyword.guid;
                node.owner       = null;
                AddEntries(node, new[] { "Keywords", "Keyword: " + keyword.displayName }, nodeEntries);
            }

            // Sort the entries lexicographically by group then title with the requirement that items always comes before sub-groups in the same group.
            // Example result:
            // - Art/BlendMode
            // - Art/Adjustments/ColorBalance
            // - Art/Adjustments/Contrast
            nodeEntries.Sort((entry1, entry2) =>
            {
                for (var i = 0; i < entry1.title.Length; i++)
                {
                    if (i >= entry2.title.Length)
                    {
                        return(1);
                    }
                    var value = entry1.title[i].CompareTo(entry2.title[i]);
                    if (value != 0)
                    {
                        // Make sure that leaves go before nodes
                        if (entry1.title.Length != entry2.title.Length && (i == entry1.title.Length - 1 || i == entry2.title.Length - 1))
                        {
                            //once nodes are sorted, sort slot entries by slot order instead of alphebetically
                            var alphaOrder = entry1.title.Length < entry2.title.Length ? -1 : 1;
                            var slotOrder  = entry1.compatibleSlotId.CompareTo(entry2.compatibleSlotId);
                            return(alphaOrder.CompareTo(slotOrder));
                        }

                        return(value);
                    }
                }
                return(0);
            });


            currentNodeEntries = nodeEntries;
        }
        void CreateNode(object obj, Vector2 nodePosition)
        {
            var texture2D = obj as Texture2D;

            if (texture2D != null)
            {
                graph.owner.RegisterCompleteObjectUndo("Drag Texture");

                bool isNormalMap = false;
                if (EditorUtility.IsPersistent(texture2D) && !string.IsNullOrEmpty(AssetDatabase.GetAssetPath(texture2D)))
                {
                    var importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(texture2D)) as TextureImporter;
                    if (importer != null)
                    {
                        isNormalMap = importer.textureType == TextureImporterType.NormalMap;
                    }
                }

                var node      = new SampleTexture2DNode();
                var drawState = node.drawState;
                drawState.position = new Rect(nodePosition, drawState.position.size);
                node.drawState     = drawState;
                graph.AddNode(node);

                if (isNormalMap)
                {
                    node.textureType = TextureType.Normal;
                }

                var inputslot = node.FindInputSlot <Texture2DInputMaterialSlot>(SampleTexture2DNode.TextureInputId);
                if (inputslot != null)
                {
                    inputslot.texture = texture2D;
                }
            }

            var textureArray = obj as Texture2DArray;

            if (textureArray != null)
            {
                graph.owner.RegisterCompleteObjectUndo("Drag Texture Array");

                var node      = new SampleTexture2DArrayNode();
                var drawState = node.drawState;
                drawState.position = new Rect(nodePosition, drawState.position.size);
                node.drawState     = drawState;
                graph.AddNode(node);

                var inputslot = node.FindSlot <Texture2DArrayInputMaterialSlot>(SampleTexture2DArrayNode.TextureInputId);
                if (inputslot != null)
                {
                    inputslot.textureArray = textureArray;
                }
            }

            var texture3D = obj as Texture3D;

            if (texture3D != null)
            {
                graph.owner.RegisterCompleteObjectUndo("Drag Texture 3D");

                var node      = new SampleTexture3DNode();
                var drawState = node.drawState;
                drawState.position = new Rect(nodePosition, drawState.position.size);
                node.drawState     = drawState;
                graph.AddNode(node);

                var inputslot = node.FindSlot <Texture3DInputMaterialSlot>(SampleTexture3DNode.TextureInputId);
                if (inputslot != null)
                {
                    inputslot.texture = texture3D;
                }
            }

            var cubemap = obj as Cubemap;

            if (cubemap != null)
            {
                graph.owner.RegisterCompleteObjectUndo("Drag Cubemap");

                var node      = new SampleCubemapNode();
                var drawState = node.drawState;
                drawState.position = new Rect(nodePosition, drawState.position.size);
                node.drawState     = drawState;
                graph.AddNode(node);

                var inputslot = node.FindInputSlot <CubemapInputMaterialSlot>(SampleCubemapNode.CubemapInputId);
                if (inputslot != null)
                {
                    inputslot.cubemap = cubemap;
                }
            }

            var subGraphAsset = obj as SubGraphAsset;

            if (subGraphAsset != null)
            {
                graph.owner.RegisterCompleteObjectUndo("Drag Sub-Graph");
                var node = new SubGraphNode();

                var drawState = node.drawState;
                drawState.position = new Rect(nodePosition, drawState.position.size);
                node.drawState     = drawState;
                node.asset         = subGraphAsset;
                graph.AddNode(node);
            }

            var blackboardField = obj as BlackboardField;

            if (blackboardField != null)
            {
                graph.owner.RegisterCompleteObjectUndo("Drag Graph Input");

                switch (blackboardField.userData)
                {
                case AbstractShaderProperty property:
                {
                    var node      = new PropertyNode();
                    var drawState = node.drawState;
                    drawState.position = new Rect(nodePosition, drawState.position.size);
                    node.drawState     = drawState;
                    graph.AddNode(node);

                    // Setting the guid requires the graph to be set first.
                    node.propertyGuid = property.guid;
                    break;
                }

                case ShaderKeyword keyword:
                {
                    var node      = new KeywordNode();
                    var drawState = node.drawState;
                    drawState.position = new Rect(nodePosition, drawState.position.size);
                    node.drawState     = drawState;
                    graph.AddNode(node);

                    // Setting the guid requires the graph to be set first.
                    node.keywordGuid = keyword.guid;
                    break;
                }

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }
        }
Пример #19
0
        public void GenerateNodeEntries()
        {
            // First build up temporary data structure containing group & title as an array of strings (the last one is the actual title) and associated node type.
            List <NodeEntry> nodeEntries = new List <NodeEntry>();

            if (target is ContextView contextView)
            {
                // Iterate all BlockFieldDescriptors currently cached on GraphData
                foreach (var field in m_Graph.blockFieldDescriptors)
                {
                    if (field.isHidden)
                    {
                        continue;
                    }

                    // Test stage
                    if (field.shaderStage != contextView.contextData.shaderStage)
                    {
                        continue;
                    }

                    // Create title
                    List <string> title = ListPool <string> .Get();

                    if (!string.IsNullOrEmpty(field.path))
                    {
                        var path = field.path.Split('/').ToList();
                        title.AddRange(path);
                    }
                    title.Add(field.displayName);

                    // Create and initialize BlockNode instance then add entry
                    var node = (BlockNode)Activator.CreateInstance(typeof(BlockNode));
                    node.Init(field);
                    AddEntries(node, title.ToArray(), nodeEntries);
                }

                SortEntries(nodeEntries);
                currentNodeEntries = nodeEntries;
                return;
            }

            foreach (var type in TypeCache.GetTypesDerivedFrom <AbstractMaterialNode>())
            {
                if ((!type.IsClass || type.IsAbstract) ||
                    type == typeof(PropertyNode) ||
                    type == typeof(KeywordNode) ||
                    type == typeof(SubGraphNode))
                {
                    continue;
                }

                if (type.GetCustomAttributes(typeof(TitleAttribute), false) is TitleAttribute[] attrs && attrs.Length > 0)
                {
                    var node = (AbstractMaterialNode)Activator.CreateInstance(type);
                    AddEntries(node, attrs[0].title, nodeEntries);
                }
            }

            foreach (var guid in AssetDatabase.FindAssets(string.Format("t:{0}", typeof(SubGraphAsset))))
            {
                var asset = AssetDatabase.LoadAssetAtPath <SubGraphAsset>(AssetDatabase.GUIDToAssetPath(guid));
                var node  = new SubGraphNode {
                    asset = asset
                };
                var title = asset.path.Split('/').ToList();

                if (asset.descendents.Contains(m_Graph.assetGuid) || asset.assetGuid == m_Graph.assetGuid)
                {
                    continue;
                }

                if (string.IsNullOrEmpty(asset.path))
                {
                    AddEntries(node, new string[1] {
                        asset.name
                    }, nodeEntries);
                }

                else if (title[0] != k_HiddenFolderName)
                {
                    title.Add(asset.name);
                    AddEntries(node, title.ToArray(), nodeEntries);
                }
            }

            foreach (var property in m_Graph.properties)
            {
                var node = new PropertyNode();
                node.property = property;
                AddEntries(node, new[] { "Properties", "Property: " + property.displayName }, nodeEntries);
            }
            foreach (var keyword in m_Graph.keywords)
            {
                var node = new KeywordNode();
                node.keyword = keyword;
                AddEntries(node, new[] { "Keywords", "Keyword: " + keyword.displayName }, nodeEntries);
            }

            SortEntries(nodeEntries);
            currentNodeEntries = nodeEntries;
        }
        public void ToSubGraph()
        {
            var graphView = graphEditorView.graphView;

            var path = EditorUtility.SaveFilePanelInProject("Save Sub Graph", "New Shader Sub Graph", ShaderSubGraphImporter.Extension, "");

            path = path.Replace(Application.dataPath, "Assets");
            if (path.Length == 0)
            {
                return;
            }

            graphObject.RegisterCompleteObjectUndo("Convert To Subgraph");

            var nodes  = graphView.selection.OfType <IShaderNodeView>().Where(x => !(x.node is PropertyNode || x.node is SubGraphOutputNode)).Select(x => x.node).Where(x => x.allowedInSubGraph).ToArray();
            var bounds = Rect.MinMaxRect(float.PositiveInfinity, float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity);

            foreach (var node in nodes)
            {
                var center = node.drawState.position.center;
                bounds = Rect.MinMaxRect(
                    Mathf.Min(bounds.xMin, center.x),
                    Mathf.Min(bounds.yMin, center.y),
                    Mathf.Max(bounds.xMax, center.x),
                    Mathf.Max(bounds.yMax, center.y));
            }
            var middle = bounds.center;

            bounds.center = Vector2.zero;

            // Collect graph inputs
            var graphInputs = graphView.selection.OfType <BlackboardField>().Select(x => x.userData as ShaderInput);

            // Collect the property nodes and get the corresponding properties
            var propertyNodeGuids = graphView.selection.OfType <IShaderNodeView>().Where(x => (x.node is PropertyNode)).Select(x => ((PropertyNode)x.node).propertyGuid);
            var metaProperties    = graphView.graph.properties.Where(x => propertyNodeGuids.Contains(x.guid));

            // Collect the keyword nodes and get the corresponding keywords
            var keywordNodeGuids = graphView.selection.OfType <IShaderNodeView>().Where(x => (x.node is KeywordNode)).Select(x => ((KeywordNode)x.node).keywordGuid);
            var metaKeywords     = graphView.graph.keywords.Where(x => keywordNodeGuids.Contains(x.guid));

            var copyPasteGraph = new CopyPasteGraph(
                graphView.graph.assetGuid,
                graphView.selection.OfType <ShaderGroup>().Select(x => x.userData),
                graphView.selection.OfType <IShaderNodeView>().Where(x => !(x.node is PropertyNode || x.node is SubGraphOutputNode)).Select(x => x.node).Where(x => x.allowedInSubGraph).ToArray(),
                graphView.selection.OfType <Edge>().Select(x => x.userData as IEdge),
                graphInputs,
                metaProperties,
                metaKeywords,
                graphView.selection.OfType <StickyNote>().Select(x => x.userData));

            var deserialized = CopyPasteGraph.FromJson(JsonUtility.ToJson(copyPasteGraph, false));

            if (deserialized == null)
            {
                return;
            }

            var subGraph = new GraphData {
                isSubGraph = true
            };

            subGraph.path = "Sub Graphs";
            var subGraphOutputNode = new SubGraphOutputNode();

            {
                var drawState = subGraphOutputNode.drawState;
                drawState.position           = new Rect(new Vector2(bounds.xMax + 200f, 0f), drawState.position.size);
                subGraphOutputNode.drawState = drawState;
            }
            subGraph.AddNode(subGraphOutputNode);

            // Always copy deserialized keyword inputs
            foreach (ShaderKeyword keyword in deserialized.metaKeywords)
            {
                ShaderInput copiedInput = keyword.Copy();
                subGraph.SanitizeGraphInputName(copiedInput);
                subGraph.SanitizeGraphInputReferenceName(copiedInput, keyword.overrideReferenceName);
                subGraph.AddGraphInput(copiedInput);

                // Update the keyword nodes that depends on the copied keyword
                var dependentKeywordNodes = deserialized.GetNodes <KeywordNode>().Where(x => x.keywordGuid == keyword.guid);
                foreach (var node in dependentKeywordNodes)
                {
                    node.owner       = graphView.graph;
                    node.keywordGuid = copiedInput.guid;
                }
            }

            var groupGuidMap = new Dictionary <Guid, Guid>();

            foreach (GroupData groupData in deserialized.groups)
            {
                var oldGuid = groupData.guid;
                var newGuid = groupData.RewriteGuid();
                groupGuidMap[oldGuid] = newGuid;
                subGraph.CreateGroup(groupData);
            }

            List <Guid> groupGuids  = new List <Guid>();
            var         nodeGuidMap = new Dictionary <Guid, Guid>();

            foreach (var node in deserialized.GetNodes <AbstractMaterialNode>())
            {
                var oldGuid = node.guid;
                var newGuid = node.RewriteGuid();
                nodeGuidMap[oldGuid] = newGuid;
                var drawState = node.drawState;
                drawState.position = new Rect(drawState.position.position - middle, drawState.position.size);
                node.drawState     = drawState;

                if (!groupGuids.Contains(node.groupGuid))
                {
                    groupGuids.Add(node.groupGuid);
                }

                // Checking if the group guid is also being copied.
                // If not then nullify that guid
                if (node.groupGuid != Guid.Empty)
                {
                    node.groupGuid = !groupGuidMap.ContainsKey(node.groupGuid) ? Guid.Empty : groupGuidMap[node.groupGuid];
                }

                subGraph.AddNode(node);
            }

            foreach (var note in deserialized.stickyNotes)
            {
                if (!groupGuids.Contains(note.groupGuid))
                {
                    groupGuids.Add(note.groupGuid);
                }

                if (note.groupGuid != Guid.Empty)
                {
                    note.groupGuid = !groupGuidMap.ContainsKey(note.groupGuid) ? Guid.Empty : groupGuidMap[note.groupGuid];
                }

                note.RewriteGuid();
                subGraph.AddStickyNote(note);
            }

            // figure out what needs remapping
            var externalOutputSlots = new List <IEdge>();
            var externalInputSlots  = new List <IEdge>();

            foreach (var edge in deserialized.edges)
            {
                var outputSlot = edge.outputSlot;
                var inputSlot  = edge.inputSlot;

                Guid remappedOutputNodeGuid;
                Guid remappedInputNodeGuid;
                var  outputSlotExistsInSubgraph = nodeGuidMap.TryGetValue(outputSlot.nodeGuid, out remappedOutputNodeGuid);
                var  inputSlotExistsInSubgraph  = nodeGuidMap.TryGetValue(inputSlot.nodeGuid, out remappedInputNodeGuid);

                // pasting nice internal links!
                if (outputSlotExistsInSubgraph && inputSlotExistsInSubgraph)
                {
                    var outputSlotRef = new SlotReference(remappedOutputNodeGuid, outputSlot.slotId);
                    var inputSlotRef  = new SlotReference(remappedInputNodeGuid, inputSlot.slotId);
                    subGraph.Connect(outputSlotRef, inputSlotRef);
                }
                // one edge needs to go to outside world
                else if (outputSlotExistsInSubgraph)
                {
                    externalInputSlots.Add(edge);
                }
                else if (inputSlotExistsInSubgraph)
                {
                    externalOutputSlots.Add(edge);
                }
            }

            // Find the unique edges coming INTO the graph
            var uniqueIncomingEdges = externalOutputSlots.GroupBy(
                edge => edge.outputSlot,
                edge => edge,
                (key, edges) => new { slotRef = key, edges = edges.ToList() });

            var externalInputNeedingConnection = new List <KeyValuePair <IEdge, AbstractShaderProperty> >();

            var       amountOfProps  = uniqueIncomingEdges.Count();
            const int height         = 40;
            const int subtractHeight = 20;
            var       propPos        = new Vector2(0, -((amountOfProps / 2) + height) - subtractHeight);

            foreach (var group in uniqueIncomingEdges)
            {
                var sr       = group.slotRef;
                var fromNode = graphObject.graph.GetNodeFromGuid(sr.nodeGuid);
                var fromSlot = fromNode.FindOutputSlot <MaterialSlot>(sr.slotId);

                AbstractShaderProperty prop;
                switch (fromSlot.concreteValueType)
                {
                case ConcreteSlotValueType.Texture2D:
                    prop = new Texture2DShaderProperty();
                    break;

                case ConcreteSlotValueType.Texture2DArray:
                    prop = new Texture2DArrayShaderProperty();
                    break;

                case ConcreteSlotValueType.Texture3D:
                    prop = new Texture3DShaderProperty();
                    break;

                case ConcreteSlotValueType.Cubemap:
                    prop = new CubemapShaderProperty();
                    break;

                case ConcreteSlotValueType.Vector4:
                    prop = new Vector4ShaderProperty();
                    break;

                case ConcreteSlotValueType.Vector3:
                    prop = new Vector3ShaderProperty();
                    break;

                case ConcreteSlotValueType.Vector2:
                    prop = new Vector2ShaderProperty();
                    break;

                case ConcreteSlotValueType.Vector1:
                    prop = new Vector1ShaderProperty();
                    break;

                case ConcreteSlotValueType.Boolean:
                    prop = new BooleanShaderProperty();
                    break;

                case ConcreteSlotValueType.Matrix2:
                    prop = new Matrix2ShaderProperty();
                    break;

                case ConcreteSlotValueType.Matrix3:
                    prop = new Matrix3ShaderProperty();
                    break;

                case ConcreteSlotValueType.Matrix4:
                    prop = new Matrix4ShaderProperty();
                    break;

                case ConcreteSlotValueType.SamplerState:
                    prop = new SamplerStateShaderProperty();
                    break;

                case ConcreteSlotValueType.Gradient:
                    prop = new GradientShaderProperty();
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                if (prop != null)
                {
                    var materialGraph    = (GraphData)graphObject.graph;
                    var fromPropertyNode = fromNode as PropertyNode;
                    var fromProperty     = fromPropertyNode != null?materialGraph.properties.FirstOrDefault(p => p.guid == fromPropertyNode.propertyGuid) : null;

                    prop.displayName = fromProperty != null ? fromProperty.displayName : fromSlot.concreteValueType.ToString();

                    subGraph.AddGraphInput(prop);
                    var propNode = new PropertyNode();
                    {
                        var drawState = propNode.drawState;
                        drawState.position = new Rect(new Vector2(bounds.xMin - 300f, 0f) + propPos, drawState.position.size);
                        propPos           += new Vector2(0, height);
                        propNode.drawState = drawState;
                    }
                    subGraph.AddNode(propNode);
                    propNode.propertyGuid = prop.guid;

                    foreach (var edge in group.edges)
                    {
                        subGraph.Connect(
                            new SlotReference(propNode.guid, PropertyNode.OutputSlotId),
                            new SlotReference(nodeGuidMap[edge.inputSlot.nodeGuid], edge.inputSlot.slotId));
                        externalInputNeedingConnection.Add(new KeyValuePair <IEdge, AbstractShaderProperty>(edge, prop));
                    }
                }
            }

            var uniqueOutgoingEdges = externalInputSlots.GroupBy(
                edge => edge.outputSlot,
                edge => edge,
                (key, edges) => new { slot = key, edges = edges.ToList() });

            var externalOutputsNeedingConnection = new List <KeyValuePair <IEdge, IEdge> >();

            foreach (var group in uniqueOutgoingEdges)
            {
                var outputNode = subGraph.outputNode as SubGraphOutputNode;

                AbstractMaterialNode node = graphView.graph.GetNodeFromGuid(group.edges[0].outputSlot.nodeGuid);
                MaterialSlot         slot = node.FindSlot <MaterialSlot>(group.edges[0].outputSlot.slotId);
                var slotId = outputNode.AddSlot(slot.concreteValueType);

                var inputSlotRef = new SlotReference(outputNode.guid, slotId);

                foreach (var edge in group.edges)
                {
                    var newEdge = subGraph.Connect(new SlotReference(nodeGuidMap[edge.outputSlot.nodeGuid], edge.outputSlot.slotId), inputSlotRef);
                    externalOutputsNeedingConnection.Add(new KeyValuePair <IEdge, IEdge>(edge, newEdge));
                }
            }

            if (FileUtilities.WriteShaderGraphToDisk(path, subGraph))
            {
                AssetDatabase.ImportAsset(path);
            }

            var loadedSubGraph = AssetDatabase.LoadAssetAtPath(path, typeof(SubGraphAsset)) as SubGraphAsset;

            if (loadedSubGraph == null)
            {
                return;
            }

            var subGraphNode = new SubGraphNode();
            var ds           = subGraphNode.drawState;

            ds.position            = new Rect(middle - new Vector2(100f, 150f), Vector2.zero);
            subGraphNode.drawState = ds;

            // Add the subgraph into the group if the nodes was all in the same group group
            if (groupGuids.Count == 1)
            {
                subGraphNode.groupGuid = groupGuids[0];
            }

            graphObject.graph.AddNode(subGraphNode);
            subGraphNode.asset = loadedSubGraph;

            foreach (var edgeMap in externalInputNeedingConnection)
            {
                graphObject.graph.Connect(edgeMap.Key.outputSlot, new SlotReference(subGraphNode.guid, edgeMap.Value.guid.GetHashCode()));
            }

            foreach (var edgeMap in externalOutputsNeedingConnection)
            {
                graphObject.graph.Connect(new SlotReference(subGraphNode.guid, edgeMap.Value.inputSlot.slotId), edgeMap.Key.inputSlot);
            }

            graphObject.graph.RemoveElements(
                graphView.selection.OfType <IShaderNodeView>().Select(x => x.node).Where(x => x.allowedInSubGraph).ToArray(),
                new IEdge[] {},
                new GroupData[] {},
                graphView.selection.OfType <StickyNote>().Select(x => x.userData).ToArray());
            graphObject.graph.ValidateGraph();
        }
Пример #21
0
        void CreateNode(object obj, Vector2 nodePosition)
        {
            var texture2D = obj as Texture2D;

            if (texture2D != null)
            {
                graph.owner.RegisterCompleteObjectUndo("Drag Texture");

                bool isNormalMap = false;
                if (EditorUtility.IsPersistent(texture2D) && !string.IsNullOrEmpty(AssetDatabase.GetAssetPath(texture2D)))
                {
                    var importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(texture2D)) as TextureImporter;
                    if (importer != null)
                    {
                        isNormalMap = importer.textureType == TextureImporterType.NormalMap;
                    }
                }

                var node = new SampleTexture2DNode();

                var drawState = node.drawState;
                drawState.position = new Rect(nodePosition, drawState.position.size);
                node.drawState     = drawState;
                graph.AddNode(node);

                if (isNormalMap)
                {
                    node.textureType = TextureType.Normal;
                }

                var inputslot = node.FindInputSlot <Texture2DInputMaterialSlot>(SampleTexture2DNode.TextureInputId);
                if (inputslot != null)
                {
                    inputslot.texture = texture2D;
                }
            }

            var textureArray = obj as Texture2DArray;

            if (textureArray != null)
            {
                graph.owner.RegisterCompleteObjectUndo("Drag Texture Array");
                var property = new Texture2DArrayShaderProperty {
                    displayName = textureArray.name, value = { textureArray = textureArray }
                };
                graph.AddShaderProperty(property);
                var node      = new SampleTexture2DArrayNode();
                var drawState = node.drawState;
                drawState.position = new Rect(nodePosition, drawState.position.size);
                node.drawState     = drawState;
                graph.AddNode(node);
                var inputslot = node.FindSlot <Texture2DArrayInputMaterialSlot>(SampleTexture2DArrayNode.TextureInputId);
                if (inputslot != null)
                {
                    inputslot.textureArray = textureArray;
                }
            }

            var texture3D = obj as Texture3D;

            if (texture3D != null)
            {
                graph.owner.RegisterCompleteObjectUndo("Drag Texture 3D");
                var property = new Texture3DShaderProperty {
                    displayName = texture3D.name, value = { texture = texture3D }
                };
                graph.AddShaderProperty(property);
                var node      = new SampleTexture3DNode();
                var drawState = node.drawState;
                drawState.position = new Rect(nodePosition, drawState.position.size);
                node.drawState     = drawState;
                graph.AddNode(node);
                var inputslot = node.FindSlot <Texture3DInputMaterialSlot>(SampleTexture3DNode.TextureInputId);
                if (inputslot != null)
                {
                    inputslot.texture = texture3D;
                }
            }

            var cubemap = obj as Cubemap;

            if (cubemap != null)
            {
                graph.owner.RegisterCompleteObjectUndo("Drag Cubemap");
                var property = new CubemapShaderProperty {
                    displayName = cubemap.name, value = { cubemap = cubemap }
                };
                graph.AddShaderProperty(property);
                var node = new SampleCubemapNode();

                var drawState = node.drawState;
                drawState.position = new Rect(nodePosition, drawState.position.size);
                node.drawState     = drawState;
                graph.AddNode(node);

                var inputslot = node.FindInputSlot <CubemapInputMaterialSlot>(SampleCubemapNode.CubemapInputId);
                if (inputslot != null)
                {
                    inputslot.cubemap = cubemap;
                }
            }

            var subGraphAsset = obj as SubGraphAsset;

            if (subGraphAsset != null)
            {
                graph.owner.RegisterCompleteObjectUndo("Drag Sub-Graph");
                var node = new SubGraphNode();

                var drawState = node.drawState;
                drawState.position = new Rect(nodePosition, drawState.position.size);
                node.drawState     = drawState;
                node.subGraphAsset = subGraphAsset;
                graph.AddNode(node);
            }

            var blackboardField = obj as BlackboardField;

            if (blackboardField != null)
            {
                AbstractShaderProperty property = blackboardField.userData as AbstractShaderProperty;
                if (property != null)
                {
                    graph.owner.RegisterCompleteObjectUndo("Drag Property");
                    var node = new PropertyNode();

                    var drawState = node.drawState;
                    drawState.position = new Rect(nodePosition, drawState.position.size);
                    node.drawState     = drawState;
                    graph.AddNode(node);

                    // Setting the guid requires the graph to be set first.
                    node.propertyGuid = property.guid;
                }
            }
        }
Пример #22
0
        void CreateNode(object obj, Vector2 nodePosition)
        {
            var texture2D = obj as Texture2D;

            if (texture2D != null)
            {
                graph.owner.RegisterCompleteObjectUndo("Drag Texture");

                bool isNormalMap = false;
                if (EditorUtility.IsPersistent(texture2D) && !string.IsNullOrEmpty(AssetDatabase.GetAssetPath(texture2D)))
                {
                    var importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(texture2D)) as TextureImporter;
                    if (importer != null)
                    {
                        isNormalMap = importer.textureType == TextureImporterType.NormalMap;
                    }
                }

                var node      = new SampleTexture2DNode();
                var drawState = node.drawState;
                drawState.position = new Rect(nodePosition, drawState.position.size);
                node.drawState     = drawState;
                graph.AddNode(node);

                if (isNormalMap)
                {
                    node.textureType = TextureType.Normal;
                }

                var inputslot = node.FindInputSlot <Texture2DInputMaterialSlot>(SampleTexture2DNode.TextureInputId);
                if (inputslot != null)
                {
                    inputslot.texture = texture2D;
                }
            }

            var textureArray = obj as Texture2DArray;

            if (textureArray != null)
            {
                graph.owner.RegisterCompleteObjectUndo("Drag Texture Array");

                var node      = new SampleTexture2DArrayNode();
                var drawState = node.drawState;
                drawState.position = new Rect(nodePosition, drawState.position.size);
                node.drawState     = drawState;
                graph.AddNode(node);

                var inputslot = node.FindSlot <Texture2DArrayInputMaterialSlot>(SampleTexture2DArrayNode.TextureInputId);
                if (inputslot != null)
                {
                    inputslot.textureArray = textureArray;
                }
            }

            var texture3D = obj as Texture3D;

            if (texture3D != null)
            {
                graph.owner.RegisterCompleteObjectUndo("Drag Texture 3D");

                var node      = new SampleTexture3DNode();
                var drawState = node.drawState;
                drawState.position = new Rect(nodePosition, drawState.position.size);
                node.drawState     = drawState;
                graph.AddNode(node);

                var inputslot = node.FindSlot <Texture3DInputMaterialSlot>(SampleTexture3DNode.TextureInputId);
                if (inputslot != null)
                {
                    inputslot.texture = texture3D;
                }
            }

            var cubemap = obj as Cubemap;

            if (cubemap != null)
            {
                graph.owner.RegisterCompleteObjectUndo("Drag Cubemap");

                var node      = new SampleCubemapNode();
                var drawState = node.drawState;
                drawState.position = new Rect(nodePosition, drawState.position.size);
                node.drawState     = drawState;
                graph.AddNode(node);

                var inputslot = node.FindInputSlot <CubemapInputMaterialSlot>(SampleCubemapNode.CubemapInputId);
                if (inputslot != null)
                {
                    inputslot.cubemap = cubemap;
                }
            }

            var subGraphAsset = obj as SubGraphAsset;

            if (subGraphAsset != null)
            {
                graph.owner.RegisterCompleteObjectUndo("Drag Sub-Graph");
                var node = new SubGraphNode();

                var drawState = node.drawState;
                drawState.position = new Rect(nodePosition, drawState.position.size);
                node.drawState     = drawState;
                node.asset         = subGraphAsset;
                graph.AddNode(node);
            }

            var blackboardField = obj as BlackboardField;

            if (blackboardField != null)
            {
                graph.owner.RegisterCompleteObjectUndo("Drag Graph Input");

                switch (blackboardField.userData)
                {
                case AbstractShaderProperty property:
                {
                    // This could be from another graph, in which case we add a copy of the ShaderInput to this graph.
                    if (graph.properties.FirstOrDefault(p => p.guid == property.guid) == null)
                    {
                        var copy = (AbstractShaderProperty)property.Copy();
                        graph.SanitizeGraphInputName(copy);
                        graph.SanitizeGraphInputReferenceName(copy, property.overrideReferenceName);     // We do want to copy the overrideReferenceName

                        property = copy;
                        graph.AddGraphInput(property);
                    }

                    var node      = new PropertyNode();
                    var drawState = node.drawState;
                    drawState.position = new Rect(nodePosition, drawState.position.size);
                    node.drawState     = drawState;
                    graph.AddNode(node);

                    // Setting the guid requires the graph to be set first.
                    node.propertyGuid = property.guid;
                    break;
                }

                case ShaderKeyword keyword:
                {
                    // This could be from another graph, in which case we add a copy of the ShaderInput to this graph.
                    if (graph.keywords.FirstOrDefault(k => k.guid == keyword.guid) == null)
                    {
                        var copy = (ShaderKeyword)keyword.Copy();
                        graph.SanitizeGraphInputName(copy);
                        graph.SanitizeGraphInputReferenceName(copy, keyword.overrideReferenceName);     // We do want to copy the overrideReferenceName

                        keyword = copy;
                        graph.AddGraphInput(keyword);
                    }

                    var node      = new KeywordNode();
                    var drawState = node.drawState;
                    drawState.position = new Rect(nodePosition, drawState.position.size);
                    node.drawState     = drawState;
                    graph.AddNode(node);

                    // Setting the guid requires the graph to be set first.
                    node.keywordGuid = keyword.guid;
                    break;
                }

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }
        }
Пример #23
0
        public void GenerateNodeEntries()
        {
            Profiler.BeginSample("SearchWindowProvider.GenerateNodeEntries");
            // First build up temporary data structure containing group & title as an array of strings (the last one is the actual title) and associated node type.
            List <NodeEntry> nodeEntries = new List <NodeEntry>();

            if (target is ContextView contextView)
            {
                // Iterate all BlockFieldDescriptors currently cached on GraphData
                foreach (var field in m_Graph.blockFieldDescriptors)
                {
                    if (field.isHidden)
                    {
                        continue;
                    }

                    // Test stage
                    if (field.shaderStage != contextView.contextData.shaderStage)
                    {
                        continue;
                    }

                    // Create title
                    List <string> title = ListPool <string> .Get();

                    if (!string.IsNullOrEmpty(field.path))
                    {
                        var path = field.path.Split('/').ToList();
                        title.AddRange(path);
                    }
                    title.Add(field.displayName);

                    // Create and initialize BlockNode instance then add entry
                    var node = (BlockNode)Activator.CreateInstance(typeof(BlockNode));
                    node.Init(field);
                    AddEntries(node, title.ToArray(), nodeEntries);
                }

                SortEntries(nodeEntries);
                currentNodeEntries = nodeEntries;
                return;
            }

            foreach (var type in NodeClassCache.knownNodeTypes)
            {
                if ((!type.IsClass || type.IsAbstract) ||
                    type == typeof(PropertyNode) ||
                    type == typeof(KeywordNode) ||
                    type == typeof(SubGraphNode))
                {
                    continue;
                }

                TitleAttribute titleAttribute = NodeClassCache.GetAttributeOnNodeType <TitleAttribute>(type);
                if (titleAttribute != null)
                {
                    var node = (AbstractMaterialNode)Activator.CreateInstance(type);
                    if (ShaderGraphPreferences.allowDeprecatedBehaviors && node.latestVersion > 0)
                    {
                        var  versions = node.allowedNodeVersions ?? Enumerable.Range(0, node.latestVersion + 1);
                        bool multiple = (versions.Count() > 1);
                        foreach (int i in versions)
                        {
                            var depNode = (AbstractMaterialNode)Activator.CreateInstance(type);
                            depNode.ChangeVersion(i);
                            if (multiple)
                            {
                                AddEntries(depNode, titleAttribute.title.Append($"V{i}").ToArray(), nodeEntries);
                            }
                            else
                            {
                                AddEntries(depNode, titleAttribute.title, nodeEntries);
                            }
                        }
                    }
                    else
                    {
                        AddEntries(node, titleAttribute.title, nodeEntries);
                    }
                }
            }

            foreach (var guid in AssetDatabase.FindAssets(string.Format("t:{0}", typeof(SubGraphAsset))))
            {
                var asset = AssetDatabase.LoadAssetAtPath <SubGraphAsset>(AssetDatabase.GUIDToAssetPath(guid));
                var node  = new SubGraphNode {
                    asset = asset
                };
                var title = asset.path.Split('/').ToList();

                if (asset.descendents.Contains(m_Graph.assetGuid) || asset.assetGuid == m_Graph.assetGuid)
                {
                    continue;
                }

                if (string.IsNullOrEmpty(asset.path))
                {
                    AddEntries(node, new string[1] {
                        asset.name
                    }, nodeEntries);
                }

                else if (title[0] != k_HiddenFolderName)
                {
                    title.Add(asset.name);
                    AddEntries(node, title.ToArray(), nodeEntries);
                }
            }

            foreach (var property in m_Graph.properties)
            {
                if (property is Serialization.MultiJsonInternal.UnknownShaderPropertyType)
                {
                    continue;
                }

                var node = new PropertyNode();
                node.property = property;
                AddEntries(node, new[] { "Properties", "Property: " + property.displayName }, nodeEntries);
            }
            foreach (var keyword in m_Graph.keywords)
            {
                var node = new KeywordNode();
                node.keyword = keyword;
                AddEntries(node, new[] { "Keywords", "Keyword: " + keyword.displayName }, nodeEntries);
            }

            SortEntries(nodeEntries);
            currentNodeEntries = nodeEntries;
            Profiler.EndSample();
        }
Пример #24
0
        void CreateNode(Object obj, Vector2 nodePosition)
        {
            var texture2D = obj as Texture2D;

            if (texture2D != null)
            {
                m_Graph.owner.RegisterCompleteObjectUndo("Drag Texture");

                bool isNormalMap = false;
                if (EditorUtility.IsPersistent(texture2D) &&
                    !string.IsNullOrEmpty(AssetDatabase.GetAssetPath(texture2D)))
                {
                    var importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(texture2D)) as TextureImporter;
                    if (importer != null)
                    {
                        isNormalMap = importer.textureType == TextureImporterType.NormalMap;
                    }
                }

                var node = new SampleTexture2DNode();
                if (isNormalMap)
                {
                    node.textureType = TextureType.Normal;
                }

                var drawState = node.drawState;
                drawState.position = new Rect(nodePosition, drawState.position.size);
                node.drawState     = drawState;
                m_Graph.AddNode(node);
                var inputslot = node.FindSlot <Texture2DInputMaterialSlot>(SampleTexture2DNode.TextureInputId);
                if (inputslot != null)
                {
                    inputslot.texture = texture2D;
                }
            }

            var cubemap = obj as Cubemap;

            if (cubemap != null)
            {
                m_Graph.owner.RegisterCompleteObjectUndo("Drag Cubemap");
                var property = new CubemapShaderProperty {
                    displayName = cubemap.name, value = { cubemap = cubemap }
                };
                m_Graph.AddShaderProperty(property);
                var node      = new SampleCubemapNode();
                var drawState = node.drawState;
                drawState.position = new Rect(nodePosition, drawState.position.size);
                node.drawState     = drawState;
                m_Graph.AddNode(node);
                var inputslot = node.FindSlot <CubemapInputMaterialSlot>(SampleCubemapNode.CubemapInputId);
                if (inputslot != null)
                {
                    inputslot.cubemap = cubemap;
                }
            }

            var subGraphAsset = obj as MaterialSubGraphAsset;

            if (subGraphAsset != null)
            {
                m_Graph.owner.RegisterCompleteObjectUndo("Drag Sub-Graph");
                var node      = new SubGraphNode();
                var drawState = node.drawState;
                drawState.position = new Rect(nodePosition, drawState.position.size);
                node.drawState     = drawState;
                node.subGraphAsset = subGraphAsset;
                m_Graph.AddNode(node);
            }
        }