Example #1
0
        void RenderPreview(PreviewRenderData renderData, Mesh mesh, Matrix4x4 transform)
        {
            var node = renderData.shaderData.node;

            Assert.IsTrue((node != null && node.hasPreview && node.previewExpanded) || node == masterRenderData?.shaderData?.node);

            if (renderData.shaderData.hasError)
            {
                renderData.texture = m_ErrorTexture;
                return;
            }

            var previousRenderTexture = RenderTexture.active;

            //Temp workaround for alpha previews...
            var temp = RenderTexture.GetTemporary(renderData.renderTexture.descriptor);

            RenderTexture.active = temp;
            Graphics.Blit(Texture2D.whiteTexture, temp, m_SceneResources.checkerboardMaterial);

            m_SceneResources.camera.targetTexture = temp;
            Graphics.DrawMesh(mesh, transform, renderData.shaderData.mat, 1, m_SceneResources.camera, 0, null, ShadowCastingMode.Off, false, null, false);

            var previousUseSRP = Unsupported.useScriptableRenderPipeline;

            Unsupported.useScriptableRenderPipeline = renderData.shaderData.node is IMasterNode;
            m_SceneResources.camera.Render();
            Unsupported.useScriptableRenderPipeline = previousUseSRP;

            Graphics.Blit(temp, renderData.renderTexture, m_SceneResources.blitNoAlphaMaterial);
            RenderTexture.ReleaseTemporary(temp);

            RenderTexture.active = previousRenderTexture;
            renderData.texture   = renderData.renderTexture;
        }
Example #2
0
        void DestroyPreview(Identifier nodeId)
        {
            var renderData = Get(m_RenderDatas, nodeId);

            if (renderData == null)
            {
                return;
            }

            DestroyRenderData(renderData);

            Set(m_RenderDatas, nodeId, null);
            Set(m_Identifiers, nodeId, default(Identifier));

            // Check if we're destroying the shader data used by the master preview
            if (masterRenderData == renderData)
            {
                m_MasterRenderData = null;
                if (!m_Graph.isSubGraph && renderData.shaderData.node.guid != m_Graph.activeOutputNodeGuid)
                {
                    AddPreview(m_Graph.outputNode);
                }

                if (onPrimaryMasterChanged != null)
                {
                    onPrimaryMasterChanged();
                }
            }
        }
Example #3
0
        void AddPreview(INode node)
        {
            var shaderData = new PreviewShaderData
            {
                node = node
            };
            var renderData = new PreviewRenderData
            {
                shaderData    = shaderData,
                renderTexture = new RenderTexture(200, 200, 16, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default)
                {
                    hideFlags = HideFlags.HideAndDontSave
                }
            };

            renderData.renderTexture.Create();
            Set(m_Identifiers, node.tempId, node.tempId);
            Set(m_RenderDatas, node.tempId, renderData);
            m_DirtyShaders.Add(node.tempId.index);
            node.RegisterCallback(OnNodeModified);
            if (node.RequiresTime())
            {
                m_TimeDependentPreviews.Add(node.tempId.index);
            }

            var masterNode = node as IMasterNode;

            if (masterRenderData.shaderData == null && masterNode != null)
            {
                masterRenderData.shaderData = shaderData;
            }
        }
Example #4
0
        public PreviewManager(AbstractMaterialGraph graph)
        {
            m_Graph           = graph;
            m_PreviewMaterial = new Material(Shader.Find("Unlit/Color"))
            {
                hideFlags = HideFlags.HideInHierarchy
            };
            m_PreviewMaterial.hideFlags = HideFlags.HideAndDontSave;
            m_PreviewPropertyBlock      = new MaterialPropertyBlock();
            m_ErrorTexture = new Texture2D(2, 2);
            m_ErrorTexture.SetPixel(0, 0, Color.magenta);
            m_ErrorTexture.SetPixel(0, 1, Color.black);
            m_ErrorTexture.SetPixel(1, 0, Color.black);
            m_ErrorTexture.SetPixel(1, 1, Color.magenta);
            m_ErrorTexture.filterMode = FilterMode.Point;
            m_ErrorTexture.Apply();
            m_SceneResources        = new PreviewSceneResources();
            m_ColorShader           = ShaderUtil.CreateShaderAsset(k_EmptyShader);
            m_ColorShader.hideFlags = HideFlags.HideAndDontSave;
            m_MasterRenderData      = new PreviewRenderData
            {
                renderTexture = new RenderTexture(400, 400, 16, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default)
                {
                    hideFlags = HideFlags.HideAndDontSave
                }
            };
            m_MasterRenderData.renderTexture.Create();

            foreach (var node in m_Graph.GetNodes <INode>())
            {
                AddPreview(node);
            }
        }
Example #5
0
        void UpdateShaders()
        {
            using (UpdateShadersMarker.Auto())
            {
                ProcessCompletedShaderCompilations();

                if (m_NodesShaderChanged.Count > 0)
                {
                    // nodes with shader changes cause all downstream nodes to need recompilation
                    PropagateNodes(m_NodesShaderChanged, PropagationDirection.Downstream, m_NodesNeedsRecompile);
                    m_NodesShaderChanged.Clear();
                }

                // if there's nothing to update, or if too many nodes are still compiling, then just return
                if ((m_NodesNeedsRecompile.Count == 0) || (m_NodesCompiling.Count >= m_MaxNodesCompiling))
                {
                    return;
                }

                // flag all nodes in m_NodesNeedRecompile as having out of date textures, and redraw them
                foreach (var node in m_NodesNeedsRecompile)
                {
                    PreviewRenderData previewRendererData = GetPreviewRenderData(node);
                    if ((previewRendererData != null) && !previewRendererData.shaderData.isOutOfDate)
                    {
                        previewRendererData.shaderData.isOutOfDate = true;
                        previewRendererData.NotifyPreviewChanged();
                    }
                }

                InitializeSRPIfNeeded();    // SRP must be initialized to compile master node previews

                KickOffShaderCompilations();
            }
        }
Example #6
0
        void RenderPreview(PreviewRenderData renderData, Mesh mesh, Matrix4x4 transform)
        {
            m_PreviewPropertyBlock.SetFloat(m_OutputIdName, renderData.shaderData.node.tempId.index);
            if (m_PreviewMaterial.shader != renderData.shaderData.shader)
            {
                m_PreviewMaterial.shader = renderData.shaderData.shader;
            }
            var previousRenderTexure = RenderTexture.active;


            //Temp workaround for alpha previews...
            var temp = RenderTexture.GetTemporary(renderData.renderTexture.descriptor);

            RenderTexture.active = temp;
            GL.Clear(true, true, Color.black);
            Graphics.Blit(Texture2D.whiteTexture, temp, m_SceneResources.checkerboardMaterial);

            m_SceneResources.camera.targetTexture = temp;
            Graphics.DrawMesh(mesh, transform, m_PreviewMaterial, 1, m_SceneResources.camera, 0, m_PreviewPropertyBlock, ShadowCastingMode.Off, false, null, false);

            var previousUseSRP = Unsupported.useScriptableRenderPipeline;

            Unsupported.useScriptableRenderPipeline = renderData.shaderData.node is IMasterNode;
            m_SceneResources.camera.Render();
            Unsupported.useScriptableRenderPipeline = previousUseSRP;

            Graphics.Blit(temp, renderData.renderTexture, m_SceneResources.blitNoAlphaMaterial);
            RenderTexture.ReleaseTemporary(temp);

            RenderTexture.active = previousRenderTexure;
            renderData.texture   = renderData.renderTexture;
        }
Example #7
0
        void InitializeSRPIfNeeded()
        {
            if ((Shader.globalRenderPipeline != null) && (Shader.globalRenderPipeline.Length > 0))
            {
                return;
            }

            // issue a dummy SRP render to force SRP initialization, use the master node texture
            PreviewRenderData renderData = m_MasterRenderData;
            var previousRenderTexture    = RenderTexture.active;

            //Temp workaround for alpha previews...
            var temp = RenderTexture.GetTemporary(renderData.renderTexture.descriptor);

            RenderTexture.active = temp;
            Graphics.Blit(Texture2D.whiteTexture, temp, m_SceneResources.checkerboardMaterial);

            m_SceneResources.camera.targetTexture = temp;

            var previousUseSRP = Unsupported.useScriptableRenderPipeline;

            Unsupported.useScriptableRenderPipeline = true;
            m_SceneResources.camera.Render();
            Unsupported.useScriptableRenderPipeline = previousUseSRP;

            RenderTexture.ReleaseTemporary(temp);

            RenderTexture.active = previousRenderTexture;
        }
Example #8
0
        void DestroyPreview(Identifier nodeId)
        {
            var renderData = Get(m_RenderDatas, nodeId);

            // Check if we're destroying the shader data used by the master preview
            if (masterRenderData == renderData)
            {
                m_MasterRenderData =
                    m_RenderDatas.FirstOrDefault(x => x?.shaderData.node is IMasterNode && x != renderData);
                ResizeMasterPreview(new Vector2(400, 400));

                if (m_MasterRenderData != null)
                {
                    m_NodesToUpdate.Add(m_MasterRenderData.shaderData.node);
                }

                if (onPrimaryMasterChanged != null)
                {
                    onPrimaryMasterChanged();
                }
            }

            DestroyRenderData(renderData);

            Set(m_RenderDatas, nodeId, null);
            Set(m_Identifiers, nodeId, default(Identifier));
        }
Example #9
0
        void DestroyPreview(string nodeId)
        {
            if (!m_RenderDatas.TryGetValue(nodeId, out var renderData))
            {
                return;
            }

            DestroyRenderData(renderData);
            m_RenderDatas.Remove(nodeId);

            // Check if we're destroying the shader data used by the master preview
            if (masterRenderData == renderData)
            {
                m_MasterRenderData = null;
                if (!m_Graph.isSubGraph && renderData.shaderData.node != m_Graph.outputNode)
                {
                    AddPreview(m_Graph.outputNode);
                }

                if (onPrimaryMasterChanged != null)
                {
                    onPrimaryMasterChanged();
                }
            }
        }
Example #10
0
        void BeginCompile(PreviewRenderData renderData, string shaderStr, int shaderPass)
        {
            var shaderData = renderData.shaderData;

            ShaderUtil.UpdateShaderAsset(shaderData.shader, shaderStr, false);
            ShaderUtil.CompilePass(shaderData.mat, shaderPass);
            shaderData.isCompiling = true;
            renderData.NotifyPreviewChanged();
        }
Example #11
0
        void AddPreview(AbstractMaterialNode node)
        {
            var isMaster = false;

            if (node is IMasterNode || node is SubGraphOutputNode)
            {
                // we don't build preview render data for output nodes that aren't the active output node
                if (masterRenderData != null || (node is IMasterNode && node != node.owner.outputNode))
                {
                    return;
                }

                isMaster = true;
            }

            var renderData = new PreviewRenderData
            {
                renderTexture =
                    new RenderTexture(200, 200, 16, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default)
                {
                    hideFlags = HideFlags.HideAndDontSave
                }
            };

            if (isMaster)
            {
                m_MasterRenderData             = renderData;
                renderData.renderTexture.width = renderData.renderTexture.height = 400;
            }

            renderData.renderTexture.Create();

            var shaderData = new PreviewShaderData
            {
                node            = node,
                passesCompiling = 0,
                isOutOfDate     = true,
                hasError        = false,
            };

            renderData.shaderData = shaderData;

            m_RenderDatas.Add(node.objectId, renderData);
            node.RegisterCallback(OnNodeModified);

            if (node.RequiresTime())
            {
                m_RefreshTimedNodes = true;
            }

            if (m_MasterRenderData == renderData && onPrimaryMasterChanged != null)
            {
                onPrimaryMasterChanged();
            }

            m_NodesNeedsRecompile.Add(node);
        }
Example #12
0
        public PreviewRenderData GetPreviewRenderData(AbstractMaterialNode node)
        {
            PreviewRenderData result = null;

            if (node != null)
            {
                m_RenderDatas.TryGetValue(node.objectId, out result);
            }
            return(result);
        }
Example #13
0
        void BeginCompile(PreviewRenderData renderData, string shaderStr)
        {
            var shaderData = renderData.shaderData;

            ShaderUtil.ClearCachedData(shaderData.shader);
            ShaderUtil.UpdateShaderAsset(shaderData.shader, shaderStr, false);
            for (var i = 0; i < shaderData.mat.passCount; i++)
            {
                ShaderUtil.CompilePass(shaderData.mat, i);
            }
            shaderData.isCompiling = true;
            renderData.NotifyPreviewChanged();
        }
Example #14
0
        void AddPreview(AbstractMaterialNode node)
        {
            var renderData = new PreviewRenderData
            {
                renderTexture =
                    new RenderTexture(200, 200, 16, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default)
                {
                    hideFlags = HideFlags.HideAndDontSave
                }
            };

            if (masterRenderData == null && (node is IMasterNode || node is SubGraphOutputNode))
            {
                m_MasterRenderData             = renderData;
                renderData.renderTexture.width = renderData.renderTexture.height = 400;
            }

            renderData.renderTexture.Create();

            var shaderData = new PreviewShaderData
            {
                node        = node,
                isCompiling = false,
                hasError    = false,
                shader      = ShaderUtil.CreateShaderAsset(k_EmptyShader, false)
            };

            shaderData.shader.hideFlags = HideFlags.HideAndDontSave;
            shaderData.mat = new Material(shaderData.shader)
            {
                hideFlags = HideFlags.HideAndDontSave
            };
            renderData.shaderData = shaderData;

            Set(m_Identifiers, node.tempId, node.tempId);
            Set(m_RenderDatas, node.tempId, renderData);
            node.RegisterCallback(OnNodeModified);

            if (node.RequiresTime())
            {
                m_RefreshTimedNodes = true;
            }

            if (m_MasterRenderData == renderData && onPrimaryMasterChanged != null)
            {
                onPrimaryMasterChanged();
            }

            m_NodesToUpdate.Add(node);
        }
Example #15
0
        public void Dispose()
        {
            foreach (var portInputView in m_PortInputContainer.OfType <PortInputView>())
            {
                portInputView.Dispose();
            }

            node = null;
            if (m_PreviewRenderData != null)
            {
                m_PreviewRenderData.onPreviewChanged -= UpdatePreviewTexture;
                m_PreviewRenderData = null;
            }
        }
Example #16
0
        public void Dispose()
        {
            foreach (var portInputView in m_PortInputContainer.Children().OfType <PortInputView>())
            {
                portInputView.Dispose();
            }

            node = null;
            ((VisualElement)this).userData = null;
            if (m_PreviewRenderData != null)
            {
                m_PreviewRenderData.onPreviewChanged -= UpdatePreviewTexture;
                m_PreviewRenderData = null;
            }
        }
Example #17
0
        void DestroyRenderData(PreviewRenderData renderData)
        {
            if (renderData.shaderData.shader != null && renderData.shaderData.shader != m_UberShader)
            {
                Object.DestroyImmediate(renderData.shaderData.shader, true);
            }
            if (renderData.renderTexture != null)
            {
                Object.DestroyImmediate(renderData.renderTexture, true);
            }
            var node = renderData.shaderData.node;

            if (node != null)
            {
                node.onModified -= OnNodeModified;
            }
        }
Example #18
0
        void DestroyRenderData(PreviewRenderData renderData)
        {
            if (renderData.shaderData != null &&
                renderData.shaderData.shader != null)
            {
                Object.DestroyImmediate(renderData.shaderData.shader, true);
            }
            if (renderData.renderTexture != null)
            {
                Object.DestroyImmediate(renderData.renderTexture, true);
            }

            if (renderData.shaderData != null && renderData.shaderData.node != null)
            {
                renderData.shaderData.node.UnregisterCallback(OnNodeModified);
            }
        }
        public void Dispose()
        {
            foreach (var attacher in m_Attachers)
            {
                ((PortInputView)attacher.element).Dispose();
                attacher.Detach();
                attacher.element.parent.Remove(attacher.element);
            }
            m_Attachers.Clear();

            node = null;
            if (m_PreviewRenderData != null)
            {
                m_PreviewRenderData.onPreviewChanged -= UpdatePreviewTexture;
                m_PreviewRenderData = null;
            }
        }
Example #20
0
        void CollectShaderProperties(AbstractMaterialNode node, PreviewRenderData renderData)
        {
            m_PreviewProperties.Clear();
            m_PropertyNodes.Clear();

            m_PropertyNodes.Add(node);
            PropagateNodeList(m_PropertyNodes, PropagationDirection.Upstream);

            foreach (var propNode in m_PropertyNodes)
            {
                propNode.CollectPreviewMaterialProperties(m_PreviewProperties);
            }

            foreach (var prop in m_Graph.properties)
            {
                m_PreviewProperties.Add(prop.GetPreviewMaterialProperty());
            }

            foreach (var previewProperty in m_PreviewProperties)
            {
                renderData.shaderData.mat.SetPreviewProperty(previewProperty);
            }
        }
Example #21
0
        void AddPreview(INode node)
        {
            var shaderData = new PreviewShaderData
            {
                node   = node,
                shader = m_UberShader
            };
            var renderData = new PreviewRenderData
            {
                shaderData    = shaderData,
                renderTexture = new RenderTexture(200, 200, 16, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default)
                {
                    hideFlags = HideFlags.HideAndDontSave
                },
            };

            renderData.renderTexture.Create();
            Set(m_Identifiers, node.tempId, node.tempId);
            Set(m_RenderDatas, node.tempId, renderData);
            node.RegisterCallback(OnNodeModified);

            var isMaster = node is IMasterNode;

            if (masterRenderData.shaderData == null &&
                (isMaster || node is SubGraphOutputNode))
            {
                masterRenderData.shaderData = shaderData;
                // If it's actually the master, clear the shader since it will be assigned
                // later. SubGraphOutputNode still needs the UberShader.
                if (isMaster)
                {
                    masterRenderData.shaderData.shader = null;
                }
            }

            m_NeedShaderUpdate = true;
        }
Example #22
0
        void BeginCompile(PreviewRenderData renderData, string shaderStr)
        {
            using (BeginCompileMarker.Auto())
            {
                var shaderData = renderData.shaderData;

                // want to ensure this so we don't get confused with multiple compile versions in flight
                Assert.IsTrue(shaderData.passesCompiling == 0);

                if (shaderData.shader == null)
                {
                    shaderData.shader           = ShaderUtil.CreateShaderAsset(shaderStr, false);
                    shaderData.shader.hideFlags = HideFlags.HideAndDontSave;
                }
                else
                {
                    ShaderUtil.ClearCachedData(shaderData.shader);
                    ShaderUtil.UpdateShaderAsset(shaderData.shader, shaderStr, false);
                }

                if (shaderData.mat == null)
                {
                    shaderData.mat = new Material(shaderData.shader)
                    {
                        hideFlags = HideFlags.HideAndDontSave
                    };
                }

                shaderData.passesCompiling = shaderData.mat.passCount;
                for (var i = 0; i < shaderData.mat.passCount; i++)
                {
                    ShaderUtil.CompilePass(shaderData.mat, i);
                }
                m_NodesCompiling.Add(shaderData.node);
            }
        }
Example #23
0
        public void Initialize(AbstractMaterialNode inNode, PreviewManager previewManager, IEdgeConnectorListener connectorListener, MaterialGraphView graphView)
        {
            styleSheets.Add(Resources.Load <StyleSheet>("Styles/MaterialNodeView"));
            styleSheets.Add(Resources.Load <StyleSheet>($"Styles/ColorMode"));
            AddToClassList("MaterialNode");

            if (inNode == null)
            {
                return;
            }

            var contents = this.Q("contents");

            m_GraphView = graphView;
            mainContainer.style.overflow = StyleKeyword.None;    // Override explicit style set in base class
            m_ConnectorListener          = connectorListener;
            node        = inNode;
            viewDataKey = node.objectId;
            UpdateTitle();

            // Add disabled overlay
            Add(new VisualElement()
            {
                name = "disabledOverlay", pickingMode = PickingMode.Ignore
            });

            // Add controls container
            var controlsContainer = new VisualElement {
                name = "controls"
            };

            {
                m_ControlsDivider = new VisualElement {
                    name = "divider"
                };
                m_ControlsDivider.AddToClassList("horizontal");
                controlsContainer.Add(m_ControlsDivider);
                m_ControlItems = new VisualElement {
                    name = "items"
                };
                controlsContainer.Add(m_ControlItems);

                // Instantiate control views from node
                foreach (var propertyInfo in node.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
                {
                    foreach (IControlAttribute attribute in propertyInfo.GetCustomAttributes(typeof(IControlAttribute), false))
                    {
                        m_ControlItems.Add(attribute.InstantiateControl(node, propertyInfo));
                    }
                }
            }
            if (m_ControlItems.childCount > 0)
            {
                contents.Add(controlsContainer);
            }

            // Add dropdowns container
            var dropdownContainer = new VisualElement {
                name = "dropdowns"
            };

            {
                m_DropdownsDivider = new VisualElement {
                    name = "divider"
                };
                m_DropdownsDivider.AddToClassList("horizontal");
                dropdownContainer.Add(m_DropdownsDivider);
                m_DropdownItems = new VisualElement {
                    name = "items"
                };
                dropdownContainer.Add(m_DropdownItems);
                UpdateDropdownEntries();
            }
            if (m_DropdownItems.childCount > 0)
            {
                contents.Add(dropdownContainer);
            }

            if (node.hasPreview)
            {
                // Add actual preview which floats on top of the node
                m_PreviewContainer = new VisualElement
                {
                    name        = "previewContainer",
                    style       = { overflow = Overflow.Hidden },
                    pickingMode = PickingMode.Ignore
                };
                m_PreviewImage = new Image
                {
                    name        = "preview",
                    pickingMode = PickingMode.Ignore,
                    image       = Texture2D.whiteTexture,
                };
                {
                    // Add preview collapse button on top of preview
                    var collapsePreviewButton = new VisualElement {
                        name = "collapse"
                    };
                    collapsePreviewButton.Add(new VisualElement {
                        name = "icon"
                    });
                    collapsePreviewButton.AddManipulator(new Clickable(() =>
                    {
                        SetPreviewExpandedStateOnSelection(false);
                    }));
                    m_PreviewImage.Add(collapsePreviewButton);
                }
                m_PreviewContainer.Add(m_PreviewImage);

                // Hook up preview image to preview manager
                m_PreviewRenderData = previewManager.GetPreviewRenderData(inNode);
                m_PreviewRenderData.onPreviewChanged += UpdatePreviewTexture;
                UpdatePreviewTexture();

                // Add fake preview which pads out the node to provide space for the floating preview
                m_PreviewFiller = new VisualElement {
                    name = "previewFiller"
                };
                m_PreviewFiller.AddToClassList("expanded");
                {
                    var previewDivider = new VisualElement {
                        name = "divider"
                    };
                    previewDivider.AddToClassList("horizontal");
                    m_PreviewFiller.Add(previewDivider);

                    var expandPreviewButton = new VisualElement {
                        name = "expand"
                    };
                    expandPreviewButton.Add(new VisualElement {
                        name = "icon"
                    });
                    expandPreviewButton.AddManipulator(new Clickable(() =>
                    {
                        SetPreviewExpandedStateOnSelection(true);
                    }));
                    m_PreviewFiller.Add(expandPreviewButton);
                }
                contents.Add(m_PreviewFiller);

                UpdatePreviewExpandedState(node.previewExpanded);
            }

            base.expanded = node.drawState.expanded;
            AddSlots(node.GetSlots <MaterialSlot>());

            if (node is SubGraphNode)
            {
                RegisterCallback <MouseDownEvent>(OnSubGraphDoubleClick);
            }

            m_TitleContainer = this.Q("title");

            if (node is BlockNode blockData)
            {
                AddToClassList("blockData");
                m_TitleContainer.RemoveFromHierarchy();
            }
            else
            {
                SetPosition(new Rect(node.drawState.position.x, node.drawState.position.y, 0, 0));
            }

            // Update active state
            SetActive(node.isActive);

            // Register OnMouseHover callbacks for node highlighting
            RegisterCallback <MouseEnterEvent>(OnMouseHover);
            RegisterCallback <MouseLeaveEvent>(OnMouseHover);

            ShaderGraphPreferences.onAllowDeprecatedChanged += UpdateTitle;
        }
        public void Initialize(AbstractMaterialNode inNode, PreviewManager previewManager, IEdgeConnectorListener connectorListener)
        {
            AddToClassList("MaterialNode");

            if (inNode == null)
            {
                return;
            }

            m_ConnectorListener = connectorListener;
            node           = inNode;
            persistenceKey = node.guid.ToString();
            UpdateTitle();

            m_ControlsContainer = new VisualElement
            {
                name = "controls"
            };
            extensionContainer.Add(m_ControlsContainer);
            m_ControlsDivider = new VisualElement {
                name = "divider"
            };
            m_ControlsDivider.AddToClassList("horizontal");

            if (node.hasPreview)
            {
                m_PreviewContainer = new VisualElement {
                    name = "previewContainer"
                };
                m_PreviewContainer.AddToClassList("expanded");
                {
                    m_PreviewTextureView = new PreviewTextureView
                    {
                        name        = "preview",
                        pickingMode = PickingMode.Ignore,
                        image       = Texture2D.whiteTexture
                    };
                    m_PreviewRenderData = previewManager.GetPreview(inNode);
                    m_PreviewRenderData.onPreviewChanged += UpdatePreviewTexture;
                    UpdatePreviewTexture();

                    var collapsePreviewButton = new VisualElement {
                        name = "collapse"
                    };
                    collapsePreviewButton.Add(new VisualElement {
                        name = "icon"
                    });
                    collapsePreviewButton.AddManipulator(new Clickable(() =>
                    {
                        node.owner.owner.RegisterCompleteObjectUndo("Collapse Preview");
                        UpdatePreviewExpandedState(false);
                    }));
                    UpdatePreviewExpandedState(node.previewExpanded);
                    m_PreviewTextureView.Add(collapsePreviewButton);

                    var expandPreviewButton = new VisualElement {
                        name = "expand"
                    };
                    expandPreviewButton.Add(new VisualElement {
                        name = "icon"
                    });
                    expandPreviewButton.AddManipulator(new Clickable(() =>
                    {
                        node.owner.owner.RegisterCompleteObjectUndo("Expand Preview");
                        UpdatePreviewExpandedState(true);
                    }));
                    m_PreviewContainer.Add(expandPreviewButton);
                }

                extensionContainer.Add(m_PreviewContainer);
            }

            m_ControlViews = new List <VisualElement>();
            foreach (var propertyInfo in node.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
            {
                foreach (IControlAttribute attribute in propertyInfo.GetCustomAttributes(typeof(IControlAttribute), false))
                {
                    m_ControlViews.Add(attribute.InstantiateControl(node, propertyInfo));
                }
            }
            m_Attachers = new List <Attacher>(node.GetInputSlots <MaterialSlot>().Count());

            AddSlots(node.GetSlots <MaterialSlot>());
            UpdateSlotAttachers();
            base.expanded = node.drawState.expanded;
            RefreshExpandedState(); //This should not be needed. GraphView needs to improve the extension api here
            UpdatePortInputVisibilities();

            SetPosition(new Rect(node.drawState.position.x, node.drawState.position.y, 0, 0));
            UpdateControls();

            if (node is PreviewNode)
            {
                var resizeHandle = new Label {
                    name = "resize", text = ""
                };
                resizeHandle.AddManipulator(new Draggable(OnResize));
                Add(resizeHandle);
                UpdateSize();
            }
        }
Example #25
0
        void ProcessCompletedShaderCompilations()
        {
            // Check for shaders that finished compiling and set them to redraw
            using (ProcessCompletedShaderCompilationsMarker.Auto())
                using (var nodesCompiled = PooledHashSet <AbstractMaterialNode> .Get())
                {
                    foreach (var node in m_NodesCompiling)
                    {
                        PreviewRenderData renderData = GetPreviewRenderData(node);
                        PreviewShaderData shaderData = renderData.shaderData;
                        Assert.IsTrue(shaderData.passesCompiling > 0);

                        if (shaderData.passesCompiling != renderData.shaderData.mat.passCount)
                        {
                            // attempt to re-kick the compilation a few times
                            compileFailRekicks++;
                            if (compileFailRekicks <= 3)
                            {
                                renderData.shaderData.passesCompiling = 0;
                                m_NodesNeedsRecompile.Add(node);
                                nodesCompiled.Add(node);
                                continue;
                            }
                            else if (compileFailRekicks == 4)
                            {
                                Debug.LogWarning("Unexpected error in compiling preview shaders: some previews might not update. You can try to re-open the Shader Graph window, or select <b>Help > Report a Bug</b> in the menu and report this bug.");
                            }
                        }

                        // check that all passes have compiled
                        var allPassesCompiled = true;
                        for (var i = 0; i < renderData.shaderData.mat.passCount; i++)
                        {
                            if (!ShaderUtil.IsPassCompiled(renderData.shaderData.mat, i))
                            {
                                allPassesCompiled = false;
                                break;
                            }
                        }

                        if (!allPassesCompiled)
                        {
                            continue;
                        }

                        // Force the material to re-generate all it's shader properties, by reassigning the shader
                        renderData.shaderData.mat.shader      = renderData.shaderData.shader;
                        renderData.shaderData.passesCompiling = 0;
                        renderData.shaderData.isOutOfDate     = false;
                        CheckForErrors(renderData.shaderData);

                        nodesCompiled.Add(renderData.shaderData.node);

                        var masterNode = renderData.shaderData.node as IMasterNode;
                        masterNode?.ProcessPreviewMaterial(renderData.shaderData.mat);
                    }

                    // removed compiled nodes from compiling list
                    m_NodesCompiling.ExceptWith(nodesCompiled);

                    // and add them to the draw list
                    m_NodesToDraw.UnionWith(nodesCompiled);
                }
        }
Example #26
0
        public void Initialize(AbstractMaterialNode inNode, PreviewManager previewManager, IEdgeConnectorListener connectorListener, MaterialGraphView graphView)
        {
            styleSheets.Add(Resources.Load <StyleSheet>("Styles/MaterialNodeView"));
            styleSheets.Add(Resources.Load <StyleSheet>($"Styles/ColorMode"));
            AddToClassList("MaterialNode");

            if (inNode == null)
            {
                return;
            }

            var contents = this.Q("contents");

            m_GraphView = graphView;
            mainContainer.style.overflow = StyleKeyword.None;    // Override explicit style set in base class
            m_ConnectorListener          = connectorListener;
            node        = inNode;
            viewDataKey = node.objectId;
            UpdateTitle();

            // Add controls container
            var controlsContainer = new VisualElement {
                name = "controls"
            };

            {
                m_ControlsDivider = new VisualElement {
                    name = "divider"
                };
                m_ControlsDivider.AddToClassList("horizontal");
                controlsContainer.Add(m_ControlsDivider);
                m_ControlItems = new VisualElement {
                    name = "items"
                };
                controlsContainer.Add(m_ControlItems);

                // Instantiate control views from node
                foreach (var propertyInfo in node.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
                {
                    foreach (IControlAttribute attribute in propertyInfo.GetCustomAttributes(typeof(IControlAttribute), false))
                    {
                        m_ControlItems.Add(attribute.InstantiateControl(node, propertyInfo));
                    }
                }
            }
            if (m_ControlItems.childCount > 0)
            {
                contents.Add(controlsContainer);
            }

            if (node.hasPreview)
            {
                // Add actual preview which floats on top of the node
                m_PreviewContainer = new VisualElement
                {
                    name        = "previewContainer",
                    style       = { overflow = Overflow.Hidden },
                    pickingMode = PickingMode.Ignore
                };
                m_PreviewImage = new Image
                {
                    name        = "preview",
                    pickingMode = PickingMode.Ignore,
                    image       = Texture2D.whiteTexture,
                };
                {
                    // Add preview collapse button on top of preview
                    var collapsePreviewButton = new VisualElement {
                        name = "collapse"
                    };
                    collapsePreviewButton.Add(new VisualElement {
                        name = "icon"
                    });
                    collapsePreviewButton.AddManipulator(new Clickable(() =>
                    {
                        SetPreviewExpandedStateOnSelection(false);
                    }));
                    m_PreviewImage.Add(collapsePreviewButton);
                }
                m_PreviewContainer.Add(m_PreviewImage);

                // Hook up preview image to preview manager
                m_PreviewRenderData = previewManager.GetPreviewRenderData(inNode);
                m_PreviewRenderData.onPreviewChanged += UpdatePreviewTexture;
                UpdatePreviewTexture();

                // Add fake preview which pads out the node to provide space for the floating preview
                m_PreviewFiller = new VisualElement {
                    name = "previewFiller"
                };
                m_PreviewFiller.AddToClassList("expanded");
                {
                    var previewDivider = new VisualElement {
                        name = "divider"
                    };
                    previewDivider.AddToClassList("horizontal");
                    m_PreviewFiller.Add(previewDivider);

                    var expandPreviewButton = new VisualElement {
                        name = "expand"
                    };
                    expandPreviewButton.Add(new VisualElement {
                        name = "icon"
                    });
                    expandPreviewButton.AddManipulator(new Clickable(() =>
                    {
                        SetPreviewExpandedStateOnSelection(true);
                    }));
                    m_PreviewFiller.Add(expandPreviewButton);
                }
                contents.Add(m_PreviewFiller);

                UpdatePreviewExpandedState(node.previewExpanded);
            }

            base.expanded = node.drawState.expanded;
            AddSlots(node.GetSlots <MaterialSlot>());

            SetPosition(new Rect(node.drawState.position.x, node.drawState.position.y, 0, 0));

            if (node is SubGraphNode)
            {
                RegisterCallback <MouseDownEvent>(OnSubGraphDoubleClick);
            }

            m_TitleContainer = this.Q("title");

            if (node is IMasterNode)
            {
                AddToClassList("master");
                bool validTarget = false;
                foreach (Target activeTarget in node.owner.validTargets)
                {
                    //if we have a valid active target implementation and render pipeline, don't display the error
                    if (activeTarget.IsPipelineCompatible(GraphicsSettings.currentRenderPipeline))
                    {
                        validTarget = true;
                        break;
                    }
                }

                //if no active target implementations are valid with the current pipeline, display the error
                m_GraphView.graph.messageManager?.ClearAllFromProvider(this);
                if (!validTarget)
                {
                    m_GraphView.graph.messageManager?.AddOrAppendError(this, node.objectId,
                                                                       new ShaderMessage("The active Master Node is not compatible with the current Render Pipeline," +
                                                                                         " or no Render Pipeline is assigned." +
                                                                                         " Assign a Render Pipeline in the graphics settings that is compatible with this Master Node.",
                                                                                         ShaderCompilerMessageSeverity.Error));
                }
            }

            m_NodeSettingsView         = new NodeSettingsView();
            m_NodeSettingsView.visible = false;
            Add(m_NodeSettingsView);

            m_SettingsButton = new VisualElement {
                name = "settings-button"
            };
            m_SettingsButton.Add(new VisualElement {
                name = "icon"
            });

            m_Settings = new VisualElement();
            AddDefaultSettings();

            // Add Node type specific settings
            var nodeTypeSettings = node as IHasSettings;

            if (nodeTypeSettings != null)
            {
                m_Settings.Add(nodeTypeSettings.CreateSettingsElement());
            }

            // Add manipulators
            m_SettingsButton.AddManipulator(new Clickable(() =>
            {
                UpdateSettingsExpandedState();
            }));

            if (m_Settings.childCount > 0)
            {
                m_ButtonContainer = new VisualElement {
                    name = "button-container"
                };
                m_ButtonContainer.style.flexDirection = FlexDirection.Row;
                m_ButtonContainer.Add(m_SettingsButton);
                m_ButtonContainer.Add(m_CollapseButton);
                m_TitleContainer.Add(m_ButtonContainer);
            }

            // Register OnMouseHover callbacks for node highlighting
            RegisterCallback <MouseEnterEvent>(OnMouseHover);
            RegisterCallback <MouseLeaveEvent>(OnMouseHover);
        }
        public void Initialize(AbstractMaterialNode inNode, PreviewManager previewManager, IEdgeConnectorListener connectorListener)
        {
            AddStyleSheetPath("Styles/MaterialNodeView");
            AddToClassList("MaterialNode");

            if (inNode == null)
            {
                return;
            }

            var contents = this.Q("contents");

            m_ConnectorListener = connectorListener;
            node           = inNode;
            persistenceKey = node.guid.ToString();
            UpdateTitle();

            // Add controls container
            var controlsContainer = new VisualElement {
                name = "controls"
            };

            {
                m_ControlsDivider = new VisualElement {
                    name = "divider"
                };
                m_ControlsDivider.AddToClassList("horizontal");
                controlsContainer.Add(m_ControlsDivider);
                m_ControlItems = new VisualElement {
                    name = "items"
                };
                controlsContainer.Add(m_ControlItems);

                // Instantiate control views from node
                foreach (var propertyInfo in node.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
                {
                    foreach (IControlAttribute attribute in propertyInfo.GetCustomAttributes(typeof(IControlAttribute), false))
                    {
                        m_ControlItems.Add(attribute.InstantiateControl(node, propertyInfo));
                    }
                }
            }
            if (m_ControlItems.childCount > 0)
            {
                contents.Add(controlsContainer);
            }

            if (node.hasPreview)
            {
                // Add actual preview which floats on top of the node
                m_PreviewContainer = new VisualElement
                {
                    name            = "previewContainer",
                    clippingOptions = ClippingOptions.ClipAndCacheContents,
                    pickingMode     = PickingMode.Ignore
                };
                m_PreviewImage = new Image
                {
                    name        = "preview",
                    pickingMode = PickingMode.Ignore,
                    image       = Texture2D.whiteTexture,
                };
                {
                    // Add preview collapse button on top of preview
                    var collapsePreviewButton = new VisualElement {
                        name = "collapse"
                    };
                    collapsePreviewButton.Add(new VisualElement {
                        name = "icon"
                    });
                    collapsePreviewButton.AddManipulator(new Clickable(() =>
                    {
                        node.owner.owner.RegisterCompleteObjectUndo("Collapse Preview");
                        UpdatePreviewExpandedState(false);
                    }));
                    m_PreviewImage.Add(collapsePreviewButton);
                }
                m_PreviewContainer.Add(m_PreviewImage);

                // Hook up preview image to preview manager
                m_PreviewRenderData = previewManager.GetPreview(inNode);
                m_PreviewRenderData.onPreviewChanged += UpdatePreviewTexture;
                UpdatePreviewTexture();

                // Add fake preview which pads out the node to provide space for the floating preview
                m_PreviewFiller = new VisualElement {
                    name = "previewFiller"
                };
                m_PreviewFiller.AddToClassList("expanded");
                {
                    var previewDivider = new VisualElement {
                        name = "divider"
                    };
                    previewDivider.AddToClassList("horizontal");
                    m_PreviewFiller.Add(previewDivider);

                    var expandPreviewButton = new VisualElement {
                        name = "expand"
                    };
                    expandPreviewButton.Add(new VisualElement {
                        name = "icon"
                    });
                    expandPreviewButton.AddManipulator(new Clickable(() =>
                    {
                        node.owner.owner.RegisterCompleteObjectUndo("Expand Preview");
                        UpdatePreviewExpandedState(true);
                    }));
                    m_PreviewFiller.Add(expandPreviewButton);
                }
                contents.Add(m_PreviewFiller);

                UpdatePreviewExpandedState(node.previewExpanded);
            }

            // Add port input container, which acts as a pixel cache for all port inputs
            m_PortInputContainer = new VisualElement
            {
                name            = "portInputContainer",
                clippingOptions = ClippingOptions.ClipAndCacheContents,
                pickingMode     = PickingMode.Ignore
            };
            Add(m_PortInputContainer);

            AddSlots(node.GetSlots <MaterialSlot>());
            UpdatePortInputs();
            base.expanded = node.drawState.expanded;
            RefreshExpandedState(); //This should not be needed. GraphView needs to improve the extension api here
            UpdatePortInputVisibilities();

            SetPosition(new Rect(node.drawState.position.x, node.drawState.position.y, 0, 0));

            if (node is SubGraphNode)
            {
                RegisterCallback <MouseDownEvent>(OnSubGraphDoubleClick);
            }

            var masterNode = node as IMasterNode;

            if (masterNode != null)
            {
                if (!masterNode.IsPipelineCompatible(RenderPipelineManager.currentPipeline))
                {
                    IconBadge wrongPipeline = IconBadge.CreateError("The current render pipeline is not compatible with this node preview.");
                    Add(wrongPipeline);
                    VisualElement title = this.Q("title");
                    wrongPipeline.AttachTo(title, SpriteAlignment.LeftCenter);
                }
            }

            m_PortInputContainer.SendToBack();

            // Remove this after updated to the correct API call has landed in trunk. ------------
            VisualElement m_TitleContainer;
            VisualElement m_ButtonContainer;

            m_TitleContainer = this.Q("title");
            // -----------------------------------------------------------------------------------

            var settings = node as IHasSettings;

            if (settings != null)
            {
                m_NodeSettingsView         = new NodeSettingsView();
                m_NodeSettingsView.visible = false;

                Add(m_NodeSettingsView);

                m_SettingsButton = new VisualElement {
                    name = "settings-button"
                };
                m_SettingsButton.Add(new VisualElement {
                    name = "icon"
                });

                m_Settings = settings.CreateSettingsElement();

                m_SettingsButton.AddManipulator(new Clickable(() =>
                {
                    UpdateSettingsExpandedState();
                }));

                // Remove this after updated to the correct API call has landed in trunk. ------------
                m_ButtonContainer = new VisualElement {
                    name = "button-container"
                };
                m_ButtonContainer.style.flexDirection = StyleValue <FlexDirection> .Create(FlexDirection.Row);

                m_ButtonContainer.Add(m_SettingsButton);
                m_ButtonContainer.Add(m_CollapseButton);
                m_TitleContainer.Add(m_ButtonContainer);
                // -----------------------------------------------------------------------------------
                //titleButtonContainer.Add(m_SettingsButton);
                //titleButtonContainer.Add(m_CollapseButton);

                RegisterCallback <GeometryChangedEvent>(OnGeometryChanged);
            }
        }
        public void Initialize(AbstractMaterialNode inNode, PreviewManager previewManager, IEdgeConnectorListener connectorListener, GraphView graphView)
        {
            styleSheets.Add(Resources.Load <StyleSheet>("Styles/MaterialNodeView"));
            styleSheets.Add(Resources.Load <StyleSheet>($"Styles/ColorMode"));
            AddToClassList("MaterialNode");

            if (inNode == null)
            {
                return;
            }

            var contents = this.Q("contents");

            m_GraphView = graphView;

            m_ConnectorListener = connectorListener;
            node        = inNode;
            viewDataKey = node.guid.ToString();
            UpdateTitle();

            // Add controls container
            var controlsContainer = new VisualElement {
                name = "controls"
            };

            {
                m_ControlsDivider = new VisualElement {
                    name = "divider"
                };
                m_ControlsDivider.AddToClassList("horizontal");
                controlsContainer.Add(m_ControlsDivider);
                m_ControlItems = new VisualElement {
                    name = "items"
                };
                controlsContainer.Add(m_ControlItems);

                // Instantiate control views from node
                foreach (var propertyInfo in node.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
                {
                    foreach (IControlAttribute attribute in propertyInfo.GetCustomAttributes(typeof(IControlAttribute), false))
                    {
                        m_ControlItems.Add(attribute.InstantiateControl(node, propertyInfo));
                    }
                }
            }
            if (m_ControlItems.childCount > 0)
            {
                contents.Add(controlsContainer);
            }

            if (node.hasPreview)
            {
                // Add actual preview which floats on top of the node
                m_PreviewContainer = new VisualElement
                {
                    name          = "previewContainer",
                    cacheAsBitmap = true,
                    style         = { overflow = Overflow.Hidden },
                    pickingMode   = PickingMode.Ignore
                };
                m_PreviewImage = new Image
                {
                    name        = "preview",
                    pickingMode = PickingMode.Ignore,
                    image       = Texture2D.whiteTexture,
                };
                {
                    // Add preview collapse button on top of preview
                    var collapsePreviewButton = new VisualElement {
                        name = "collapse"
                    };
                    collapsePreviewButton.Add(new VisualElement {
                        name = "icon"
                    });
                    collapsePreviewButton.AddManipulator(new Clickable(() =>
                    {
                        node.owner.owner.RegisterCompleteObjectUndo("Collapse Preview");
                        UpdatePreviewExpandedState(false);
                    }));
                    m_PreviewImage.Add(collapsePreviewButton);
                }
                m_PreviewContainer.Add(m_PreviewImage);

                // Hook up preview image to preview manager
                m_PreviewRenderData = previewManager.GetPreview(inNode);
                m_PreviewRenderData.onPreviewChanged += UpdatePreviewTexture;
                UpdatePreviewTexture();

                // Add fake preview which pads out the node to provide space for the floating preview
                m_PreviewFiller = new VisualElement {
                    name = "previewFiller"
                };
                m_PreviewFiller.AddToClassList("expanded");
                {
                    var previewDivider = new VisualElement {
                        name = "divider"
                    };
                    previewDivider.AddToClassList("horizontal");
                    m_PreviewFiller.Add(previewDivider);

                    var expandPreviewButton = new VisualElement {
                        name = "expand"
                    };
                    expandPreviewButton.Add(new VisualElement {
                        name = "icon"
                    });
                    expandPreviewButton.AddManipulator(new Clickable(() =>
                    {
                        node.owner.owner.RegisterCompleteObjectUndo("Expand Preview");
                        UpdatePreviewExpandedState(true);
                    }));
                    m_PreviewFiller.Add(expandPreviewButton);
                }
                contents.Add(m_PreviewFiller);

                UpdatePreviewExpandedState(node.previewExpanded);
            }

            // Add port input container, which acts as a pixel cache for all port inputs
            m_PortInputContainer = new VisualElement
            {
                name          = "portInputContainer",
                cacheAsBitmap = true,
                style         = { overflow = Overflow.Hidden },
                pickingMode   = PickingMode.Ignore
            };
            Add(m_PortInputContainer);

            AddSlots(node.GetSlots <MaterialSlot>());
            UpdatePortInputs();
            base.expanded = node.drawState.expanded;
            RefreshExpandedState(); //This should not be needed. GraphView needs to improve the extension api here
            UpdatePortInputVisibilities();

            SetPosition(new Rect(node.drawState.position.x, node.drawState.position.y, 0, 0));

            if (node is SubGraphNode)
            {
                RegisterCallback <MouseDownEvent>(OnSubGraphDoubleClick);
            }

            m_PortInputContainer.SendToBack();

            m_TitleContainer = this.Q("title");

            var masterNode = node as IMasterNode;

            if (masterNode != null)
            {
                AddToClassList("master");

                if (!masterNode.IsPipelineCompatible(GraphicsSettings.renderPipelineAsset))
                {
                    AttachMessage("The current render pipeline is not compatible with this master node.", ShaderCompilerMessageSeverity.Error);
                }
            }

            m_NodeSettingsView         = new NodeSettingsView();
            m_NodeSettingsView.visible = false;
            Add(m_NodeSettingsView);

            m_SettingsButton = new VisualElement {
                name = "settings-button"
            };
            m_SettingsButton.Add(new VisualElement {
                name = "icon"
            });

            m_Settings = new VisualElement();
            AddDefaultSettings();

            // Add Node type specific settings
            var nodeTypeSettings = node as IHasSettings;

            if (nodeTypeSettings != null)
            {
                m_Settings.Add(nodeTypeSettings.CreateSettingsElement());
            }

            // Add manipulators
            m_SettingsButton.AddManipulator(new Clickable(() =>
            {
                UpdateSettingsExpandedState();
            }));

            if (m_Settings.childCount > 0)
            {
                m_ButtonContainer = new VisualElement {
                    name = "button-container"
                };
                m_ButtonContainer.style.flexDirection = FlexDirection.Row;
                m_ButtonContainer.Add(m_SettingsButton);
                m_ButtonContainer.Add(m_CollapseButton);
                m_TitleContainer.Add(m_ButtonContainer);
            }
        }
Example #29
0
        public void Initialize(AbstractMaterialNode inNode, PreviewManager previewManager, IEdgeConnectorListener connectorListener)
        {
            AddStyleSheetPath("Styles/MaterialNodeView");
            AddToClassList("MaterialNode");

            if (inNode == null)
            {
                return;
            }

            var contents = this.Q("contents");

            m_ConnectorListener = connectorListener;
            node           = inNode;
            persistenceKey = node.guid.ToString();
            UpdateTitle();

            // Add controls container
            var controlsContainer = new VisualElement {
                name = "controls"
            };

            {
                m_ControlsDivider = new VisualElement {
                    name = "divider"
                };
                m_ControlsDivider.AddToClassList("horizontal");
                controlsContainer.Add(m_ControlsDivider);
                m_ControlItems = new VisualElement {
                    name = "items"
                };
                controlsContainer.Add(m_ControlItems);

                // Instantiate control views from node
                foreach (var propertyInfo in node.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
                {
                    foreach (IControlAttribute attribute in propertyInfo.GetCustomAttributes(typeof(IControlAttribute), false))
                    {
                        m_ControlItems.Add(attribute.InstantiateControl(node, propertyInfo));
                    }
                }
            }
            if (m_ControlItems.childCount > 0)
            {
                contents.Add(controlsContainer);
            }

            if (node.hasPreview)
            {
                // Add actual preview which floats on top of the node
                m_PreviewContainer = new VisualElement
                {
                    name            = "previewContainer",
                    clippingOptions = ClippingOptions.ClipAndCacheContents,
                    pickingMode     = PickingMode.Ignore
                };
                m_PreviewImage = new Image
                {
                    name        = "preview",
                    pickingMode = PickingMode.Ignore,
                    image       = Texture2D.whiteTexture,
                };
                {
                    // Add preview collapse button on top of preview
                    var collapsePreviewButton = new VisualElement {
                        name = "collapse"
                    };
                    collapsePreviewButton.Add(new VisualElement {
                        name = "icon"
                    });
                    collapsePreviewButton.AddManipulator(new Clickable(() =>
                    {
                        node.owner.owner.RegisterCompleteObjectUndo("Collapse Preview");
                        UpdatePreviewExpandedState(false);
                    }));
                    m_PreviewImage.Add(collapsePreviewButton);
                }
                m_PreviewContainer.Add(m_PreviewImage);

                // Hook up preview image to preview manager
                m_PreviewRenderData = previewManager.GetPreview(inNode);
                m_PreviewRenderData.onPreviewChanged += UpdatePreviewTexture;
                UpdatePreviewTexture();

                // Add fake preview which pads out the node to provide space for the floating preview
                m_PreviewFiller = new VisualElement {
                    name = "previewFiller"
                };
                m_PreviewFiller.AddToClassList("expanded");
                {
                    var previewDivider = new VisualElement {
                        name = "divider"
                    };
                    previewDivider.AddToClassList("horizontal");
                    m_PreviewFiller.Add(previewDivider);

                    var expandPreviewButton = new VisualElement {
                        name = "expand"
                    };
                    expandPreviewButton.Add(new VisualElement {
                        name = "icon"
                    });
                    expandPreviewButton.AddManipulator(new Clickable(() =>
                    {
                        node.owner.owner.RegisterCompleteObjectUndo("Expand Preview");
                        UpdatePreviewExpandedState(true);
                    }));
                    m_PreviewFiller.Add(expandPreviewButton);
                }
                contents.Add(m_PreviewFiller);

                UpdatePreviewExpandedState(node.previewExpanded);
            }

            // Add port input container, which acts as a pixel cache for all port inputs
            m_PortInputContainer = new VisualElement
            {
                name            = "portInputContainer",
                clippingOptions = ClippingOptions.ClipAndCacheContents,
                pickingMode     = PickingMode.Ignore
            };
            Add(m_PortInputContainer);

            AddSlots(node.GetSlots <MaterialSlot>());
            UpdatePortInputs();
            base.expanded = node.drawState.expanded;
            RefreshExpandedState(); //This should not be needed. GraphView needs to improve the extension api here
            UpdatePortInputVisibilities();

            SetPosition(new Rect(node.drawState.position.x, node.drawState.position.y, 0, 0));

            /*if (node is PreviewNode)
             * {
             *  var resizeHandle = new Label { name = "resize", text = "" };
             *  resizeHandle.AddManipulator(new Draggable(OnResize));
             *  Add(resizeHandle);
             *  UpdateSize();
             * }*/

            if (node is SubGraphNode)
            {
                RegisterCallback <MouseDownEvent>(OnSubGraphDoubleClick);
            }

            m_PortInputContainer.SendToBack();
            if (node.hasPreview)
            {
                m_PreviewFiller.BringToFront();
            }
        }