public void TestSerializationHelperCanSerializeThenDeserialize()
        {
            var toSerialize = new List <SimpleSerializeClass>()
            {
                SimpleSerializeClass.instance
            };

            var serialized = SerializationHelper.Serialize <SimpleSerializeClass>(toSerialize);

            Assert.AreEqual(1, serialized.Count);

            var loaded = SerializationHelper.Deserialize <SimpleSerializeClass>(serialized, GraphUtil.GetLegacyTypeRemapping());

            Assert.AreEqual(1, loaded.Count);
            Assert.IsInstanceOf <SimpleSerializeClass>(loaded[0]);
            loaded[0].AssertAsReference();
        }
Exemple #2
0
        protected override bool DoShadersStripper(HDRenderPipelineAsset hdrpAsset, Shader shader, ShaderSnippetData snippet, ShaderCompilerData inputData)
        {
            // CAUTION: Pass Name and Lightmode name must match in master node and .shader.
            // HDRP use LightMode to do drawRenderer and pass name is use here for stripping!
            bool isGBufferPass            = snippet.passName == "GBuffer";
            bool isForwardPass            = snippet.passName == "Forward";
            bool isDepthOnlyPass          = snippet.passName == "DepthOnly";
            bool isMotionPass             = snippet.passName == "MotionVectors";
            bool isTransparentPrepass     = snippet.passName == "TransparentDepthPrepass";
            bool isTransparentPostpass    = snippet.passName == "TransparentDepthPostpass";
            bool isTransparentBackface    = snippet.passName == "TransparentBackface";
            bool isDistortionPass         = snippet.passName == "DistortionVectors";
            bool isTransparentForwardPass = isTransparentPostpass || isTransparentBackface || isTransparentPrepass || isDistortionPass;

            // Using Contains to include the Tessellation variants
            bool isBuiltInTerrainLit = shader.name.Contains("HDRP/TerrainLit");
            bool isBuiltInLit        = shader.name.Contains("HDRP/Lit") || shader.name.Contains("HDRP/LayeredLit") || isBuiltInTerrainLit;

            if (shader.IsShaderGraph())
            {
                string shaderPath = AssetDatabase.GetAssetPath(shader);
                isBuiltInLit |= GraphUtil.GetOutputNodeType(shaderPath) == typeof(HDLitMasterNode);
            }

            // Caution: Currently only HDRP/TerrainLit is using keyword _ALPHATEST_ON with multi compile, we shouldn't test any other built in shader
            if (isBuiltInTerrainLit)
            {
                if (inputData.shaderKeywordSet.IsEnabled(m_AlphaTestOn) && !hdrpAsset.currentPlatformRenderPipelineSettings.supportTerrainHole)
                {
                    return(true);
                }
            }

            // When using forward only, we never need GBuffer pass (only Forward)
            // Gbuffer Pass is suppose to exist only for Lit shader thus why we test the condition here in case another shader generate a GBuffer pass (like VFX)
            if (hdrpAsset.currentPlatformRenderPipelineSettings.supportedLitShaderMode == RenderPipelineSettings.SupportedLitShaderMode.ForwardOnly && isGBufferPass)
            {
                return(true);
            }

            // Variant of light layer only exist in GBuffer pass, so we test it here
            if (inputData.shaderKeywordSet.IsEnabled(m_LightLayers) && isGBufferPass && !hdrpAsset.currentPlatformRenderPipelineSettings.supportLightLayers)
            {
                return(true);
            }

            // This test include all Lit variant from Shader Graph (Because we check "DepthOnly" pass)
            // Other forward material ("DepthForwardOnly") don't use keyword for WriteNormalBuffer but #define
            if (isDepthOnlyPass)
            {
                // When we are full forward, we don't have depth prepass or motion vectors pass without writeNormalBuffer
                if (hdrpAsset.currentPlatformRenderPipelineSettings.supportedLitShaderMode == RenderPipelineSettings.SupportedLitShaderMode.ForwardOnly && !inputData.shaderKeywordSet.IsEnabled(m_WriteNormalBuffer))
                {
                    return(true);
                }

                // When we are deferred, we don't have depth prepass or motion vectors pass with writeNormalBuffer
                // Note: This rule is safe with Forward Material because WRITE_NORMAL_BUFFER is not a keyword for them, so it will not be removed
                if (hdrpAsset.currentPlatformRenderPipelineSettings.supportedLitShaderMode == RenderPipelineSettings.SupportedLitShaderMode.DeferredOnly && inputData.shaderKeywordSet.IsEnabled(m_WriteNormalBuffer))
                {
                    return(true);
                }
            }

            // Apply following set of rules only to inspector version of shader as we don't have Transparent keyword with shader graph
            if (isBuiltInLit)
            {
                // Forward material don't use keyword for WriteNormalBuffer but #define so we can't test for the keyword outside of isBuiltInLit
                // otherwise the pass will be remove for non-lit shader graph version (like StackLit)
                if (isMotionPass)
                {
                    // When we are full forward, we don't have depth prepass or motion vectors pass without writeNormalBuffer
                    if (hdrpAsset.currentPlatformRenderPipelineSettings.supportedLitShaderMode == RenderPipelineSettings.SupportedLitShaderMode.ForwardOnly && !inputData.shaderKeywordSet.IsEnabled(m_WriteNormalBuffer))
                    {
                        return(true);
                    }

                    // When we are deferred, we don't have depth prepass or motion vectors pass with writeNormalBuffer
                    // Note: This rule is safe with Forward Material because WRITE_NORMAL_BUFFER is not a keyword for them, so it will not be removed
                    if (hdrpAsset.currentPlatformRenderPipelineSettings.supportedLitShaderMode == RenderPipelineSettings.SupportedLitShaderMode.DeferredOnly && inputData.shaderKeywordSet.IsEnabled(m_WriteNormalBuffer))
                    {
                        return(true);
                    }
                }

                if (!inputData.shaderKeywordSet.IsEnabled(m_Transparent)) // Opaque
                {
                    // If opaque, we never need transparent specific passes (even in forward only mode)
                    if (isTransparentForwardPass)
                    {
                        return(true);
                    }

                    if (hdrpAsset.currentPlatformRenderPipelineSettings.supportedLitShaderMode == RenderPipelineSettings.SupportedLitShaderMode.DeferredOnly)
                    {
                        // When we are in deferred, we only support tile lighting
                        if (inputData.shaderKeywordSet.IsEnabled(m_ClusterLighting))
                        {
                            return(true);
                        }

                        if (isForwardPass && !inputData.shaderKeywordSet.IsEnabled(m_DebugDisplay))
                        {
                            return(true);
                        }
                    }

                    // TODO: Should we remove Cluster version if we know MSAA is disabled ? This prevent to manipulate LightLoop Settings (useFPTL option)
                    // For now comment following code
                    // if (inputData.shaderKeywordSet.IsEnabled(m_ClusterLighting) && !hdrpAsset.currentPlatformRenderPipelineSettings.supportMSAA)
                    //    return true;
                }
            }

            // We strip passes for transparent passes outside of isBuiltInLit because we want Hair, Fabric
            // and StackLit shader graphs to be taken in account.
            if (inputData.shaderKeywordSet.IsEnabled(m_Transparent))
            {
                // If transparent, we never need GBuffer pass.
                if (isGBufferPass)
                {
                    return(true);
                }

                // If transparent we don't need the depth only pass
                if (isDepthOnlyPass)
                {
                    return(true);
                }

                // If transparent we don't need the motion vector pass
                if (isMotionPass)
                {
                    return(true);
                }

                // If we are transparent we use cluster lighting and not tile lighting
                if (inputData.shaderKeywordSet.IsEnabled(m_TileLighting))
                {
                    return(true);
                }
            }

            // TODO: Tests for later
            // We need to find a way to strip useless shader features for passes/shader stages that don't need them (example, vertex shaders won't ever need SSS Feature flag)
            // This causes several problems:
            // - Runtime code that "finds" shader variants based on feature flags might not find them anymore... thus fall backing to the "let's give a score to variant" code path that may find the wrong variant.
            // - Another issue is that if a feature is declared without a "_" fall-back, if we strip the other variants, none may be left to use! This needs to be changed on our side.
            //if (snippet.shaderType == ShaderType.Vertex && inputData.shaderKeywordSet.IsEnabled(m_FeatureSSS))
            //    return true;

            return(false);
        }
        GraphData DeserializeGraph()
        {
            var deserializedGraph = SerializationHelper.Deserialize <GraphData>(m_SerializedGraph, GraphUtil.GetLegacyTypeRemapping());

            deserializedGraph.isSubGraph = m_IsSubGraph;
            deserializedGraph.assetGuid  = m_AssetGuid;
            m_DeserializedVersion        = m_SerializedVersion;
            m_SerializedGraph            = default(SerializationHelper.JSONSerializedElement);
            return(deserializedGraph);
        }
Exemple #4
0
        protected virtual void UpdateLineEnds()
        {
            if (Vertex.Get("BackgroundColor:") != null)
            {
                BackgroundColor = UIWpf.GetBrushFromColorVertex(Vertex.Get("BackgroundColor:"));
            }
            else
            {
                BackgroundColor = (Brush)Line.FindResource("0BackgroundBrush");
            }

            if (Vertex.Get("ForegroundColor:") != null)
            {
                ForegroundColor = UIWpf.GetBrushFromColorVertex(Vertex.Get("ForegroundColor:"));
            }
            else
            {
                ForegroundColor = (Brush)Line.FindResource("0ForegroundBrush");
            }

            LineEndings.Stroke = ForegroundColor;
            Line.Stroke        = ForegroundColor;
            Label.Foreground   = ForegroundColor;


            string StartAnchor = (string)GraphUtil.GetValue(Vertex.Get(@"StartAnchor:"));
            string EndAnchor   = (string)GraphUtil.GetValue(Vertex.Get(@"EndAnchor:"));

            if (StartAnchor == "Straight")
            {
                LineEndings.StartEnding = LineEndEnum.Straight;
                Line.StartEnding        = LineEndEnum.Straight;
            }

            if (EndAnchor == "Straight")
            {
                LineEndings.EndEnding = LineEndEnum.Straight;
                Line.EndEnding        = LineEndEnum.Straight;
            }

            if (StartAnchor == "Arrow")
            {
                LineEndings.StartEnding = LineEndEnum.Arrow;
                Line.StartEnding        = LineEndEnum.Arrow;
            }

            if (EndAnchor == "Arrow")
            {
                LineEndings.EndEnding = LineEndEnum.Arrow;
                Line.EndEnding        = LineEndEnum.Arrow;
            }

            if (StartAnchor == "Triangle")
            {
                LineEndings.StartEnding = LineEndEnum.Triangle;
                Line.StartEnding        = LineEndEnum.Triangle;

                FillBrush          = BackgroundColor;
                HighlightFillBrush = BackgroundColor;
            }

            if (EndAnchor == "Triangle")
            {
                LineEndings.EndEnding = LineEndEnum.Triangle;
                Line.EndEnding        = LineEndEnum.Triangle;

                FillBrush          = BackgroundColor;
                HighlightFillBrush = BackgroundColor;
            }

            if (StartAnchor == "FilledTriangle")
            {
                LineEndings.StartEnding = LineEndEnum.FilledTriangle;
                Line.StartEnding        = LineEndEnum.FilledTriangle;

                FillBrush          = ForegroundColor;
                HighlightFillBrush = (Brush)LineEndings.FindResource("0LightHighlightBrush");
            }

            if (EndAnchor == "FilledTriangle")
            {
                LineEndings.EndEnding = LineEndEnum.FilledTriangle;
                Line.EndEnding        = LineEndEnum.FilledTriangle;

                FillBrush          = ForegroundColor;
                HighlightFillBrush = (Brush)LineEndings.FindResource("0LightHighlightBrush");
            }

            if (StartAnchor == "Diamond")
            {
                LineEndings.StartEnding = LineEndEnum.Diamond;
                Line.StartEnding        = LineEndEnum.Diamond;

                FillBrush          = BackgroundColor;
                HighlightFillBrush = BackgroundColor;
            }

            if (EndAnchor == "Diamond")
            {
                LineEndings.EndEnding = LineEndEnum.Diamond;
                Line.EndEnding        = LineEndEnum.Diamond;

                FillBrush          = BackgroundColor;
                HighlightFillBrush = BackgroundColor;
            }

            if (StartAnchor == "FilledDiamond")
            {
                LineEndings.StartEnding = LineEndEnum.FilledDiamond;
                Line.StartEnding        = LineEndEnum.FilledDiamond;

                FillBrush          = ForegroundColor;
                HighlightFillBrush = (Brush)LineEndings.FindResource("0LightHighlightBrush");
            }

            if (EndAnchor == "FilledDiamond")
            {
                LineEndings.EndEnding = LineEndEnum.FilledDiamond;
                Line.EndEnding        = LineEndEnum.FilledDiamond;

                FillBrush          = ForegroundColor;
                HighlightFillBrush = (Brush)LineEndings.FindResource("0LightHighlightBrush");
            }


            if (FillBrush != null)
            {
                LineEndings.Fill = FillBrush;
            }

            LineEndings.ArrowLength = 0;
            Line.ArrowLength        = 0;
            LineEndings.ArrowLength = 15;
            Line.ArrowLength        = 15;
        }
        static string GetShaderPassFromTemplate(bool isColorPass, string template, SpriteLitMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions)
        {
            // ----------------------------------------------------- //
            //                         SETUP                         //
            // ----------------------------------------------------- //

            // -------------------------------------
            // String builders

            var shaderProperties       = new PropertyCollector();
            var shaderPropertyUniforms = new ShaderStringBuilder(1);
            var functionBuilder        = new ShaderStringBuilder(1);
            var functionRegistry       = new FunctionRegistry(functionBuilder);

            var defines = new ShaderStringBuilder(1);
            var graph   = new ShaderStringBuilder(0);

            var vertexDescriptionInputStruct = new ShaderStringBuilder(1);
            var vertexDescriptionStruct      = new ShaderStringBuilder(1);
            var vertexDescriptionFunction    = new ShaderStringBuilder(1);

            var surfaceDescriptionInputStruct = new ShaderStringBuilder(1);
            var surfaceDescriptionStruct      = new ShaderStringBuilder(1);
            var surfaceDescriptionFunction    = new ShaderStringBuilder(1);

            var vertexInputStruct  = new ShaderStringBuilder(1);
            var vertexOutputStruct = new ShaderStringBuilder(2);

            var vertexShader = new ShaderStringBuilder(2);
            var vertexShaderDescriptionInputs = new ShaderStringBuilder(2);
            var vertexShaderOutputs           = new ShaderStringBuilder(2);

            var pixelShader = new ShaderStringBuilder(2);
            var pixelShaderSurfaceInputs = new ShaderStringBuilder(2);

            // -------------------------------------
            // Get Slot and Node lists per stage
            var vertexSlots = pass.VertexShaderSlots.Select(masterNode.FindSlot <MaterialSlot>).ToList();
            var vertexNodes = ListPool <AbstractMaterialNode> .Get();

            NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots);

            var pixelSlots = pass.PixelShaderSlots.Select(masterNode.FindSlot <MaterialSlot>).ToList();
            var pixelNodes = ListPool <AbstractMaterialNode> .Get();

            NodeUtils.DepthFirstCollectNodesFromNode(pixelNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots);

            // -------------------------------------
            // Get Requirements
            var vertexRequirements  = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false);
            var pixelRequirements   = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment);
            var surfaceRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment, false);

            var modelRequiements = ShaderGraphRequirements.none;

            modelRequiements.requiresVertexColor = true;

            if (isColorPass)
            {
                modelRequiements.requiresMeshUVs = new List <UVChannel>()
                {
                    UVChannel.UV0
                };
            }

            // ----------------------------------------------------- //
            //                START SHADER GENERATION                //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Calculate material options

            var blendingBuilder = new ShaderStringBuilder(1);
            var cullingBuilder  = new ShaderStringBuilder(1);
            var zTestBuilder    = new ShaderStringBuilder(1);
            var zWriteBuilder   = new ShaderStringBuilder(1);

            materialOptions.GetBlend(blendingBuilder);
            materialOptions.GetCull(cullingBuilder);
            materialOptions.GetDepthTest(zTestBuilder);
            materialOptions.GetDepthWrite(zWriteBuilder);


            // ----------------------------------------------------- //
            //                START VERTEX DESCRIPTION               //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Generate Input structure for Vertex Description function
            // TODO - Vertex Description Input requirements are needed to exclude intermediate translation spaces

            vertexDescriptionInputStruct.AppendLine("struct VertexDescriptionInputs");
            using (vertexDescriptionInputStruct.BlockSemicolonScope())
            {
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresNormal, InterpolatorType.Normal, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresTangent, InterpolatorType.Tangent, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresBitangent, InterpolatorType.BiTangent, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresViewDir, InterpolatorType.ViewDirection, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresPosition, InterpolatorType.Position, vertexDescriptionInputStruct);

                if (vertexRequirements.requiresVertexColor)
                {
                    vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
                }

                if (vertexRequirements.requiresScreenPosition)
                {
                    vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
                }

                foreach (var channel in vertexRequirements.requiresMeshUVs.Distinct())
                {
                    vertexDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
                }
            }

            // -------------------------------------
            // Generate Output structure for Vertex Description function

            GraphUtil.GenerateVertexDescriptionStruct(vertexDescriptionStruct, vertexSlots);

            // -------------------------------------
            // Generate Vertex Description function

            GraphUtil.GenerateVertexDescriptionFunction(
                masterNode.owner as GraphData,
                vertexDescriptionFunction,
                functionRegistry,
                shaderProperties,
                mode,
                vertexNodes,
                vertexSlots);

            // ----------------------------------------------------- //
            //               START SURFACE DESCRIPTION               //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Generate Input structure for Surface Description function
            // Surface Description Input requirements are needed to exclude intermediate translation spaces

            surfaceDescriptionInputStruct.AppendLine("struct SurfaceDescriptionInputs");
            using (surfaceDescriptionInputStruct.BlockSemicolonScope())
            {
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresNormal, InterpolatorType.Normal, surfaceDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresTangent, InterpolatorType.Tangent, surfaceDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresBitangent, InterpolatorType.BiTangent, surfaceDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresPosition, InterpolatorType.Position, surfaceDescriptionInputStruct);

                if (surfaceRequirements.requiresVertexColor)
                {
                    surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
                }

                if (surfaceRequirements.requiresScreenPosition)
                {
                    surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
                }

                if (surfaceRequirements.requiresFaceSign)
                {
                    surfaceDescriptionInputStruct.AppendLine("float {0};", ShaderGeneratorNames.FaceSign);
                }

                foreach (var channel in surfaceRequirements.requiresMeshUVs.Distinct())
                {
                    surfaceDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
                }
            }

            // -------------------------------------
            // Generate Output structure for Surface Description function

            GraphUtil.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, pixelSlots);

            // -------------------------------------
            // Generate Surface Description function

            GraphUtil.GenerateSurfaceDescriptionFunction(
                pixelNodes,
                masterNode,
                masterNode.owner as GraphData,
                surfaceDescriptionFunction,
                functionRegistry,
                shaderProperties,
                pixelRequirements,
                mode,
                "PopulateSurfaceData",
                "SurfaceDescription",
                null,
                pixelSlots);

            // ----------------------------------------------------- //
            //           GENERATE VERTEX > PIXEL PIPELINE            //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Property uniforms

            shaderProperties.GetPropertiesDeclaration(shaderPropertyUniforms, mode, masterNode.owner.concretePrecision);

            // -------------------------------------
            // Generate Input structure for Vertex shader

            GraphUtil.GenerateApplicationVertexInputs(vertexRequirements.Union(pixelRequirements.Union(modelRequiements)), vertexInputStruct);

            // -------------------------------------
            // Generate standard transformations
            // This method ensures all required transform data is available in vertex and pixel stages

            ShaderGenerator.GenerateStandardTransforms(
                3,
                10,
                vertexOutputStruct,
                vertexShader,
                vertexShaderDescriptionInputs,
                vertexShaderOutputs,
                pixelShader,
                pixelShaderSurfaceInputs,
                pixelRequirements,
                surfaceRequirements,
                modelRequiements,
                vertexRequirements,
                CoordinateSpace.World);


            // ----------------------------------------------------- //
            //                      FINALIZE                         //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Combine Graph sections

            graph.AppendLines(shaderPropertyUniforms.ToString());

            graph.AppendLine(vertexDescriptionInputStruct.ToString());
            graph.AppendLine(surfaceDescriptionInputStruct.ToString());

            graph.AppendLine(functionBuilder.ToString());

            graph.AppendLine(vertexDescriptionStruct.ToString());
            graph.AppendLine(vertexDescriptionFunction.ToString());

            graph.AppendLine(surfaceDescriptionStruct.ToString());
            graph.AppendLine(surfaceDescriptionFunction.ToString());

            graph.AppendLine(vertexInputStruct.ToString());

            // -------------------------------------
            // Generate final subshader

            var resultPass = template.Replace("${Tags}", string.Empty);

            resultPass = resultPass.Replace("${Blending}", blendingBuilder.ToString());
            resultPass = resultPass.Replace("${Culling}", cullingBuilder.ToString());
            resultPass = resultPass.Replace("${ZTest}", zTestBuilder.ToString());
            resultPass = resultPass.Replace("${ZWrite}", zWriteBuilder.ToString());
            resultPass = resultPass.Replace("${Defines}", defines.ToString());

            resultPass = resultPass.Replace("${Graph}", graph.ToString());
            resultPass = resultPass.Replace("${VertexOutputStruct}", vertexOutputStruct.ToString());

            resultPass = resultPass.Replace("${VertexShader}", vertexShader.ToString());
            resultPass = resultPass.Replace("${VertexShaderDescriptionInputs}", vertexShaderDescriptionInputs.ToString());
            resultPass = resultPass.Replace("${VertexShaderOutputs}", vertexShaderOutputs.ToString());

            resultPass = resultPass.Replace("${PixelShader}", pixelShader.ToString());
            resultPass = resultPass.Replace("${PixelShaderSurfaceInputs}", pixelShaderSurfaceInputs.ToString());

            return(resultPass);
        }
Exemple #6
0
 public static void CreateMaterialGraph()
 {
     GraphUtil.CreateNewGraph(new HDUnlitMasterNode());
 }
Exemple #7
0
        public void ToSubGraph()
        {
            var graphView = graphEditorView.graphView;

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

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

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

            graphObject.RegisterCompleteObjectUndo("Convert To Subgraph");

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

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

            bounds.center = Vector2.zero;

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

            // Collect the property nodes and get the corresponding properties
            var 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();
                    prop.displayName = GraphUtil.SanitizeName(subGraph.addedInputs.Select(p => p.displayName), "{0} ({1})", prop.displayName);

                    subGraph.AddGraphInput(prop);
                    var propNode = new PropertyNode();
                    {
                        var drawState = propNode.drawState;
                        drawState.position = new Rect(new Vector2(bounds.xMin - 300f, 0f) + propPos, drawState.position.size);
                        propPos           += new Vector2(0, height);
                        propNode.drawState = drawState;
                    }
                    subGraph.AddNode(propNode);
                    propNode.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);
            }

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

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

            if (loadedSubGraph == null)
            {
                return;
            }

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

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

            // Add the subgraph into the group if the nodes was all in the same group group
            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();
        }
        private static bool GenerateShaderPassLit(AbstractMaterialNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions, ShaderGenerator result, List <string> sourceAssetDependencyPaths)
        {
            var templateLocation = Path.Combine(Path.Combine(Path.Combine(HDEditorUtils.GetHDRenderPipelinePath(), "Editor"), "ShaderGraph"), pass.TemplateName);

            if (!File.Exists(templateLocation))
            {
                // TODO: produce error here
                return(false);
            }

            if (sourceAssetDependencyPaths != null)
            {
                sourceAssetDependencyPaths.Add(templateLocation);
            }

            // grab all of the active nodes (for pixel and vertex graphs)
            var vertexNodes = ListPool <INode> .Get();

            NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots);

            var pixelNodes = ListPool <INode> .Get();

            NodeUtils.DepthFirstCollectNodesFromNode(pixelNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots);

            // graph requirements describe what the graph itself requires
            var pixelRequirements  = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment, false);  // TODO: is ShaderStageCapability.Fragment correct?
            var vertexRequirements = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false);

            // Function Registry tracks functions to remove duplicates, it wraps a string builder that stores the combined function string
            ShaderStringBuilder graphNodeFunctions = new ShaderStringBuilder();

            graphNodeFunctions.IncreaseIndent();
            var functionRegistry = new FunctionRegistry(graphNodeFunctions);

            // TODO: this can be a shared function for all HDRP master nodes -- From here through GraphUtil.GenerateSurfaceDescription(..)

            // Build the list of active slots based on what the pass requires
            var pixelSlots  = HDSubShaderUtilities.FindMaterialSlotsOnNode(pass.PixelShaderSlots, masterNode);
            var vertexSlots = HDSubShaderUtilities.FindMaterialSlotsOnNode(pass.VertexShaderSlots, masterNode);

            // properties used by either pixel and vertex shader
            PropertyCollector sharedProperties = new PropertyCollector();

            // build the graph outputs structure to hold the results of each active slots (and fill out activeFields to indicate they are active)
            string pixelGraphInputStructName           = "SurfaceDescriptionInputs";
            string pixelGraphOutputStructName          = "SurfaceDescription";
            string pixelGraphEvalFunctionName          = "SurfaceDescriptionFunction";
            ShaderStringBuilder pixelGraphEvalFunction = new ShaderStringBuilder();
            ShaderStringBuilder pixelGraphOutputs      = new ShaderStringBuilder();

            // dependency tracker -- set of active fields
            HashSet <string> activeFields = GetActiveFieldsFromMasterNode(masterNode, pass);

            // build initial requirements
            HDRPShaderStructs.AddActiveFieldsFromPixelGraphRequirements(activeFields, pixelRequirements);

            // build the graph outputs structure, and populate activeFields with the fields of that structure
            GraphUtil.GenerateSurfaceDescriptionStruct(pixelGraphOutputs, pixelSlots, true, pixelGraphOutputStructName, activeFields);

            // Build the graph evaluation code, to evaluate the specified slots
            GraphUtil.GenerateSurfaceDescriptionFunction(
                pixelNodes,
                masterNode,
                masterNode.owner as AbstractMaterialGraph,
                pixelGraphEvalFunction,
                functionRegistry,
                sharedProperties,
                pixelRequirements,  // TODO : REMOVE UNUSED
                mode,
                pixelGraphEvalFunctionName,
                pixelGraphOutputStructName,
                null,
                pixelSlots,
                pixelGraphInputStructName);

            string vertexGraphInputStructName           = "VertexDescriptionInputs";
            string vertexGraphOutputStructName          = "VertexDescription";
            string vertexGraphEvalFunctionName          = "VertexDescriptionFunction";
            ShaderStringBuilder vertexGraphEvalFunction = new ShaderStringBuilder();
            ShaderStringBuilder vertexGraphOutputs      = new ShaderStringBuilder();

            // check for vertex animation -- enables HAVE_VERTEX_MODIFICATION
            bool vertexActive = false;

            if (masterNode.IsSlotConnected(PBRMasterNode.PositionSlotId))
            {
                vertexActive = true;
                activeFields.Add("features.modifyMesh");
                HDRPShaderStructs.AddActiveFieldsFromVertexGraphRequirements(activeFields, vertexRequirements);

                // -------------------------------------
                // Generate Output structure for Vertex Description function
                GraphUtil.GenerateVertexDescriptionStruct(vertexGraphOutputs, vertexSlots, vertexGraphOutputStructName, activeFields);

                // -------------------------------------
                // Generate Vertex Description function
                GraphUtil.GenerateVertexDescriptionFunction(
                    masterNode.owner as AbstractMaterialGraph,
                    vertexGraphEvalFunction,
                    functionRegistry,
                    sharedProperties,
                    mode,
                    vertexNodes,
                    vertexSlots,
                    vertexGraphInputStructName,
                    vertexGraphEvalFunctionName,
                    vertexGraphOutputStructName);
            }

            var blendCode     = new ShaderStringBuilder();
            var cullCode      = new ShaderStringBuilder();
            var zTestCode     = new ShaderStringBuilder();
            var zWriteCode    = new ShaderStringBuilder();
            var stencilCode   = new ShaderStringBuilder();
            var colorMaskCode = new ShaderStringBuilder();

            HDSubShaderUtilities.BuildRenderStatesFromPassAndMaterialOptions(pass, materialOptions, blendCode, cullCode, zTestCode, zWriteCode, stencilCode, colorMaskCode);

            HDRPShaderStructs.AddRequiredFields(pass.RequiredFields, activeFields);

            // apply dependencies to the active fields, and build interpolators (TODO: split this function)
            var packedInterpolatorCode = new ShaderGenerator();

            HDRPShaderStructs.Generate(
                packedInterpolatorCode,
                activeFields);

            // debug output all active fields
            var interpolatorDefines = new ShaderGenerator();
            {
                interpolatorDefines.AddShaderChunk("// ACTIVE FIELDS:");
                foreach (string f in activeFields)
                {
                    interpolatorDefines.AddShaderChunk("//   " + f);
                }
            }

            // build graph inputs structures
            ShaderGenerator pixelGraphInputs = new ShaderGenerator();

            ShaderSpliceUtil.BuildType(typeof(HDRPShaderStructs.SurfaceDescriptionInputs), activeFields, pixelGraphInputs);
            ShaderGenerator vertexGraphInputs = new ShaderGenerator();

            ShaderSpliceUtil.BuildType(typeof(HDRPShaderStructs.VertexDescriptionInputs), activeFields, vertexGraphInputs);

            ShaderGenerator defines = new ShaderGenerator();
            {
                defines.AddShaderChunk(string.Format("#define SHADERPASS {0}", pass.ShaderPassName), true);
                if (pass.ExtraDefines != null)
                {
                    foreach (var define in pass.ExtraDefines)
                    {
                        defines.AddShaderChunk(define);
                    }
                }
                defines.AddGenerator(interpolatorDefines);
            }

            var shaderPassIncludes = new ShaderGenerator();

            if (pass.Includes != null)
            {
                foreach (var include in pass.Includes)
                {
                    shaderPassIncludes.AddShaderChunk(include);
                }
            }


            // build graph code
            var graph = new ShaderGenerator();
            {
                graph.AddShaderChunk("// Shared Graph Properties (uniform inputs)");
                graph.AddShaderChunk(sharedProperties.GetPropertiesDeclaration(1));

                if (vertexActive)
                {
                    graph.AddShaderChunk("// Vertex Graph Inputs");
                    graph.Indent();
                    graph.AddGenerator(vertexGraphInputs);
                    graph.Deindent();
                    graph.AddShaderChunk("// Vertex Graph Outputs");
                    graph.Indent();
                    graph.AddShaderChunk(vertexGraphOutputs.ToString());
                    graph.Deindent();
                }

                graph.AddShaderChunk("// Pixel Graph Inputs");
                graph.Indent();
                graph.AddGenerator(pixelGraphInputs);
                graph.Deindent();
                graph.AddShaderChunk("// Pixel Graph Outputs");
                graph.Indent();
                graph.AddShaderChunk(pixelGraphOutputs.ToString());
                graph.Deindent();

                graph.AddShaderChunk("// Shared Graph Node Functions");
                graph.AddShaderChunk(graphNodeFunctions.ToString());

                if (vertexActive)
                {
                    graph.AddShaderChunk("// Vertex Graph Evaluation");
                    graph.Indent();
                    graph.AddShaderChunk(vertexGraphEvalFunction.ToString());
                    graph.Deindent();
                }

                graph.AddShaderChunk("// Pixel Graph Evaluation");
                graph.Indent();
                graph.AddShaderChunk(pixelGraphEvalFunction.ToString());
                graph.Deindent();
            }

            // build the hash table of all named fragments      TODO: could make this Dictionary<string, ShaderGenerator / string>  ?
            Dictionary <string, string> namedFragments = new Dictionary <string, string>();

            namedFragments.Add("${Defines}", defines.GetShaderString(2, false));
            namedFragments.Add("${Graph}", graph.GetShaderString(2, false));
            namedFragments.Add("${LightMode}", pass.LightMode);
            namedFragments.Add("${PassName}", pass.Name);
            namedFragments.Add("${Includes}", shaderPassIncludes.GetShaderString(2, false));
            namedFragments.Add("${InterpolatorPacking}", packedInterpolatorCode.GetShaderString(2, false));
            namedFragments.Add("${Blending}", blendCode.ToString());
            namedFragments.Add("${Culling}", cullCode.ToString());
            namedFragments.Add("${ZTest}", zTestCode.ToString());
            namedFragments.Add("${ZWrite}", zWriteCode.ToString());
            namedFragments.Add("${Stencil}", stencilCode.ToString());
            namedFragments.Add("${ColorMask}", colorMaskCode.ToString());
            namedFragments.Add("${LOD}", materialOptions.lod.ToString());

            // process the template to generate the shader code for this pass   TODO: could make this a shared function
            string[] templateLines            = File.ReadAllLines(templateLocation);
            System.Text.StringBuilder builder = new System.Text.StringBuilder();
            foreach (string line in templateLines)
            {
                ShaderSpliceUtil.PreprocessShaderCode(line, activeFields, namedFragments, builder);
                builder.AppendLine();
            }

            result.AddShaderChunk(builder.ToString(), false);

            return(true);
        }
Exemple #9
0
        /// <summary>
        /// Create a SMILES for a reaction of the flavour specified in the constructor and
        /// write the output order to the provided array.
        /// </summary>
        /// <param name="reaction">CDK reaction instance</param>
        /// <param name="ordering">order of output</param>
        /// <returns>reaction SMILES</returns>
        public string Create(IReaction reaction, int[] ordering)
        {
            var reactants = reaction.Reactants;
            var agents    = reaction.Agents;
            var products  = reaction.Products;

            var reactantPart = reaction.Builder.NewAtomContainer();
            var agentPart    = reaction.Builder.NewAtomContainer();
            var productPart  = reaction.Builder.NewAtomContainer();

            var sgroups = new List <Sgroup>();

            foreach (var reactant in reactants)
            {
                reactantPart.Add(reactant);
                SafeAddSgroups(sgroups, reactant);
            }
            foreach (var agent in agents)
            {
                agentPart.Add(agent);
                SafeAddSgroups(sgroups, agent);
            }
            foreach (var product in products)
            {
                productPart.Add(product);
                SafeAddSgroups(sgroups, product);
            }

            var reactantOrder = new int[reactantPart.Atoms.Count];
            var agentOrder    = new int[agentPart.Atoms.Count];
            var productOrder  = new int[productPart.Atoms.Count];

            var expectedSize = reactantOrder.Length + agentOrder.Length + productOrder.Length;

            if (expectedSize != ordering.Length)
            {
                throw new CDKException($"Output ordering array does not have correct amount of space: {ordering.Length} expected: {expectedSize}");
            }

            // we need to make sure we generate without the CXSMILES layers
            string smi = Create(reactantPart, flavour & ~SmiFlavors.CxSmilesWithCoords, reactantOrder) + ">" +
                         Create(agentPart, flavour & ~SmiFlavors.CxSmilesWithCoords, agentOrder) + ">" +
                         Create(productPart, flavour & ~SmiFlavors.CxSmilesWithCoords, productOrder);

            // copy ordering back to unified array and adjust values
            var agentBeg = reactantOrder.Length;
            var agentEnd = reactantOrder.Length + agentOrder.Length;
            var prodEnd  = reactantOrder.Length + agentOrder.Length + productOrder.Length;

            System.Array.Copy(reactantOrder, 0, ordering, 0, agentBeg);
            System.Array.Copy(agentOrder, 0, ordering, agentBeg, agentEnd - agentBeg);
            System.Array.Copy(productOrder, 0, ordering, agentEnd, prodEnd - agentEnd);
            for (int i = agentBeg; i < agentEnd; i++)
            {
                ordering[i] += agentBeg;
            }
            for (int i = agentEnd; i < prodEnd; i++)
            {
                ordering[i] += agentEnd;
            }

            if (SmiFlavorTool.IsSet(flavour, SmiFlavors.CxSmilesWithCoords))
            {
                var unified = reaction.Builder.NewAtomContainer();
                unified.Add(reactantPart);
                unified.Add(agentPart);
                unified.Add(productPart);
                unified.SetCtabSgroups(sgroups);

                // base CXSMILES state information
                var cxstate = GetCxSmilesState(flavour, unified);

                int[] components = null;

                // extra state info on fragment grouping, specific to reactions
                if (SmiFlavorTool.IsSet(flavour, SmiFlavors.CxFragmentGroup))
                {
                    cxstate.fragGroups = new List <List <int> >();

                    // calculate the connected components
                    components = new ConnectedComponents(GraphUtil.ToAdjList(unified)).GetComponents();

                    // AtomContainerSet is ordered so this is safe, it was actually a set we
                    // would need some extra data structures
                    var tmp = new HashSet <int>();
                    int beg = 0, end = 0;
                    foreach (var mol in reactants)
                    {
                        end = end + mol.Atoms.Count;
                        tmp.Clear();
                        for (int i = beg; i < end; i++)
                        {
                            tmp.Add(components[i]);
                        }
                        if (tmp.Count > 1)
                        {
                            cxstate.fragGroups.Add(new List <int>(tmp));
                        }
                        beg = end;
                    }
                    foreach (var mol in agents)
                    {
                        end = end + mol.Atoms.Count;
                        tmp.Clear();
                        for (int i = beg; i < end; i++)
                        {
                            tmp.Add(components[i]);
                        }
                        if (tmp.Count > 1)
                        {
                            cxstate.fragGroups.Add(new List <int>(tmp));
                        }
                        beg = end;
                    }
                    foreach (var mol in products)
                    {
                        end = end + mol.Atoms.Count;
                        tmp.Clear();
                        for (int i = beg; i < end; i++)
                        {
                            tmp.Add(components[i]);
                        }
                        if (tmp.Count > 1)
                        {
                            cxstate.fragGroups.Add(new List <int>(tmp));
                        }
                        beg = end;
                    }
                }

                smi += CxSmilesGenerator.Generate(cxstate, flavour, components, ordering);
            }

            return(smi);
        }
        public override void VisualiserUpdate()
        {
            base.VisualiserUpdate();

            if (Vertex.Get("ShowMeta:False") != null)
            {
                if (Vertex.Get(@"BaseEdge:\To:").Value != null)
                {
                    this.Title.Text = Vertex.Get(@"BaseEdge:\To:").Value.ToString();
                }
                else
                {
                    this.Title.Text = "Ø";
                }
            }
            else
            {
                string mtext, ttext;

                if (Vertex.Get(@"BaseEdge:\Meta:").Value != null)
                {
                    mtext = Vertex.Get(@"BaseEdge:\Meta:").Value.ToString();
                }
                else
                {
                    mtext = "Ø";
                }

                if (Vertex.Get(@"BaseEdge:\To:").Value != null)
                {
                    ttext = Vertex.Get(@"BaseEdge:\To:").Value.ToString();
                }
                else
                {
                    ttext = "Ø";
                }

                this.Title.Text = mtext + " : " + ttext;
            }



            if (Vertex.Get("RoundEdgeSize:") != null)
            {
                int esize = GraphUtil.GetIntegerValue(Vertex.Get("RoundEdgeSize:"));


                this.Frame.CornerRadius = new CornerRadius(esize);

                if (Vertex.Get("VisualiserClass:") != null)
                {
                    this.Title.Margin = new Thickness(esize, esize, esize, 0);

                    ((FrameworkElement)this.ContentVisualiser).Margin = new Thickness(esize, 0, esize, esize);

                    TheGrid.RowDefinitions[0].Height = new GridLength(18 + esize);
                }
                else
                {
                    this.Title.Margin = new Thickness(esize);

                    this.Title.TextWrapping = TextWrapping.Wrap;

                    TheGrid.RowDefinitions[0].Height = new GridLength(0, GridUnitType.Auto);

                    TheGrid.Children.Remove(InternalFrame);
                }
            }

            this.Frame.Background = BackgroundColor;

            this.Title.Foreground = ForegroundColor;

            this.InternalFrame.BorderBrush = ForegroundColor;

            this.Frame.BorderBrush = ForegroundColor;

            if (ContentVisualiser != null) // not always works, but can
            {
                GeneralUtil.SetPropertyIfPresent(ContentVisualiser, "Foreground", ForegroundColor);
                GeneralUtil.SetPropertyIfPresent(ContentVisualiser, "Background", BackgroundColor);
            }

            if (LineWidth != 0)
            {
                this.Frame.BorderThickness = new Thickness(LineWidth);

                if (ContentVisualiser != null)
                {
                    this.InternalFrame.BorderThickness = new Thickness(LineWidth / 2);

                    this.TheGrid.RowDefinitions[1].Height = new GridLength(LineWidth);
                }
            }
        }
Exemple #11
0
 /// <summary>
 /// Create a new RingSearch for the specified container.
 /// </summary>
 /// <param name="container">non-null input structure</param>
 /// <exception cref="ArgumentNullException">if the container was null</exception>
 /// <exception cref="ArgumentException">if the container contains a bond which references an atom which could not be found</exception>
 public RingSearch(IAtomContainer container)
     : this(container, GraphUtil.ToAdjList(container))
 {
 }
Exemple #12
0
        public int[] GetShortestHamiltonianCycle()
        {
            var cycles = GetAllHamiltorianCycles();

            return(cycles.Count == 0 ? null : GraphUtil.ShortestRoute(weights, cycles));
        }
Exemple #13
0
        protected override void VertexChange(object sender, VertexChangeEventArgs e)
        {
            if ((sender == Vertex) && (e.Type == VertexChangeType.EdgeAdded) && (GeneralUtil.CompareStrings(e.Edge.Meta.Value, "BaseEdge")) ||
                (sender == Vertex.Get("BaseEdge:") && e.Type == VertexChangeType.ValueChanged) ||
                ((sender == Vertex.Get("BaseEdge:")) && (e.Type == VertexChangeType.EdgeAdded) && ((GeneralUtil.CompareStrings(e.Edge.Meta.Value, "To")))))
            {
                UpdateBaseEdge();
            }

            if (sender == Vertex.Get(@"BaseEdge:\To:") && (e.Type == VertexChangeType.EdgeAdded || e.Type == VertexChangeType.EdgeRemoved))
            {
                UpdateBaseEdge();
            }

            if ((sender == Vertex) && (e.Type == VertexChangeType.EdgeAdded) && (GeneralUtil.CompareStrings(e.Edge.Meta.Value, "ToShowEdgesMeta")))
            {
                UpdateBaseEdge();
            }

            //if (sender == Vertex.Get(@"ToShowEdgesMeta:") && (e.Type == VertexChangeType.EdgeAdded || e.Type == VertexChangeType.EdgeRemoved))
            //  UpdateBaseEdge();
            // there is update loop with this, so commenting out and leaving only what is above

            if ((sender == Vertex) && (e.Type == VertexChangeType.EdgeAdded) && (GeneralUtil.CompareStrings(e.Edge.Meta.Value, "SelectedEdges")))
            {
                SelectedVertexesUpdated();
            }

            if ((sender == Vertex.Get("SelectedEdges:")) && ((e.Type == VertexChangeType.EdgeAdded) || (e.Type == VertexChangeType.EdgeRemoved)))
            {
                SelectedVertexesUpdated();
            }

            if (sender is IVertex && GraphUtil.FindEdgeByToVertex(Vertex.GetAll(@"SelectedEdges:\"), (IVertex)sender) != null)
            {
                SelectedVertexesUpdated();
            }

            if (sender == Vertex.Get("IsMetaRightAlign:") && e.Type == VertexChangeType.ValueChanged)
            {
                ResetView();
            }

            if (sender == Vertex.Get("IsAllVisualisersEdit:") && e.Type == VertexChangeType.ValueChanged)
            {
                ResetView();
            }

            if (sender == Vertex.Get("ZoomVisualiserContent:") && e.Type == VertexChangeType.ValueChanged)
            {
                ChangeZoomVisualiserContent();
            }

            if (sender == Vertex.Get("FilterQuery:") && e.Type == VertexChangeType.ValueChanged)
            {
                UpdateBaseEdge();
            }

            if (sender == Vertex.Get("ExpertMode:") && e.Type == VertexChangeType.ValueChanged)
            {
                UpdateBaseEdge();
            }

            if ((sender == Vertex) && (e.Type == VertexChangeType.EdgeAdded) && (GeneralUtil.CompareStrings(e.Edge.Meta.Value, "FilterQuery")))
            {
                UpdateBaseEdge();
            }

            if (sender == Vertex.Get("ShowHeader:") && e.Type == VertexChangeType.ValueChanged)
            {
                ResetView();
            }

            if (sender == Vertex.Get("AlternatingRows:") && e.Type == VertexChangeType.ValueChanged)
            {
                ResetView();
            }

            if ((sender == Vertex) && (e.Type == VertexChangeType.EdgeAdded) && (GeneralUtil.CompareStrings(e.Edge.Meta.Value, "ShowHeader")))
            {
                ResetView();
            }
        }
Exemple #14
0
        protected override void UpdateBaseEdge()
        {
            IVertex bas = Vertex.Get(@"BaseEdge:\To:");

            if (bas != null)
            {
                ToShowEdgesMeta = null;

                if (Vertex.Get(@"ToShowEdgesMeta:\Meta:") != null)
                {
                    ToShowEdgesMeta = Vertex.Get(@"ToShowEdgesMeta:\Meta:");
                }

                if (ToShowEdgesMeta == null) // take first edge from BaseEdge\To, to have Meta as ToShowEdesMeta:\Meta:==null
                {
                    IEdge e = bas.FirstOrDefault();

                    if (e != null)
                    {
                        ToShowEdgesMeta = e.Meta;

                        VertexChangeListenOff();

                        Edge.AddEdgeEdges(Vertex.Get(@"ToShowEdgesMeta:"), e);

                        VertexChangeListenOn();
                    }
                }

                if (ToShowEdgesMeta != null)
                {
                    ((EasyVertex)Vertex.Get(@"FilterQuery:")).CanFireChangeEvent = false;

                    Vertex.Get(@"FilterQuery:").Value = ToShowEdgesMeta.Value + ":";

                    ((EasyVertex)Vertex.Get(@"FilterQuery:")).CanFireChangeEvent = true;
                }


                if (Vertex.Get(@"FilterQuery:") != null && Vertex.Get(@"FilterQuery:").Value != null) // do the filtering
                {
                    IVertex data = VertexOperations.DoFilter(bas, Vertex.Get(@"FilterQuery:"));

                    if (data != null)
                    {
                        ThisDataGrid.ItemsSource = data.ToList();
                    }
                    else
                    {
                        ThisDataGrid.ItemsSource = null;
                    }
                }
                else
                {
                    ThisDataGrid.ItemsSource = bas.ToList(); // if there is no .ToList DataGrid can not edit
                }
                if (GraphUtil.GetValueAndCompareStrings(Vertex.Get("ExpertMode:"), "True"))
                {
                    ExpertMode = true;
                }
                else
                {
                    ExpertMode = false;
                }

                ResetView();
            }
        }
Exemple #15
0
        public void OnAfterDeserialize()
        {
            var nodes = SerializationHelper.Deserialize <AbstractMaterialNode>(m_SerializableNodes, GraphUtil.GetLegacyTypeRemapping());

            m_Nodes.Clear();
            foreach (var node in nodes)
            {
                m_Nodes.Add(node);
            }
            m_SerializableNodes = null;

            var edges = SerializationHelper.Deserialize <IEdge>(m_SerializableEdges, GraphUtil.GetLegacyTypeRemapping());

            m_Edges.Clear();
            foreach (var edge in edges)
            {
                m_Edges.Add(edge);
            }
            m_SerializableEdges = null;

            var inputs = SerializationHelper.Deserialize <ShaderInput>(m_SerilaizeableInputs, GraphUtil.GetLegacyTypeRemapping());

            m_Inputs.Clear();
            foreach (var input in inputs)
            {
                m_Inputs.Add(input);
            }
            m_SerilaizeableInputs = null;

            var metaProperties = SerializationHelper.Deserialize <AbstractShaderProperty>(m_SerializableMetaProperties, GraphUtil.GetLegacyTypeRemapping());

            m_MetaProperties.Clear();
            foreach (var metaProperty in metaProperties)
            {
                m_MetaProperties.Add(metaProperty);
            }
            m_SerializableMetaProperties = null;
        }
Exemple #16
0
        public void TestSerializationHelperElementCanSerialize()
        {
            var toSerialize = new List <SimpleSerializeClass>()
            {
                SimpleSerializeClass.instance
            };

            var serialized = SerializationHelper.Serialize <SimpleSerializeClass>(toSerialize);

            Assert.AreEqual(1, serialized.Count);

            var container = new SerializationContainer
            {
                serializedElements = serialized
            };

            var serializedContainer = JsonUtility.ToJson(container, true);

            var deserializedContainer = JsonUtility.FromJson <SerializationContainer>(serializedContainer);
            var loaded = SerializationHelper.Deserialize <SimpleSerializeClass>(deserializedContainer.serializedElements, GraphUtil.GetLegacyTypeRemapping());

            Assert.AreEqual(1, loaded.Count);
            Assert.IsInstanceOf <SimpleSerializeClass>(loaded[0]);
            loaded[0].AssertAsReference();
        }
Exemple #17
0
        public void OnAfterDeserialize()
        {
            var deserializedGraph = SerializationHelper.Deserialize <GraphData>(m_SerializedGraph, GraphUtil.GetLegacyTypeRemapping());

            deserializedGraph.isSubGraph = m_IsSubGraph;
            if (graph == null)
            {
                graph = deserializedGraph;
            }
            else
            {
                m_DeserializedGraph = deserializedGraph;
            }
        }
Exemple #18
0
        public void TestSerializableSlotCanSerialize()
        {
            var toSerialize = new List <MaterialSlot>()
            {
                new TestSlot(0, "InSlot", SlotType.Input, 0),
                new TestSlot(1, "OutSlot", SlotType.Output, 5),
            };

            var serialized = SerializationHelper.Serialize <MaterialSlot>(toSerialize);
            var loaded     = SerializationHelper.Deserialize <MaterialSlot>(serialized, GraphUtil.GetLegacyTypeRemapping());

            Assert.AreEqual(2, loaded.Count);

            Assert.IsInstanceOf <MaterialSlot>(loaded[0]);
            Assert.IsInstanceOf <MaterialSlot>(loaded[1]);

            Assert.AreEqual(0, loaded[0].id);
            Assert.AreEqual("InSlot", loaded[0].displayName);
            Assert.IsTrue(loaded[0].isInputSlot);
            Assert.AreEqual(0, loaded[0].priority);

            Assert.AreEqual(1, loaded[1].id);
            Assert.AreEqual("OutSlot", loaded[1].displayName);
            Assert.IsTrue(loaded[1].isOutputSlot);
            Assert.AreEqual(5, loaded[1].priority);
        }
Exemple #19
0
    // Use this for initialization
    void Start()
    {
        m_Graph = new GraphUtil(500, 250);
        m_CellCountLog = new List<int>();
        m_CellMap = new GameObject[width * height];

        for(int n = 0; n < m_CellMap.Length; ++n)
        {
            m_CellMap[n] = null;
        }
        for(int n = 0; n < width * height * first_cell_percent / 100; ++n)
        {
            int target = Random.Range(0, width * height - 1);
            if(m_CellMap[target] == null)
            {
                m_CellMap[target] = CreateNewCell(target % width, target / width, Quaternion.identity);
            }
        }
    }
        internal static void AddCustomInterpolatorProperties(VisualElement parentElement, BlockNode node, Action setNodesAsDirtyCallback, Action updateNodeViewsCallback)
        {
            if (!node.isCustomBlock)
            {
                return;
            }

            TextField textField = null;
            {
                textField = new TextField {
                    value = node.customName, multiline = false
                };
                var propertyRow = new PropertyRow(new Label("Name"));
                propertyRow.Add(textField, (field) =>
                {
                    field.RegisterCallback <FocusOutEvent>(evt =>
                    {
                        if (field.value.Equals(node.customName))
                        {
                            return;
                        }

                        HashSet <string> usedNames = new HashSet <string>();
                        foreach (var other in node.contextData.blocks)
                        {
                            if (other != node)
                            {
                                usedNames.Add(other.value.descriptor.displayName);
                            }
                        }

                        setNodesAsDirtyCallback?.Invoke();
                        node.owner.owner.RegisterCompleteObjectUndo("Change Block Name");
                        field.value = node.customName = GraphUtil.SanitizeName(usedNames, "{0}_{1}", NodeUtils.ConvertToValidHLSLIdentifier(field.value));
                        updateNodeViewsCallback?.Invoke();
                        node.Dirty(ModificationScope.Node);
                        node.owner?.ValidateGraph();
                    });
                });
                parentElement.Add(propertyRow);
            }

            EnumField typeField = null;
            {
                typeField = new EnumField(node.customWidth);
                var propertyRow = new PropertyRow(new Label("Type"));
                propertyRow.Add(typeField, (field) =>
                {
                    field.RegisterValueChangedCallback(evt =>
                    {
                        if (evt.newValue.Equals(node.customWidth))
                        {
                            return;
                        }

                        setNodesAsDirtyCallback?.Invoke();
                        node.owner.owner.RegisterCompleteObjectUndo("Change Block Type");
                        node.customWidth = (BlockNode.CustomBlockType)evt.newValue;
                        updateNodeViewsCallback?.Invoke();
                        node.Dirty(ModificationScope.Topological);
                        node.owner?.ValidateGraph();
                    });
                });
                parentElement.Add(propertyRow);
            }
        }
Exemple #21
0
        static string GetExtraPassesFromTemplate(string template, UnlitMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions)
        {
            // ----------------------------------------------------- //
            //                         SETUP                         //
            // ----------------------------------------------------- //

            // -------------------------------------
            // String builders

            var dummyBuilder     = new ShaderStringBuilder(0);
            var shaderProperties = new PropertyCollector();
            var functionBuilder  = new ShaderStringBuilder(1);
            var functionRegistry = new FunctionRegistry(functionBuilder);

            var defines = new ShaderStringBuilder(2);
            var graph   = new ShaderStringBuilder(0);

            var vertexDescriptionInputStruct = new ShaderStringBuilder(1);
            var vertexDescriptionStruct      = new ShaderStringBuilder(1);
            var vertexDescriptionFunction    = new ShaderStringBuilder(1);

            var vertexInputStruct = new ShaderStringBuilder(1);

            var vertexShader            = new ShaderStringBuilder(2);
            var vertexDescriptionInputs = new ShaderStringBuilder(2);

            // -------------------------------------
            // Get Slot and Node lists per stage

            var vertexSlots = pass.VertexShaderSlots.Select(masterNode.FindSlot <MaterialSlot>).ToList();
            var vertexNodes = ListPool <AbstractMaterialNode> .Get();

            NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots);

            // -------------------------------------
            // Get requirements

            var vertexRequirements = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false);

            var modelRequiements = ShaderGraphRequirements.none;

            modelRequiements.requiresNormal   |= m_VertexCoordinateSpace;
            modelRequiements.requiresPosition |= m_VertexCoordinateSpace;
            modelRequiements.requiresMeshUVs.Add(UVChannel.UV1);

            // ----------------------------------------------------- //
            //                START SHADER GENERATION                //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Calculate material options

            var cullingBuilder = new ShaderStringBuilder(1);

            materialOptions.GetCull(cullingBuilder);

            // -------------------------------------
            // Generate defines

            if (masterNode.IsSlotConnected(PBRMasterNode.AlphaThresholdSlotId))
            {
                defines.AppendLine("#define _AlphaClip 1");
            }

            // ----------------------------------------------------- //
            //                START VERTEX DESCRIPTION               //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Generate Input structure for Vertex Description function
            // TODO - Vertex Description Input requirements are needed to exclude intermediate translation spaces

            vertexDescriptionInputStruct.AppendLine("struct VertexDescriptionInputs");
            using (vertexDescriptionInputStruct.BlockSemicolonScope())
            {
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresNormal, InterpolatorType.Normal, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresTangent, InterpolatorType.Tangent, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresBitangent, InterpolatorType.BiTangent, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresViewDir, InterpolatorType.ViewDirection, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresPosition, InterpolatorType.Position, vertexDescriptionInputStruct);

                if (vertexRequirements.requiresVertexColor)
                {
                    vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
                }

                if (vertexRequirements.requiresScreenPosition)
                {
                    vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
                }

                foreach (var channel in vertexRequirements.requiresMeshUVs.Distinct())
                {
                    vertexDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
                }
            }

            // -------------------------------------
            // Generate Output structure for Vertex Description function

            GraphUtil.GenerateVertexDescriptionStruct(vertexDescriptionStruct, vertexSlots);

            // -------------------------------------
            // Generate Vertex Description function

            GraphUtil.GenerateVertexDescriptionFunction(
                masterNode.owner as AbstractMaterialGraph,
                vertexDescriptionFunction,
                functionRegistry,
                shaderProperties,
                mode,
                vertexNodes,
                vertexSlots);

            // ----------------------------------------------------- //
            //           GENERATE VERTEX > PIXEL PIPELINE            //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Generate Input structure for Vertex shader

            GraphUtil.GenerateApplicationVertexInputs(vertexRequirements.Union(modelRequiements), vertexInputStruct);

            // -------------------------------------
            // Generate standard transformations
            // This method ensures all required transform data is available in vertex and pixel stages

            ShaderGenerator.GenerateStandardTransforms(
                3,
                10,
                dummyBuilder,
                vertexShader,
                vertexDescriptionInputs,
                dummyBuilder,
                dummyBuilder,
                dummyBuilder,
                ShaderGraphRequirements.none,
                ShaderGraphRequirements.none,
                modelRequiements,
                vertexRequirements,
                CoordinateSpace.World);

            // ----------------------------------------------------- //
            //                      FINALIZE                         //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Combine Graph sections

            graph.AppendLine(shaderProperties.GetPropertiesDeclaration(1));

            graph.AppendLine(vertexDescriptionInputStruct.ToString());

            graph.AppendLine(functionBuilder.ToString());

            graph.AppendLine(vertexDescriptionStruct.ToString());
            graph.AppendLine(vertexDescriptionFunction.ToString());

            graph.AppendLine(vertexInputStruct.ToString());

            // -------------------------------------
            // Generate final subshader

            var resultPass = template.Replace("${Culling}", cullingBuilder.ToString());

            resultPass = resultPass.Replace("${Defines}", defines.ToString());
            resultPass = resultPass.Replace("${Graph}", graph.ToString());
            resultPass = resultPass.Replace("${VertexShader}", vertexShader.ToString());
            resultPass = resultPass.Replace("${VertexShaderDescriptionInputs}", vertexDescriptionInputs.ToString());

            return(resultPass);
        }
Exemple #22
0
        public void CreateBirdFormGos(bool posttransform = false)
        {
            Transform pvt = null;

            if (birdformgo != null)
            {
                pvt = birdformgo.transform;
                Destroy(birdformgo);
                birdformgo = null;
            }
            var shrink = 1f;

            if (posttransform)
            {
                // todo: we should probably be translating and rotating too
                //       so we need to test shifted scenes (like when we do error correction)
                //       with "change bird form"
                shrink = rman.rgoScale;
            }
            switch (birdform)
            {
            case BirdFormE.sphere:
            {
                var sphsize = shrink * 0.2f;
                birdformgo = GraphUtil.CreateMarkerSphere("sphere", Vector3.zero, size: sphsize, clr: "yellow");
                break;
            }

            case BirdFormE.olive:
            {
                birdformgo = GraphUtil.CreateMarkerSphere("sphere", Vector3.zero, size: 0.2f, clr: "olive");
                birdformgo.transform.localScale = shrink * (new Vector3(0.2f, 0.2f, 0.28f));

                var nosept = shrink * (new Vector3(0, 0, 0.1f));
                var gonose = GraphUtil.CreateMarkerSphere("nose", nosept, size: shrink * 0.1f, clr: "red");
                gonose.transform.parent = birdformgo.transform;
                break;
            }

            default:
            case BirdFormE.hummingbird:
            {
                var objPrefab = (GameObject)Resources.Load("hummingbird");
                birdformgo = Instantiate(objPrefab) as GameObject;
                var s        = shrink * 0.5e-3f;
                var minscale = 0.1375f * s;         // value experimentally discovered
                if (s * rman.rgoScale < minscale)
                {
                    s = minscale / rman.rgoScale;
                }
                birdformgo.transform.localScale = new Vector3(s, s, s);
                break;
            }

            case BirdFormE.utahteapot:
            {
                var objPrefab = (GameObject)Resources.Load("teapot");
                birdformgo = Instantiate(objPrefab) as GameObject;
                birdformgo.GetComponent <Renderer>().material.SetColor("_Color", GraphUtil.getcolorbyname("chinawhite"));
                var s = shrink * 60.0f;
                birdformgo.transform.localScale = new Vector3(s, s, s);
                birdformgo.transform.Rotate(0, 90, 0);
                break;
            }
            }
            var pt   = birdgo.transform.position;
            var text = "Hummingbird\n" + pt;

            addFloatingText(birdgo, pt, text, "yellow");
            if (posttransform)
            {
                //rman.GlobInvTransGo(birdformgo);
                //var s = rman.rgoScale;
                //birdformgo.transform.localScale = new Vector3(s, s, s);
                //birdformgo.transform.Rotate(0, rman.rgoRotate, 0);
                //birdformgo.transform.Translate(rman.rgoTranslate);
            }
            birdformgo.transform.parent = birdgo.transform;
        }
Exemple #23
0
 void getDepth()
 {
     GraphUtil.GetVertexDepths(_graph, SourceRO(), Depth);
 }
        public void OnAfterDeserialize()
        {
            m_SourceGraphGuid = SerializationHelper.Deserialize <SerializableGuid>(m_SerializeableSourceGraphGuid, GraphUtil.GetLegacyTypeRemapping());

            var nodes = SerializationHelper.Deserialize <INode>(m_SerializableNodes, GraphUtil.GetLegacyTypeRemapping());

            m_Nodes.Clear();
            foreach (var node in nodes)
            {
                m_Nodes.Add(node);
            }
            m_SerializableNodes = null;

            var edges = SerializationHelper.Deserialize <IEdge>(m_SerializableEdges, GraphUtil.GetLegacyTypeRemapping());

            m_Edges.Clear();
            foreach (var edge in edges)
            {
                m_Edges.Add(edge);
            }
            m_SerializableEdges = null;

            var properties = SerializationHelper.Deserialize <IShaderProperty>(m_SerilaizeableProperties, GraphUtil.GetLegacyTypeRemapping());

            m_Properties.Clear();
            foreach (var property in properties)
            {
                m_Properties.Add(property);
            }
            m_SerilaizeableProperties = null;

            var metaProperties = SerializationHelper.Deserialize <IShaderProperty>(m_SerializableMetaProperties, GraphUtil.GetLegacyTypeRemapping());

            m_MetaProperties.Clear();
            foreach (var metaProperty in metaProperties)
            {
                m_MetaProperties.Add(metaProperty);
            }
            m_SerializableMetaProperties = null;
        }
        void AttachQuadImageToBackground()
        {
            DeactivateBackgroundImage();
            var o     = 0.5f;
            var w     = Screen.width + 0.5f;
            var h     = Screen.height + 0.5f;
            var gap   = 0.1f;
            var zdist = cam.farClipPlane - gap;

            var pos   = cam.transform.position;
            var pos00 = cam.ScreenToWorldPoint(new Vector3(o, o, zdist));
            var pos01 = cam.ScreenToWorldPoint(new Vector3(o, h, zdist));
            var pos10 = cam.ScreenToWorldPoint(new Vector3(w, o, zdist));
            var pos11 = cam.ScreenToWorldPoint(new Vector3(w, h, zdist));
            var poscn = cam.transform.position + cam.transform.forward * zdist;



            pos00 = Vector3.Lerp(pos, pos00, lamb);
            pos01 = Vector3.Lerp(pos, pos01, lamb);
            pos10 = Vector3.Lerp(pos, pos10, lamb);
            pos11 = Vector3.Lerp(pos, pos11, lamb);
            poscn = Vector3.Lerp(pos, poscn, lamb);

            quadgo = GameObject.CreatePrimitive(PrimitiveType.Quad);
            quadgo.transform.position      = poscn;
            quadgo.transform.localRotation = camgo.transform.localRotation;
            quadgo.transform.parent        = camgo.transform;
            quadgo.transform.localScale    = new Vector3(Vector3.Magnitude(pos10 - pos00), Vector3.Magnitude(pos01 - pos00), 1);

            if (showSpheres)
            {
                var sgo00 = GraphUtil.CreateMarkerSphere("csph-00", pos00, 20, "purple");
                sgo00.transform.parent = quadgo.transform;
                var sgo01 = GraphUtil.CreateMarkerSphere("csph-01", pos01, 20, "purple");
                sgo01.transform.parent = quadgo.transform;
                var sgo10 = GraphUtil.CreateMarkerSphere("csph-10", pos10, 20, "purple");
                sgo10.transform.parent = quadgo.transform;
                var sgo11 = GraphUtil.CreateMarkerSphere("csph-11", pos11, 20, "purple");
                sgo11.transform.parent = quadgo.transform;
                var sgo = GraphUtil.CreateMarkerSphere("csph-cen", poscn, 30, "purple");
                sgo.transform.parent = quadgo.transform;
            }

            bool addLight = false;

            if (addLight)
            {
                var lightob = new GameObject("quadlight");
                var dlight  = lightob.AddComponent <Light>();
                dlight.type = LightType.Directional;
                lightob.transform.SetParent(quadgo.transform);
                lightob.transform.localRotation = Quaternion.Euler(66, 0, 0);
            }

            if (showBackground)
            {
                var tex  = LoadImage();
                var rend = quadgo.GetComponent <Renderer>();
                rend.material.mainTexture = tex;
            }
        }
Exemple #26
0
        private static bool GenerateShaderPass(PBRMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions, ShaderGenerator result)
        {
            var templateLocation = Path.Combine(Path.Combine(Path.Combine(HDEditorUtils.GetHDRenderPipelinePath(), "Editor"), "ShaderGraph"), pass.TemplateName);

            if (!File.Exists(templateLocation))
            {
                // TODO: produce error here
                return(false);
            }

            // grab all of the active nodes
            var activeNodeList = ListPool <INode> .Get();

            NodeUtils.DepthFirstCollectNodesFromNode(activeNodeList, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots);

            // graph requirements describe what the graph itself requires
            var graphRequirements = ShaderGraphRequirements.FromNodes(activeNodeList, ShaderStageCapability.Fragment);

            ShaderStringBuilder graphNodeFunctions = new ShaderStringBuilder();

            graphNodeFunctions.IncreaseIndent();
            var functionRegistry = new FunctionRegistry(graphNodeFunctions);

            // Build the list of active slots based on what the pass requires
            // TODO: this can be a shared function -- From here through GraphUtil.GenerateSurfaceDescription(..)
            var activeSlots = new List <MaterialSlot>();

            foreach (var id in pass.PixelShaderSlots)
            {
                MaterialSlot slot = masterNode.FindSlot <MaterialSlot>(id);
                if (slot != null)
                {
                    activeSlots.Add(slot);
                }
            }

            // build the graph outputs structure to hold the results of each active slots (and fill out activeFields to indicate they are active)
            string graphInputStructName           = "SurfaceDescriptionInputs";
            string graphOutputStructName          = "SurfaceDescription";
            string graphEvalFunctionName          = "SurfaceDescriptionFunction";
            ShaderStringBuilder graphEvalFunction = new ShaderStringBuilder();
            ShaderStringBuilder graphOutputs      = new ShaderStringBuilder();
            PropertyCollector   graphProperties   = new PropertyCollector();

            // build the graph outputs structure, and populate activeFields with the fields of that structure
            HashSet <string> activeFields = new HashSet <string>();

            GraphUtil.GenerateSurfaceDescriptionStruct(graphOutputs, activeSlots, true);
            //GraphUtil.GenerateSurfaceDescriptionStruct(graphOutputs, activeSlots, true, graphOutputStructName, activeFields);

            // Build the graph evaluation code, to evaluate the specified slots
            GraphUtil.GenerateSurfaceDescriptionFunction(
                activeNodeList,
                masterNode,
                masterNode.owner as AbstractMaterialGraph,
                graphEvalFunction,
                functionRegistry,
                graphProperties,
                graphRequirements,  // TODO : REMOVE UNUSED
                mode,
                graphEvalFunctionName,
                graphOutputStructName,
                null,
                activeSlots,
                graphInputStructName);

            var blendCode     = new ShaderStringBuilder();
            var cullCode      = new ShaderStringBuilder();
            var zTestCode     = new ShaderStringBuilder();
            var zWriteCode    = new ShaderStringBuilder();
            var stencilCode   = new ShaderStringBuilder();
            var colorMaskCode = new ShaderStringBuilder();

            HDSubShaderUtilities.BuildRenderStatesFromPassAndMaterialOptions(pass, materialOptions, blendCode, cullCode, zTestCode, zWriteCode, stencilCode, colorMaskCode);

            if (masterNode.twoSided.isOn)
            {
                activeFields.Add("DoubleSided");
                if (pass.ShaderPassName != "SHADERPASS_VELOCITY")   // HACK to get around lack of a good interpolator dependency system
                {                                                   // we need to be able to build interpolators using multiple input structs
                                                                    // also: should only require isFrontFace if Normals are required...
                    activeFields.Add("DoubleSided.Mirror");         // TODO: change this depending on what kind of normal flip you want..
                    activeFields.Add("FragInputs.isFrontFace");     // will need this for determining normal flip mode
                }
            }

            if (pass.PixelShaderSlots != null)
            {
                foreach (var slotId in pass.PixelShaderSlots)
                {
                    var slot = masterNode.FindSlot <MaterialSlot>(slotId);
                    if (slot != null)
                    {
                        var rawSlotName    = slot.RawDisplayName().ToString();
                        var descriptionVar = string.Format("{0}.{1}", graphOutputStructName, rawSlotName);
                        activeFields.Add(descriptionVar);
                    }
                }
            }

            var packedInterpolatorCode = new ShaderGenerator();
            var graphInputs            = new ShaderGenerator();

            HDRPShaderStructs.Generate(
                packedInterpolatorCode,
                graphInputs,
                graphRequirements,
                pass.RequiredFields,
                CoordinateSpace.World,
                activeFields);

            // debug output all active fields
            var interpolatorDefines = new ShaderGenerator();
            {
                interpolatorDefines.AddShaderChunk("// ACTIVE FIELDS:");
                foreach (string f in activeFields)
                {
                    interpolatorDefines.AddShaderChunk("//   " + f);
                }
            }

            ShaderGenerator defines = new ShaderGenerator();
            {
                defines.AddShaderChunk(string.Format("#define SHADERPASS {0}", pass.ShaderPassName), true);
                if (pass.ExtraDefines != null)
                {
                    foreach (var define in pass.ExtraDefines)
                    {
                        defines.AddShaderChunk(define);
                    }
                }
                defines.AddGenerator(interpolatorDefines);
            }

            var shaderPassIncludes = new ShaderGenerator();

            if (pass.Includes != null)
            {
                foreach (var include in pass.Includes)
                {
                    shaderPassIncludes.AddShaderChunk(include);
                }
            }


            // build graph code
            var graph = new ShaderGenerator();

            graph.AddShaderChunk("// Graph Inputs");
            graph.Indent();
            graph.AddGenerator(graphInputs);
            graph.Deindent();
            graph.AddShaderChunk("// Graph Outputs");
            graph.Indent();
            graph.AddShaderChunk(graphOutputs.ToString());
            //graph.AddGenerator(graphOutputs);
            graph.Deindent();
            graph.AddShaderChunk("// Graph Properties (uniform inputs)");
            graph.AddShaderChunk(graphProperties.GetPropertiesDeclaration(1));
            graph.AddShaderChunk("// Graph Node Functions");
            graph.AddShaderChunk(graphNodeFunctions.ToString());
            graph.AddShaderChunk("// Graph Evaluation");
            graph.Indent();
            graph.AddShaderChunk(graphEvalFunction.ToString());
            //graph.AddGenerator(graphEvalFunction);
            graph.Deindent();

            // build the hash table of all named fragments      TODO: could make this Dictionary<string, ShaderGenerator / string>  ?
            Dictionary <string, string> namedFragments = new Dictionary <string, string>();

            namedFragments.Add("${Defines}", defines.GetShaderString(2, false));
            namedFragments.Add("${Graph}", graph.GetShaderString(2, false));
            namedFragments.Add("${LightMode}", pass.LightMode);
            namedFragments.Add("${PassName}", pass.Name);
            namedFragments.Add("${Includes}", shaderPassIncludes.GetShaderString(2, false));
            namedFragments.Add("${InterpolatorPacking}", packedInterpolatorCode.GetShaderString(2, false));
            namedFragments.Add("${Blending}", blendCode.ToString());
            namedFragments.Add("${Culling}", cullCode.ToString());
            namedFragments.Add("${ZTest}", zTestCode.ToString());
            namedFragments.Add("${ZWrite}", zWriteCode.ToString());
            namedFragments.Add("${Stencil}", stencilCode.ToString());
            namedFragments.Add("${ColorMask}", colorMaskCode.ToString());
            namedFragments.Add("${LOD}", materialOptions.lod.ToString());
            namedFragments.Add("${VariantDefines}", GetVariantDefines(masterNode));

            // process the template to generate the shader code for this pass   TODO: could make this a shared function
            string[] templateLines            = File.ReadAllLines(templateLocation);
            System.Text.StringBuilder builder = new System.Text.StringBuilder();
            foreach (string line in templateLines)
            {
                ShaderSpliceUtil.PreprocessShaderCode(line, activeFields, namedFragments, builder);
                builder.AppendLine();
            }

            result.AddShaderChunk(builder.ToString(), false);

            return(true);
        }
        static string GetShaderPassFromTemplate(string template, UnlitMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions)
        {
            // ----------------------------------------------------- //
            //                         SETUP                         //
            // ----------------------------------------------------- //

            // -------------------------------------
            // String builders

            var shaderProperties = new PropertyCollector();
            var functionBuilder  = new ShaderStringBuilder(1);
            var functionRegistry = new FunctionRegistry(functionBuilder);

            var defines = new ShaderStringBuilder(1);
            var graph   = new ShaderStringBuilder(0);

            var vertexDescriptionInputStruct = new ShaderStringBuilder(1);
            var vertexDescriptionStruct      = new ShaderStringBuilder(1);
            var vertexDescriptionFunction    = new ShaderStringBuilder(1);

            var surfaceDescriptionInputStruct = new ShaderStringBuilder(1);
            var surfaceDescriptionStruct      = new ShaderStringBuilder(1);
            var surfaceDescriptionFunction    = new ShaderStringBuilder(1);

            var vertexInputStruct  = new ShaderStringBuilder(1);
            var vertexOutputStruct = new ShaderStringBuilder(2);

            var vertexShader = new ShaderStringBuilder(2);
            var vertexShaderDescriptionInputs = new ShaderStringBuilder(2);
            var vertexShaderOutputs           = new ShaderStringBuilder(2);

            var pixelShader = new ShaderStringBuilder(2);
            var pixelShaderSurfaceInputs = new ShaderStringBuilder(2);
            var pixelShaderSurfaceRemap  = new ShaderStringBuilder(2);

            // -------------------------------------
            // Get Slot and Node lists per stage

            var vertexSlots = pass.VertexShaderSlots.Select(masterNode.FindSlot <MaterialSlot>).ToList();
            var vertexNodes = ListPool <INode> .Get();

            NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots);

            var pixelSlots = pass.PixelShaderSlots.Select(masterNode.FindSlot <MaterialSlot>).ToList();
            var pixelNodes = ListPool <INode> .Get();

            NodeUtils.DepthFirstCollectNodesFromNode(pixelNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.PixelShaderSlots);

            // -------------------------------------
            // Get Requirements

            var vertexRequirements  = ShaderGraphRequirements.FromNodes(vertexNodes, ShaderStageCapability.Vertex, false);
            var pixelRequirements   = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment);
            var graphRequirements   = pixelRequirements.Union(vertexRequirements);
            var surfaceRequirements = ShaderGraphRequirements.FromNodes(pixelNodes, ShaderStageCapability.Fragment, false);

            var modelRequiements = ShaderGraphRequirements.none;

            modelRequiements.requiresNormal    |= k_PixelCoordinateSpace;
            modelRequiements.requiresTangent   |= k_PixelCoordinateSpace;
            modelRequiements.requiresBitangent |= k_PixelCoordinateSpace;
            modelRequiements.requiresPosition  |= k_PixelCoordinateSpace;
            modelRequiements.requiresViewDir   |= k_PixelCoordinateSpace;
            modelRequiements.requiresMeshUVs.Add(UVChannel.UV1);

            // ----------------------------------------------------- //
            //                START SHADER GENERATION                //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Calculate material options

            var blendingBuilder = new ShaderStringBuilder(1);
            var cullingBuilder  = new ShaderStringBuilder(1);
            var zTestBuilder    = new ShaderStringBuilder(1);
            var zWriteBuilder   = new ShaderStringBuilder(1);

            materialOptions.GetBlend(blendingBuilder);
            materialOptions.GetCull(cullingBuilder);
            materialOptions.GetDepthTest(zTestBuilder);
            materialOptions.GetDepthWrite(zWriteBuilder);

            // -------------------------------------
            // Generate defines

            if (masterNode.IsSlotConnected(UnlitMasterNode.AlphaThresholdSlotId))
            {
                defines.AppendLine("#define _AlphaClip 1");
            }

            if (masterNode.surfaceType == SurfaceType.Transparent && masterNode.alphaMode == AlphaMode.Premultiply)
            {
                defines.AppendLine("#define _ALPHAPREMULTIPLY_ON 1");
            }

            if (graphRequirements.requiresDepthTexture)
            {
                defines.AppendLine("#define REQUIRE_DEPTH_TEXTURE");
            }

            if (graphRequirements.requiresCameraOpaqueTexture)
            {
                defines.AppendLine("#define REQUIRE_OPAQUE_TEXTURE");
            }

            // ----------------------------------------------------- //
            //                START VERTEX DESCRIPTION               //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Generate Input structure for Vertex Description function
            // TODO - Vertex Description Input requirements are needed to exclude intermediate translation spaces

            vertexDescriptionInputStruct.AppendLine("struct VertexDescriptionInputs");
            using (vertexDescriptionInputStruct.BlockSemicolonScope())
            {
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresNormal, InterpolatorType.Normal, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresTangent, InterpolatorType.Tangent, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresBitangent, InterpolatorType.BiTangent, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresViewDir, InterpolatorType.ViewDirection, vertexDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(vertexRequirements.requiresPosition, InterpolatorType.Position, vertexDescriptionInputStruct);

                if (vertexRequirements.requiresVertexColor)
                {
                    vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
                }

                if (vertexRequirements.requiresScreenPosition)
                {
                    vertexDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
                }

                foreach (var channel in vertexRequirements.requiresMeshUVs.Distinct())
                {
                    vertexDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
                }
            }

            // -------------------------------------
            // Generate Output structure for Vertex Description function

            GraphUtil.GenerateVertexDescriptionStruct(vertexDescriptionStruct, vertexSlots);

            // -------------------------------------
            // Generate Vertex Description function

            GraphUtil.GenerateVertexDescriptionFunction(
                masterNode.owner as AbstractMaterialGraph,
                vertexDescriptionFunction,
                functionRegistry,
                shaderProperties,
                mode,
                vertexNodes,
                vertexSlots);

            // ----------------------------------------------------- //
            //               START SURFACE DESCRIPTION               //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Generate Input structure for Surface Description function
            // Surface Description Input requirements are needed to exclude intermediate translation spaces

            surfaceDescriptionInputStruct.AppendLine("struct SurfaceDescriptionInputs");
            using (surfaceDescriptionInputStruct.BlockSemicolonScope())
            {
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresNormal, InterpolatorType.Normal, surfaceDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresTangent, InterpolatorType.Tangent, surfaceDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresBitangent, InterpolatorType.BiTangent, surfaceDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceDescriptionInputStruct);
                ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(surfaceRequirements.requiresPosition, InterpolatorType.Position, surfaceDescriptionInputStruct);

                if (surfaceRequirements.requiresVertexColor)
                {
                    surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.VertexColor);
                }

                if (surfaceRequirements.requiresScreenPosition)
                {
                    surfaceDescriptionInputStruct.AppendLine("float4 {0};", ShaderGeneratorNames.ScreenPosition);
                }

                if (surfaceRequirements.requiresFaceSign)
                {
                    surfaceDescriptionInputStruct.AppendLine("float {0};", ShaderGeneratorNames.FaceSign);
                }

                foreach (var channel in surfaceRequirements.requiresMeshUVs.Distinct())
                {
                    surfaceDescriptionInputStruct.AppendLine("half4 {0};", channel.GetUVName());
                }
            }

            // -------------------------------------
            // Generate Output structure for Surface Description function

            GraphUtil.GenerateSurfaceDescriptionStruct(surfaceDescriptionStruct, pixelSlots, true);

            // -------------------------------------
            // Generate Surface Description function

            GraphUtil.GenerateSurfaceDescriptionFunction(
                pixelNodes,
                masterNode,
                masterNode.owner as AbstractMaterialGraph,
                surfaceDescriptionFunction,
                functionRegistry,
                shaderProperties,
                pixelRequirements,
                mode,
                "PopulateSurfaceData",
                "SurfaceDescription",
                null,
                pixelSlots);

            // ----------------------------------------------------- //
            //           GENERATE VERTEX > PIXEL PIPELINE            //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Generate Input structure for Vertex shader

            GraphUtil.GenerateApplicationVertexInputs(vertexRequirements.Union(pixelRequirements.Union(modelRequiements)), vertexInputStruct);

            // -------------------------------------
            // Generate standard transformations
            // This method ensures all required transform data is available in vertex and pixel stages

            ShaderGenerator.GenerateStandardTransforms(
                3,
                10,
                vertexOutputStruct,
                vertexShader,
                vertexShaderDescriptionInputs,
                vertexShaderOutputs,
                pixelShader,
                pixelShaderSurfaceInputs,
                pixelRequirements,
                surfaceRequirements,
                modelRequiements,
                vertexRequirements,
                CoordinateSpace.World);

            // -------------------------------------
            // Generate pixel shader surface remap

            foreach (var slot in pixelSlots)
            {
                pixelShaderSurfaceRemap.AppendLine("{0} = surf.{0};", slot.shaderOutputName);
            }

            // -------------------------------------
            // Extra pixel shader work

            var faceSign = new ShaderStringBuilder();

            if (pixelRequirements.requiresFaceSign)
            {
                faceSign.AppendLine(", half FaceSign : VFACE");
            }

            // ----------------------------------------------------- //
            //                      FINALIZE                         //
            // ----------------------------------------------------- //

            // -------------------------------------
            // Combine Graph sections

            graph.AppendLine(shaderProperties.GetPropertiesDeclaration(1));

            graph.AppendLine(vertexDescriptionInputStruct.ToString());
            graph.AppendLine(surfaceDescriptionInputStruct.ToString());

            graph.AppendLine(functionBuilder.ToString());

            graph.AppendLine(vertexDescriptionStruct.ToString());
            graph.AppendLine(vertexDescriptionFunction.ToString());

            graph.AppendLine(surfaceDescriptionStruct.ToString());
            graph.AppendLine(surfaceDescriptionFunction.ToString());

            graph.AppendLine(vertexInputStruct.ToString());

            // -------------------------------------
            // Generate final subshader

            var resultPass = template.Replace("${Tags}", string.Empty);

            resultPass = resultPass.Replace("${Blending}", blendingBuilder.ToString());
            resultPass = resultPass.Replace("${Culling}", cullingBuilder.ToString());
            resultPass = resultPass.Replace("${ZTest}", zTestBuilder.ToString());
            resultPass = resultPass.Replace("${ZWrite}", zWriteBuilder.ToString());
            resultPass = resultPass.Replace("${Defines}", defines.ToString());

            resultPass = resultPass.Replace("${Graph}", graph.ToString());
            resultPass = resultPass.Replace("${VertexOutputStruct}", vertexOutputStruct.ToString());

            resultPass = resultPass.Replace("${VertexShader}", vertexShader.ToString());
            resultPass = resultPass.Replace("${VertexShaderDescriptionInputs}", vertexShaderDescriptionInputs.ToString());
            resultPass = resultPass.Replace("${VertexShaderOutputs}", vertexShaderOutputs.ToString());

            resultPass = resultPass.Replace("${FaceSign}", faceSign.ToString());
            resultPass = resultPass.Replace("${PixelShader}", pixelShader.ToString());
            resultPass = resultPass.Replace("${PixelShaderSurfaceInputs}", pixelShaderSurfaceInputs.ToString());
            resultPass = resultPass.Replace("${PixelShaderSurfaceRemap}", pixelShaderSurfaceRemap.ToString());

            return(resultPass);
        }
Exemple #28
0
 /// <summary>
 /// Calculates priority for atoms in a Molecule.
 /// </summary>
 /// <param name="mol">connected molecule</param>
 /// <seealso cref="Priority"/>
 internal static void Prioritise(IAtomContainer mol)
 {
     Prioritise(mol, GraphUtil.ToAdjList(mol));
 }
Exemple #29
0
        ExportToNewMatrixWorkbook()
        {
            AssertValid();

            // Merge duplicate edges and add an edge weight column.

            (new DuplicateEdgeMerger()).MergeDuplicateEdges(m_oWorkbookToExport);

            // Read the workbook, including the edge weight column.

            ReadWorkbookContext oReadWorkbookContext = new ReadWorkbookContext();

            oReadWorkbookContext.ReadEdgeWeights = true;

            IGraph oGraph = (new WorkbookReader()).ReadWorkbook(
                m_oWorkbookToExport, oReadWorkbookContext);

            // Get an array of non-isolated vertices.  Isolated vertices don't get
            // exported.

            List <IVertex> oNonIsolatedVertices =
                GraphUtil.GetNonIsolatedVertices(oGraph);

            Int32 iNonIsolatedVertices = oNonIsolatedVertices.Count;

            if (iNonIsolatedVertices == 0)
            {
                throw new ExportWorkbookException(
                          "There are no edges to export."
                          );
            }

            Workbook oNewWorkbook =
                m_oWorkbookToExport.Application.Workbooks.Add(Missing.Value);

            Worksheet oNewWorksheet = (Worksheet)oNewWorkbook.ActiveSheet;

            // Fill in row 1 and column A with the vertex names, starting at B1 and
            // A2, respectively.

            String [,] asVertexNamesForRow1 = ExcelUtil.GetSingleRow2DStringArray(
                iNonIsolatedVertices);

            String [,] asVertexNamesForColumnA =
                ExcelUtil.GetSingleColumn2DStringArray(iNonIsolatedVertices);

            for (Int32 i = 0; i < iNonIsolatedVertices; i++)
            {
                asVertexNamesForRow1[1, i + 1]             = asVertexNamesForColumnA[i + 1, 1]
                                                           = oNonIsolatedVertices[i].Name;
            }

            ExcelUtil.SetRangeValues((Range)oNewWorksheet.Cells[1, 2],
                                     asVertexNamesForRow1);

            ExcelUtil.SetRangeValues((Range)oNewWorksheet.Cells[2, 1],
                                     asVertexNamesForColumnA);

            asVertexNamesForRow1 = asVertexNamesForColumnA = null;

            // Now fill in the edge weights, row by row.

            Range oFirstColumnCell = (Range)oNewWorksheet.Cells[2, 2];

            for (Int32 i = 0; i < iNonIsolatedVertices; i++)
            {
                Object [,] aoEdgeWeights = ExcelUtil.GetSingleRow2DArray(
                    iNonIsolatedVertices);

                IVertex oVertexI = oNonIsolatedVertices[i];

                for (Int32 j = 0; j < iNonIsolatedVertices; j++)
                {
                    aoEdgeWeights[1, j + 1] = EdgeUtil.GetEdgeWeight(oVertexI,
                                                                     oNonIsolatedVertices[j]);
                }

                ExcelUtil.SetRangeValues(oFirstColumnCell, aoEdgeWeights);

                oFirstColumnCell = oFirstColumnCell.get_Offset(1, 0);
            }

            return(oNewWorkbook);
        }
        public void ToSubGraph()
        {
            var graphView = graphEditorView.graphView;

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

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

            path = EditorUtility.SaveFilePanelInProject("Save Sub Graph", "New Shader Sub Graph", ShaderSubGraphImporter.Extension, "", path);
            path = path.Replace(Application.dataPath, "Assets");

            // Friendly warning that the user is generating a subgraph that would overwrite the one they are currently working on.
            if (AssetDatabase.AssetPathToGUID(path) == selectedGuid)
            {
                if (!EditorUtility.DisplayDialog("Overwrite Current Subgraph", "Do you want to overwrite this Sub Graph that you are currently working on? You cannot undo this operation.", "Yes", "Cancel"))
                {
                    path = "";
                }
            }

            if (path.Length == 0)
            {
                return;
            }

            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();

            // Convert To Subgraph could create recursive reference loops if the target path already exists
            // Let's check for that here
            if (!string.IsNullOrEmpty(path))
            {
                if (GraphUtil.CheckForRecursiveDependencyOnPendingSave(path, nodes.OfType <SubGraphNode>(), "Convert To SubGraph"))
                {
                    return;
                }
            }

            graphObject.RegisterCompleteObjectUndo("Convert To Subgraph");

            var bounds = Rect.MinMaxRect(float.PositiveInfinity, float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity);

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

            bounds.center = Vector2.zero;

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

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

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

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

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

            if (deserialized == null)
            {
                return;
            }

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

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

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

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

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

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

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

                subGraph.AddNode(node);
            }

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

                subGraph.AddStickyNote(note);
            }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                default:
                    throw new ArgumentOutOfRangeException();
                }

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

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

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

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

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

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

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

                var inputSlotRef = new SlotReference(outputNode, slotId);

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

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

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

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

            if (loadedSubGraph == null)
            {
                return;
            }

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

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

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

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

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

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

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

            graphObject.graph.RemoveElements(
                graphView.selection.OfType <IShaderNodeView>().Select(x => x.node).Where(x => x.allowedInSubGraph).ToArray(),
                new IEdge[] {},
                new GroupData[] {},
                graphView.selection.OfType <StickyNote>().Select(x => x.userData).ToArray());
            graphObject.graph.ValidateGraph();
        }
        public void TestPolymorphicSerializationPreservesTypesViaInterface()
        {
            var toSerialize = new List <ITestInterface>()
            {
                SimpleSerializeClass.instance,
                ChildClassA.instance,
                ChildClassB.instance
            };

            var serialized = SerializationHelper.Serialize <ITestInterface>(toSerialize);

            Assert.AreEqual(3, serialized.Count);

            var loaded = SerializationHelper.Deserialize <SimpleSerializeClass>(serialized, GraphUtil.GetLegacyTypeRemapping());

            Assert.AreEqual(3, loaded.Count);
            Assert.IsInstanceOf <SimpleSerializeClass>(loaded[0]);
            Assert.IsInstanceOf <ChildClassA>(loaded[1]);
            Assert.IsInstanceOf <ChildClassB>(loaded[2]);
            loaded[0].AssertAsReference();
            loaded[1].AssertAsReference();
            loaded[2].AssertAsReference();
        }
Exemple #32
0
 private bool IsYieldingHeader(GraphUtil.Graph<Block> graph, Block header)
 {
     foreach (Block backEdgeNode in graph.BackEdgeNodes(header))
     {
         foreach (Block x in graph.NaturalLoops(header, backEdgeNode))
         {
             foreach (Cmd cmd in x.Cmds)
             {
                 if (cmd is YieldCmd)
                     return true;
                 if (cmd is ParCallCmd)
                     return true;
                 CallCmd callCmd = cmd as CallCmd;
                 if (callCmd == null) continue;
                 if (callCmd.IsAsync || QKeyValue.FindBoolAttribute(callCmd.Proc.Attributes, "yields"))
                     return true;
             }
         }
     }
     return false;
 }