Example #1
0
    void ApplyShadows(ref ScriptableRenderContext context, ref CullingResults cullingResults)
    {
        if (shadowData == null || shadowData.lights == null || shadowData.shadowMaps == null)
        {
            return;
        }

        ShaderInput.SetShadowMaps(buffer, shadowData.shadowMaps);

        worldToShadowMatricesBuffer = CreateBuffer(worldToShadowMatrices);
        ShaderInput.SetWorldToShadowMatrices(buffer, worldToShadowMatricesBuffer);

        cascadeDataBuffer = CreateBuffer(cascadeData);
        ShaderInput.SetCascadeData(buffer, cascadeDataBuffer);

        cullingSpheresBuffer = CreateBuffer(cullingSpheres);
        ShaderInput.SetCullingSpheres(buffer, cullingSpheresBuffer);

        shadowSettingsBuffer = CreateBuffer(shadowSettings);
        ShaderInput.SetShadowSettings(buffer, shadowSettingsBuffer);

        ShaderInput.SetHardShadows(buffer, hasShadowsHard);
        ShaderInput.SetSoftShadows(buffer, hasShadowsSoft);

        SubmitBuffer(ref context, buffer);
    }
Example #2
0
    void RenderSpotShadow(ref ScriptableRenderContext context, ref CullingResults cullingResults, int shadowMapSize, int index, ref VisibleLight visibleLight)
    {
        if (shadowData.lights[index] == null)
        {
            return;
        }

        CoreUtils.SetRenderTarget(buffer, shadowData.shadowMaps, ClearFlag.Depth, 0, CubemapFace.Unknown, index);
        SubmitBuffer(ref context, buffer);

        if (shadowData.lights[index].cascades[0] == null)
        {
            return;
        }

        Rect tileViewport = new Rect(0, 0, shadowMapSize, shadowMapSize);

        buffer.SetViewport(new Rect(tileViewport));
        buffer.SetViewProjectionMatrices(shadowData.lights[index].cascades[0].viewMatrix, shadowData.lights[index].cascades[0].projectionMatrix);
        ShaderInput.SetShadowBias(buffer, visibleLight.light.shadowBias);
        SubmitBuffer(ref context, buffer);

        ShadowDrawingSettings shadowSettings = new ShadowDrawingSettings(cullingResults, index);

        shadowSettings.splitData = shadowData.lights[index].cascades[0].splitData;
        context.DrawShadows(ref shadowSettings);
    }
Example #3
0
    void RenderDirectionalShadow(ref ScriptableRenderContext context, ref CullingResults cullingResults, int shadowMapSize, int index, ref VisibleLight visibleLight)
    {
        if (shadowData.lights[index] == null)
        {
            return;
        }

        CoreUtils.SetRenderTarget(buffer, shadowData.shadowMaps, ClearFlag.Depth, 0, CubemapFace.Unknown, index);
        SubmitBuffer(ref context, buffer);

        for (int j = 0; j < 4; j++)
        {
            if (shadowData.lights[index].cascades[j] == null)
            {
                continue;
            }

            Rect tileViewport = new Rect(shadowData.lights[index].cascades[j].tileOffset.x * shadowData.lights[index].tileSize, shadowData.lights[index].cascades[j].tileOffset.y * shadowData.lights[index].tileSize, shadowData.lights[index].tileSize, shadowData.lights[index].tileSize);

            buffer.SetViewport(new Rect(tileViewport));
            buffer.EnableScissorRect(new Rect(tileViewport.x + 4f, tileViewport.y + 4f, shadowData.lights[index].tileSize - 8f, shadowData.lights[index].tileSize - 8f));
            buffer.SetViewProjectionMatrices(shadowData.lights[index].cascades[j].viewMatrix, shadowData.lights[index].cascades[j].projectionMatrix);
            ShaderInput.SetShadowBias(buffer, visibleLight.light.shadowBias);
            SubmitBuffer(ref context, buffer);

            ShadowDrawingSettings shadowSettings = new ShadowDrawingSettings(cullingResults, index);
            shadowSettings.splitData = shadowData.lights[index].cascades[j].splitData;
            context.DrawShadows(ref shadowSettings);
        }

        buffer.DisableScissorRect();
        SubmitBuffer(ref context, buffer);
    }
Example #4
0
        void OnMouseHover(EventBase evt, ShaderInput input)
        {
            var graphView = blackboard.GetFirstAncestorOfType <MaterialGraphView>();

            if (evt.eventTypeId == MouseEnterEvent.TypeId())
            {
                foreach (var node in graphView.nodes.ToList())
                {
                    if (input is AbstractShaderProperty property)
                    {
                        if (node.userData is PropertyNode propertyNode)
                        {
                            if (propertyNode.propertyGuid == input.guid)
                            {
                                m_SelectedNodes.Add(node);
                                node.AddToClassList("hovered");
                            }
                        }
                    }
                }
            }
            else if (evt.eventTypeId == MouseLeaveEvent.TypeId() && m_SelectedNodes.Any())
            {
                foreach (var node in m_SelectedNodes)
                {
                    node.RemoveFromClassList("hovered");
                }
                m_SelectedNodes.Clear();
            }
        }
        void BuildKeywordFields(PropertySheet propertySheet, ShaderInput shaderInput)
        {
            var keyword = shaderInput as ShaderKeyword;

            if (keyword == null)
            {
                return;
            }

            var enumPropertyDrawer = new EnumPropertyDrawer();

            propertySheet.Add(enumPropertyDrawer.CreateGUI(
                                  newValue =>
            {
                this._preChangeValueCallback("Change Keyword type");
                if (keyword.keywordDefinition == (KeywordDefinition)newValue)
                {
                    return;
                }
                keyword.keywordDefinition = (KeywordDefinition)newValue;
            },
                                  keyword.keywordDefinition,
                                  "Definition",
                                  KeywordDefinition.ShaderFeature,
                                  out var typeField));

            typeField.SetEnabled(!keyword.isBuiltIn);

            if (keyword.keywordDefinition != KeywordDefinition.Predefined)
            {
                propertySheet.Add(enumPropertyDrawer.CreateGUI(
                                      newValue =>
                {
                    this._preChangeValueCallback("Change Keyword scope");
                    if (keyword.keywordScope == (KeywordScope)newValue)
                    {
                        return;
                    }
                    keyword.keywordScope = (KeywordScope)newValue;
                },
                                      keyword.keywordScope,
                                      "Scope",
                                      KeywordScope.Local,
                                      out var scopeField));

                scopeField.SetEnabled(!keyword.isBuiltIn);
            }

            switch (keyword.keywordType)
            {
            case KeywordType.Boolean:
                BuildBooleanKeywordField(propertySheet, keyword);
                break;

            case KeywordType.Enum:
                BuildEnumKeywordField(propertySheet, keyword);
                break;
            }
        }
Example #6
0
 public BlackboardFieldView(GraphData graph, ShaderInput input, BlackBoardCallback updateBlackboardView,
                            Texture icon, string text, string typeText) : base(icon, text, typeText)
 {
     styleSheets.Add(Resources.Load <StyleSheet>("Styles/ShaderGraphBlackboard"));
     m_Graph = graph;
     m_Input = input;
     this.BlackBoardUpdateTrigger = updateBlackboardView;
 }
Example #7
0
        protected virtual AbstractMaterialNode CreateNodeForShaderInput(ShaderInput shaderInput, ShaderGraphBuilder builder, U unrealNode)
        {
            var graphNode = builder.CreateNode <PropertyNode>();

            graphNode.propertyGuid = shaderInput.guid;

            return(graphNode);
        }
Example #8
0
        protected override AbstractMaterialNode CreateNodeForShaderInput(ShaderInput shaderInput, ShaderGraphBuilder builder, MaterialExpressionStaticSwitchParameter unrealNode)
        {
            var propertyNode = base.CreateNodeForShaderInput(shaderInput, builder, unrealNode);
            var branchNode   = builder.CreateNode <BranchNode>();

            builder.PositionNodeOnGraph(propertyNode, unrealNode);
            builder.Connect(propertyNode.GetSlotReference(0), branchNode.GetSlotReference(0));

            return(branchNode);
        }
Example #9
0
        void BuildDefaultFields(ShaderInput input)
        {
            if (!m_Graph.isSubGraph)
            {
                m_ExposedToogle = new Toggle();
                m_ExposedToogle.OnToggleChanged(evt =>
                {
                    m_Graph.owner.RegisterCompleteObjectUndo("Change Exposed Toggle");
                    input.generatePropertyBlock = evt.newValue;
                    m_BlackboardField.icon      = input.generatePropertyBlock ? BlackboardProvider.exposedIcon : null;
                    Rebuild();
                    DirtyNodes(ModificationScope.Graph);
                });
                m_ExposedToogle.value = input.generatePropertyBlock;
                AddRow("Exposed", m_ExposedToogle, input.isExposable);
            }

            if (!m_Graph.isSubGraph || input is ShaderKeyword)
            {
                m_ReferenceNameField = new TextField(512, false, false, ' ')
                {
                    isDelayed = true
                };
                m_ReferenceNameField.styleSheets.Add(Resources.Load <StyleSheet>("Styles/PropertyNameReferenceField"));
                m_ReferenceNameField.value = input.referenceName;
                m_ReferenceNameField.RegisterValueChangedCallback(evt =>
                {
                    m_Graph.owner.RegisterCompleteObjectUndo("Change Reference Name");
                    if (m_ReferenceNameField.value != m_Input.referenceName)
                    {
                        m_Graph.SanitizeGraphInputReferenceName(input, evt.newValue);
                    }

                    m_ReferenceNameField.value = input.referenceName;
                    if (string.IsNullOrEmpty(input.overrideReferenceName))
                    {
                        m_ReferenceNameField.RemoveFromClassList("modified");
                    }
                    else
                    {
                        m_ReferenceNameField.AddToClassList("modified");
                    }

                    Rebuild();
                    DirtyNodes(ModificationScope.Graph);
                    UpdateReferenceNameResetMenu();
                });
                if (!string.IsNullOrEmpty(input.overrideReferenceName))
                {
                    m_ReferenceNameField.AddToClassList("modified");
                }

                AddRow("Reference", m_ReferenceNameField, input.isRenamable);
            }
        }
Example #10
0
 public BlackboardRow GetBlackboardRow(ShaderInput input)
 {
     if (m_InputRows.ContainsKey(input))
     {
         return(m_InputRows[input]);
     }
     else
     {
         return(null);
     }
 }
Example #11
0
        public override void BuildCustomFields(ShaderInput input)
        {
            m_Keyword = input as ShaderKeyword;
            if (m_Keyword == null)
            {
                return;
            }

            // KeywordDefinition
            var keywordDefinitionField = new EnumField((Enum)m_Keyword.keywordDefinition);

            keywordDefinitionField.RegisterValueChangedCallback(evt =>
            {
                graph.owner.RegisterCompleteObjectUndo("Change Keyword Type");
                if (m_Keyword.keywordDefinition == (KeywordDefinition)evt.newValue)
                {
                    return;
                }
                m_Keyword.keywordDefinition = (KeywordDefinition)evt.newValue;
                Rebuild();
            });
            AddRow("Definition", keywordDefinitionField, m_Keyword.isEditable);

            // KeywordScope
            if (m_Keyword.keywordDefinition != KeywordDefinition.Predefined)
            {
                var keywordScopeField = new EnumField((Enum)m_Keyword.keywordScope);
                keywordScopeField.RegisterValueChangedCallback(evt =>
                {
                    graph.owner.RegisterCompleteObjectUndo("Change Keyword Type");
                    if (m_Keyword.keywordScope == (KeywordScope)evt.newValue)
                    {
                        return;
                    }
                    m_Keyword.keywordScope = (KeywordScope)evt.newValue;
                });
                AddRow("Scope", keywordScopeField, m_Keyword.isEditable);
            }

            switch (m_Keyword.keywordType)
            {
            case KeywordType.Boolean:
                BuildBooleanKeywordField(m_Keyword);
                break;

            case KeywordType.Enum:
                BuildEnumKeywordField(m_Keyword);
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
Example #12
0
        public BlackboardFieldView(GraphData graph, ShaderInput input, BlackBoardCallback updateBlackboardView,
                                   Texture icon, string text, string typeText) : base(icon, text, typeText)
        {
            styleSheets.Add(Resources.Load <StyleSheet>("Styles/ShaderGraphBlackboard"));
            m_Graph = graph;
            m_Input = input;
            this.BlackBoardUpdateTrigger = updateBlackboardView;
            this.name = "blackboardFieldView";
            ShaderGraphPreferences.onAllowDeprecatedChanged += UpdateTypeText;

            UpdateRightClickMenu();
        }
Example #13
0
        protected override AbstractMaterialNode CreateNodeForShaderInput(ShaderInput shaderInput, ShaderGraphBuilder builder, MaterialExpressionTextureSampleParameter2D unrealNode)
        {
            var propertyNode = base.CreateNodeForShaderInput(shaderInput, builder, unrealNode);
            var sampleNode   = builder.CreateNode <SampleTexture2DNode>();

            sampleNode.textureType = TextureType.Default;

            builder.PositionNodeOnGraph(propertyNode, unrealNode);
            builder.Connect(propertyNode.GetSlotReference(PropertyNode.OutputSlotId), sampleNode.GetSlotReference(SampleTexture2DNode.TextureInputId));

            return(sampleNode);
        }
        public VisualElement DrawProperty(
            PropertyInfo propertyInfo,
            object actualObject,
            InspectableAttribute attribute)
        {
            var propertySheet = new PropertySheet();

            shaderInput = actualObject as ShaderInput;
            BuildExposedField(propertySheet);
            BuildReferenceNameField(propertySheet);
            BuildPropertyFields(propertySheet);
            BuildKeywordFields(propertySheet, shaderInput);
            return(propertySheet);
        }
Example #15
0
        public BlackboardFieldView(GraphData graph,
                                   ShaderInput input,
                                   Texture icon,
                                   string text,
                                   string typeText) : base(icon, text, typeText)
        {
            styleSheets.Add(Resources.Load <StyleSheet>("Styles/ShaderGraphBlackboard"));
            m_Graph   = graph;
            m_Input   = input;
            this.name = "blackboardFieldView";
            ShaderGraphPreferences.onAllowDeprecatedChanged += UpdateTypeText;

            // add the right click context menu
            IManipulator contextMenuManipulator = new ContextualMenuManipulator(AddContextMenuOptions);

            this.AddManipulator(contextMenuManipulator);

            var nameTextField = this.Q("textField") as TextField;
            var textinput     = nameTextField.Q(TextField.textInputUssName);

            // When a display name is changed through the BlackboardPill, this callback handle it
            textinput.RegisterCallback <FocusOutEvent>(e =>
            {
                this.RegisterPropertyChangeUndo("Change Display Name");

                if (nameTextField.text != m_Input.displayName)
                {
                    m_Input.SetDisplayNameAndSanitizeForGraph(m_Graph, nameTextField.text);
                }

                // This gets triggered on property creation so need to check for inspector update trigger being valid (which it might not be at the time)
                if (this.m_inspectorUpdateTrigger != null)
                {
                    this.MarkNodesAsDirty(true, ModificationScope.Topological);
                }
                else
                {
                    DirtyNodes(ModificationScope.Topological);
                }
            });

            m_NameLabelField = this.Q("title-label") as Label;

            // Set callback association for display name updates
            m_Input.displayNameUpdateTrigger += UpdateDisplayNameText;
        }
Example #16
0
        public BlackboardFieldView(BlackboardField blackboardField, GraphData graph, ShaderInput input)
        {
            styleSheets.Add(Resources.Load <StyleSheet>("Styles/ShaderGraphBlackboard"));
            m_BlackboardField = blackboardField;
            m_Graph           = graph;
            m_Input           = input;
            m_Rows            = new List <VisualElement>();

            m_KeyDownCallback = new EventCallback <KeyDownEvent>(evt =>
            {
                // Record Undo for input field edit
                if (m_UndoGroup == -1)
                {
                    m_UndoGroup = Undo.GetCurrentGroup();
                    graph.owner.RegisterCompleteObjectUndo("Change property value");
                }
                // Handle scaping input field edit
                if (evt.keyCode == KeyCode.Escape && m_UndoGroup > -1)
                {
                    Undo.RevertAllDownToGroup(m_UndoGroup);
                    m_UndoGroup = -1;
                    evt.StopPropagation();
                }
                // Dont record Undo again until input field is unfocused
                m_UndoGroup++;
                this.MarkDirtyRepaint();
            });

            m_FocusOutCallback = new EventCallback <FocusOutEvent>(evt =>
            {
                // Reset UndoGroup when done editing input field
                m_UndoGroup = -1;
            });

            BuildDefaultFields(input);
            BuildCustomFields(input);

            AddToClassList("sgblackboardFieldView");
        }
Example #17
0
        void AddPropertyItems(GenericMenu gm)
        {
            var shaderInputTypes = TypeCache.GetTypesWithAttribute <BlackboardInputInfo>().ToList();

            // Sort the ShaderInput by priority using the BlackboardInputInfo attribute
            shaderInputTypes.Sort((s1, s2) => {
                var info1 = Attribute.GetCustomAttribute(s1, typeof(BlackboardInputInfo)) as BlackboardInputInfo;
                var info2 = Attribute.GetCustomAttribute(s2, typeof(BlackboardInputInfo)) as BlackboardInputInfo;

                if (info1.priority == info2.priority)
                {
                    return((info1.name ?? s1.Name).CompareTo(info2.name ?? s2.Name));
                }
                else
                {
                    return(info1.priority.CompareTo(info2.priority));
                }
            });

            foreach (var t in shaderInputTypes)
            {
                if (t.IsAbstract)
                {
                    continue;
                }

                var         info = Attribute.GetCustomAttribute(t, typeof(BlackboardInputInfo)) as BlackboardInputInfo;
                string      name = info?.name ?? ObjectNames.NicifyVariableName(t.Name.Replace("ShaderProperty", ""));
                ShaderInput si   = Activator.CreateInstance(t, true) as ShaderInput;
                gm.AddItem(new GUIContent(name), false, () => AddInputRow(si, true));
                //QUICK FIX TO DEAL WITH DEPRECATED COLOR PROPERTY
                if (ShaderGraphPreferences.allowDeprecatedBehaviors && si is ColorShaderProperty csp)
                {
                    gm.AddItem(new GUIContent($"Color (Deprecated)"), false, () => AddInputRow(new ColorShaderProperty(ColorShaderProperty.deprecatedVersion), true));
                }
            }
            gm.AddSeparator($"/");
        }
Example #18
0
    void ApplyLights(ref ScriptableRenderContext context, ref CullingResults cullingResults)
    {
        colorsBuffer = CreateBuffer(colors);
        ShaderInput.SetLightsColors(buffer, colorsBuffer);

        positionsBuffer = CreateBuffer(positions);
        ShaderInput.SetLightsPositions(buffer, positionsBuffer);

        spotDirectionsBuffer = CreateBuffer(spotDirections);
        ShaderInput.SetLightsSpotDirections(buffer, spotDirectionsBuffer);

        attenuationsBuffer = CreateBuffer(attenuations);
        ShaderInput.SetLightsAttenuations(buffer, attenuationsBuffer);

        if (cullingResults.lightAndReflectionProbeIndexCount >= 1)
        {
            lightIndicesBuffer = new ComputeBuffer(cullingResults.lightAndReflectionProbeIndexCount, 4);
            cullingResults.FillLightAndReflectionProbeIndices(lightIndicesBuffer);
            ShaderInput.SetLightIndices(buffer, lightIndicesBuffer);
        }

        SubmitBuffer(ref context, buffer);
    }
Example #19
0
 void OnExpanded(MouseDownEvent evt, ShaderInput input)
 {
     m_ExpandedInputs[input] = !m_InputRows[input.guid].expanded;
 }
Example #20
0
        void AddInputRow(ShaderInput input, bool create = false, int index = -1)
        {
            if (m_InputRows.ContainsKey(input.guid))
            {
                return;
            }

            if (create)
            {
                m_Graph.SanitizeGraphInputName(input);
            }

            if (index < 0)
            {
                index = m_InputRows.Count;
            }

            BlackboardField field = null;
            BlackboardRow   row   = null;

            switch (input)
            {
            case AbstractShaderProperty property:
            {
                var icon = (m_Graph.isSubGraph || (property.isExposable && property.generatePropertyBlock)) ? exposedIcon : null;
                field = new BlackboardField(icon, property.displayName, property.propertyType.ToString())
                {
                    userData = property
                };
                var propertyView = new BlackboardFieldPropertyView(field, m_Graph, property);
                row = new BlackboardRow(field, propertyView)
                {
                    userData = input
                };
                if (index == m_PropertySection.childCount)
                {
                    m_PropertySection.Add(row);
                }
                else
                {
                    m_PropertySection.Insert(index, row);
                }
                break;
            }

            default:
                throw new ArgumentOutOfRangeException();
            }

            if (field == null || row == null)
            {
                return;
            }

            var pill = row.Q <Pill>();

            pill.RegisterCallback <MouseEnterEvent>(evt => OnMouseHover(evt, input));
            pill.RegisterCallback <MouseLeaveEvent>(evt => OnMouseHover(evt, input));
            pill.RegisterCallback <DragUpdatedEvent>(OnDragUpdatedEvent);

            var expandButton = row.Q <Button>("expandButton");

            expandButton.RegisterCallback <MouseDownEvent>(evt => OnExpanded(evt, input), TrickleDown.TrickleDown);

            m_InputRows[input.guid]          = row;
            m_InputRows[input.guid].expanded = SessionState.GetBool(input.guid.ToString(), true);

            if (create)
            {
                row.expanded = true;
                m_Graph.owner.RegisterCompleteObjectUndo("Create Graph Input");
                m_Graph.AddGraphInput(input);
                field.OpenTextEditor();
            }
        }
Example #21
0
        void AddInputRow(ShaderInput input, bool addToGraph = false, int index = -1)
        {
            if (m_InputRows.ContainsKey(input))
            {
                return;
            }

            if (addToGraph)
            {
                m_Graph.owner.RegisterCompleteObjectUndo("Create Graph Input");

                // this pathway is mostly used for adding newly inputs to the graph
                // so this is setting up the default state for those inputs
                // here we flag it exposed, if the input type is exposable
                input.generatePropertyBlock = input.isExposable;

                m_Graph.AddGraphInput(input);       // TODO: index after currently selected property
            }

            BlackboardFieldView field = null;
            BlackboardRow       row   = null;

            switch (input)
            {
            case AbstractShaderProperty property:
            {
                var icon = (m_Graph.isSubGraph || property.isExposed) ? exposedIcon : null;
                field = new BlackboardFieldView(m_Graph, property, icon, property.displayName, property.GetPropertyTypeString())
                {
                    userData = property
                };
                field.RegisterCallback <AttachToPanelEvent>(UpdateSelectionAfterUndoRedo);
                property.onBeforeVersionChange += (_) => m_Graph.owner.RegisterCompleteObjectUndo($"Change {property.displayName} Version");
                void UpdateField()
                {
                    field.typeText = property.GetPropertyTypeString();
                    field.InspectorUpdateTrigger();
                }

                property.onAfterVersionChange += UpdateField;
                row = new BlackboardRow(field, null);

                if (index < 0 || index > m_InputRows.Count)
                {
                    index = m_InputRows.Count;
                }

                if (index == m_InputRows.Count)
                {
                    m_PropertySection.Add(row);
                }
                else
                {
                    m_PropertySection.Insert(index, row);
                }

                break;
            }

            case ShaderKeyword keyword:
            {
                var icon = (m_Graph.isSubGraph || keyword.isExposed) ? exposedIcon : null;

                string typeText = keyword.keywordType.ToString() + " Keyword";
                typeText = keyword.isBuiltIn ? "Built-in " + typeText : typeText;

                field = new BlackboardFieldView(m_Graph, keyword, icon, keyword.displayName, typeText)
                {
                    userData = keyword
                };
                field.RegisterCallback <AttachToPanelEvent>(UpdateSelectionAfterUndoRedo);
                row = new BlackboardRow(field, null);

                if (index < 0 || index > m_InputRows.Count)
                {
                    index = m_InputRows.Count;
                }

                if (index == m_InputRows.Count)
                {
                    m_KeywordSection.Add(row);
                }
                else
                {
                    m_KeywordSection.Insert(index, row);
                }

                break;
            }

            default:

                throw new ArgumentOutOfRangeException();
            }

            field.RegisterCallback <MouseEnterEvent>(evt => OnMouseHover(evt, input));
            field.RegisterCallback <MouseLeaveEvent>(evt => OnMouseHover(evt, input));
            field.RegisterCallback <DragUpdatedEvent>(OnDragUpdatedEvent);
            // These callbacks are used for the property dragging scroll behavior
            field.RegisterCallback <DragEnterEvent>(evt => blackboard.ShowScrollBoundaryRegions());
            field.RegisterCallback <DragExitedEvent>(evt => blackboard.HideScrollBoundaryRegions());

            // Removing the expand button from the blackboard, its added by default
            var expandButton = row.Q <Button>("expandButton");

            expandButton.RemoveFromHierarchy();

            m_InputRows[input] = row;

            if (!addToGraph)
            {
                m_InputRows[input].expanded = SessionState.GetBool($"Unity.ShaderGraph.Input.{input.objectId}.isExpanded", false);
            }
            else
            {
                row.expanded = true;
                field.OpenTextEditor();
                if (input as ShaderKeyword != null)
                {
                    m_Graph.OnKeywordChangedNoValidate();
                }
            }
        }
Example #22
0
 public abstract void BuildCustomFields(ShaderInput input);
Example #23
0
 public BlackboardFieldKeywordView(BlackboardField blackboardField, GraphData graph, ShaderInput input)
     : base(blackboardField, graph, input)
 {
 }
Example #24
0
 public BlackboardRow GetBlackboardRow(ShaderInput input)
 {
     return(m_InputRows[input]);
 }
Example #25
0
        void AddInputRow(ShaderInput input, bool create = false, int index = -1)
        {
            if (m_InputRows.ContainsKey(input))
            {
                return;
            }

            if (create)
            {
                m_Graph.SanitizeGraphInputName(input);
                input.generatePropertyBlock = input.isExposable;
            }

            BlackboardFieldView field = null;
            BlackboardRow       row   = null;

            switch (input)
            {
            case AbstractShaderProperty property:
            {
                var icon = (m_Graph.isSubGraph || (property.isExposable && property.generatePropertyBlock)) ? exposedIcon : null;
                field = new BlackboardFieldView(m_Graph, property, UpdateBlackboardView, icon, property.displayName, property.GetPropertyTypeString())
                {
                    userData = property
                };
                field.RegisterCallback <AttachToPanelEvent>(UpdateSelectionAfterUndoRedo);
                property.onBeforeVersionChange += (_) => m_Graph.owner.RegisterCompleteObjectUndo($"Change {property.displayName} Version");
                void UpdateField()
                {
                    field.typeText = property.GetPropertyTypeString();
                    field.InspectorUpdateTrigger();
                }

                property.onAfterVersionChange += UpdateField;
                row = new BlackboardRow(field, null);

                if (index < 0 || index > m_InputRows.Count)
                {
                    index = m_InputRows.Count;
                }

                if (index == m_InputRows.Count)
                {
                    m_PropertySection.Add(row);
                }
                else
                {
                    m_PropertySection.Insert(index, row);
                }

                break;
            }

            case ShaderKeyword keyword:
            {
                var icon = (m_Graph.isSubGraph || (keyword.isExposable && keyword.generatePropertyBlock)) ? exposedIcon : null;

                string typeText = keyword.keywordType.ToString() + " Keyword";
                typeText = keyword.isBuiltIn ? "Built-in " + typeText : typeText;

                field = new BlackboardFieldView(m_Graph, keyword, UpdateBlackboardView, icon, keyword.displayName, typeText)
                {
                    userData = keyword
                };
                field.RegisterCallback <AttachToPanelEvent>(UpdateSelectionAfterUndoRedo);
                row = new BlackboardRow(field, null);

                if (index < 0 || index > m_InputRows.Count)
                {
                    index = m_InputRows.Count;
                }

                if (index == m_InputRows.Count)
                {
                    m_KeywordSection.Add(row);
                }
                else
                {
                    m_KeywordSection.Insert(index, row);
                }

                break;
            }

            default:
                throw new ArgumentOutOfRangeException();
            }

            field.RegisterCallback <MouseEnterEvent>(evt => OnMouseHover(evt, input));
            field.RegisterCallback <MouseLeaveEvent>(evt => OnMouseHover(evt, input));
            field.RegisterCallback <DragUpdatedEvent>(OnDragUpdatedEvent);

            // Removing the expand button from the blackboard, its added by default
            var expandButton = row.Q <Button>("expandButton");

            expandButton.RemoveFromHierarchy();

            m_InputRows[input] = row;

            if (!create)
            {
                m_InputRows[input].expanded = SessionState.GetBool($"Unity.ShaderGraph.Input.{input.objectId}.isExpanded", false);
            }
            else
            {
                row.expanded = true;
                m_Graph.owner.RegisterCompleteObjectUndo("Create Graph Input");
                m_Graph.AddGraphInput(input);
                field.OpenTextEditor();

                if (input as ShaderKeyword != null)
                {
                    m_Graph.OnKeywordChangedNoValidate();
                }
            }
        }
Example #26
0
	public void Load (string S){
		S = ShaderUtil.Sanitize(S);
		string[] parts = S.Split(new string[] { "#^" }, StringSplitOptions.None);
//		Debug.Log(parts[0]);
		if (CType == Types.Vec)
		Vector.Load(parts[0]);
		if (CType == Types.Float)
		float.TryParse(parts[0],out Float);
		if (CType == Types.Type)
		Type = int.Parse(parts[0]);
		if (CType == Types.Toggle)
		On = bool.Parse(parts[0]);
		if (CType == Types.Text)
		Text = parts[0];
		if (CType == Types.Texture){
			ImageGUID = parts[0];
			Image = (Texture2D)AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(ImageGUID),typeof(Texture2D));
		}
		if (CType == Types.Cubemap){
			CubeGUID = parts[0];
			Cube = (Cubemap)AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(CubeGUID),typeof(Cubemap));
		}
		//int ExpectedLength = 2;
		if (CType == Types.ObjectArray){
			Selected = int.Parse(parts[0]);
		}
		if (parts.Length>1){
			if (parts[1].Trim()!="AUTO"&&!parts[1].Trim().StartsWith("CC")){
				if (ShaderBase.Current.ShaderInputs.Count>int.Parse(parts[1].Trim()))
					Input = ShaderBase.Current.ShaderInputs[int.Parse(parts[1].Trim())];
			}
			//Debug.Log(parts[1].Trim());
			if (parts[1].Trim().StartsWith("CC")){
				ColorComponent = int.Parse(parts[1].Trim().Replace("CC",""));
			}
		}
		if (parts.Length==3){
			if (parts[2].Trim()!="AUTO"&&!parts[2].Trim().StartsWith("CC")){
				if (ShaderBase.Current.ShaderInputs.Count>int.Parse(parts[2].Trim()))
					Input = ShaderBase.Current.ShaderInputs[int.Parse(parts[2].Trim())];
			}
		}
		UpdateToInput();
	}
Example #27
0
 public void AddInput(ShaderInput input)
 {
     m_Inputs.Add(input);
 }
        internal static void InsertCopyPasteGraph(this MaterialGraphView graphView, CopyPasteGraph copyGraph)
        {
            if (copyGraph == null)
            {
                return;
            }

            // Keywords need to be tested against variant limit based on multiple factors
            bool keywordsDirty = false;

            // Make new inputs from the copied graph
            foreach (ShaderInput input in copyGraph.inputs)
            {
                ShaderInput copiedInput = input.Copy();
                graphView.graph.SanitizeGraphInputName(copiedInput);
                graphView.graph.SanitizeGraphInputReferenceName(copiedInput, input.overrideReferenceName);
                graphView.graph.AddGraphInput(copiedInput);

                switch (input)
                {
                case AbstractShaderProperty property:
                    // Update the property nodes that depends on the copied node
                    var dependentPropertyNodes = copyGraph.GetNodes <PropertyNode>().Where(x => x.propertyGuid == input.guid);
                    foreach (var node in dependentPropertyNodes)
                    {
                        node.owner        = graphView.graph;
                        node.propertyGuid = copiedInput.guid;
                    }
                    break;

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

                    // Pasting a new Keyword so need to test against variant limit
                    keywordsDirty = true;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            // Pasting a Sub Graph node that contains Keywords so need to test against variant limit
            foreach (SubGraphNode subGraphNode in copyGraph.GetNodes <SubGraphNode>())
            {
                if (subGraphNode.asset.keywords.Count > 0)
                {
                    keywordsDirty = true;
                }
            }

            // Test Keywords against variant limit
            if (keywordsDirty)
            {
                graphView.graph.OnKeywordChangedNoValidate();
            }

            using (var remappedNodesDisposable = ListPool <AbstractMaterialNode> .GetDisposable())
            {
                using (var remappedEdgesDisposable = ListPool <IEdge> .GetDisposable())
                {
                    var remappedNodes = remappedNodesDisposable.value;
                    var remappedEdges = remappedEdgesDisposable.value;
                    graphView.graph.PasteGraph(copyGraph, remappedNodes, remappedEdges);

                    if (graphView.graph.assetGuid != copyGraph.sourceGraphGuid)
                    {
                        // Compute the mean of the copied nodes.
                        Vector2 centroid = Vector2.zero;
                        var     count    = 1;
                        foreach (var node in remappedNodes)
                        {
                            var position = node.drawState.position.position;
                            centroid = centroid + (position - centroid) / count;
                            ++count;
                        }

                        // Get the center of the current view
                        var viewCenter = graphView.contentViewContainer.WorldToLocal(graphView.layout.center);

                        foreach (var node in remappedNodes)
                        {
                            var drawState    = node.drawState;
                            var positionRect = drawState.position;
                            var position     = positionRect.position;
                            position += viewCenter - centroid;
                            positionRect.position = position;
                            drawState.position    = positionRect;
                            node.drawState        = drawState;
                        }
                    }

                    // Add new elements to selection
                    graphView.ClearSelection();
                    graphView.graphElements.ForEach(element =>
                    {
                        if (element is Edge edge && remappedEdges.Contains(edge.userData as IEdge))
                        {
                            graphView.AddToSelection(edge);
                        }

                        if (element is IShaderNodeView nodeView && remappedNodes.Contains(nodeView.node))
                        {
                            graphView.AddToSelection((Node)nodeView);
                        }
                    });
                }
            }
        }
        public override void BuildCustomFields(ShaderInput input)
        {
            AbstractShaderProperty property = input as AbstractShaderProperty;

            if (property == null)
            {
                return;
            }

            switch (input)
            {
            case Vector1ShaderProperty vector1Property:
                BuildVector1PropertyField(vector1Property);
                break;

            case Vector2ShaderProperty vector2Property:
                BuildVector2PropertyField(vector2Property);
                break;

            case Vector3ShaderProperty vector3Property:
                BuildVector3PropertyField(vector3Property);
                break;

            case Vector4ShaderProperty vector4Property:
                BuildVector4PropertyField(vector4Property);
                break;

            case ColorShaderProperty colorProperty:
                BuildColorPropertyField(colorProperty);
                break;

            case TextureShaderProperty texture2DProperty:
                BuildTexture2DPropertyField(texture2DProperty);
                break;

            case Texture2DArrayShaderProperty texture2DArrayProperty:
                BuildTexture2DArrayPropertyField(texture2DArrayProperty);
                break;

            case Texture3DShaderProperty texture3DProperty:
                BuildTexture3DPropertyField(texture3DProperty);
                break;

            case CubemapShaderProperty cubemapProperty:
                BuildCubemapPropertyField(cubemapProperty);
                break;

            case BooleanShaderProperty booleanProperty:
                BuildBooleanPropertyField(booleanProperty);
                break;

            case Matrix2ShaderProperty matrix2Property:
                BuildMatrix2PropertyField(matrix2Property);
                break;

            case Matrix3ShaderProperty matrix3Property:
                BuildMatrix3PropertyField(matrix3Property);
                break;

            case Matrix4ShaderProperty matrix4Property:
                BuildMatrix4PropertyField(matrix4Property);
                break;

            case SamplerStateShaderProperty samplerStateProperty:
                BuildSamplerStatePropertyField(samplerStateProperty);
                break;

            case GradientShaderProperty gradientProperty:
                BuildGradientPropertyField(gradientProperty);
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            // Precision
            var precisionField = new EnumField((Enum)property.precision);

            precisionField.RegisterValueChangedCallback(evt =>
            {
                graph.owner.RegisterCompleteObjectUndo("Change Precision");
                if (property.precision == (Precision)evt.newValue)
                {
                    return;
                }

                property.precision = (Precision)evt.newValue;
                graph.ValidateGraph();
                precisionField.MarkDirtyRepaint();
                DirtyNodes();
            });
            AddRow("Precision", precisionField);
        }
Example #30
0
	public void UseEditingMouse(bool Paint){
		Rect rect = LastUsedRect;
		rect.x-=150-LabelOffset;
		ShaderInput OrigInput = Input;
		int OrigComponent = ColorComponent;
		if (EditingPopup>0f){
			
			if ((Event.current.type == EventType.MouseDown) &&(
			//!(new Rect(rect.x+110,rect.y,20,20).Contains(Event.current.mousePosition))&&
			!(new Rect(rect.x+110,rect.y-(20*EditingPopup)-20,110,40).Contains(Event.current.mousePosition))
			)){
				ShaderSandwich.ShaderVarEditing = null;
				GUI.changed = true;
			}
		
			if (Paint==true){
				if (EditingPopup>0f){
				//Debug.Log(rect);
					GUI.color = new Color(GUI.color.r,GUI.color.g,GUI.color.b,EditingPopup);
					ShaderUtil.BeginGroup(new Rect(rect.x+110,rect.y-(20*EditingPopup)-20,120,40),GUI.skin.button);

					GUIStyle ButtonStyle = new GUIStyle(GUI.skin.button);
					ButtonStyle.padding = new RectOffset(0,0,0,0);
					ButtonStyle.margin = new RectOffset(0,0,0,0);

					List<string> InputNamesList = new List<string>();
					List<int> InputIntsList = new List<int>();
					List<ShaderInput> InputInputsList = new List<ShaderInput>();
					List<int> InputComponentsList = new List<int>();
					InputNamesList.Add("-");
					InputIntsList.Add(0);
					InputInputsList.Add(null);
					InputComponentsList.Add(0);
					int ii = 1;
					foreach(ShaderInput SI in ShaderBase.Current.ShaderInputs){
						string SIType = "";
						if (SI.Type==0)
						SIType = "Tex";
						if (SI.Type==1)
						SIType = "Color";
						if (SI.Type==2)
						SIType = "Cube";
						if (SI.Type==3)
						SIType = "Float";
						if (SI.Type==4)
						SIType = "Range";
						if (
						(CType == Types.Float&&(SI.Type==3||SI.Type==4||SI.Type==1))||
						(CType == Types.Vec&&SI.Type==1)||
						(CType == Types.Texture&&SI.Type==0)||
						(CType == Types.Cubemap&&SI.Type==2)
						){
							if (CType == Types.Float&&SI.Type==1){
								InputNamesList.Add(SIType+": "+SI.VisName.Replace("-","/")+"/R");
								InputIntsList.Add(ii);
								InputInputsList.Add(SI);
								InputComponentsList.Add(0);
								ii++;
								InputNamesList.Add(SIType+": "+SI.VisName.Replace("-","/")+"/G");
								InputIntsList.Add(ii);
								InputInputsList.Add(SI);
								InputComponentsList.Add(1);
								ii++;
								InputNamesList.Add(SIType+": "+SI.VisName.Replace("-","/")+"/B");
								InputIntsList.Add(ii);
								InputInputsList.Add(SI);
								InputComponentsList.Add(2);
								ii++;
								InputNamesList.Add(SIType+": "+SI.VisName.Replace("-","/")+"/A");
								InputIntsList.Add(ii);
								InputInputsList.Add(SI);
								InputComponentsList.Add(3);
								ii++;
							}
							else{
								InputNamesList.Add(SIType+": "+SI.VisName.Replace("-","/"));
								InputIntsList.Add(ii);
								InputInputsList.Add(SI);
								InputComponentsList.Add(0);
								ii++;
							}
						}
						
					}
					string[] InputNames = InputNamesList.ToArray();
					int[] InputInts = InputIntsList.ToArray();
					//InputNames[ii] = "Add New Input";
					
					int IndexOfInput = 0;
					if (InputInputsList.IndexOf(Input)!=-1)
					IndexOfInput = InputInputsList.IndexOf(Input)+ColorComponent;
					//IndexOfInput = ShaderBase.Current.ShaderInputs.IndexOf(Input)+1+ColorComponent;
					//Debug.Log(IndexOfInput);
					SU.Label(new Rect(5,5,110,15),"Inputs:",11);
					//IndexOfInput = 5;
					//int SIS = InputInts[EditorGUI.Popup(new Rect(5,20,75,15), Array.IndexOf(InputInts,IndexOfInput), InputNames,GUI.skin.GetStyle("MiniPopup"))];
					//IntInput = EditorGUI.Popup(new Rect(5,20,75,15),IntInput, InputNames,GUI.skin.GetStyle("MiniPopup"));
					//int SIS = IntInput;
					int SIS = EditorGUI.IntPopup(new Rect(5,20,75,15), IndexOfInput, InputNames,InputInts,GUI.skin.GetStyle("MiniPopup"));
					
					if (SIS>=InputInputsList.Count)
					SIS = 0;
					
					if (SIS==0)
					Input = null;
					else{
						Input = InputInputsList[SIS];
						ColorComponent = InputComponentsList[SIS];
					}
					//Debug.Log(SIS);
					//Debug.Log(ColorComponent);
					//Input = ShaderBase.Current.ShaderInputs[SIS-1];
					if (GUI.Button(new Rect(80,20,15,15),ShaderSandwich.Plus,ButtonStyle)||ShaderUtil.MouseUpIn(new Rect(80,20,15,15))){
						AddInput();
						ShaderSandwich.ShaderVarEditing = null;
						ShaderSandwich.ValueChanged = true;
						GUI.changed = true;
						ShaderSandwich.Instance.RegenShaderPreview();
						ShaderSandwich.Instance.UpdateShaderPreview();
					}
					if (GUI.Button(new Rect(100,20,15,15),ShaderSandwich.CrossRed,ButtonStyle)||ShaderUtil.MouseUpIn(new Rect(100,20,15,15))){
						/*ShaderBase.Current.ShaderInputs.Remove(Input);
						List<ShaderVar> SVs = new List<ShaderVar>();
						foreach (ShaderLayer SL in ShaderUtil.GetAllLayers()){
							SL.UpdateShaderVars(true);
							SVs.AddRange(SL.ShaderVars);
						}
						SVs.AddRange(ShaderBase.Current.GetMyShaderVars());
						ShaderInput OldInput = Input;
						foreach(ShaderVar SV in SVs){
							if (SV.Input==OldInput)
							SV.Input = null;
						}*/
						if (Input!=null){
						ShaderInput OldInput = Input;
						Input = null;
						List<ShaderVar> SVs = new List<ShaderVar>();
						foreach (ShaderLayer SL in ShaderUtil.GetAllLayers()){
							SL.UpdateShaderVars(true);
							SVs.AddRange(SL.ShaderVars);
						}
						SVs.AddRange(ShaderBase.Current.GetMyShaderVars());
						OldInput.UsedCount = 0;
						foreach(ShaderVar SV in SVs){
							if (SV.Input==OldInput)
								OldInput.UsedCount+=1;
						}
						if (OldInput.UsedCount==0){
							ShaderBase.Current.ShaderInputs.Remove(OldInput);
							foreach(ShaderVar SV in SVs){
								if (SV.Input==OldInput)
									SV.Input = null;
							}
						}
						//UEObject.DestroyImmediate(SL,false);
						ShaderSandwich.ShaderVarEditing = null;
						EditorGUIUtility.ExitGUI();
						}
					}
					if (OrigInput!=Input||OrigComponent!=ColorComponent){
						UpdateToInput();
						GUI.changed = true;
						ShaderSandwich.Instance.ChangeSaveTemp(MyParent);
					}
					ShaderUtil.EndGroup();
				}

			}
		}
	}
Example #31
0
	public ShaderInput AddInput(){
		Input = ShaderInput.CreateInstance<ShaderInput>();
		Input.AutoCreated = true;
		//Debug.Log(MyParent);
		if (MyParent!=null)
		Input.VisName = MyParent.Name.Text+" - "+Name;
		else
		Input.VisName = Name;
		ShaderBase.Current.ShaderInputs.Add(Input);
		ShaderBase.Current.RecalculateAutoInputs();
		Input.Number = Float;
		Input.Range0 = Range0;
		Input.Range1 = Range1;
		Input.Color = Vector;

		if (CType==Types.Vec)
		Input.Type=1;
		if (CType==Types.Float)
		if (NoSlider==false)
		Input.Type=4;
		else
		Input.Type=3;
		

		if (CType==Types.Texture){
			Input.Image = Image;
			Input.ImageGUID = ImageGUID;
			Input.Type = 0;
		}
		if (CType==Types.Cubemap){
			Input.Cube = Cube;
			Input.CubeGUID = CubeGUID;
			Input.Type = 2;
		}
		return Input;
	}
        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();
        }
 public BlackboardFieldPropertyView(BlackboardField blackboardField, GraphData graph, ShaderInput input)
     : base(blackboardField, graph, input)
 {
 }