Пример #1
0
        public void AddKeywordsByName(string[] names)
        {
            bool changes = false;

            for (int k = 0; k < names.Length; k++)
            {
                // is it already included?
                int  kwCount  = keywords.Count;
                bool repeated = false;
                for (int j = 0; j < kwCount; j++)
                {
                    if (keywords[j].name.Equals(names[k]))
                    {
                        repeated = true;
                        break;
                    }
                }
                if (repeated)
                {
                    continue;
                }
                SCKeyword keyword = new SCKeyword(names[k]);
                keywords.Add(keyword);
                changes = true;
            }
            if (changes)
            {
                keywords.Sort(delegate(SCKeyword k1, SCKeyword k2) { return(k1.name.CompareTo(k2.name)); });
            }
        }
Пример #2
0
        public void Add(SCKeyword keyword)
        {
            if (GetKeyword(keyword.name) != null)
            {
                return;
            }
            // ignore underscore keywords
            bool goodKeyword = false;

            for (int k = 0; k < keyword.name.Length; k++)
            {
                if (keyword.name[k] != '_')
                {
                    goodKeyword = true;
                    break;
                }
            }
            keyword.isMultiCompile = pragmaType == PragmaType.MultiCompileGlobal || pragmaType == PragmaType.MultiCompileLocal;
            if (goodKeyword)
            {
                keyword.isGlobal     = pragmaType != PragmaType.FeatureLocal && pragmaType != PragmaType.MultiCompileLocal && pragmaType != PragmaType.Unknown;
                keyword.verboseName  = keyword.name + " (";
                keyword.verboseName += keyword.isMultiCompile ? "multi_compile" : "shader_feature";
                keyword.verboseName += keyword.isGlobal ? ", global)" : ", local)";
                keywords.Add(keyword);
            }
            else
            {
                keyword.isUnderscoreKeyword = true;
                hasUnderscoreVariant        = true;
            }
        }
Пример #3
0
        public void Add(SCKeyword keyword)
        {
            if (GetKeyword(keyword.name) != null)
            {
                return;
            }
            // ignore underscore keywords
            bool goodKeyword = false;

            for (int k = 0; k < keyword.name.Length; k++)
            {
                if (keyword.name [k] != '_')
                {
                    goodKeyword = true;
                    break;
                }
            }
            if (goodKeyword)
            {
                keywords.Add(keyword);
            }
            else
            {
                keyword.isUnderscoreKeyword = true;
                hasUnderscoreVariant        = true;
            }
        }
        void BuildUpdateShaderKeywordsState(SCShader shader)
        {
            if (shader == null || shader.keywords == null)
            {
                return;
            }
            if (shadersBuildInfo == null)
            {
                return;
            }
            int shadersCount = shadersBuildInfo.shaders.Count;

            for (int s = 0; s < shadersCount; s++)
            {
                ShaderBuildInfo sb = shadersBuildInfo.shaders[s];
                if (sb != null && sb.name.Equals(shader.fullName))
                {
                    for (int k = 0; k < shader.keywords.Count; k++)
                    {
                        SCKeyword keyword = shader.keywords[k];
                        sb.ToggleIncludeKeyword(keyword.name, keyword.enabled);
                    }
                }
            }
            shadersBuildInfo.requiresBuild = true;
        }
Пример #5
0
        void ConvertToLocalNonGraph(SCKeyword keyword, SCShader shader)
        {
            string path = shader.path;

            if (!File.Exists(path))
            {
                return;
            }
            string[] lines   = File.ReadAllLines(path);
            bool     changed = false;

            for (int k = 0; k < lines.Length; k++)
            {
                // Just convert to local shader_features for now since multi_compile global keywords can be nabled using the Shader global API
                if (lines[k].IndexOf(SCKeywordLine.PRAGMA_FEATURE_GLOBAL, StringComparison.InvariantCultureIgnoreCase) >= 0 && lines[k].IndexOf(keyword.name, StringComparison.InvariantCultureIgnoreCase) >= 0)
                {
                    lines[k] = lines[k].Replace(SCKeywordLine.PRAGMA_FEATURE_GLOBAL, SCKeywordLine.PRAGMA_FEATURE_LOCAL);
                    lines[k] = lines[k].Replace(SCKeywordLine.PRAGMA_FEATURE_GLOBAL.ToUpper(), SCKeywordLine.PRAGMA_FEATURE_LOCAL);
                    changed  = true;
                }
            }
            if (changed)
            {
                MakeBackup(shader);
                File.WriteAllLines(path, lines, Encoding.UTF8);
            }
        }
Пример #6
0
        void ConvertToLocal(SCKeyword keyword, SCShader shader)
        {
            // Check total local keyword does not exceed 64 limit
            int potentialCount = 0;
            int kwCount        = shader.keywords.Count;

            for (int k = 0; k < kwCount; k++)
            {
                SCKeyword kw = shader.keywords[k];
                if (!kw.isMultiCompile)
                {
                    potentialCount++;
                }
            }
            if (potentialCount > 64)
            {
                return;
            }


            if (shader.isShaderGraph)
            {
                ConvertToLocalGraph(keyword, shader);
            }
            else
            {
                ConvertToLocalNonGraph(keyword, shader);
            }
        }
Пример #7
0
        public void UpdateVariantCount()
        {
            totalVariantCount       = 0;
            actualBuildVariantCount = 0;
            passes.ForEach((SCShaderPass pass) => {
                int matCount       = materials.Count;
                int passCount      = 1;
                int passBuildCount = 1;
                for (int l = 0; l < pass.keywordLines.Count; l++)
                {
                    SCKeywordLine line    = pass.keywordLines[l];
                    int kLineEnabledCount = line.hasUnderscoreVariant ? 1 : 0;
                    int kLineCount        = kLineEnabledCount + line.keywords.Count;
                    for (int k = 0; k < line.keywords.Count; k++)
                    {
                        SCKeyword keyword = line.keywords[k];
                        if (keyword.enabled)
                        {
                            // if this is a shader feature, check if there's at least one material using it
                            if (line.pragmaType == PragmaType.FeatureGlobal || line.pragmaType == PragmaType.FeatureLocal)
                            {
                                for (int m = 0; m < matCount; m++)
                                {
                                    if (materials[m].ContainsKeyword(keyword.name))
                                    {
                                        kLineEnabledCount++;
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                kLineEnabledCount++;
                            }
                        }
                    }
                    if (kLineEnabledCount > 0)
                    {
                        passBuildCount *= kLineEnabledCount;
                    }
                    passCount *= kLineCount;
                }
                totalVariantCount       += passCount;
                actualBuildVariantCount += passBuildCount;
            });

            keywordEnabledCount = 0;
            int keywordCount = keywords.Count;

            for (int k = 0; k < keywordCount; k++)
            {
                if (keywords[k].enabled)
                {
                    keywordEnabledCount++;
                }
            }
        }
Пример #8
0
 public override bool Equals(object obj)
 {
     if (obj is SCKeyword)
     {
         SCKeyword other = (SCKeyword)obj;
         return(name.Equals(other.name));
     }
     return(false);
 }
        void ScanShaderGraph(SCShader shader)
        {
            shader.editedByShaderControl = File.Exists(shader.path + BACKUP_SUFFIX);

            // Reads shader
            string shaderContents = File.ReadAllText(shader.path, Encoding.UTF8);

            shaderContents = shaderContents.Replace("UnityEditor.ShaderGraph.ShaderKeyword", "ShaderControl.SCWindow.SerializedKeyword");
            ShaderGraphProxy graph = JsonUtility.FromJson <ShaderGraphProxy>(shaderContents);

            SCShaderPass currentPass = new SCShaderPass();

            if (graph.m_SerializedKeywords != null)
            {
                for (int k = 0; k < graph.m_SerializedKeywords.Length; k++)
                {
                    SerializedKeywordData skw = graph.m_SerializedKeywords[k];
                    if (string.IsNullOrEmpty(skw.JSONnodeData))
                    {
                        continue;
                    }

                    SerializedKeywordProxy kw = JsonUtility.FromJson <SerializedKeywordProxy>(skw.JSONnodeData);

                    PragmaType pragmaType = PragmaType.Unknown;
                    if (kw.m_KeywordDefinition == SHADER_GRAPH_KEYWORD_DEFINITION_MULTI_COMPILE && kw.m_KeywordScope == SHADER_GRAPH_KEYWORD_SCOPE_GLOBAL)
                    {
                        pragmaType = PragmaType.MultiCompileGlobal;
                    }
                    else if (kw.m_KeywordDefinition == SHADER_GRAPH_KEYWORD_DEFINITION_MULTI_COMPILE && kw.m_KeywordScope == SHADER_GRAPH_KEYWORD_SCOPE_LOCAL)
                    {
                        pragmaType = PragmaType.MultiCompileLocal;
                    }
                    else if (kw.m_KeywordDefinition == SHADER_GRAPH_KEYWORD_DEFINITION_SHADER_FEATURE && kw.m_KeywordScope == SHADER_GRAPH_KEYWORD_SCOPE_GLOBAL)
                    {
                        pragmaType = PragmaType.FeatureGlobal;
                    }
                    else if (kw.m_KeywordDefinition == SHADER_GRAPH_KEYWORD_DEFINITION_SHADER_FEATURE && kw.m_KeywordScope == SHADER_GRAPH_KEYWORD_SCOPE_LOCAL)
                    {
                        pragmaType = PragmaType.FeatureLocal;
                    }

                    SCKeywordLine keywordLine = new SCKeywordLine();
                    keywordLine.pragmaType = pragmaType;

                    SCKeyword keyword = new SCKeyword(kw.m_DefaultReferenceName, kw.m_Name);
                    keywordLine.Add(keyword);
                    currentPass.Add(keywordLine);
                }
            }
            shader.Add(currentPass);
            shader.UpdateVariantCount();
        }
Пример #10
0
 public void SetKeywords(string[] names)
 {
     for (int k = 0; k < names.Length; k++)
     {
         if (!keywordSet.Contains(names[k]))
         {
             keywordSet.Add(names[k]);
             SCKeyword keyword = new SCKeyword(names[k]);
             keywords.Add(keyword);
         }
     }
     keywords.Sort(delegate(SCKeyword k1, SCKeyword k2) { return(k1.name.CompareTo(k2.name)); });
 }
Пример #11
0
        public SCKeyword GetKeyword(string name)
        {
            int kc = keywords.Count;

            for (int k = 0; k < kc; k++)
            {
                SCKeyword keyword = keywords [k];
                if (keyword.name.Equals(name))
                {
                    return(keyword);
                }
            }
            return(null);
        }
Пример #12
0
        void ConvertToLocalAll()
        {
            int kvCount = keywordView.Count;

            for (int s = 0; s < kvCount; s++)
            {
                SCKeyword keyword = keywordView[s].keyword;
                if (keyword.isGlobal && !keyword.isMultiCompile)
                {
                    ConvertToLocal(keyword);
                }
            }
            AssetDatabase.Refresh();
        }
Пример #13
0
 public void RemoveKeyword(string name)
 {
     for (int k = 0; k < keywords.Count; k++)
     {
         SCKeyword keyword = keywords[k];
         if (keyword.name.Equals(name))
         {
             if (keyword.enabled)
             {
                 keywordEnabledCount--;
             }
             keywords.Remove(keyword);
             return;
         }
     }
 }
Пример #14
0
 void UpdateKeywords()
 {
     passes.ForEach((SCShaderPass pass) => {
         for (int l = 0; l < pass.keywordLines.Count; l++)
         {
             SCKeywordLine line = pass.keywordLines [l];
             for (int k = 0; k < line.keywords.Count; k++)
             {
                 SCKeyword keyword = line.keywords [k];
                 if (!keywords.Contains(keyword))
                 {
                     keywords.Add(keyword);
                 }
             }
         }
     });
 }
Пример #15
0
        void ConvertToLocal(SCKeyword keyword)
        {
            List <SCShader> shaders;

            if (!uniqueKeywords.TryGetValue(keyword.name, out shaders))
            {
                return;
            }
            if (shaders == null)
            {
                return;
            }
            for (int k = 0; k < shaders.Count; k++)
            {
                ConvertToLocal(keyword, shaders[k]);
            }
            AssetDatabase.Refresh();
        }
Пример #16
0
        void ConvertToLocal(SCKeyword keyword, SCShader shader)
        {
            // Check total local keyword does not exceed 64 limit
            int potentialCount = 0;
            int kwCount        = shader.keywords.Count;

            for (int k = 0; k < kwCount; k++)
            {
                SCKeyword kw = shader.keywords[k];
                if (!kw.isMultiCompile)
                {
                    potentialCount++;
                }
            }
            if (potentialCount > 64)
            {
                return;
            }

            string path = shader.path;

            if (!File.Exists(path))
            {
                return;
            }
            string[] lines   = File.ReadAllLines(path);
            bool     changed = false;

            for (int k = 0; k < lines.Length; k++)
            {
                // Just convert to local shader_features for now since multi_compile global keywords can be nabled using the Shader global API
                if (lines[k].IndexOf(SCKeywordLine.PRAGMA_FEATURE_GLOBAL, StringComparison.InvariantCultureIgnoreCase) >= 0 && lines[k].IndexOf(keyword.name, StringComparison.InvariantCultureIgnoreCase) >= 0)
                {
                    lines[k] = lines[k].Replace(SCKeywordLine.PRAGMA_FEATURE_GLOBAL, SCKeywordLine.PRAGMA_FEATURE_LOCAL);
                    lines[k] = lines[k].Replace(SCKeywordLine.PRAGMA_FEATURE_GLOBAL.ToUpper(), SCKeywordLine.PRAGMA_FEATURE_LOCAL);
                    changed  = true;
                }
            }
            if (changed)
            {
                MakeBackup(shader);
                File.WriteAllLines(path, lines, Encoding.UTF8);
            }
        }
        void ConvertToLocalGraph(SCKeyword keyword, SCShader shader)
        {
            string contents = File.ReadAllText(shader.path, Encoding.UTF8);
            int    i        = contents.IndexOf("m_SerializedKeywords");

            if (i < 0)
            {
                return;
            }
            int j = contents.IndexOf("m_SerializedNodes");

            if (j < 0)
            {
                j = contents.Length - 1;
            }

            int  pos     = contents.IndexOf(keyword.name, i);
            bool changed = false;

            if (pos > i && pos < j)
            {
                int dataBlockPos = contents.LastIndexOf(JSON_NODE_DATA, pos);
                if (dataBlockPos > 0)
                {
                    int scopePos = contents.IndexOf(JSON_KEYWORD_SCOPE, dataBlockPos);
                    if (scopePos > dataBlockPos && scopePos < j)
                    {
                        scopePos += JSON_KEYWORD_SCOPE.Length + 2;
                        int valuePos  = contents.IndexOf("1", scopePos);
                        int safetyPos = contents.IndexOf("\"", scopePos);
                        if (valuePos > scopePos && valuePos < safetyPos && safetyPos > valuePos)
                        {
                            contents = contents.Substring(0, valuePos) + "0" + contents.Substring(valuePos + 1);
                            changed  = true;
                        }
                    }
                }
            }
            if (changed)
            {
                MakeBackup(shader);
                File.WriteAllText(shader.path, contents, Encoding.UTF8);
            }
        }
Пример #18
0
        void DrawProjectGUI()
        {
            GUILayout.Box(new GUIContent("List of shader files in your project and modify their keywords.\nOnly shaders with source code or referenced by materials are included in this tab.\nUse the <color=orange><b>Build View</b></color> tab for a complete list of shaders, including hidden/internal Unity shaders."), titleStyle);
            EditorGUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            scanAllShaders = EditorGUILayout.Toggle(new GUIContent("Force scan all shaders", "Also includes shaders that are not located within a Resources folder"), scanAllShaders);
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            if (GUILayout.Button(new GUIContent("Scan Project Folders", "Quickly scans the project and finds shaders that use keywords.")))
            {
                ScanProject();
                GUIUtility.ExitGUI();
                return;
            }
            if (shaders != null && shaders.Count > 0 && GUILayout.Button(new GUIContent("Clean All Materials", "Removes all disabled keywords in all materials.  This option is provided to ensure no existing materials are referencing a disabled shader keyword.\n\nTo disable keywords, first expand any shader from the list and uncheck the unwanted keywords (press 'Save' to modify the shader file and to clean any existing material that uses that specific shader)."), GUILayout.Width(120)))
            {
                CleanAllMaterials();
                GUIUtility.ExitGUI();
                return;
            }
            if (GUILayout.Button("Help", GUILayout.Width(40)))
            {
                ShowHelpWindowProjectView();
            }
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.EndVertical();

            if (shaders != null)
            {
                string totalGlobalKeywordsTxt = totalGlobalKeywords != totalKeywords ? " (" + totalGlobalKeywords + " global) " : " ";
                if (totalKeywords == totalUsedKeywords || totalKeywords == 0)
                {
                    EditorGUILayout.HelpBox("Shaders Found: " + totalShaderCount.ToString() + "  Shaders Using Keywords: " + shaders.Count.ToString() + "\nKeywords: " + totalKeywords.ToString() + totalGlobalKeywordsTxt + " Variants: " + totalVariants.ToString(), MessageType.Info);
                }
                else
                {
                    int keywordsPerc = totalUsedKeywords * 100 / totalKeywords;
                    int variantsPerc = totalBuildVariants * 100 / totalVariants;
                    EditorGUILayout.HelpBox("Shaders Found: " + totalShaderCount.ToString() + "  Shaders Using Keywords: " + shaders.Count.ToString() + "\nUsed Keywords: " + totalUsedKeywords.ToString() + " of " + totalKeywords.ToString() + " (" + keywordsPerc.ToString() + "%) " + totalGlobalKeywordsTxt + " Actual Variants: " + totalBuildVariants.ToString() + " of " + totalVariants.ToString() + " (" + variantsPerc.ToString() + "%)", MessageType.Info);
                }
                EditorGUILayout.Separator();
                int shaderCount = shaders.Count;
                if (shaderCount > 1)
                {
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField("Sort By", GUILayout.Width(90));
                    SortType prevSortType = sortType;
                    sortType = (SortType)EditorGUILayout.EnumPopup(sortType);
                    if (sortType != prevSortType)
                    {
                        ScanProject();
                        EditorGUIUtility.ExitGUI();
                        return;
                    }
                    EditorGUILayout.EndHorizontal();

                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField("Name Filter", GUILayout.Width(90));
                    projectShaderNameFilter = EditorGUILayout.TextField(projectShaderNameFilter);
                    if (GUILayout.Button(new GUIContent("Clear", "Clear filter."), EditorStyles.miniButton, GUILayout.Width(60)))
                    {
                        projectShaderNameFilter    = "";
                        GUIUtility.keyboardControl = 0;
                    }
                    EditorGUILayout.EndHorizontal();

                    if (sortType != SortType.Keyword)
                    {
                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.LabelField("Keywords >=", GUILayout.Width(90));
                        minimumKeywordCount = EditorGUILayout.IntSlider(minimumKeywordCount, 0, maxKeywordsCountFound);
                        EditorGUILayout.EndHorizontal();
                    }

                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField("Keyword Filter", GUILayout.Width(90));
                    keywordFilter = EditorGUILayout.TextField(keywordFilter);
                    if (GUILayout.Button(new GUIContent("Clear", "Clear filter."), EditorStyles.miniButton, GUILayout.Width(60)))
                    {
                        keywordFilter = "";
                        GUIUtility.keyboardControl = 0;
                    }
                    EditorGUILayout.EndHorizontal();

                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField("Keyword Scope", GUILayout.Width(90));
                    keywordScopeFilter = (KeywordScopeFilter)EditorGUILayout.EnumPopup(keywordScopeFilter);
                    EditorGUILayout.EndHorizontal();

                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField("Pragma Type", GUILayout.Width(90));
                    pragmaTypeFilter = (PragmaTypeFilter)EditorGUILayout.EnumPopup(pragmaTypeFilter);
                    EditorGUILayout.EndHorizontal();

                    if (sortType != SortType.Keyword)
                    {
                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.LabelField("Modified", GUILayout.Width(90));
                        modifiedStatus = (ModifiedStatus)EditorGUILayout.EnumPopup(modifiedStatus);
                        EditorGUILayout.EndHorizontal();
                    }

                    if (keywordScopeFilter != KeywordScopeFilter.GlobalKeywords || pragmaTypeFilter != PragmaTypeFilter.ShaderFeature)
                    {
                        if (totalGlobalShaderFeatures > 0)
                        {
                            if (GUILayout.Button(new GUIContent("Click to show " + totalGlobalShaderFeatures + " global keyword(s) found of type 'shader_feature'", "Lists all shaders using global keywords that can be converted to local safely.")))
                            {
                                sortType                   = SortType.Keyword;
                                keywordScopeFilter         = KeywordScopeFilter.GlobalKeywords;
                                pragmaTypeFilter           = PragmaTypeFilter.ShaderFeature;
                                keywordFilter              = "";
                                GUIUtility.keyboardControl = 0;
                                minimumKeywordCount        = 0;
                            }
                        }
                    }
                    else
                    {
                        if (sortType == SortType.Keyword && totalGlobalShaderFeatures > 1)
                        {
                            if (GUILayout.Button(new GUIContent("Convert all these " + totalGlobalShaderFeatures + " keyword(s) to local", "Converts all global keywords of type Shader_Feature to local keywords, reducing the total keyword usage count.\n A local keyword does not count towards the limit of 256 total keywords in project.")))
                            {
                                ConvertToLocalAll();
                                EditorUtility.DisplayDialog("Process complete!", "All keywords of type shader_feature have been converted to local.\n\nPlease restart Unity to refresh keyword changes.", "Ok");
                                ScanProject();
                                GUIUtility.ExitGUI();
                            }
                        }
                    }
                    EditorGUILayout.Separator();
                }
                scrollViewPosProject = EditorGUILayout.BeginScrollView(scrollViewPosProject);
                if (sortType == SortType.Keyword)
                {
                    if (keywordView != null)
                    {
                        int kvCount = keywordView.Count;
                        for (int s = 0; s < kvCount; s++)
                        {
                            SCKeyword keyword = keywordView[s].keyword;
                            if (keywordScopeFilter != KeywordScopeFilter.Any && ((keywordScopeFilter == KeywordScopeFilter.GlobalKeywords && !keyword.isGlobal) || (keywordScopeFilter == KeywordScopeFilter.LocalKeywords && keyword.isGlobal)))
                            {
                                continue;
                            }
                            if (pragmaTypeFilter != PragmaTypeFilter.Any && ((pragmaTypeFilter == PragmaTypeFilter.MultiCompile && !keyword.isMultiCompile) || (pragmaTypeFilter == PragmaTypeFilter.ShaderFeature && keyword.isMultiCompile)))
                            {
                                continue;
                            }
                            if (!string.IsNullOrEmpty(keywordFilter) && keyword.name.IndexOf(keywordFilter, StringComparison.InvariantCultureIgnoreCase) < 0)
                            {
                                continue;
                            }
                            EditorGUILayout.BeginHorizontal();
                            keywordView[s].foldout = EditorGUILayout.Foldout(keywordView[s].foldout, new GUIContent("Keyword <b>" + keywordView[s].keyword + "</b> found in " + keywordView[s].shaders.Count + " shader(s)"), foldoutRTF);
                            GUILayout.FlexibleSpace();
                            if (!keyword.isMultiCompile && keyword.isGlobal)
                            {
                                if (GUILayout.Button("Convert To Local Keyword", EditorStyles.miniButtonRight))
                                {
                                    if (EditorUtility.DisplayDialog("Convert global keyword to local", "Keyword " + keyword.name + " will be converted to local. This means the keyword won't count toward the maximum global keyword limit (256). Continue?", "Ok", "Cancel"))
                                    {
                                        ConvertToLocal(keyword);
                                        ScanProject();
                                        GUIUtility.ExitGUI();
                                    }
                                }
                            }
                            else if (!keyword.isGlobal)
                            {
                                GUILayout.Label("(Local keyword)");
                            }
                            EditorGUILayout.EndHorizontal();
                            if (keywordView[s].foldout)
                            {
                                int kvShadersCount = keywordView[s].shaders.Count;
                                for (int m = 0; m < kvShadersCount; m++)
                                {
                                    EditorGUILayout.BeginHorizontal();
                                    EditorGUILayout.LabelField("", GUILayout.Width(30));
                                    EditorGUILayout.LabelField(shaderIcon, GUILayout.Width(18));
                                    EditorGUILayout.LabelField(keywordView[s].shaders[m].name);
                                    SCShader shader = keywordView[s].shaders[m];
                                    GUI.enabled = shader.hasSource;
                                    if (GUILayout.Button(new GUIContent("Locate", "Locates the shader in the shader view."), EditorStyles.miniButton, GUILayout.Width(60)))
                                    {
                                        Shader theShader = AssetDatabase.LoadAssetAtPath <Shader>(shader.path);
                                        Selection.activeObject = theShader;
                                        EditorGUIUtility.PingObject(theShader);
                                    }
                                    GUI.enabled = true;
                                    if (GUILayout.Button(new GUIContent("Filter", "Show shaders using this keyword."), EditorStyles.miniButton, GUILayout.Width(60)))
                                    {
                                        keywordFilter = keywordView[s].keyword.name;
                                        sortType      = SortType.VariantsCount;
                                        GUIUtility.ExitGUI();
                                        return;
                                    }
                                    if (!shader.hasBackup)
                                    {
                                        GUI.enabled = false;
                                    }
                                    if (GUILayout.Button(new GUIContent("Restore", "Restores shader from the backup copy."), EditorStyles.miniButton))
                                    {
                                        RestoreShader(shader);
                                        GUIUtility.ExitGUI();
                                        return;
                                    }
                                    GUI.enabled = true;
                                    EditorGUILayout.EndHorizontal();
                                }
                            }
                        }
                    }
                }
                else
                {
                    int shadersListedCount = 0;
                    for (int s = 0; s < shaderCount; s++)
                    {
                        SCShader shader = shaders[s];
                        if (shader.keywordEnabledCount < minimumKeywordCount)
                        {
                            continue;
                        }
                        if (modifiedStatus == ModifiedStatus.OnlyModified && !shader.editedByShaderControl)
                        {
                            continue;
                        }
                        if (modifiedStatus == ModifiedStatus.NonModified && shader.editedByShaderControl)
                        {
                            continue;
                        }
                        bool filterByKeywordName = !string.IsNullOrEmpty(keywordFilter);
                        if (filterByKeywordName || keywordScopeFilter != KeywordScopeFilter.Any || pragmaTypeFilter != PragmaTypeFilter.Any)
                        {
                            int  kwCount = shader.keywords.Count;
                            bool found   = false;
                            for (int w = 0; w < kwCount; w++)
                            {
                                found = true;
                                SCKeyword keyword = shader.keywords[w];
                                if (filterByKeywordName)
                                {
                                    if (keyword.name.IndexOf(keywordFilter, StringComparison.InvariantCultureIgnoreCase) < 0)
                                    {
                                        found = false;
                                    }
                                }
                                if (keywordScopeFilter != KeywordScopeFilter.Any && ((keywordScopeFilter == KeywordScopeFilter.GlobalKeywords && !keyword.isGlobal) || (keywordScopeFilter == KeywordScopeFilter.LocalKeywords && keyword.isGlobal)))
                                {
                                    found = false;
                                }
                                if (pragmaTypeFilter != PragmaTypeFilter.Any && ((pragmaTypeFilter == PragmaTypeFilter.MultiCompile && !keyword.isMultiCompile) || (pragmaTypeFilter == PragmaTypeFilter.ShaderFeature && keyword.isMultiCompile)))
                                {
                                    found = false;
                                }
                                if (found)
                                {
                                    break;
                                }
                            }
                            if (!found)
                            {
                                continue;
                            }
                        }
                        if (!string.IsNullOrEmpty(projectShaderNameFilter) && shader.name.IndexOf(projectShaderNameFilter, StringComparison.InvariantCultureIgnoreCase) < 0)
                        {
                            continue;
                        }

                        shadersListedCount++;
                        EditorGUILayout.BeginHorizontal();
                        string shaderName = shader.isReadOnly ? shader.name + " (readonly)" : shader.name;
                        if (shader.hasSource)
                        {
                            shader.foldout = EditorGUILayout.Foldout(shader.foldout, new GUIContent(shaderName + " (" + shader.keywords.Count + " keywords, " + shader.keywordEnabledCount + " used, " + shader.actualBuildVariantCount + " variants)"), shader.editedByShaderControl ? foldoutBold : foldoutNormal);
                        }
                        else
                        {
                            shader.foldout = EditorGUILayout.Foldout(shader.foldout, new GUIContent(shaderName + " (" + shader.keywordEnabledCount + " keywords used by materials)"), foldoutDim);
                        }
                        EditorGUILayout.EndHorizontal();
                        if (shader.foldout)
                        {
                            EditorGUILayout.BeginHorizontal();
                            EditorGUILayout.LabelField("", GUILayout.Width(15));
                            if (shader.hasSource)
                            {
                                if (GUILayout.Button(new GUIContent("Locate", "Locate the shader in the project panel."), EditorStyles.miniButton))
                                {
                                    Shader theShader = AssetDatabase.LoadAssetAtPath <Shader>(shader.path);
                                    Selection.activeObject = theShader;
                                    EditorGUIUtility.PingObject(theShader);
                                }
                                if (GUILayout.Button(new GUIContent("Open", "Open the shader with the system default editor."), EditorStyles.miniButton))
                                {
                                    EditorUtility.OpenWithDefaultApp(shader.path);
                                }
                                if (!shader.pendingChanges)
                                {
                                    GUI.enabled = false;
                                }
                                if (GUILayout.Button(new GUIContent("Save", "Saves any keyword change to the shader file (disable/enable the keywords just clicking on the toggle next to the keywords shown below). A backup is created in the same folder."), EditorStyles.miniButton))
                                {
                                    UpdateShader(shader);
                                }
                                GUI.enabled = true;
                                if (!shader.hasBackup)
                                {
                                    GUI.enabled = false;
                                }
                                if (GUILayout.Button(new GUIContent("Restore", "Restores shader from the backup copy."), EditorStyles.miniButton))
                                {
                                    RestoreShader(shader);
                                    GUIUtility.ExitGUI();
                                    return;
                                }
                                GUI.enabled = true;
                            }
                            else
                            {
                                EditorGUILayout.LabelField("(Shader source not available)");
                            }
                            if (shader.materials.Count > 0)
                            {
                                if (GUILayout.Button(new GUIContent(shader.showMaterials ? "Hide Materials" : "List Materials", "Show or hide the materials that use these keywords."), EditorStyles.miniButton))
                                {
                                    shader.showMaterials = !shader.showMaterials;
                                    GUIUtility.ExitGUI();
                                    return;
                                }
                                if (shader.showMaterials)
                                {
                                    EditorGUILayout.EndHorizontal();
                                    EditorGUILayout.BeginHorizontal();
                                    EditorGUILayout.LabelField("", GUILayout.Width(15));
                                    if (GUILayout.Button("Select Materials In Project", EditorStyles.miniButton))
                                    {
                                        int             matCount     = shader.materials.Count;
                                        List <Material> allMaterials = new List <Material>();
                                        for (int m = 0; m < matCount; m++)
                                        {
                                            SCMaterial material = shader.materials[m];
                                            allMaterials.Add(material.unityMaterial);
                                        }
                                        if (allMaterials.Count > 0)
                                        {
                                            Selection.objects = allMaterials.ToArray();
                                            EditorGUIUtility.PingObject(allMaterials[0]);
                                        }
                                        else
                                        {
                                            EditorUtility.DisplayDialog("Select Materials In Project", "No matching materials found in project.", "Ok");
                                        }
                                    }
                                    if (GUILayout.Button("Select Materials In Scene", EditorStyles.miniButton))
                                    {
                                        int matCount          = shader.materials.Count;
                                        List <GameObject> gos = new List <GameObject>();
                                        Renderer[]        rr  = FindObjectsOfType <Renderer>();
                                        foreach (Renderer r in rr)
                                        {
                                            GameObject go = r.gameObject;
                                            if (go == null)
                                            {
                                                continue;
                                            }
                                            if ((go.hideFlags & HideFlags.NotEditable) != 0 || (go.hideFlags & HideFlags.HideAndDontSave) != 0)
                                            {
                                                continue;
                                            }

                                            Material[] mats = r.sharedMaterials;
                                            if (mats == null)
                                            {
                                                continue;
                                            }

                                            for (int m = 0; m < matCount; m++)
                                            {
                                                Material mat = shader.materials[m].unityMaterial;
                                                for (int sm = 0; sm < mats.Length; sm++)
                                                {
                                                    Debug.Log(mat.name + " " + mats[sm].name);
                                                    if (mats[sm] == mat)
                                                    {
                                                        gos.Add(go);
                                                        m = matCount;
                                                        break;
                                                    }
                                                }
                                            }
                                        }
                                        if (gos.Count > 0)
                                        {
                                            Selection.objects = gos.ToArray();
                                        }
                                        else
                                        {
                                            EditorUtility.DisplayDialog("Select Materials In Scene", "No matching materials found in objects of this scene.", "Ok");
                                        }
                                    }
                                }
                            }
                            EditorGUILayout.EndHorizontal();

                            for (int k = 0; k < shader.keywords.Count; k++)
                            {
                                SCKeyword keyword = shader.keywords[k];
                                if (keyword.isUnderscoreKeyword)
                                {
                                    continue;
                                }
                                EditorGUILayout.BeginHorizontal();
                                EditorGUILayout.LabelField("", GUILayout.Width(15));
                                if (shader.hasSource)
                                {
                                    bool prevState = keyword.enabled;
                                    keyword.enabled = EditorGUILayout.Toggle(prevState, GUILayout.Width(18));
                                    if (prevState != keyword.enabled)
                                    {
                                        shader.pendingChanges = true;
                                        shader.UpdateVariantCount();
                                        UpdateProjectStats();
                                        GUIUtility.ExitGUI();
                                        return;
                                    }
                                }
                                else
                                {
                                    EditorGUILayout.Toggle(true, GUILayout.Width(18));
                                }
                                if (!keyword.enabled)
                                {
                                    EditorGUILayout.LabelField(keyword.verboseName);
                                }
                                else
                                {
                                    EditorGUILayout.LabelField(keyword.verboseName);
                                    if (!shader.hasSource && GUILayout.Button(new GUIContent("Prune Keyword", "Removes the keyword from all materials that reference it."), EditorStyles.miniButton, GUILayout.Width(110)))
                                    {
                                        if (EditorUtility.DisplayDialog("Prune Keyword", "This option will disable the keyword " + keyword.name + " in all materials that use " + shader.name + " shader.\nDo you want to continue?", "Ok", "Cancel"))
                                        {
                                            PruneMaterials(shader, keyword.name);
                                            UpdateProjectStats();
                                        }
                                    }
                                }
                                EditorGUILayout.EndHorizontal();
                                if (shader.showMaterials)
                                {
                                    // show materials using this shader
                                    int matCount = shader.materials.Count;
                                    for (int m = 0; m < matCount; m++)
                                    {
                                        SCMaterial material = shader.materials[m];
                                        if (material.ContainsKeyword(keyword.name))
                                        {
                                            EditorGUILayout.BeginHorizontal();
                                            EditorGUILayout.LabelField("", GUILayout.Width(30));
                                            EditorGUILayout.LabelField(matIcon, GUILayout.Width(18));
                                            EditorGUILayout.LabelField(material.unityMaterial.name);
                                            if (GUILayout.Button(new GUIContent("Locate", "Locates the material in the project panel."), EditorStyles.miniButton, GUILayout.Width(60)))
                                            {
                                                Material theMaterial = AssetDatabase.LoadAssetAtPath <Material>(material.path) as Material;
                                                Selection.activeObject = theMaterial;
                                                EditorGUIUtility.PingObject(theMaterial);
                                            }
                                            EditorGUILayout.EndHorizontal();
                                        }
                                    }
                                }
                            }

                            if (shader.showMaterials)
                            {
                                // show materials using this shader that does not use any keywords
                                bool first    = true;
                                int  matCount = shader.materials.Count;
                                for (int m = 0; m < matCount; m++)
                                {
                                    SCMaterial material = shader.materials[m];
                                    if (material.keywords.Count == 0)
                                    {
                                        if (first)
                                        {
                                            first = false;
                                            EditorGUILayout.BeginHorizontal();
                                            EditorGUILayout.LabelField("", GUILayout.Width(15));
                                            EditorGUILayout.LabelField("Materials using this shader and no keywords:");
                                            EditorGUILayout.EndHorizontal();
                                        }
                                        EditorGUILayout.BeginHorizontal();
                                        EditorGUILayout.LabelField("", GUILayout.Width(15));
                                        EditorGUILayout.LabelField(matIcon, GUILayout.Width(18));
                                        EditorGUILayout.LabelField(material.unityMaterial.name);
                                        if (GUILayout.Button(new GUIContent("Locate", "Locates the material in the project panel."), EditorStyles.miniButton, GUILayout.Width(60)))
                                        {
                                            Material theMaterial = AssetDatabase.LoadAssetAtPath <Material>(material.path) as Material;
                                            Selection.activeObject = theMaterial;
                                            EditorGUIUtility.PingObject(theMaterial);
                                        }
                                        EditorGUILayout.EndHorizontal();
                                    }
                                }
                            }
                        }
                        EditorGUILayout.Separator();
                    }
                    if (shadersListedCount == 0 && !string.IsNullOrEmpty(projectShaderNameFilter))
                    {
                        EditorGUILayout.HelpBox("No shader matching '" + projectShaderNameFilter + "' name found. Either the shader doesn't exist in the project as source file or the shader does not use explicit keywords.", MessageType.Info);
                    }
                }
                EditorGUILayout.EndScrollView();
            }
        }
Пример #19
0
        void DrawSVCMgrGUI()
        {
            svcSettingsInfo = CheckSVCSettingsStore(svcSettingsInfo);
            if (null == svcSettingsInfo)
            {
                return;
            }

            GUILayout.Box(new GUIContent(" Set All Shader Variant Colletion Usage "), titleStyle, GUILayout.ExpandWidth(true));
            for (int i = 0; i < svcSettingsInfo.collection.Count; i++)
            {
                EditorGUILayout.BeginHorizontal();
                {
                    EditorGUILayout.LabelField(string.Format("Set SVC Usage {0}:", (i + 1)), GUILayout.Width(80));

                    EditorGUI.BeginChangeCheck();
                    {
                        svcSettingsInfo.collection[i] = (ShaderVariantCollection)EditorGUILayout.ObjectField(svcSettingsInfo.collection[i], typeof(ShaderVariantCollection), false);

                        ShaderVariantUsage usage = (ShaderVariantUsage)EditorGUILayout.EnumPopup("Usage", (ShaderVariantUsage)svcSettingsInfo.usage[i]);
                        svcSettingsInfo.usage[i] = (int)usage;

                        if (GUILayout.Button("¡ª", GUILayout.Width(30)))
                        {
                            //delete in loop
                            svcSettingsInfo.collection.RemoveAt(i);
                            svcSettingsInfo.usage.RemoveAt(i);
                            i--;
                        }
                    }
                    if (EditorGUI.EndChangeCheck())
                    {
                        EditorUtility.SetDirty(svcSettingsInfo);
                        AssetDatabase.SaveAssets();
                    }
                }
                EditorGUILayout.EndHorizontal();
            }

            EditorGUILayout.BeginHorizontal();
            {
                EditorGUI.BeginChangeCheck();
                {
                    if (GUILayout.Button(new GUIContent("Add Shader Variant Collection")))
                    {
                        svcSettingsInfo.collection.Add(null);
                        svcSettingsInfo.usage.Add(0);
                    }
                    if (EditorGUI.EndChangeCheck())
                    {
                        EditorUtility.SetDirty(svcSettingsInfo);
                        AssetDatabase.SaveAssets();
                    }
                }
            }
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.EndVertical();
            EditorGUILayout.Separator();

            //if (GUILayout.Button(new GUIContent("Collect SVC in target Scenes", "Quickly scans the project and finds shaders that use keywords.")))
            //{
            //    LoadAllScenesCollectMaterial();
            //    GUIUtility.ExitGUI();
            //    return;
            //}
            if (shaders != null && shaders.Count > 0 && GUILayout.Button(new GUIContent("Clean All Materials", "Removes all disabled keywords in all materials.  This option is provided to ensure no existing materials are referencing a disabled shader keyword.\n\nTo disable keywords, first expand any shader from the list and uncheck the unwanted keywords (press 'Save' to modify the shader file and to clean any existing material that uses that specific shader)."), GUILayout.Width(130)))
            {
                CleanAllMaterials();
                GUIUtility.ExitGUI();
                return;
            }
            //if (GUILayout.Button("Help", GUILayout.Width(40))) {
            //    ShowHelpWindowProjectView();
            //}
            //EditorGUILayout.EndHorizontal();
            //EditorGUILayout.EndVertical();
            //EditorGUILayout.Separator();

            EditorGUILayout.BeginVertical(blackStyle);
            EditorGUILayout.BeginHorizontal();
            {
                if (GUILayout.Button(new GUIContent("Save Shader Variant Collection Settings", "save current shader variants")))
                {
                    string message   = "Save shader variant collection";
                    string assetPath = EditorUtility.SaveFilePanelInProject("Save Shader Variant Collection", "NewShaderVariants", "shadervariants", message);
                    if (!string.IsNullOrEmpty(assetPath))
                    {
                        SVCTool.ShaderUtils.SaveCurrentShaderVariantCollection(assetPath);
                        PostProcessSavedSVC(assetPath);
                    }

                    GUIUtility.ExitGUI();
                    return;
                }
            }
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.EndVertical();
            EditorGUILayout.Separator();


            if (shaders != null)
            {
                string totalGlobalKeywordsTxt = totalGlobalKeywords != totalKeywords ? " (" + totalGlobalKeywords + " global) " : " ";
                string statsText;
                if (totalKeywords == totalUsedKeywords || totalKeywords == 0)
                {
                    statsText = "Shaders Found: " + totalShaderCount.ToString() + "  Shaders Using Keywords: " + shaders.Count.ToString() + "\nKeywords: " + totalKeywords.ToString() + totalGlobalKeywordsTxt + " Variants: " + totalVariants.ToString();
                }
                else
                {
                    int keywordsPerc = totalUsedKeywords * 100 / totalKeywords;
                    int variantsPerc = totalBuildVariants * 100 / totalVariants;
                    statsText = "Shaders Found: " + totalShaderCount.ToString() + "  Shaders Using Keywords: " + shaders.Count.ToString() + "\nUsed Keywords: " + totalUsedKeywords.ToString() + " of " + totalKeywords.ToString() + " (" + keywordsPerc.ToString() + "%) " + totalGlobalKeywordsTxt + " Actual Variants: " + totalBuildVariants.ToString() + " of " + totalVariants.ToString() + " (" + variantsPerc.ToString() + "%)";
                }
                if (totalBuildShaders == 0)
                {
                    statsText += "\nNote: Total keyword count maybe higher. Use 'Build View' tab to detect additional shaders/keywords used by Unity.";
                }
                else if (plusBuildKeywords > 0)
                {
                    statsText += "\n+ " + plusBuildKeywords + " additional keywords detected in last build.";
                }
                EditorGUILayout.HelpBox(statsText, MessageType.Info);
                EditorGUILayout.Separator();
                int shaderCount = shaders.Count;
                if (shaderCount > 0)
                {
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField("Sort By", GUILayout.Width(100));
                    SortType prevSortType = sortType;
                    sortType = (SortType)EditorGUILayout.EnumPopup(sortType);
                    if (sortType != prevSortType)
                    {
                        ScanProject();
                        GUIUtility.ExitGUI();
                        return;
                    }
                    EditorGUILayout.EndHorizontal();

                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField("Name Filter", GUILayout.Width(100));
                    projectShaderNameFilter = EditorGUILayout.TextField(projectShaderNameFilter);
                    if (GUILayout.Button(new GUIContent("Clear", "Clear filter."), EditorStyles.miniButton, GUILayout.Width(60)))
                    {
                        projectShaderNameFilter    = "";
                        GUIUtility.keyboardControl = 0;
                    }
                    EditorGUILayout.EndHorizontal();

                    if (sortType != SortType.Keyword)
                    {
                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.LabelField("Keywords >=", GUILayout.Width(100));
                        minimumKeywordCount = EditorGUILayout.IntSlider(minimumKeywordCount, 0, maxKeywordsCountFound);
                        EditorGUILayout.EndHorizontal();
                    }

                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField("Keyword Filter", GUILayout.Width(100));
                    keywordFilter = EditorGUILayout.TextField(keywordFilter);
                    if (GUILayout.Button(new GUIContent("Clear", "Clear filter."), EditorStyles.miniButton, GUILayout.Width(60)))
                    {
                        keywordFilter = "";
                        GUIUtility.keyboardControl = 0;
                    }
                    EditorGUILayout.EndHorizontal();

                    if (sortType != SortType.Material)
                    {
                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.LabelField("Keyword Scope", GUILayout.Width(100));
                        keywordScopeFilter = (KeywordScopeFilter)EditorGUILayout.EnumPopup(keywordScopeFilter);
                        EditorGUILayout.EndHorizontal();

                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.LabelField("Pragma Type", GUILayout.Width(100));
                        pragmaTypeFilter = (PragmaTypeFilter)EditorGUILayout.EnumPopup(pragmaTypeFilter);
                        EditorGUILayout.EndHorizontal();

                        if (sortType != SortType.Keyword)
                        {
                            EditorGUILayout.BeginHorizontal();
                            EditorGUILayout.LabelField("Modified", GUILayout.Width(100));
                            modifiedStatus = (ModifiedStatus)EditorGUILayout.EnumPopup(modifiedStatus);
                            EditorGUILayout.EndHorizontal();
                            notIncludedInBuild = EditorGUILayout.ToggleLeft("List Shaders Not Used In Build", notIncludedInBuild);
                            if (notIncludedInBuild)
                            {
                                if (totalBuildShaders == 0)
                                {
                                    EditorGUILayout.HelpBox("No build data yet. Perform a build to detect which shaders are being included in your build. Use 'Quick Build' from the Build View tab to make a fast build.", MessageType.Error);
                                }
                            }
                        }

                        if (keywordScopeFilter != KeywordScopeFilter.GlobalKeywords || pragmaTypeFilter != PragmaTypeFilter.ShaderFeature)
                        {
                            if (totalGlobalShaderFeatures > 0)
                            {
                                if (GUILayout.Button(new GUIContent("Click to show " + totalGlobalShaderFeatures + " global keyword(s) found of type 'shader_feature'", "Lists all shaders using global keywords that can be converted to local safely.")))
                                {
                                    sortType                   = SortType.Keyword;
                                    keywordScopeFilter         = KeywordScopeFilter.GlobalKeywords;
                                    pragmaTypeFilter           = PragmaTypeFilter.ShaderFeature;
                                    keywordFilter              = "";
                                    GUIUtility.keyboardControl = 0;
                                    minimumKeywordCount        = 0;
                                }
                            }
                        }
                        else
                        {
                            if (sortType == SortType.Keyword && totalGlobalShaderFeatures > 1)
                            {
                                if (GUILayout.Button(new GUIContent("Convert all these " + totalGlobalShaderFeatures + " keyword(s) to local", "Converts all global keywords of type Shader_Feature to local keywords, reducing the total keyword usage count.\n A local keyword does not count towards the limit of 256 total keywords in project.")))
                                {
                                    ConvertToLocalAll();
                                    EditorUtility.DisplayDialog("Process complete!", "All keywords of type shader_feature have been converted to local.\n\nPlease restart Unity to refresh keyword changes.", "Ok");
                                    ScanProject();
                                    GUIUtility.ExitGUI();
                                }
                            }
                        }
                    }
                    EditorGUILayout.Separator();
                }
                scrollViewPosProject = EditorGUILayout.BeginScrollView(scrollViewPosProject);
                if (sortType == SortType.Material)
                {
                    if (projectMaterials != null)
                    {
                        int matCount = projectMaterials.Count;
                        for (int s = 0; s < matCount; s++)
                        {
                            SCMaterial mat          = projectMaterials[s];
                            int        keywordCount = mat.keywords.Count;
                            if (keywordCount < minimumKeywordCount)
                            {
                                continue;
                            }
                            if (!string.IsNullOrEmpty(projectShaderNameFilter) && mat.unityMaterial.name.IndexOf(projectShaderNameFilter, StringComparison.InvariantCultureIgnoreCase) < 0)
                            {
                                continue;
                            }

                            mat.foldout = EditorGUILayout.Foldout(mat.foldout, new GUIContent("Material <b>" + mat.unityMaterial.name + "</b> referencing " + keywordCount + " keywords."), foldoutRTF);
                            if (mat.foldout)
                            {
                                for (int m = 0; m < keywordCount; m++)
                                {
                                    EditorGUILayout.BeginHorizontal();
                                    EditorGUILayout.LabelField("", GUILayout.Width(30));
                                    EditorGUILayout.LabelField(shaderIcon, GUILayout.Width(18));
                                    EditorGUILayout.LabelField(mat.keywords[m].name);
                                    if (GUILayout.Button(new GUIContent("Locate", "Locates material in project."), EditorStyles.miniButton, GUILayout.Width(60)))
                                    {
                                        Selection.activeObject = mat.unityMaterial;
                                        EditorGUIUtility.PingObject(mat.unityMaterial);
                                    }
                                    if (GUILayout.Button(new GUIContent("Prune", "Removes keyword from this material."), EditorStyles.miniButton, GUILayout.Width(60)))
                                    {
                                        if (EditorUtility.DisplayDialog("Prune Keyword", "Remove this keyword from the material?", "Yes", "No"))
                                        {
                                            mat.unityMaterial.DisableKeyword(mat.keywords[m].name);
                                            EditorUtility.SetDirty(mat.unityMaterial);
                                            mat.RemoveKeyword(mat.keywords[m].name);
                                            GUIUtility.ExitGUI();
                                            return;
                                        }
                                    }
                                    if (GUILayout.Button(new GUIContent("Prune All", "Removes this keyword from all materials."), EditorStyles.miniButton, GUILayout.Width(80)))
                                    {
                                        if (EditorUtility.DisplayDialog("Prune All", "Remove this keyword from all materials?", "Yes", "No"))
                                        {
                                            PruneMaterials(mat.keywords[m].name);
                                            UpdateProjectStats();
                                            GUIUtility.ExitGUI();
                                            return;
                                        }
                                    }
                                    EditorGUILayout.EndHorizontal();
                                }
                            }
                        }
                    }
                }
                else if (sortType == SortType.Keyword)
                {
                    if (keywordView != null)
                    {
                        int kvCount = keywordView.Count;
                        for (int s = 0; s < kvCount; s++)
                        {
                            SCKeyword keyword = keywordView[s].keyword;
                            if (keywordScopeFilter != KeywordScopeFilter.Any && ((keywordScopeFilter == KeywordScopeFilter.GlobalKeywords && !keyword.isGlobal) || (keywordScopeFilter == KeywordScopeFilter.LocalKeywords && keyword.isGlobal)))
                            {
                                continue;
                            }
                            if (pragmaTypeFilter != PragmaTypeFilter.Any && ((pragmaTypeFilter == PragmaTypeFilter.MultiCompile && !keyword.isMultiCompile) || (pragmaTypeFilter == PragmaTypeFilter.ShaderFeature && keyword.isMultiCompile)))
                            {
                                continue;
                            }
                            if (!string.IsNullOrEmpty(keywordFilter) && keyword.name.IndexOf(keywordFilter, StringComparison.InvariantCultureIgnoreCase) < 0)
                            {
                                continue;
                            }
                            EditorGUILayout.BeginHorizontal();
                            keywordView[s].foldout = EditorGUILayout.Foldout(keywordView[s].foldout, new GUIContent("Keyword <b>" + keywordView[s].keyword + "</b> found in " + keywordView[s].shaders.Count + " shader(s)"), foldoutRTF);
                            GUILayout.FlexibleSpace();
                            if (!keyword.isMultiCompile && keyword.isGlobal)
                            {
                                if (GUILayout.Button("Convert To Local Keyword", EditorStyles.miniButtonRight, GUILayout.Width(190)))
                                {
                                    if (EditorUtility.DisplayDialog("Convert global keyword to local", "Keyword " + keyword.name + " will be converted to local. This means the keyword won't count toward the maximum global keyword limit (256). Continue?", "Ok", "Cancel"))
                                    {
                                        ConvertToLocal(keyword);
                                        ScanProject();
                                        GUIUtility.ExitGUI();
                                    }
                                }
                            }
                            else if (!keyword.isGlobal)
                            {
                                GUILayout.Label("(Local keyword)");
                            }
                            EditorGUILayout.EndHorizontal();
                            if (keywordView[s].foldout)
                            {
                                int kvShadersCount = keywordView[s].shaders.Count;
                                for (int m = 0; m < kvShadersCount; m++)
                                {
                                    EditorGUILayout.BeginHorizontal();
                                    EditorGUILayout.LabelField("", GUILayout.Width(30));
                                    EditorGUILayout.LabelField(shaderIcon, GUILayout.Width(18));
                                    EditorGUILayout.LabelField(keywordView[s].shaders[m].name);
                                    SCShader shader = keywordView[s].shaders[m];
                                    GUI.enabled = shader.hasSource;
                                    if (GUILayout.Button(new GUIContent("Locate", "Locates the shader in the shader view."), EditorStyles.miniButton, GUILayout.Width(60)))
                                    {
                                        Shader theShader = AssetDatabase.LoadAssetAtPath <Shader>(shader.path);
                                        Selection.activeObject = theShader;
                                        EditorGUIUtility.PingObject(theShader);
                                    }
                                    GUI.enabled = true;
                                    if (GUILayout.Button(new GUIContent("Filter", "Show shaders using this keyword."), EditorStyles.miniButton, GUILayout.Width(60)))
                                    {
                                        keywordFilter = keywordView[s].keyword.name;
                                        sortType      = SortType.VariantsCount;
                                        GUIUtility.ExitGUI();
                                        return;
                                    }
                                    if (!shader.hasBackup)
                                    {
                                        GUI.enabled = false;
                                    }
                                    if (GUILayout.Button(new GUIContent("Restore", "Restores shader from the backup copy."), EditorStyles.miniButton))
                                    {
                                        RestoreShader(shader);
                                        GUIUtility.ExitGUI();
                                        return;
                                    }
                                    GUI.enabled = true;
                                    EditorGUILayout.EndHorizontal();
                                }
                            }
                        }
                    }
                }
                else
                {
                    int shadersListedCount = 0;

                    for (int s = 0; s < shaderCount; s++)
                    {
                        SCShader shader = shaders[s];
                        if (shader.keywordEnabledCount < minimumKeywordCount)
                        {
                            continue;
                        }
                        if (modifiedStatus == ModifiedStatus.OnlyModified && !shader.editedByShaderControl)
                        {
                            continue;
                        }
                        if (modifiedStatus == ModifiedStatus.NonModified && shader.editedByShaderControl)
                        {
                            continue;
                        }
                        bool filterByKeywordName = !string.IsNullOrEmpty(keywordFilter);
                        if (filterByKeywordName || keywordScopeFilter != KeywordScopeFilter.Any || pragmaTypeFilter != PragmaTypeFilter.Any)
                        {
                            int  kwCount = shader.keywords.Count;
                            bool found   = false;
                            for (int w = 0; w < kwCount; w++)
                            {
                                found = true;
                                SCKeyword keyword = shader.keywords[w];
                                if (filterByKeywordName)
                                {
                                    if (keyword.name.IndexOf(keywordFilter, StringComparison.InvariantCultureIgnoreCase) < 0)
                                    {
                                        found = false;
                                    }
                                }
                                if (keywordScopeFilter != KeywordScopeFilter.Any && ((keywordScopeFilter == KeywordScopeFilter.GlobalKeywords && !keyword.isGlobal) || (keywordScopeFilter == KeywordScopeFilter.LocalKeywords && keyword.isGlobal)))
                                {
                                    found = false;
                                }
                                if (pragmaTypeFilter != PragmaTypeFilter.Any && ((pragmaTypeFilter == PragmaTypeFilter.MultiCompile && !keyword.isMultiCompile) || (pragmaTypeFilter == PragmaTypeFilter.ShaderFeature && keyword.isMultiCompile)))
                                {
                                    found = false;
                                }
                                if (found)
                                {
                                    break;
                                }
                            }
                            if (!found)
                            {
                                continue;
                            }
                        }
                        if (!string.IsNullOrEmpty(projectShaderNameFilter) && shader.name.IndexOf(projectShaderNameFilter, StringComparison.InvariantCultureIgnoreCase) < 0)
                        {
                            continue;
                        }
                        if (notIncludedInBuild && totalBuildShaders > 0)
                        {
                            bool included = false;
                            for (int sb = 0; sb < totalBuildShaders; sb++)
                            {
                                if (shadersBuildInfo.shaders[sb].name.Equals(shader.fullName))
                                {
                                    included = true;
                                    break;
                                }
                            }
                            if (included)
                            {
                                continue;
                            }
                        }

                        shadersListedCount++;
                        EditorGUILayout.BeginHorizontal();
                        string shaderName = shader.isReadOnly ? shader.name + " (readonly)" : shader.name;
                        if (shader.hasSource)
                        {
                            shader.foldout = EditorGUILayout.Foldout(shader.foldout, new GUIContent(shaderName + " (" + shader.keywords.Count + " keywords, " + shader.keywordEnabledCount + " used, " + shader.actualBuildVariantCount + " variants)"), shader.editedByShaderControl ? foldoutBold : foldoutNormal);
                        }
                        else
                        {
                            shader.foldout = EditorGUILayout.Foldout(shader.foldout, new GUIContent(shaderName + " (" + shader.keywordEnabledCount + " keywords used by materials)"), foldoutDim);
                        }
                        EditorGUILayout.EndHorizontal();
                        if (shader.foldout)
                        {
                            EditorGUILayout.BeginHorizontal();
                            EditorGUILayout.LabelField("", GUILayout.Width(15));
                            if (shader.hasSource)
                            {
                                if (GUILayout.Button(new GUIContent("Locate", "Locate the shader in the project panel."), EditorStyles.miniButton))
                                {
                                    Shader theShader = AssetDatabase.LoadAssetAtPath <Shader>(shader.path);
                                    Selection.activeObject = theShader;
                                    EditorGUIUtility.PingObject(theShader);
                                }
                                if (!shader.isShaderGraph)
                                {
                                    if (GUILayout.Button(new GUIContent("Open", "Open the shader with the system default editor."), EditorStyles.miniButton))
                                    {
                                        EditorUtility.OpenWithDefaultApp(shader.path);
                                    }
                                    if (!shader.pendingChanges)
                                    {
                                        GUI.enabled = false;
                                    }
                                    if (GUILayout.Button(new GUIContent("Save", "Saves any keyword change to the shader file (disable/enable the keywords just clicking on the toggle next to the keywords shown below). A backup is created in the same folder."), EditorStyles.miniButton))
                                    {
                                        UpdateShader(shader);
                                    }
                                    GUI.enabled = true;
                                }
                                if (!shader.hasBackup)
                                {
                                    GUI.enabled = false;
                                }
                                if (GUILayout.Button(new GUIContent("Restore", "Restores shader from the backup copy."), EditorStyles.miniButton))
                                {
                                    RestoreShader(shader);
                                    GUIUtility.ExitGUI();
                                    return;
                                }
                                GUI.enabled = true;
                            }
                            else
                            {
                                EditorGUILayout.LabelField("(Shader source not available)");
                            }
                            if (shader.materials.Count > 0)
                            {
                                if (GUILayout.Button(new GUIContent(shader.showMaterials ? "Hide Materials" : "List Materials", "Show or hide the materials that use these keywords."), EditorStyles.miniButton))
                                {
                                    shader.showMaterials = !shader.showMaterials;
                                    GUIUtility.ExitGUI();
                                    return;
                                }
                                if (shader.showMaterials)
                                {
                                    EditorGUILayout.EndHorizontal();
                                    EditorGUILayout.BeginHorizontal();
                                    EditorGUILayout.LabelField("", GUILayout.Width(15));
                                    if (GUILayout.Button("Select Materials In Project", EditorStyles.miniButton))
                                    {
                                        int             matCount     = shader.materials.Count;
                                        List <Material> allMaterials = new List <Material>();
                                        for (int m = 0; m < matCount; m++)
                                        {
                                            SCMaterial material = shader.materials[m];
                                            allMaterials.Add(material.unityMaterial);
                                        }
                                        if (allMaterials.Count > 0)
                                        {
                                            Selection.objects = allMaterials.ToArray();
                                            EditorGUIUtility.PingObject(allMaterials[0]);
                                        }
                                        else
                                        {
                                            EditorUtility.DisplayDialog("Select Materials In Project", "No matching materials found in project.", "Ok");
                                        }
                                    }
                                    if (GUILayout.Button("Select Materials In Scene", EditorStyles.miniButton))
                                    {
                                        int matCount          = shader.materials.Count;
                                        List <GameObject> gos = new List <GameObject>();
                                        Renderer[]        rr  = FindObjectsOfType <Renderer>();
                                        foreach (Renderer r in rr)
                                        {
                                            GameObject go = r.gameObject;
                                            if (go == null)
                                            {
                                                continue;
                                            }
                                            if ((go.hideFlags & HideFlags.NotEditable) != 0 || (go.hideFlags & HideFlags.HideAndDontSave) != 0)
                                            {
                                                continue;
                                            }

                                            Material[] mats = r.sharedMaterials;
                                            if (mats == null)
                                            {
                                                continue;
                                            }

                                            for (int m = 0; m < matCount; m++)
                                            {
                                                Material mat = shader.materials[m].unityMaterial;
                                                for (int sm = 0; sm < mats.Length; sm++)
                                                {
                                                    Debug.Log(mat.name + " " + mats[sm].name);
                                                    if (mats[sm] == mat)
                                                    {
                                                        gos.Add(go);
                                                        m = matCount;
                                                        break;
                                                    }
                                                }
                                            }
                                        }
                                        if (gos.Count > 0)
                                        {
                                            Selection.objects = gos.ToArray();
                                        }
                                        else
                                        {
                                            EditorUtility.DisplayDialog("Select Materials In Scene", "No matching materials found in objects of this scene.", "Ok");
                                        }
                                    }
                                }
                            }
                            EditorGUILayout.EndHorizontal();

                            for (int k = 0; k < shader.keywords.Count; k++)
                            {
                                SCKeyword keyword = shader.keywords[k];
                                if (keyword.isUnderscoreKeyword)
                                {
                                    continue;
                                }
                                EditorGUILayout.BeginHorizontal();
                                EditorGUILayout.LabelField("", GUILayout.Width(15));
                                if (shader.hasSource && !shader.isShaderGraph)
                                {
                                    bool prevState = keyword.enabled;
                                    keyword.enabled = EditorGUILayout.Toggle(prevState, GUILayout.Width(18));
                                    if (prevState != keyword.enabled)
                                    {
                                        shader.pendingChanges = true;
                                        shader.UpdateVariantCount();
                                        UpdateProjectStats();
                                        GUIUtility.ExitGUI();
                                        return;
                                    }
                                }
                                else
                                {
                                    EditorGUILayout.Toggle(true, GUILayout.Width(18));
                                }
                                EditorGUILayout.LabelField(keyword.verboseName);
                                if (keyword.enabled)
                                {
                                    if (!shader.hasSource && GUILayout.Button(new GUIContent("Prune Keyword", "Removes the keyword from all materials that reference it."), EditorStyles.miniButton, GUILayout.Width(110)))
                                    {
                                        if (EditorUtility.DisplayDialog("Prune Keyword", "This option will disable the keyword " + keyword.name + " in all materials that use " + shader.name + " shader.\nDo you want to continue?", "Ok", "Cancel"))
                                        {
                                            PruneMaterials(keyword.name);
                                            UpdateProjectStats();
                                        }
                                    }
                                    if (!keyword.isMultiCompile && keyword.isGlobal)
                                    {
                                        if (GUILayout.Button("Convert To Local Keyword", EditorStyles.miniButtonRight, GUILayout.Width(190)))
                                        {
                                            if (EditorUtility.DisplayDialog("Convert global keyword to local", "Keyword " + keyword.name + " will be converted to local. This means the keyword won't count toward the maximum global keyword limit (256). Continue?", "Ok", "Cancel"))
                                            {
                                                ConvertToLocal(keyword);
                                                ScanProject();
                                                GUIUtility.ExitGUI();
                                            }
                                        }
                                    }
                                }
                                EditorGUILayout.EndHorizontal();
                                if (shader.showMaterials)
                                {
                                    // show materials using this shader
                                    int matCount = shader.materials.Count;
                                    for (int m = 0; m < matCount; m++)
                                    {
                                        SCMaterial material = shader.materials[m];
                                        if (material.ContainsKeyword(keyword.name))
                                        {
                                            EditorGUILayout.BeginHorizontal();
                                            EditorGUILayout.LabelField("", GUILayout.Width(30));
                                            EditorGUILayout.LabelField(matIcon, GUILayout.Width(18));
                                            EditorGUILayout.LabelField(material.unityMaterial.name);
                                            if (GUILayout.Button(new GUIContent("Locate", "Locates the material in the project panel."), EditorStyles.miniButton, GUILayout.Width(60)))
                                            {
                                                Material theMaterial = AssetDatabase.LoadAssetAtPath <Material>(material.path) as Material;
                                                Selection.activeObject = theMaterial;
                                                EditorGUIUtility.PingObject(theMaterial);
                                            }
                                            EditorGUILayout.EndHorizontal();
                                        }
                                    }
                                }
                            }

                            if (shader.showMaterials)
                            {
                                // show materials using this shader that does not use any keywords
                                bool first    = true;
                                int  matCount = shader.materials.Count;
                                for (int m = 0; m < matCount; m++)
                                {
                                    SCMaterial material = shader.materials[m];
                                    if (material.keywords.Count == 0)
                                    {
                                        if (first)
                                        {
                                            first = false;
                                            EditorGUILayout.BeginHorizontal();
                                            EditorGUILayout.LabelField("", GUILayout.Width(15));
                                            EditorGUILayout.LabelField("Materials using this shader and no keywords:");
                                            EditorGUILayout.EndHorizontal();
                                        }
                                        EditorGUILayout.BeginHorizontal();
                                        EditorGUILayout.LabelField("", GUILayout.Width(15));
                                        EditorGUILayout.LabelField(matIcon, GUILayout.Width(18));
                                        EditorGUILayout.LabelField(material.unityMaterial.name);
                                        if (GUILayout.Button(new GUIContent("Locate", "Locates the material in the project panel."), EditorStyles.miniButton, GUILayout.Width(60)))
                                        {
                                            Material theMaterial = AssetDatabase.LoadAssetAtPath <Material>(material.path) as Material;
                                            Selection.activeObject = theMaterial;
                                            EditorGUIUtility.PingObject(theMaterial);
                                        }
                                        EditorGUILayout.EndHorizontal();
                                    }
                                }
                            }
                        }
                        EditorGUILayout.Separator();
                    }
                    if (shadersListedCount == 0 && !string.IsNullOrEmpty(projectShaderNameFilter))
                    {
                        EditorGUILayout.HelpBox("No shader matching '" + projectShaderNameFilter + "' name found. Either the shader doesn't exist in the project as source file or the shader does not use explicit keywords.", MessageType.Info);
                    }
                }
                EditorGUILayout.EndScrollView();
            }
        }
Пример #20
0
        void UpdateShaderNonGraph(SCShader shader)
        {
            // Reads and updates shader from disk
            string[]      shaderLines   = File.ReadAllLines(shader.path);
            string[]      separator     = new string[] { " " };
            StringBuilder sb            = new StringBuilder();
            int           pragmaControl = 0;

            shader.editedByShaderControl = false;
            SCKeywordLine keywordLine  = new SCKeywordLine();
            bool          blockComment = false;

            for (int k = 0; k < shaderLines.Length; k++)
            {
                int lineCommentIndex = shaderLines[k].IndexOf("//");
                int blocCommentIndex = shaderLines[k].IndexOf("/*");
                int endCommentIndex  = shaderLines[k].IndexOf("*/");
                if (blocCommentIndex > 0 && (lineCommentIndex > blocCommentIndex || lineCommentIndex < 0))
                {
                    blockComment = true;
                }
                if (endCommentIndex > blocCommentIndex && (lineCommentIndex > endCommentIndex || lineCommentIndex < 0))
                {
                    blockComment = false;
                }

                int        j          = -1;
                PragmaType pragmaType = PragmaType.Unknown;
                if (!blockComment)
                {
                    j = shaderLines[k].IndexOf(PRAGMA_COMMENT_MARK);
                    if (j >= 0)
                    {
                        pragmaControl = 1;
                    }
                    j = shaderLines[k].IndexOf(SCKeywordLine.PRAGMA_MULTICOMPILE_GLOBAL);
                    if (j >= 0)
                    {
                        pragmaType = PragmaType.MultiCompileGlobal;
                    }
                    else
                    {
                        j = shaderLines[k].IndexOf(SCKeywordLine.PRAGMA_FEATURE_GLOBAL);
                        if (j >= 0)
                        {
                            pragmaType = PragmaType.FeatureGlobal;
                        }
                        else
                        {
                            j = shaderLines[k].IndexOf(SCKeywordLine.PRAGMA_MULTICOMPILE_LOCAL);
                            if (j >= 0)
                            {
                                pragmaType = PragmaType.MultiCompileLocal;
                            }
                            else
                            {
                                j = shaderLines[k].IndexOf(SCKeywordLine.PRAGMA_FEATURE_LOCAL);
                                if (j >= 0)
                                {
                                    pragmaType = PragmaType.FeatureLocal;
                                }
                            }
                        }
                    }
                    if (pragmaControl != 1 && lineCommentIndex == 0 && shaderLines[k].IndexOf(PRAGMA_DISABLED_MARK) < 0)
                    {
                        // do not process a commented line
                        j = -1;
                    }
                }
                if (j >= 0)
                {
                    if (pragmaControl != 2)
                    {
                        keywordLine.Clear();
                    }
                    keywordLine.pragmaType = pragmaType;
                    j = shaderLines[k].IndexOf(' ', j + 20) + 1; // first space after pragma declaration
                    if (j >= shaderLines[k].Length)
                    {
                        continue;
                    }
                    // exclude potential comments inside the #pragma line
                    int lastStringPos = shaderLines[k].IndexOf("//", j);
                    if (lastStringPos < 0)
                    {
                        lastStringPos = shaderLines[k].Length;
                    }
                    int      length = lastStringPos - j;
                    string[] kk     = shaderLines[k].Substring(j, length).Split(separator, StringSplitOptions.RemoveEmptyEntries);
                    // Sanitize keywords
                    for (int i = 0; i < kk.Length; i++)
                    {
                        kk[i] = kk[i].Trim();
                    }
                    // Act on keywords
                    switch (pragmaControl)
                    {
                    case 1:
                        // Read original keywords
                        for (int s = 0; s < kk.Length; s++)
                        {
                            SCKeyword keyword = shader.GetKeyword(kk[s]);
                            keywordLine.Add(keyword);
                        }
                        pragmaControl = 2;
                        break;

                    case 0:
                    case 2:
                        if (pragmaControl == 0)
                        {
                            for (int s = 0; s < kk.Length; s++)
                            {
                                SCKeyword keyword = shader.GetKeyword(kk[s]);
                                keywordLine.Add(keyword);
                            }
                        }
                        int kCount        = keywordLine.keywordCount;
                        int kEnabledCount = keywordLine.keywordsEnabledCount;
                        if (kEnabledCount < kCount)
                        {
                            // write original keywords
                            if (kEnabledCount == 0)
                            {
                                sb.Append(PRAGMA_DISABLED_MARK);
                            }
                            else
                            {
                                sb.Append(PRAGMA_COMMENT_MARK);
                            }
                            shader.editedByShaderControl = true;
                            sb.Append(keywordLine.GetPragma());
                            if (keywordLine.hasUnderscoreVariant)
                            {
                                sb.Append(PRAGMA_UNDERSCORE);
                            }
                            for (int s = 0; s < kCount; s++)
                            {
                                SCKeyword keyword = keywordLine.keywords[s];
                                sb.Append(keyword.name);
                                if (s < kCount - 1)
                                {
                                    sb.Append(" ");
                                }
                            }
                            sb.AppendLine();
                        }

                        if (kEnabledCount > 0)
                        {
                            // Write actual keywords
                            sb.Append(keywordLine.GetPragma());
                            if (keywordLine.hasUnderscoreVariant)
                            {
                                sb.Append(PRAGMA_UNDERSCORE);
                            }
                            for (int s = 0; s < kCount; s++)
                            {
                                SCKeyword keyword = keywordLine.keywords[s];
                                if (keyword.enabled)
                                {
                                    sb.Append(keyword.name);
                                    if (s < kCount - 1)
                                    {
                                        sb.Append(" ");
                                    }
                                }
                            }
                            sb.AppendLine();
                        }
                        pragmaControl = 0;
                        break;
                    }
                }
                else
                {
                    sb.AppendLine(shaderLines[k]);
                }
            }

            // Writes modified shader
            File.WriteAllText(shader.path, sb.ToString());
            AssetDatabase.Refresh();
        }
Пример #21
0
        void ScanShaderNonGraph(SCShader shader)
        {
            // Reads shader
            string[]      shaderLines   = File.ReadAllLines(shader.path);
            string[]      separator     = new string[] { " " };
            SCShaderPass  currentPass   = new SCShaderPass();
            SCShaderPass  basePass      = null;
            int           pragmaControl = 0;
            int           pass          = -1;
            bool          blockComment  = false;
            SCKeywordLine keywordLine   = new SCKeywordLine();

            for (int k = 0; k < shaderLines.Length; k++)
            {
                string line = shaderLines[k].Trim();
                if (line.Length == 0)
                {
                    continue;
                }

                int lineCommentIndex = line.IndexOf("//");
                int blocCommentIndex = line.IndexOf("/*");
                int endCommentIndex  = line.IndexOf("*/");
                if (blocCommentIndex > 0 && (lineCommentIndex > blocCommentIndex || lineCommentIndex < 0))
                {
                    blockComment = true;
                }
                if (endCommentIndex > blocCommentIndex && (lineCommentIndex > endCommentIndex || lineCommentIndex < 0))
                {
                    blockComment = false;
                }
                if (blockComment)
                {
                    continue;
                }

                string lineUPPER = line.ToUpper();
                if (lineUPPER.Equals("PASS") || lineUPPER.StartsWith("PASS "))
                {
                    if (pass >= 0)
                    {
                        currentPass.pass = pass;
                        if (basePass != null)
                        {
                            currentPass.Add(basePass.keywordLines);
                        }
                        shader.Add(currentPass);
                    }
                    else if (currentPass.keywordCount > 0)
                    {
                        basePass = currentPass;
                    }
                    currentPass = new SCShaderPass();
                    pass++;
                    continue;
                }
                int j = line.IndexOf(PRAGMA_COMMENT_MARK);
                if (j >= 0)
                {
                    pragmaControl = 1;
                }
                else
                {
                    j = line.IndexOf(PRAGMA_DISABLED_MARK);
                    if (j >= 0)
                    {
                        pragmaControl = 3;
                    }
                }
                if (lineCommentIndex == 0 && pragmaControl != 1 && pragmaControl != 3)
                {
                    continue; // do not process lines commented by user
                }

                PragmaType pragmaType = PragmaType.Unknown;
                int        offset     = 0;
                j = line.IndexOf(SCKeywordLine.PRAGMA_MULTICOMPILE_GLOBAL);
                if (j >= 0)
                {
                    pragmaType = PragmaType.MultiCompileGlobal;
                    offset     = SCKeywordLine.PRAGMA_MULTICOMPILE_GLOBAL.Length;
                }
                else
                {
                    j = line.IndexOf(SCKeywordLine.PRAGMA_FEATURE_GLOBAL);
                    if (j >= 0)
                    {
                        pragmaType = PragmaType.FeatureGlobal;
                        offset     = SCKeywordLine.PRAGMA_FEATURE_GLOBAL.Length;
                    }
                    else
                    {
                        j = line.IndexOf(SCKeywordLine.PRAGMA_MULTICOMPILE_LOCAL);
                        if (j >= 0)
                        {
                            pragmaType = PragmaType.MultiCompileLocal;
                            offset     = SCKeywordLine.PRAGMA_MULTICOMPILE_LOCAL.Length;
                        }
                        else
                        {
                            j = line.IndexOf(SCKeywordLine.PRAGMA_FEATURE_LOCAL);
                            if (j >= 0)
                            {
                                pragmaType = PragmaType.FeatureLocal;
                                offset     = SCKeywordLine.PRAGMA_FEATURE_LOCAL.Length;
                            }
                        }
                    }
                }
                if (j >= 0)
                {
                    if (pragmaControl != 2)
                    {
                        keywordLine = new SCKeywordLine();
                    }
                    keywordLine.pragmaType = pragmaType;
                    // exclude potential comments inside the #pragma line
                    int lastStringPos = line.IndexOf("//", j + offset);
                    if (lastStringPos < 0)
                    {
                        lastStringPos = line.Length;
                    }
                    int      length = lastStringPos - j - offset;
                    string[] kk     = line.Substring(j + offset, length).Split(separator, StringSplitOptions.RemoveEmptyEntries);
                    // Sanitize keywords
                    for (int i = 0; i < kk.Length; i++)
                    {
                        kk[i] = kk[i].Trim();
                    }
                    // Act on keywords
                    switch (pragmaControl)
                    {
                    case 1:     // Edited by Shader Control line
                        shader.editedByShaderControl = true;
                        // Add original keywords to current line
                        for (int s = 0; s < kk.Length; s++)
                        {
                            keywordLine.Add(shader.GetKeyword(kk[s]));
                        }
                        pragmaControl = 2;
                        break;

                    case 2:
                        // check enabled keywords
                        keywordLine.DisableKeywords();
                        for (int s = 0; s < kk.Length; s++)
                        {
                            SCKeyword keyword = keywordLine.GetKeyword(kk[s]);
                            if (keyword != null)
                            {
                                keyword.enabled = true;
                            }
                        }
                        currentPass.Add(keywordLine);
                        pragmaControl = 0;
                        break;

                    case 3:     // disabled by Shader Control line
                        shader.editedByShaderControl = true;
                        // Add original keywords to current line
                        for (int s = 0; s < kk.Length; s++)
                        {
                            SCKeyword keyword = shader.GetKeyword(kk[s]);
                            keyword.enabled = false;
                            keywordLine.Add(keyword);
                        }
                        currentPass.Add(keywordLine);
                        pragmaControl = 0;
                        break;

                    case 0:
                        // Add keywords to current line
                        for (int s = 0; s < kk.Length; s++)
                        {
                            keywordLine.Add(shader.GetKeyword(kk[s]));
                        }
                        currentPass.Add(keywordLine);
                        break;
                    }
                }
            }
            currentPass.pass = Mathf.Max(pass, 0);
            if (basePass != null)
            {
                currentPass.Add(basePass.keywordLines);
            }
            shader.Add(currentPass);
            shader.UpdateVariantCount();
        }
Пример #22
0
        void UpdateProjectStats()
        {
            totalKeywords             = 0;
            totalGlobalKeywords       = 0;
            totalUsedKeywords         = 0;
            totalVariants             = 0;
            totalBuildVariants        = 0;
            totalGlobalShaderFeatures = 0;

            if (shaders == null)
            {
                return;
            }

            if (keywordsDict == null)
            {
                keywordsDict = new Dictionary <string, SCKeyword>();
            }
            else
            {
                keywordsDict.Clear();
            }
            if (uniqueKeywords == null)
            {
                uniqueKeywords = new Dictionary <string, List <SCShader> >();
            }
            else
            {
                uniqueKeywords.Clear();
            }
            if (uniqueEnabledKeywords == null)
            {
                uniqueEnabledKeywords = new Dictionary <string, List <SCShader> >();
            }
            else
            {
                uniqueEnabledKeywords.Clear();
            }

            int shadersCount = shaders.Count;

            for (int k = 0; k < shadersCount; k++)
            {
                SCShader shader        = shaders[k];
                int      keywordsCount = shader.keywords.Count;
                for (int w = 0; w < keywordsCount; w++)
                {
                    SCKeyword       keyword = shader.keywords[w];
                    List <SCShader> shadersWithThisKeyword;
                    if (!uniqueKeywords.TryGetValue(keyword.name, out shadersWithThisKeyword))
                    {
                        shadersWithThisKeyword       = new List <SCShader>();
                        uniqueKeywords[keyword.name] = shadersWithThisKeyword;
                        totalKeywords++;
                        if (keyword.isGlobal)
                        {
                            totalGlobalKeywords++;
                        }
                        if (keyword.isGlobal && !keyword.isMultiCompile && keyword.enabled)
                        {
                            totalGlobalShaderFeatures++;
                        }
                        keywordsDict[keyword.name] = keyword;
                    }
                    shadersWithThisKeyword.Add(shader);
                    if (keyword.enabled)
                    {
                        List <SCShader> shadersWithThisKeywordEnabled;
                        if (!uniqueEnabledKeywords.TryGetValue(keyword.name, out shadersWithThisKeywordEnabled))
                        {
                            shadersWithThisKeywordEnabled       = new List <SCShader>();
                            uniqueEnabledKeywords[keyword.name] = shadersWithThisKeywordEnabled;
                            totalUsedKeywords++;
                        }
                        shadersWithThisKeywordEnabled.Add(shader);
                    }
                }
                totalVariants      += shader.totalVariantCount;
                totalBuildVariants += shader.actualBuildVariantCount;
            }

            if (keywordView == null)
            {
                keywordView = new List <KeywordView>();
            }
            else
            {
                keywordView.Clear();
            }
            foreach (KeyValuePair <string, List <SCShader> > kvp in uniqueEnabledKeywords)
            {
                SCKeyword kw;
                if (!keywordsDict.TryGetValue(kvp.Key, out kw))
                {
                    continue;
                }
                KeywordView kv = new KeywordView {
                    keyword = kw, shaders = kvp.Value
                };
                keywordView.Add(kv);
            }
            keywordView.Sort(delegate(KeywordView x, KeywordView y) {
                return(y.shaders.Count.CompareTo(x.shaders.Count));
            });

            // Compute which keywords in build are not present in project
            plusBuildKeywords = 0;
            if (buildKeywordView != null)
            {
                int count = buildKeywordView.Count;
                for (int k = 0; k < count; k++)
                {
                    BuildKeywordView bkv = buildKeywordView[k];
                    if (!uniqueKeywords.ContainsKey(bkv.keyword))
                    {
                        plusBuildKeywords++;
                    }
                }
            }
        }
Пример #23
0
        public void UpdateVariantCount()
        {
            totalVariantCount       = 0;
            actualBuildVariantCount = 0;
            passes.ForEach((SCShaderPass pass) => {
                int matCount       = materials.Count;
                int passCount      = 1;
                int passBuildCount = 1;
                for (int l = 0; l < pass.keywordLines.Count; l++)
                {
                    SCKeywordLine line    = pass.keywordLines [l];
                    int kLineEnabledCount = line.hasUnderscoreVariant ? 1 : 0;
                    int kLineCount        = kLineEnabledCount + line.keywords.Count;
                    for (int k = 0; k < line.keywords.Count; k++)
                    {
                        SCKeyword keyword = line.keywords [k];
                        if (keyword.enabled)
                        {
                            // if this is a shader feature, check if there's at least one material using it
                            if (line.isFeature)
                            {
                                for (int m = 0; m < matCount; m++)
                                {
                                    if (materials[m].ContainsKeyword(keyword.name))
                                    {
                                        kLineEnabledCount++;
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                kLineEnabledCount++;
                            }
                        }
                    }
                    if (kLineEnabledCount > 0)
                    {
                        passBuildCount *= kLineEnabledCount;
                    }
                    passCount *= kLineCount;
                }
                totalVariantCount       += passCount;
                actualBuildVariantCount += passBuildCount;
            });

            keywordEnabledCount = 0;
            int keywordCount = keywords.Count;

            for (int k = 0; k < keywordCount; k++)
            {
                if (keywords [k].enabled)
                {
                    keywordEnabledCount++;
                }
            }

            // add keywords from materials if there're any
//			HashSet<string>kk = new HashSet<string>();
//			keywords.ForEach(kw => {kk.Add(kw.name);});
//			int materialsCount = materials.Count;
//			for (int m=0;m<materialsCount;m++) {
//				SCMaterial material = materials[m];
//				keywordCount = material.keywords.Count;
//				for (int k=0; k<keywordCount; k++) {
//					SCKeyword keyword = material.keywords[k];
//					if (keyword.enabled && !kk.Contains(keyword.name)) {
//						kk.Add (keyword.name);
//						keywordEnabledCount++;
//					}
//				}
//			}
        }