public static void UpdateShader(ref StripShader shader) { if (shader.isReadOnly) { EditorUtility.DisplayDialog("Locked file", "Shader file " + shader.name + " is read-only.", "Ok"); return; } try { // Create backup string backupPath = shader.path + BACKUP_SUFFIX; if (!File.Exists(backupPath)) { AssetDatabase.CopyAsset(shader.path, backupPath); shader.hasBackup = true; } // Reads and updates shader from disk // string[] shaderLines = File.ReadAllLines(shader.path); //string[] separator = new string[] { " " }; // Writes modified shader //File.WriteAllText(shader.path, sb.ToString()); AssetDatabase.Refresh(); } catch (Exception ex) { Debug.LogError("Unexpected exception caught while updating shader: " + ex.Message); } }
public static void RestoreShader(ref StripShader shader) { try { string shaderBackupPath = shader.path + BACKUP_SUFFIX; if (!File.Exists(shaderBackupPath)) { EditorUtility.DisplayDialog("Restore shader", "Shader backup is missing!", "OK"); return; } File.Copy(shaderBackupPath, shader.path, true); File.Delete(shaderBackupPath); if (File.Exists(shaderBackupPath + ".meta")) { File.Delete(shaderBackupPath + ".meta"); } AssetDatabase.Refresh(); } catch (Exception ex) { Debug.LogError("Unexpected exception caught while restoring shader: " + ex.Message); } }
public static void ScanShader(ref StripShader shader) { //重置shader shader.passes.Clear(); shader.keywords.Clear(); shader.hasBackup = File.Exists(shader.path + BACKUP_SUFFIX); shader.pendingChanges = false; shader.editedByShaderControl = false; //读取shader文本 string[] shaderLines = File.ReadAllLines(shader.path); string[] separator = new string[] { " " }; StripShaderPass currentPass = new StripShaderPass(); StripShaderPass basePass = null; int pragmaControl = 0; int pass = -1; bool blockComment = false; StripKeywordLine keywordLine = new StripKeywordLine(); 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 StripShaderPass(); 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; // 跳过注释 } //添加 multicompile bool isShaderFeature = false; j = line.IndexOf(PRAGMA_MULTICOMPILE); if (j < 0) { j = line.IndexOf(PRAGMA_SHADER_FEATURE); isShaderFeature = (j >= 0); } if (j >= 0) { if (pragmaControl != 2) { keywordLine = new StripKeywordLine(); } keywordLine.isFeature = isShaderFeature; // 处理在#pragram行中潜在的注释 int lastStringPos = line.IndexOf("//", j + 22); if (lastStringPos < 0) { lastStringPos = line.Length; } int length = lastStringPos - j - 22; string[] kk = line.Substring(j + 22, length).Split(separator, StringSplitOptions.RemoveEmptyEntries); // 清理关键字 trim for (int i = 0; i < kk.Length; i++) { kk [i] = kk [i].Trim(); } // 操作关键字 switch (pragmaControl) { case 1: // 如果是被编辑器修改的 shader.editedByShaderControl = true; // 在这行添加原始关键字 for (int s = 0; s < kk.Length; s++) { keywordLine.Add(shader.GetKeyword(kk [s])); } pragmaControl = 2; break; case 2: // 检查使用的关键字 keywordLine.DisableKeywords(); for (int s = 0; s < kk.Length; s++) { StripKeyword keyword = keywordLine.GetKeyword(kk [s]); if (keyword != null) { keyword.enabled = true; } } currentPass.Add(keywordLine); pragmaControl = 0; break; case 3: // 被编辑器关闭的关键字 shader.editedByShaderControl = true; // // 在这行添加原始的关键字 for (int s = 0; s < kk.Length; s++) { StripKeyword keyword = shader.GetKeyword(kk [s]); keyword.enabled = false; keywordLine.Add(keyword); } currentPass.Add(keywordLine); pragmaControl = 0; break; case 0: // 在这行添加关键字 for (int s = 0; s < kk.Length; s++) { keywordLine.Add(shader.GetKeyword(kk [s])); } currentPass.Add(keywordLine); break; } } //PRAGMA_MULTI_COMPILE_FWDBASE j = line.IndexOf(PRAGMA_MULTI_COMPILE_FWDBASE_FULLSHADOWS); if (j >= 0) { } } currentPass.pass = Mathf.Max(pass, 0); if (basePass != null) { currentPass.Add(basePass.keywordLines); } shader.Add(currentPass); shader.UpdateVariantCount(); }
//解析shader文本 public static void ScanShader(ref StripShader shader) { //重置shader shader.passes.Clear(); shader.keywords.Clear(); shader.hasBackup = File.Exists(shader.path + BACKUP_SUFFIX); shader.pendingChanges = false; shader.editedByShaderControl = false; //读取shader文本 string[] shaderLines = File.ReadAllLines(shader.path); string[] separator = new string[] { " " }; StripShaderPass currentPass = new StripShaderPass(); StripShaderPass basePass = null; int pass = -1; bool blockComment = false; StripKeywordLine keywordLine = new StripKeywordLine(); for (int k = 0; k < shaderLines.Length; k++) { //删除字符串头部和尾部的空格 string line = shaderLines[k].Trim(); if (line.Length == 0) { continue; } //是否是注释行 IsBlockCommentLine(line, ref blockComment); 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 StripShaderPass(); pass++; continue; } //第一个注释符号 //的位置 int lineCommentIndex = CommentLineIndex(line); //编辑器添加的语句行信息 EditorLineType editorLine = EditorLineType.NONE; int editorStartIndex = -1; int editorEndIndex = -1; ParseEditorLineType(line, ref editorLine, ref editorStartIndex, ref editorEndIndex); //该行是注释行 并且不是被主动编辑的 跳过 if (lineCommentIndex == 0 && editorLine == EditorLineType.NONE) { continue; // 跳过注释 } //shader关键字语句行信息 ShaderLineType shaderLine = ShaderLineType.NONE; int keyStartIndex = -1; int keyEndIndex = -1; ParseShaderLineType(line, ref shaderLine, ref keyStartIndex, ref keyEndIndex); //并非是被程序编辑过的 if (editorLine == EditorLineType.NONE) { //如果是手写输入的关键字 if (IsInputShortcut(shaderLine)) { keyStartIndex = Mathf.Max(0, keyStartIndex); keyEndIndex = Mathf.Max(0, keyEndIndex); //检查PRAGMA 关键字之后的字符串是否包含注释 int commentindex = CommentLineIndex(line, keyStartIndex + keyEndIndex); if (commentindex < 0) { commentindex = line.Length; } int length = commentindex - (keyStartIndex + keyEndIndex); //用空格分割 PRAGMA语句到//注释符号之间的语句 string[] splitedKeys = line.Substring(keyStartIndex + keyEndIndex, length).Split(separator, StringSplitOptions.RemoveEmptyEntries); if (splitedKeys.Length > 0) { keywordLine = new StripKeywordLine(); //是剔除字段 bool isSkip = shaderLine == ShaderLineType.SKIP_VARIANTS; currentPass.hasSkipKeyword = isSkip?isSkip:currentPass.hasSkipKeyword; //添加手写关键字 for (int i = 0; i < splitedKeys.Length; i++) { splitedKeys[i] = splitedKeys[i].Trim(); StripKeyword keyword = keywordLine.GetKeyword(splitedKeys[i]); if (keyword == null) { keyword = new StripKeyword(splitedKeys[i]); } keyword.enabled = true; keyword.isSkip = isSkip; keywordLine.Add(keyword); } keywordLine.editorLineType = editorLine; keywordLine.shaderLineType = shaderLine; currentPass.Add(keywordLine); } } else //添加缩写marco的内置关键字 if (IsBuiltinShortcut(shaderLine)) { keywordLine = new StripKeywordLine(); string[] buildinkeys = GetShortcutKeywords(shaderLine); for (int i = 0; i < buildinkeys.Length; i++) { StripKeyword keyword = keywordLine.GetKeyword(buildinkeys[i]); if (keyword == null) { keyword = new StripKeyword(buildinkeys[i]); } keyword.enabled = true; keyword.isSkip = false; keywordLine.Add(keyword); } keywordLine.editorLineType = editorLine; keywordLine.shaderLineType = shaderLine; currentPass.Add(keywordLine); } } } currentPass.pass = Mathf.Max(pass, 0); if (basePass != null) { currentPass.Add(basePass.keywordLines); } shader.Add(currentPass); shader.UpdateVariantCount(); }