using System.Collections.Generic; using System.Linq; using System.Text; namespace UnityEditor.ShaderGraph { class KeywordCollector { public readonly List keywords; public readonly List>> permutations; public KeywordCollector() { keywords = new List(); permutations = new List>>(); } public void AddShaderKeyword(ShaderKeyword chunk) { if (keywords.Any(x => x.referenceName == chunk.referenceName)) return; keywords.Add(chunk); } public void GetKeywordsDeclaration(ShaderStringBuilder builder, GenerationMode mode) { if(keywords.Count == 0) return; // Declare keywords foreach (var keyword in keywords) { // Hardcode active keywords in preview to reduce compiled variants if(mode == GenerationMode.Preview) { string declaration = keyword.GetKeywordPreviewDeclarationString(); if(!string.IsNullOrEmpty(declaration)) { builder.AppendLine(declaration); } } else { string declaration = keyword.GetKeywordDeclarationString(); if(!string.IsNullOrEmpty(declaration)) { builder.AppendLine(declaration); } } } // Declare another keyword per permutation for simpler if/defs in the graph code builder.AppendNewLine(); KeywordUtil.GetKeywordPermutationDeclarations(builder, permutations); builder.AppendNewLine(); } public void CalculateKeywordPermutations() { permutations.Clear(); // Initialize current permutation List> currentPermutation = new List>(); for(int i = 0; i < keywords.Count; i++) { currentPermutation.Add(new KeyValuePair(keywords[i], 0)); } // Recursively permute keywords PermuteKeywords(keywords, currentPermutation, 0); } void PermuteKeywords(List keywords, List> currentPermutation, int currentIndex) { if(currentIndex == keywords.Count) return; // Iterate each possible keyword at the current index int entryCount = keywords[currentIndex].keywordType == KeywordType.Enum ? keywords[currentIndex].entries.Count : 2; for(int i = 0; i < entryCount; i++) { // Set the index in the current permutation to the correct value currentPermutation[currentIndex] = new KeyValuePair(keywords[currentIndex], i); // If the current index is the last keyword we are finished with this permutation if(currentIndex == keywords.Count - 1) { permutations.Add(currentPermutation); } // Otherwise we continue adding keywords to this permutation else { PermuteKeywords(keywords, currentPermutation, currentIndex + 1); } // Duplicate current permutation currentPermutation = currentPermutation.Select(item => item).ToList(); } } } }