private static void TryKeywordRegex(string text, string expected, params string[] keywords) { Regex regex = KeywordUtil.GetKeywordRegex(keywords, StringUtils.HTML_LINE_BREAK); string replaced = regex.Replace(text, "<b>$1</b>"); Assert.AreEqual(expected, replaced); }
public void CanGetPermutationDeclaration() { var sb = new ShaderStringBuilder(); KeywordUtil.GetKeywordPermutationDeclarations(sb, m_Collector.permutations); Assert.AreEqual(kExpectedPermutationDeclaration, sb.ToString(), "Keyword permutation snippet was invalid"); }
public void CanGetPermutationDeclaration() { var sb = new ShaderStringBuilder(humanReadable: true); KeywordUtil.GetKeywordPermutationDeclarations(sb, m_Collector.permutations); Assert.AreEqual(kExpectedPermutationDeclaration.Replace("\r\n", "\n"), sb.ToString(), "Keyword permutation snippet was invalid"); }
void AddKeywordItems(GenericMenu gm) { gm.AddItem(new GUIContent($"Keyword/Boolean"), false, () => AddInputRow(new ShaderKeyword(KeywordType.Boolean), true)); gm.AddItem(new GUIContent($"Keyword/Enum"), false, () => AddInputRow(new ShaderKeyword(KeywordType.Enum), true)); gm.AddSeparator($"Keyword/"); foreach (var builtinKeywordDescriptor in KeywordUtil.GetBuiltinKeywordDescriptors()) { var keyword = ShaderKeyword.CreateBuiltInKeyword(builtinKeywordDescriptor); AddBuiltinKeyword(gm, keyword); } }
public void AppendKeywordDeclarationStrings(ShaderStringBuilder builder) { if (definition != KeywordDefinition.Predefined) { if (type == KeywordType.Boolean) { KeywordUtil.GenerateBooleanKeywordPragmaStrings(referenceName, definition, scope, stages, str => builder.AppendLine(str)); } else { KeywordUtil.GenerateEnumKeywordPragmaStrings(referenceName, definition, scope, stages, entries, str => builder.AppendLine(str)); } } }
public void TestOverlappingKeywords() { string text = "2002-2003: Acting Personal Assistant, <br />" + "2002: Acting Personal Assistant to Chief Executive Officer, Some Corporation"; var util = new KeywordUtil(StringUtils.HTML_LINE_BREAK, "<b>", "</b>", "<b>...</b> ", " <b>...</b>"); var expected = new[] { "2002-2003: Acting <b>Personal Assistant</b>, <b>...</b>", "2002: <b>Acting Personal Assistant to Chief Executive Officer</b>, Some Corporation <b>...</b>" }; // Longer keyword string first. var keywords = new[] { "acting personal assistant to Chief Executive Officer", "personal assistant" }; List <SnippetContext> results = util.GetKeywordsInContext(text, keywords); Assert.IsTrue(results.Select(sc => sc.Text).SequenceEqual(expected)); Assert.AreEqual(2, results[0].KeywordSet); Assert.AreEqual(1 + 2, results[1].KeywordSet); // Shorter keyword string first. keywords = new[] { "personal assistant", "acting personal assistant to Chief Executive Officer" }; results = util.GetKeywordsInContext(text, keywords); Assert.IsTrue(results.Select(sc => sc.Text).SequenceEqual(expected)); Assert.AreEqual(1, results[0].KeywordSet); Assert.AreEqual(1 + 2, results[1].KeywordSet); // Longer keyword string first, start with the same text. keywords = new[] { "personal assistant to Chief Executive Officer", "personal assistant" }; expected = new[] { "2002-2003: Acting <b>Personal Assistant</b>, <b>...</b>", "2002: Acting <b>Personal Assistant to Chief Executive Officer</b>, Some Corporation <b>...</b>" }; results = util.GetKeywordsInContext(text, keywords); Assert.IsTrue(results.Select(sc => sc.Text).SequenceEqual(expected)); Assert.AreEqual(2, results[0].KeywordSet); Assert.AreEqual(1 + 2, results[1].KeywordSet); // Two occurrances - one long match, one short match. text = "Personal Assistant to Chief Executive Officer - Personal Assistant to Senior" + " Management Staff"; keywords = new[] { "personal assistant", "personal assistant to Chief Executive Officer" }; expected = new[] { "<b>Personal Assistant to Chief Executive Officer</b> -" + " <b>Personal Assistant</b> to Senior Management Staff <b>...</b>" }; results = util.GetKeywordsInContext(text, keywords); Assert.IsTrue(results.Select(sc => sc.Text).SequenceEqual(expected)); Assert.AreEqual(1 + 2, results[0].KeywordSet); }
public void TestKeywordsInContext() { const string text1 = "One two three four five six seven eight nine ten eleven twelve" + " thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty" + " twentyOne twentyTwo."; const string text2 = "The keyword a b\t\tc \t d e f g.\t The second sentence is quite a" + " long one and ends with the keyword! And another sentence."; const string text3 = "One two three four five six seven a b c d e f eight nine ten" + " eleven twelve thirteen fourteen fifteen g h i j k l m n o p sixteen seventeen" + " eighteen nineteen twenty twentyOne twentyTwo."; const string text4 = "One two three four five six seven a b c d e f g eight nine ten" + " eleven twelve thirteen fourteen fifteen h i j k l m n o p sixteen seventeen" + " eighteen nineteen twenty twentyOne twentyTwo."; const string text5 = "\r\n\r\nOne two three four five six seven eight nine ten eleven twelve" + " thirteen fourteen fifteen sixteen seventeen\r\nEighteen nineteen twenty\r\n" + "twentyOne twentyTwo."; var util = new KeywordUtil("\r\n", "<", ">", "... ", " ..."); // No results. List <SnippetContext> results = util.GetKeywordsInContext("", "anything"); Assert.AreEqual(0, results.Count); results = util.GetKeywordsInContext("nothing", new[] { "anything" }); Assert.AreEqual(0, results.Count); // One snippet. results = util.GetKeywordsInContext("One", "One"); Assert.AreEqual(1, results.Count); Assert.AreEqual("<One> ...", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); results = util.GetKeywordsInContext("One of two.", "one"); Assert.AreEqual(1, results.Count); Assert.AreEqual("<One> of two.", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); results = util.GetKeywordsInContext(text1, "fifteen"); Assert.AreEqual(1, results.Count); Assert.AreEqual( "One two three four five six seven eight nine ten eleven twelve thirteen fourteen" + " <fifteen> sixteen seventeen eighteen nineteen twenty twentyOne twentyTwo.", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); // Two 14-word snippets (the first two keywords are just close enough to fit into // one 14-word snippet instead of two 7-word ones). results = util.GetKeywordsInContext(text3, "four", "eleven", "nineteen"); Assert.AreEqual(2, results.Count); Assert.AreEqual("... <four> five six seven a b c d e f eight nine ten <eleven> ...", results[0].Text); Assert.AreEqual(1 + 2, results[0].KeywordSet); Assert.AreEqual("... j k l m n o p sixteen seventeen eighteen <nineteen> twenty twentyOne twentyTwo.", results[1].Text); Assert.AreEqual(4, results[1].KeywordSet); // One 28-word snippet with two keywords. results = util.GetKeywordsInContext(text4, new[] { "four", "eleven" }); Assert.AreEqual(1, results.Count); Assert.AreEqual( "One two three <four> five six seven a b c d e f g eight nine ten" + " <eleven> twelve thirteen fourteen fifteen h i j k l m ...", results[0].Text); Assert.AreEqual(1 + 2, results[0].KeywordSet); // Three 7-word snippets. results = util.GetKeywordsInContext(text4, "four", "eleven", "nineteen"); Assert.AreEqual(3, results.Count); Assert.AreEqual("One two three <four> five six seven ...", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); Assert.AreEqual("... eight nine ten <eleven> twelve thirteen fourteen ...", results[1].Text); Assert.AreEqual(2, results[1].KeywordSet); Assert.AreEqual("... sixteen seventeen eighteen <nineteen> twenty twentyOne twentyTwo.", results[2].Text); Assert.AreEqual(4, results[2].KeywordSet); // A keyword at the end of the sentence, tabs, exclamation mark. results = util.GetKeywordsInContext(text2, "keyword"); Assert.AreEqual(2, results.Count); Assert.AreEqual("The <keyword> a b\t\tc \t d e f g.", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); Assert.AreEqual("The second sentence is quite a long one and ends with the <keyword>!", results[1].Text); Assert.AreEqual(1, results[0].KeywordSet); // Hyphen should be treated as part of the word. results = util.GetKeywordsInContext(text1, "two"); Assert.AreEqual(1, results.Count); Assert.AreEqual( "One <two> three four five six seven eight nine ten eleven twelve thirteen fourteen" + " fifteen sixteen seventeen eighteen nineteen twenty twentyOne twentyTwo.", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); // Two overlapping snippets combined into one. results = util.GetKeywordsInContext(text1, "two", "nineteen"); Assert.AreEqual(1, results.Count); Assert.AreEqual( "One <two> three four five six seven eight nine ten eleven twelve thirteen fourteen" + " fifteen sixteen seventeen eighteen <nineteen> twenty twentyOne twentyTwo.", results[0].Text); Assert.AreEqual(1 + 2, results[0].KeywordSet); // Three overlapping snippets combined into one. results = util.GetKeywordsInContext(text1, "four", "eleven", "nineteen"); Assert.AreEqual(1, results.Count); Assert.AreEqual( "One two three <four> five six seven eight nine ten <eleven> twelve thirteen" + " fourteen fifteen sixteen seventeen eighteen <nineteen> twenty twentyOne" + " twentyTwo.", results[0].Text); Assert.AreEqual(1 + 2 + 4, results[0].KeywordSet); // Keywords at the start and end of a 28-word sentence. results = util.GetKeywordsInContext( "Ignore this. Keyword a b c d e f g h i j k l m n o p q r s t u v w x y z keyword!", "keyword"); Assert.AreEqual(1, results.Count); Assert.AreEqual("<Keyword> a b c d e f g h i j k l m n o p q r s t u v w x y z <keyword>!", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); results = util.GetKeywordsInContext( "Keyword a b c d e f g h i j k l m n o p q r s t u v w x y z keyword! Ignore this.", "keyword"); Assert.AreEqual(1, results.Count); Assert.AreEqual("<Keyword> a b c d e f g h i j k l m n o p q r s t u v w x y z <keyword>!", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); results = util.GetKeywordsInContext("OneWordBefore Keyword" + " a b c d e f g h i j k l m n o p q r s t u v w x y keyworD. Ignore this.", "keyword"); Assert.AreEqual(1, results.Count); Assert.AreEqual("OneWordBefore <Keyword> a b c d e f g h i j k l m n o p q r s t u v w x y <keyworD>.", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); // New lines. results = util.GetKeywordsInContext("Ignore the first line\r\n" + "Keyword a b c d e f g h i j k l m n o p q r s t u v w x y z keyword! Ignore this.", "keyword"); Assert.AreEqual(1, results.Count); Assert.AreEqual("<Keyword> a b c d e f g h i j k l m n o p q r s t u v w x y z <keyword>!", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); results = util.GetKeywordsInContext(text5, "fifteen", "nineteen", "twentyOne"); Assert.AreEqual(3, results.Count); Assert.AreEqual("... eleven twelve thirteen fourteen <fifteen> sixteen seventeen ...", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); Assert.AreEqual("Eighteen <nineteen> twenty ...", results[1].Text); Assert.AreEqual(2, results[1].KeywordSet); Assert.AreEqual("<twentyOne> twentyTwo.", results[2].Text); Assert.AreEqual(4, results[2].KeywordSet); // A line consisting of the keyword only. results = util.GetKeywordsInContext("\r\nkeyword\r\n", "keyword"); Assert.AreEqual(1, results.Count); Assert.AreEqual("<keyword> ...", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); // Many keywords that fit into a 14-word snippet, but should be displayed in a 28-word // snippet, since it's the only one. results = util.GetKeywordsInContext("I am experienced in preparing test documentation" + " including test plans, test strategies, test scripts and test matrices.", "test"); Assert.AreEqual(1, results.Count); Assert.AreEqual( "I am experienced in preparing <test> documentation" + " including <test> plans, <test> strategies, <test> scripts and <test> matrices.", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); // Bugs found from processing actual resumes. results = util.GetKeywordsInContext("She is a well accomplished test specialist" + " with her experience crossing over roles such as Senior System Test Analyst, Test" + " Lead and Test Manager in the telecommunications, media, retail and government" + " industries.", "test"); Assert.AreEqual(1, results.Count); Assert.AreEqual( "She is a well accomplished <test> specialist with her experience crossing over roles" + " such as Senior System <Test> Analyst, <Test> Lead and <Test> Manager in the" + " telecommunications, media, ...", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); results = util.GetKeywordsInContext("I have been a Test Analyst for 6 years and in" + " mining solutions quickly and efficiently in any type of database system. \r\n\r\n" + " As a Senior Test Analyst my responsibilities involve testing and creating test" + " documentation. I have done most types of Black Box testing, including Sanity" + " testing, Functional testing, Systems testing, End to End system testing and" + " Regression testing as well as User Acceptance Testing. I am experienced in preparing" + " test documentation including test plans, test strategies, test scripts and test" + " matrices.", "test"); Assert.AreEqual(3, results.Count); Assert.AreEqual("... have been a <Test> Analyst for 6 ...", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); Assert.AreEqual("As a Senior <Test> Analyst my responsibilities involve testing and creating <test> documentation.", results[1].Text); Assert.AreEqual(1, results[1].KeywordSet); Assert.AreEqual("... preparing <test> documentation including <test> plans, <test> ...", results[2].Text); Assert.AreEqual(1, results[2].KeywordSet); // Punctuation in text. results = util.GetKeywordsInContext( "We have the keyword, an e-keyword, keyword-ing, a.keyword and keyword.net - what about this keyword?", "keyword"); Assert.AreEqual(1, results.Count); Assert.AreEqual( "We have the <keyword>, an e-<keyword>, <keyword>-ing, a.keyword and keyword.net - what about this <keyword>?", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); results = util.GetKeywordsInContext("We have the keyword, an e-keyword another/keyword" + " and keyword.net - what about this keyword ?", "keyword"); Assert.AreEqual(1, results.Count); Assert.AreEqual( "We have the <keyword>, an e-<keyword> another/<keyword>" + " and keyword.net - what about this <keyword> ?", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); results = util.GetKeywordsInContext( "What about (brackets or brackets) or (brackets) or brackets(a) ?", "brackets"); Assert.AreEqual(1, results.Count); Assert.AreEqual("What about (<brackets> or <brackets>) or (<brackets>) or <brackets>(a) ?", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); // Punctuation in keywords. results = util.GetKeywordsInContext("We have the keyword, an e-keyword, a.keyword.", "e-keyword"); Assert.AreEqual(1, results.Count); Assert.AreEqual("We have the keyword, an <e-keyword>, a.keyword.", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); results = util.GetKeywordsInContext("We have the keyword, an e/keyword, e / keyword.", "e/keyword"); Assert.AreEqual(1, results.Count); Assert.AreEqual("We have the keyword, an <e/keyword>, e / keyword.", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); results = util.GetKeywordsInContext("We have the keyword, an e/keyword, e / keyword.", "e / keyword"); Assert.AreEqual(1, results.Count); Assert.AreEqual("We have the keyword, an e/keyword, <e / keyword>.", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); results = util.GetKeywordsInContext("An & and an amp and another amp.", "amp"); Assert.AreEqual(1, results.Count); Assert.AreEqual("An & and an <amp> and another <amp>.", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); // If all keywords appear as an exact string (separated by whitespac) they should be // highlighted together. Ideally the "analyst" in "systems analyst" should be highlighted // as well, but this is not implemented yet. results = util.GetKeywordsInContext( "I have systems analyst, business analyst and business experience.", "business", "analyst"); Assert.AreEqual(1, results.Count); Assert.AreEqual("I have systems analyst, <business analyst> and <business> experience.", results[0].Text); Assert.IsTrue(((1 + 2) & results[0].KeywordSet) == (1 + 2)); results = util.GetKeywordsInContext( "I have systems analyst, business \t analyst and business experience.", "business", "analyst"); Assert.AreEqual(1, results.Count); Assert.AreEqual("I have systems analyst, <business \t analyst> and <business> experience.", results[0].Text); Assert.IsTrue(((1 + 2) & results[0].KeywordSet) == (1 + 2)); // .. and the exact match should be returned first. Ideally preceding partial matches // should be returned as well, but this is not implemented yet. results = util.GetKeywordsInContext( "I have systems analyst and business experience. I want to be a business analyst.", "business", "analyst"); Assert.AreEqual(1, results.Count); Assert.AreEqual("I want to be a <business analyst>.", results[0].Text); Assert.IsTrue(((1 + 2) & results[0].KeywordSet) == (1 + 2)); // Start of the linebreak string should not be included in the snippets. util = new KeywordUtil(StringUtils.HTML_LINE_BREAK, "<", ">", "... ", " ..."); results = util.GetKeywordsInContext("3+ years of experience as a QA Test engineer" + " in testing client server environment and doing web testing. <br />Good Knowledge" + " and Experience in Execution of Functional Test Cases on the basis of Usecase and" + " Generated Test Report.<br />And Test Director, for Bug reporting.<br />", "test"); Assert.AreEqual(3, results.Count); Assert.AreEqual("... as a QA <Test> engineer in testing ...", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); Assert.AreEqual("... Execution of Functional <Test> Cases on the basis of Usecase and Generated <Test> Report.", results[1].Text); Assert.AreEqual(1, results[1].KeywordSet); Assert.AreEqual("And <Test> Director, for Bug reporting.", results[2].Text); Assert.AreEqual(1, results[2].KeywordSet); results = util.GetKeywordsInContext("<br />management. KEYWORD was appointed Receiver" + " & Manager and managed the transition of M>business to Connex trains and Yarra Trams" + ". <br />", "keyword"); Assert.AreEqual(1, results.Count); Assert.AreEqual( "<KEYWORD> was appointed Receiver & Manager and managed the transition of M>business to" + " Connex trains and Yarra Trams.", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); results = util.GetKeywordsInContext("One keyword. Successfully did something" + " and something else by KEYWORD blah blah and blah blah.", "keyword"); Assert.AreEqual(2, results.Count); Assert.AreEqual("One <keyword>.", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); Assert.AreEqual("Successfully did something and something else by <KEYWORD> blah blah and blah blah.", results[1].Text); Assert.AreEqual(1, results[1].KeywordSet); results = util.GetKeywordsInContext("At the end keyword.<br />Ignore this.", "keyword"); Assert.AreEqual(1, results.Count); Assert.AreEqual("At the end <keyword>.", results[0].Text); Assert.AreEqual(1, results[0].KeywordSet); }
public static bool GenerateShaderPass(AbstractMaterialNode masterNode, ShaderPass pass, GenerationMode mode, ActiveFields activeFields, ShaderGenerator result, List <string> sourceAssetDependencyPaths, List <Dependency[]> dependencies, string resourceClassName, string assemblyName) { // -------------------------------------------------- // Debug // Get scripting symbols BuildTargetGroup buildTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup; string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup); bool isDebug = defines.Contains(kDebugSymbol); // -------------------------------------------------- // Setup // Initiailize Collectors var propertyCollector = new PropertyCollector(); var keywordCollector = new KeywordCollector(); masterNode.owner.CollectShaderKeywords(keywordCollector, mode); // Get upstream nodes from ShaderPass port mask List <AbstractMaterialNode> vertexNodes; List <AbstractMaterialNode> pixelNodes; GetUpstreamNodesForShaderPass(masterNode, pass, out vertexNodes, out pixelNodes); // Track permutation indices for all nodes List <int>[] vertexNodePermutations = new List <int> [vertexNodes.Count]; List <int>[] pixelNodePermutations = new List <int> [pixelNodes.Count]; // Get active fields from upstream Node requirements ShaderGraphRequirementsPerKeyword graphRequirements; GetActiveFieldsAndPermutationsForNodes(masterNode, pass, keywordCollector, vertexNodes, pixelNodes, vertexNodePermutations, pixelNodePermutations, activeFields, out graphRequirements); // GET CUSTOM ACTIVE FIELDS HERE! // Get active fields from ShaderPass AddRequiredFields(pass.requiredAttributes, activeFields.baseInstance); AddRequiredFields(pass.requiredVaryings, activeFields.baseInstance); // Get Port references from ShaderPass var pixelSlots = FindMaterialSlotsOnNode(pass.pixelPorts, masterNode); var vertexSlots = FindMaterialSlotsOnNode(pass.vertexPorts, masterNode); // Function Registry var functionBuilder = new ShaderStringBuilder(); var functionRegistry = new FunctionRegistry(functionBuilder); // Hash table of named $splice(name) commands // Key: splice token // Value: string to splice Dictionary <string, string> spliceCommands = new Dictionary <string, string>(); // -------------------------------------------------- // Dependencies // Propagate active field requirements using dependencies // Must be executed before types are built foreach (var instance in activeFields.all.instances) { ShaderSpliceUtil.ApplyDependencies(instance, dependencies); } // -------------------------------------------------- // Pass Setup // Name if (!string.IsNullOrEmpty(pass.displayName)) { spliceCommands.Add("PassName", $"Name \"{pass.displayName}\""); } else { spliceCommands.Add("PassName", "// Name: <None>"); } // Tags if (!string.IsNullOrEmpty(pass.lightMode)) { spliceCommands.Add("LightMode", $"\"LightMode\" = \"{pass.lightMode}\""); } else { spliceCommands.Add("LightMode", "// LightMode: <None>"); } // Render state BuildRenderStatesFromPass(pass, ref spliceCommands); // -------------------------------------------------- // Pass Code // Pragmas using (var passPragmaBuilder = new ShaderStringBuilder()) { if (pass.pragmas != null) { foreach (string pragma in pass.pragmas) { passPragmaBuilder.AppendLine($"#pragma {pragma}"); } } if (passPragmaBuilder.length == 0) { passPragmaBuilder.AppendLine("// PassPragmas: <None>"); } spliceCommands.Add("PassPragmas", passPragmaBuilder.ToCodeBlack()); } // Includes using (var passIncludeBuilder = new ShaderStringBuilder()) { if (pass.includes != null) { foreach (string include in pass.includes) { passIncludeBuilder.AppendLine($"#include \"{include}\""); } } if (passIncludeBuilder.length == 0) { passIncludeBuilder.AppendLine("// PassIncludes: <None>"); } spliceCommands.Add("PassIncludes", passIncludeBuilder.ToCodeBlack()); } // Keywords using (var passKeywordBuilder = new ShaderStringBuilder()) { if (pass.keywords != null) { foreach (KeywordDescriptor keyword in pass.keywords) { passKeywordBuilder.AppendLine(keyword.ToDeclarationString()); } } if (passKeywordBuilder.length == 0) { passKeywordBuilder.AppendLine("// PassKeywords: <None>"); } spliceCommands.Add("PassKeywords", passKeywordBuilder.ToCodeBlack()); } // -------------------------------------------------- // Graph Vertex var vertexBuilder = new ShaderStringBuilder(); // If vertex modification enabled if (activeFields.baseInstance.Contains("features.graphVertex")) { // Setup string vertexGraphInputName = "VertexDescriptionInputs"; string vertexGraphOutputName = "VertexDescription"; string vertexGraphFunctionName = "VertexDescriptionFunction"; var vertexGraphInputGenerator = new ShaderGenerator(); var vertexGraphFunctionBuilder = new ShaderStringBuilder(); var vertexGraphOutputBuilder = new ShaderStringBuilder(); // Build vertex graph inputs ShaderSpliceUtil.BuildType(GetTypeForStruct("VertexDescriptionInputs", resourceClassName, assemblyName), activeFields, vertexGraphInputGenerator, isDebug); // Build vertex graph outputs // Add struct fields to active fields SubShaderGenerator.GenerateVertexDescriptionStruct(vertexGraphOutputBuilder, vertexSlots, vertexGraphOutputName, activeFields.baseInstance); // Build vertex graph functions from ShaderPass vertex port mask SubShaderGenerator.GenerateVertexDescriptionFunction( masterNode.owner as GraphData, vertexGraphFunctionBuilder, functionRegistry, propertyCollector, keywordCollector, mode, masterNode, vertexNodes, vertexNodePermutations, vertexSlots, vertexGraphInputName, vertexGraphFunctionName, vertexGraphOutputName); // Generate final shader strings vertexBuilder.AppendLines(vertexGraphInputGenerator.GetShaderString(0, false)); vertexBuilder.AppendNewLine(); vertexBuilder.AppendLines(vertexGraphOutputBuilder.ToString()); vertexBuilder.AppendNewLine(); vertexBuilder.AppendLines(vertexGraphFunctionBuilder.ToString()); } // Add to splice commands if (vertexBuilder.length == 0) { vertexBuilder.AppendLine("// GraphVertex: <None>"); } spliceCommands.Add("GraphVertex", vertexBuilder.ToCodeBlack()); // -------------------------------------------------- // Graph Pixel // Setup string pixelGraphInputName = "SurfaceDescriptionInputs"; string pixelGraphOutputName = "SurfaceDescription"; string pixelGraphFunctionName = "SurfaceDescriptionFunction"; var pixelGraphInputGenerator = new ShaderGenerator(); var pixelGraphOutputBuilder = new ShaderStringBuilder(); var pixelGraphFunctionBuilder = new ShaderStringBuilder(); // Build pixel graph inputs ShaderSpliceUtil.BuildType(GetTypeForStruct("SurfaceDescriptionInputs", resourceClassName, assemblyName), activeFields, pixelGraphInputGenerator, isDebug); // Build pixel graph outputs // Add struct fields to active fields SubShaderGenerator.GenerateSurfaceDescriptionStruct(pixelGraphOutputBuilder, pixelSlots, pixelGraphOutputName, activeFields.baseInstance); // Build pixel graph functions from ShaderPass pixel port mask SubShaderGenerator.GenerateSurfaceDescriptionFunction( pixelNodes, pixelNodePermutations, masterNode, masterNode.owner as GraphData, pixelGraphFunctionBuilder, functionRegistry, propertyCollector, keywordCollector, mode, pixelGraphFunctionName, pixelGraphOutputName, null, pixelSlots, pixelGraphInputName); using (var pixelBuilder = new ShaderStringBuilder()) { // Generate final shader strings pixelBuilder.AppendLines(pixelGraphInputGenerator.GetShaderString(0, false)); pixelBuilder.AppendNewLine(); pixelBuilder.AppendLines(pixelGraphOutputBuilder.ToString()); pixelBuilder.AppendNewLine(); pixelBuilder.AppendLines(pixelGraphFunctionBuilder.ToString()); // Add to splice commands if (pixelBuilder.length == 0) { pixelBuilder.AppendLine("// GraphPixel: <None>"); } spliceCommands.Add("GraphPixel", pixelBuilder.ToCodeBlack()); } // -------------------------------------------------- // Graph Functions if (functionBuilder.length == 0) { functionBuilder.AppendLine("// GraphFunctions: <None>"); } spliceCommands.Add("GraphFunctions", functionBuilder.ToCodeBlack()); // -------------------------------------------------- // Graph Keywords using (var keywordBuilder = new ShaderStringBuilder()) { keywordCollector.GetKeywordsDeclaration(keywordBuilder, mode); if (keywordBuilder.length == 0) { keywordBuilder.AppendLine("// GraphKeywords: <None>"); } spliceCommands.Add("GraphKeywords", keywordBuilder.ToCodeBlack()); } // -------------------------------------------------- // Graph Properties using (var propertyBuilder = new ShaderStringBuilder()) { propertyCollector.GetPropertiesDeclaration(propertyBuilder, mode, masterNode.owner.concretePrecision); if (propertyBuilder.length == 0) { propertyBuilder.AppendLine("// GraphProperties: <None>"); } spliceCommands.Add("GraphProperties", propertyBuilder.ToCodeBlack()); } // -------------------------------------------------- // Graph Defines using (var graphDefines = new ShaderStringBuilder()) { graphDefines.AppendLine("#define {0}", pass.referenceName); if (graphRequirements.permutationCount > 0) { List <int> activePermutationIndices; // Depth Texture activePermutationIndices = graphRequirements.allPermutations.instances .Where(p => p.requirements.requiresDepthTexture) .Select(p => p.permutationIndex) .ToList(); if (activePermutationIndices.Count > 0) { graphDefines.AppendLine(KeywordUtil.GetKeywordPermutationSetConditional(activePermutationIndices)); graphDefines.AppendLine("#define REQUIRE_DEPTH_TEXTURE"); graphDefines.AppendLine("#endif"); } // Opaque Texture activePermutationIndices = graphRequirements.allPermutations.instances .Where(p => p.requirements.requiresCameraOpaqueTexture) .Select(p => p.permutationIndex) .ToList(); if (activePermutationIndices.Count > 0) { graphDefines.AppendLine(KeywordUtil.GetKeywordPermutationSetConditional(activePermutationIndices)); graphDefines.AppendLine("#define REQUIRE_OPAQUE_TEXTURE"); graphDefines.AppendLine("#endif"); } } else { // Depth Texture if (graphRequirements.baseInstance.requirements.requiresDepthTexture) { graphDefines.AppendLine("#define REQUIRE_DEPTH_TEXTURE"); } // Opaque Texture if (graphRequirements.baseInstance.requirements.requiresCameraOpaqueTexture) { graphDefines.AppendLine("#define REQUIRE_OPAQUE_TEXTURE"); } } // Add to splice commands spliceCommands.Add("GraphDefines", graphDefines.ToCodeBlack()); } // -------------------------------------------------- // Main // Main include is expected to contain vert/frag definitions for the pass // This must be defined after all graph code using (var mainBuilder = new ShaderStringBuilder()) { mainBuilder.AppendLine($"#include \"{pass.varyingsInclude}\""); mainBuilder.AppendLine($"#include \"{pass.passInclude}\""); // Add to splice commands spliceCommands.Add("MainInclude", mainBuilder.ToCodeBlack()); } // -------------------------------------------------- // Debug // Debug output all active fields using (var debugBuilder = new ShaderStringBuilder()) { if (isDebug) { // Active fields debugBuilder.AppendLine("// ACTIVE FIELDS:"); foreach (string field in activeFields.baseInstance.fields) { debugBuilder.AppendLine("// " + field); } } if (debugBuilder.length == 0) { debugBuilder.AppendLine("// <None>"); } // Add to splice commands spliceCommands.Add("Debug", debugBuilder.ToCodeBlack()); } // -------------------------------------------------- // Finalize // Get Template string templateLocation = GetTemplatePath("PassMesh.template"); if (!File.Exists(templateLocation)) { return(false); } // Get Template preprocessor string templatePath = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Templates"; var templatePreprocessor = new ShaderSpliceUtil.TemplatePreprocessor(activeFields, spliceCommands, isDebug, templatePath, sourceAssetDependencyPaths, assemblyName, resourceClassName); // Process Template templatePreprocessor.ProcessTemplateFile(templateLocation); result.AddShaderChunk(templatePreprocessor.GetShaderCode().ToString(), false); return(true); }