/// /// Shader Control - (C) Copyright 2016-2022 Ramiro Oliva (Kronnect) /// /// using UnityEngine; using UnityEditor; using System; using System.IO; using System.Text; using System.Collections.Generic; namespace ShaderControl { public partial class SCWindow : EditorWindow { const string JSON_NODE_DATA_V2 = "JSONnodeData"; const string JSON_KEYWORD_SCOPE_V2 = "m_KeywordScope"; [Serializable] public struct ShaderGraphChunkDataV2 { public string m_Type; public string m_ObjectId; public string m_Name; public string m_DefaultReferenceName; public int m_KeywordScope; public int m_KeywordDefinition; } List graphKeywords; void ScanShaderGraphV2(SCShader shader, string shaderContents) { // Only extract info from first JSON chunk ExtractJSONChunks(shaderContents); SCShaderPass currentPass = new SCShaderPass(); for (int k = 0; k < graphKeywords.Count; k++) { ShaderGraphChunkDataV2 kw = graphKeywords[k]; 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, kw.m_ObjectId); keywordLine.Add(keyword); currentPass.Add(keywordLine); } shader.Add(currentPass); shader.UpdateVariantCount(); } void ConvertToLocalGraphV2(SCKeyword keyword, SCShader shader) { string contents = File.ReadAllText(shader.path, Encoding.UTF8); int pos = contents.IndexOf("\"m_ObjectId\": \"" + keyword.shaderGraphObjectId); bool changed = false; if (pos > 0) { int scopePos = contents.IndexOf(JSON_KEYWORD_SCOPE, pos); if (scopePos > pos) { 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); } } static readonly char[] jsonClosures = { '{', '}' }; void ExtractJSONChunks(string json) { if (graphKeywords == null) { graphKeywords = new List(); } else { graphKeywords.Clear(); } int count = 0; int startIndex = 0, lastIndex = 0; do { int nextClosure = json.IndexOfAny(jsonClosures, lastIndex); if (nextClosure < 0) break; if (json[nextClosure] == '{') count++; else if (json[nextClosure] == '}') count--; lastIndex = nextClosure + 1; if (count == 0) { string jsonChunk = json.Substring(startIndex, lastIndex - startIndex); ShaderGraphChunkDataV2 chunk = JsonUtility.FromJson(jsonChunk); if (chunk.m_Type.Equals("UnityEditor.ShaderGraph.ShaderKeyword")) { graphKeywords.Add(chunk); } startIndex = lastIndex; } } while (true); } } }