void RefreshBuildStats(bool quick)
        {
            issueRefresh       = 1;
            nextQuickBuild     = GetEditorPrefBool("QUICK_BUILD", false);
            shadersBuildInfo   = ShaderDebugBuildProcessor.CheckShadersBuildStore(shadersBuildInfo);
            totalBuildKeywords = totalBuildIncludedKeywords = totalBuildShadersWithKeywords = totalBuildShaders = totalBuildIncludedShaders = totalBuildIncludedShadersWithKeywords = 0;
            shadersBuildInfo   = Resources.Load <ShadersBuildInfo>("BuiltShaders");
            if (shadersBuildInfo == null || shadersBuildInfo.shaders == null)
            {
                return;
            }

            if (uniqueBuildKeywords == null)
            {
                uniqueBuildKeywords = new Dictionary <string, List <ShaderBuildInfo> >();
            }
            else
            {
                uniqueBuildKeywords.Clear();
            }
            if (uniqueIncludedBuildKeywords == null)
            {
                uniqueIncludedBuildKeywords = new Dictionary <string, List <ShaderBuildInfo> >();
            }
            else
            {
                uniqueIncludedBuildKeywords.Clear();
            }

            int count = shadersBuildInfo.shaders.Count;

            totalBuildShaders          = 0;
            maxBuildKeywordsCountFound = 0;

            for (int k = 0; k < count; k++)
            {
                ShaderBuildInfo sb      = shadersBuildInfo.shaders[k];
                int             kwCount = sb.keywords != null ? sb.keywords.Count : 0;
                if (shadersBuildInfo.sortType != BuildViewSortType.Keyword)
                {
                    if (minimumKeywordCount > 0 && kwCount < minimumKeywordCount)
                    {
                        continue;
                    }
                    if (!string.IsNullOrEmpty(keywordFilter) && !sb.ContainsKeyword(keywordFilter, false))
                    {
                        continue;
                    }
                }
                if (shadersBuildInfo.viewType == BuildViewShaderOption.ProjectShaders && sb.isInternal)
                {
                    continue;
                }
                if (shadersBuildInfo.viewType == BuildViewShaderOption.UnityInternalShaders && !sb.isInternal)
                {
                    continue;
                }
                if (!string.IsNullOrEmpty(buildShaderNameFilter) && sb.name.IndexOf(buildShaderNameFilter, StringComparison.InvariantCultureIgnoreCase) < 0)
                {
                    continue;
                }
                totalBuildShaders++;

                // Check shaders exist
                if (!quick && Shader.Find(sb.name) == null)
                {
                    shadersBuildInfo.shaders.RemoveAt(k);
                    k--;
                    totalBuildShaders--;
                    count--;
                    continue;
                }
                if (sb.includeInBuild)
                {
                    totalBuildIncludedShaders++;
                }
                if (kwCount > 0)
                {
                    if (kwCount > maxBuildKeywordsCountFound)
                    {
                        maxBuildKeywordsCountFound = kwCount;
                    }
                    //totalBuildKeywords += kwCount;
                    totalBuildShadersWithKeywords++;
                    if (sb.includeInBuild)
                    {
                        totalBuildIncludedShadersWithKeywords++;
                        for (int j = 0; j < kwCount; j++)
                        {
                            List <ShaderBuildInfo> shaderList;
                            if (!uniqueBuildKeywords.TryGetValue(sb.keywords[j].keyword, out shaderList))
                            {
                                totalBuildKeywords++;
                                shaderList = new List <ShaderBuildInfo>();
                                uniqueBuildKeywords[sb.keywords[j].keyword] = shaderList;
                            }
                            shaderList.Add(sb);
                            if (sb.keywords[j].includeInBuild)
                            {
                                List <ShaderBuildInfo> includedList;
                                if (!uniqueIncludedBuildKeywords.TryGetValue(sb.keywords[j].keyword, out includedList))
                                {
                                    totalBuildIncludedKeywords++;
                                    includedList = new List <ShaderBuildInfo>();
                                    uniqueIncludedBuildKeywords[sb.keywords[j].keyword] = includedList;
                                }
                                includedList.Add(sb);
                            }
                        }
                    }
                }
            }

            if (buildKeywordView == null)
            {
                buildKeywordView = new List <BuildKeywordView>();
            }
            else
            {
                buildKeywordView.Clear();
            }
            foreach (KeyValuePair <string, List <ShaderBuildInfo> > kvp in uniqueBuildKeywords)
            {
                BuildKeywordView kv = new BuildKeywordView {
                    keyword = kvp.Key, shaders = kvp.Value
                };
                buildKeywordView.Add(kv);
            }
            buildKeywordView.Sort(delegate(BuildKeywordView x, BuildKeywordView y) {
                return(y.shaders.Count.CompareTo(x.shaders.Count));
            });
            // Annotate which keywords are used in project
            int bkwCount = buildKeywordView.Count;

            for (int k = 0; k < bkwCount; k++)
            {
                BuildKeywordView bkv        = buildKeywordView[k];
                bool             isInternal = true;
                int shadersCount            = bkv.shaders.Count;
                for (int j = 0; j < shadersCount; j++)
                {
                    if (!bkv.shaders[j].isInternal)
                    {
                        isInternal = false;
                        break;
                    }
                }
                bkv.isInternal = isInternal;
            }

            UpdateProjectStats();
        }
        void DrawBuildGUI()
        {
            GUILayout.Box(new GUIContent("This tab shows all shaders compiled in your last build.\nHere you can exclude any number of shaders or keywords from future compilations. No file is modified, only excluded from the build.\nIf you have exceeded the maximum allowed keywords in your project, use the <color=orange><b>Project View</b></color> tab to remove shaders or disable any unwanted keyword from the project."), titleStyle);
            EditorGUILayout.Separator();

            EditorGUILayout.BeginHorizontal();
            if (GUILayout.Button(new GUIContent("Quick Build", "Forces a quick compilation to extract all shaders and keywords included in the build.")))
            {
                EditorUtility.DisplayDialog("Ready for the Build!", "Now make a build as normal (select 'File -> Build Settings -> Build').\n\nShader Control will detect the shaders and keywords from the build process and list that information here.\n\nNote: in order to make this special build faster, shaders won't be compiled in this build.", "Ok");
                SetEditorPrefBool("QUICK_BUILD", true);
                nextQuickBuild = true;
                ClearBuildData();
            }
            if (GUILayout.Button("Help", GUILayout.Width(40)))
            {
                ShowHelpWindowBuildView();
            }
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.EndVertical();

            if (nextQuickBuild)
            {
                EditorGUILayout.HelpBox("Shader Control is ready to collect data during the next build.", MessageType.Info);
            }

            int shadersCount = shadersBuildInfo == null || shadersBuildInfo.shaders == null ? 0 : shadersBuildInfo.shaders.Count;

            if (!nextQuickBuild)
            {
                EditorGUILayout.LabelField("Last build: " + ((shadersBuildInfo.creationDateTicks != 0) ? shadersBuildInfo.creationDateString : "no data yet. Click 'Quick Build' for more details."), EditorStyles.boldLabel);
            }
            if (shadersBuildInfo != null && shadersBuildInfo.requiresBuild)
            {
                EditorGUILayout.HelpBox("Project shaders have been modified. Do a 'Quick Build' again to ensure the data shown in this tab is accurate.", MessageType.Warning);
            }

            if (shadersCount > 0)
            {
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("View", GUILayout.Width(90));
                EditorGUI.BeginChangeCheck();

                shadersBuildInfo.viewType = (BuildViewShaderOption)GUILayout.SelectionGrid((int)shadersBuildInfo.viewType, viewShaderTexts, 3);
                if (EditorGUI.EndChangeCheck())
                {
                    EditorUtility.SetDirty(shadersBuildInfo);
                    RefreshBuildStats(true);
                }
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField("Sort By", GUILayout.Width(90));
                EditorGUI.BeginChangeCheck();
                shadersBuildInfo.sortType = (BuildViewSortType)EditorGUILayout.EnumPopup(shadersBuildInfo.sortType);
                if (EditorGUI.EndChangeCheck())
                {
                    if (shadersBuildInfo != null)
                    {
                        shadersBuildInfo.Resort();
                    }
                    EditorUtility.SetDirty(shadersBuildInfo);
                    GUIUtility.ExitGUI();
                    return;
                }
                EditorGUILayout.EndHorizontal();

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

                if (EditorGUI.EndChangeCheck())
                {
                    RefreshBuildStats(true);
                }

                EditorGUI.BeginChangeCheck();
                if (shadersBuildInfo.sortType != BuildViewSortType.Keyword)
                {
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField("Keywords >=", GUILayout.Width(90));
                    minimumKeywordCount = EditorGUILayout.IntSlider(minimumKeywordCount, 0, maxBuildKeywordsCountFound);
                    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();
                if (EditorGUI.EndChangeCheck())
                {
                    RefreshBuildStats(true);
                }

                EditorGUILayout.Separator();

                if (totalBuildShaders == 0 || totalBuildIncludedShaders == 0 || totalBuildKeywords == 0 || (totalBuildKeywords == totalBuildIncludedKeywords && totalBuildShaders == totalBuildIncludedShaders))
                {
                    EditorGUILayout.HelpBox("Total Shaders: " + totalBuildShaders + "  Shaders Using Keywords: " + totalBuildShadersWithKeywords + "\nTotal Unique Keywords: " + totalBuildKeywords, MessageType.Info);
                }
                else
                {
                    int shadersPerc             = totalBuildIncludedShaders * 100 / totalBuildShaders;
                    int shadersWithKeywordsPerc = totalBuildIncludedShadersWithKeywords * 100 / totalBuildIncludedShaders;
                    int keywordsPerc            = totalBuildIncludedKeywords * 100 / totalBuildKeywords;
                    EditorGUILayout.HelpBox("Total Shaders: " + totalBuildIncludedShaders + " of " + totalBuildShaders + " (" + shadersPerc + "%" + "  Shaders Using Keywords: " + totalBuildIncludedShadersWithKeywords + " of " + totalBuildShadersWithKeywords + " (" + shadersWithKeywordsPerc + "%)\nTotal Unique Keywords: " + totalBuildIncludedKeywords + " of " + totalBuildKeywords + " (" + keywordsPerc.ToString() + "%)", MessageType.Info);
                }

                EditorGUILayout.Separator();

                scrollViewPosProject = EditorGUILayout.BeginScrollView(scrollViewPosProject);

                bool requireUpdate = false;

                if (shadersBuildInfo.sortType == BuildViewSortType.Keyword)
                {
                    if (buildKeywordView != null)
                    {
                        int kvCount = buildKeywordView.Count;
                        for (int s = 0; s < kvCount; s++)
                        {
                            BuildKeywordView kwv     = buildKeywordView[s];
                            string           keyword = kwv.keyword;
                            if (!string.IsNullOrEmpty(keywordFilter) && keyword.IndexOf(keywordFilter, StringComparison.InvariantCultureIgnoreCase) < 0)
                            {
                                continue;
                            }
                            EditorGUILayout.BeginHorizontal();
                            kwv.foldout = EditorGUILayout.Foldout(kwv.foldout, new GUIContent("Keyword #" + (s + 1) + " <b>" + kwv.keyword + "</b> found in " + kwv.shaders.Count + " shader(s)"), foldoutRTF);

                            if (!kwv.isInternal && GUILayout.Button("Show In Project View", EditorStyles.miniButton, GUILayout.Width(160)))
                            {
                                sortType = SortType.EnabledKeywordsCount;
                                projectShaderNameFilter = "";
                                keywordFilter           = kwv.keyword;
                                scanAllShaders          = true;
                                if (shaders == null)
                                {
                                    ScanProject();
                                }
                                viewMode = ViewMode.Project;
                                GUIUtility.ExitGUI();
                            }

                            EditorGUILayout.EndHorizontal();
                            if (kwv.foldout)
                            {
                                int kvShadersCount = kwv.shaders.Count;
                                for (int m = 0; m < kvShadersCount; m++)
                                {
                                    ShaderBuildInfo sb = kwv.shaders[m];
                                    EditorGUILayout.BeginHorizontal();
                                    EditorGUILayout.LabelField("", GUILayout.Width(30));
                                    EditorGUILayout.LabelField(shaderIcon, GUILayout.Width(18));
                                    EditorGUILayout.LabelField(sb.name);
                                    if (sb.isInternal)
                                    {
                                        GUILayout.Label("(Internal Shader)");
                                    }
                                    else
                                    {
                                        if (GUILayout.Button("Locate", EditorStyles.miniButton, GUILayout.Width(80)))
                                        {
                                            PingShader(sb.name);
                                        }
                                        if (GUILayout.Button("Show In Project View", EditorStyles.miniButton, GUILayout.Width(160)))
                                        {
                                            projectShaderNameFilter = sb.simpleName;
                                            keywordFilter           = "";
                                            scanAllShaders          = true;
                                            PingShader(sb.name);
                                            if (shaders == null)
                                            {
                                                ScanProject();
                                            }
                                            viewMode = ViewMode.Project;
                                            GUIUtility.ExitGUI();
                                        }
                                    }
                                    EditorGUILayout.EndHorizontal();
                                }
                            }
                        }
                    }
                }
                else
                {
                    for (int k = 0; k < shadersCount; k++)
                    {
                        ShaderBuildInfo sb      = shadersBuildInfo.shaders[k];
                        int             kwCount = sb.keywords == null ? 0 : sb.keywords.Count;
                        if (kwCount < minimumKeywordCount)
                        {
                            continue;
                        }
                        if (shadersBuildInfo.viewType == BuildViewShaderOption.ProjectShaders && sb.isInternal)
                        {
                            continue;
                        }
                        if (shadersBuildInfo.viewType == BuildViewShaderOption.UnityInternalShaders && !sb.isInternal)
                        {
                            continue;
                        }
                        if (!string.IsNullOrEmpty(keywordFilter) && !sb.ContainsKeyword(keywordFilter, false))
                        {
                            continue;
                        }
                        if (!string.IsNullOrEmpty(buildShaderNameFilter) && sb.name.IndexOf(buildShaderNameFilter, StringComparison.InvariantCultureIgnoreCase) < 0)
                        {
                            continue;
                        }

                        GUI.enabled = sb.includeInBuild;
                        EditorGUILayout.BeginHorizontal();
                        string shaderName = (sb.isInternal && shadersBuildInfo.viewType != BuildViewShaderOption.UnityInternalShaders) ? sb.name + " (internal)" : sb.name;
                        sb.isExpanded = EditorGUILayout.Foldout(sb.isExpanded, shaderName + " (" + kwCount + " keyword" + (kwCount != 1 ? "s)" : ")"), sb.isInternal ? foldoutDim : foldoutNormal);
                        GUILayout.FlexibleSpace();
                        GUI.enabled = true;
                        if (sb.name != "Standard")
                        {
                            EditorGUI.BeginChangeCheck();
                            sb.includeInBuild = EditorGUILayout.ToggleLeft("Include", sb.includeInBuild, GUILayout.Width(90));
                            if (EditorGUI.EndChangeCheck())
                            {
                                requireUpdate = true;
                            }
                        }
                        EditorGUILayout.EndHorizontal();
                        if (sb.isExpanded)
                        {
                            GUI.enabled = sb.includeInBuild;
                            EditorGUI.indentLevel++;
                            if (kwCount == 0)
                            {
                                EditorGUILayout.LabelField("No keywords.");
                            }
                            else
                            {
                                if (!sb.isInternal)
                                {
                                    EditorGUILayout.BeginHorizontal();
                                    EditorGUILayout.LabelField("", GUILayout.Width(15));
                                    if (GUILayout.Button("Locate", EditorStyles.miniButton, GUILayout.Width(80)))
                                    {
                                        PingShader(sb.name);
                                    }
                                    if (!sb.isInternal && GUILayout.Button("Show In Project View", EditorStyles.miniButton, GUILayout.Width(160)))
                                    {
                                        projectShaderNameFilter = sb.simpleName;
                                        scanAllShaders          = true;
                                        PingShader(sb.name);
                                        if (shaders == null)
                                        {
                                            ScanProject();
                                        }
                                        viewMode = ViewMode.Project;
                                        GUIUtility.ExitGUI();
                                    }
                                    EditorGUILayout.EndHorizontal();
                                }
                                for (int j = 0; j < kwCount; j++)
                                {
                                    KeywordBuildSettings kw = sb.keywords[j];
                                    EditorGUILayout.BeginHorizontal();
                                    EditorGUILayout.LabelField(kw.keyword);
                                    GUILayout.FlexibleSpace();
                                    EditorGUI.BeginChangeCheck();
                                    kw.includeInBuild = EditorGUILayout.ToggleLeft("Include", kw.includeInBuild, GUILayout.Width(90));
                                    if (EditorGUI.EndChangeCheck())
                                    {
                                        requireUpdate = true;
                                    }
                                    EditorGUILayout.EndHorizontal();
                                }
                            }
                            EditorGUI.indentLevel--;
                        }
                        GUI.enabled = true;
                    }
                }
                EditorGUILayout.EndScrollView();

                if (requireUpdate)
                {
                    RefreshBuildStats(true);
                    EditorUtility.SetDirty(shadersBuildInfo);
                    AssetDatabase.SaveAssets();
                }
            }
        }
Exemple #3
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++;
                    }
                }
            }
        }