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; }
public void Add(ShaderBuildInfo sb) { if (shaders == null || shadersDict == null) { Refresh(); } shaders.Add(sb); shadersDict[sb.name] = sb; }
public void Refresh() { creationDateString = new DateTime(creationDateTicks, DateTimeKind.Local).ToString(); if (shadersDict == null) { shadersDict = new Dictionary <string, ShaderBuildInfo>(); } if (shaders == null) { shaders = new List <ShaderBuildInfo>(); } shadersDict.Clear(); int count = shaders.Count; for (int k = 0; k < count; k++) { ShaderBuildInfo sb = shaders[k]; shadersDict[sb.name] = sb; } Resort(); }
public void OnProcessShader( Shader shader, ShaderSnippetData snippet, IList <ShaderCompilerData> shaderCompilerData) { bool skipCompilation = false; if (SCWindow.GetEditorPrefBool("QUICK_BUILD", false)) { skipCompilation = true; } if (shadersBuildInfo == null) { string filename = GetStoredDataPath(); shadersBuildInfo = AssetDatabase.LoadAssetAtPath <ShadersBuildInfo>(filename); if (shadersBuildInfo == null) { shadersBuildInfo = ScriptableObject.CreateInstance <ShadersBuildInfo>(); Directory.CreateDirectory(Path.GetDirectoryName(filename)); AssetDatabase.CreateAsset(shadersBuildInfo, filename); EditorUtility.SetDirty(shadersBuildInfo); } } ShaderBuildInfo sb = shadersBuildInfo.GetShader(shader.name); if (sb == null) { sb = new ShaderBuildInfo(); sb.name = shader.name; sb.simpleName = SCShader.GetSimpleName(sb.name); sb.type = snippet.shaderType; string path = AssetDatabase.GetAssetPath(shader); sb.isInternal = string.IsNullOrEmpty(path) || !File.Exists(path); shadersBuildInfo.Add(sb); EditorUtility.SetDirty(shadersBuildInfo); } else if (!sb.includeInBuild) { skipCompilation = true; } int count = shaderCompilerData.Count; for (int i = 0; i < count; ++i) { ShaderKeywordSet ks = shaderCompilerData[i].shaderKeywordSet; foreach (ShaderKeyword kw in ks.GetShaderKeywords()) { #if UNITY_2019_3_OR_NEWER string kname = ShaderKeyword.GetKeywordName(shader, kw); #else string kname = kw.GetKeywordName(); #endif if (string.IsNullOrEmpty(kname)) { continue; } if (!sb.KeywordsIsIncluded(kname)) { shaderCompilerData.RemoveAt(i); count--; i--; break; } else { EditorUtility.SetDirty(shadersBuildInfo); } } } if (skipCompilation) { shaderCompilerData.Clear(); } }
public void OnProcessShader( Shader shader, ShaderSnippetData snippet, IList <ShaderCompilerData> shaderCompilerData) { try { bool skipCompilation = false; if (SCWindow.GetEditorPrefBool("QUICK_BUILD", false)) { skipCompilation = true; } if (shadersBuildInfo == null) { string filename = GetStoredDataPath(); shadersBuildInfo = AssetDatabase.LoadAssetAtPath <ShadersBuildInfo>(filename); if (shadersBuildInfo == null) { return; } } ShaderBuildInfo sb = shadersBuildInfo.GetShader(shader.name); if (sb == null) { sb = new ShaderBuildInfo(); sb.name = shader.name; sb.simpleName = SCShader.GetSimpleName(sb.name); sb.type = snippet.shaderType; string path = AssetDatabase.GetAssetPath(shader); sb.isInternal = string.IsNullOrEmpty(path) || !File.Exists(path); shadersBuildInfo.Add(sb); EditorUtility.SetDirty(shadersBuildInfo); } else if (!sb.includeInBuild) { skipCompilation = true; } int count = shaderCompilerData.Count; for (int i = 0; i < count; ++i) { ShaderKeywordSet ks = shaderCompilerData[i].shaderKeywordSet; foreach (ShaderKeyword kw in ks.GetShaderKeywords()) { #if UNITY_2019_3_OR_NEWER string kname = ShaderKeyword.GetKeywordName(shader, kw); #else string kname = kw.GetName(); #endif if (string.IsNullOrEmpty(kname)) { continue; } if (!sb.KeywordsIsIncluded(kname)) { shaderCompilerData.RemoveAt(i); count--; i--; break; } else { EditorUtility.SetDirty(shadersBuildInfo); } } } if (skipCompilation) { shaderCompilerData.Clear(); return; } } catch (Exception ex) { Debug.LogWarning("Shader Control detected an error during compilation of one shader: " + ex.ToString()); } }
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(); } } }
public bool ShaderIsExcluded(string shader) { ShaderBuildInfo sb = GetShader(shader); return(sb != null ? !sb.includeInBuild : false); }
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(); }