using System.IO; using System.Text.RegularExpressions; using UnityEditor; using UnityEngine; namespace AllIn13DShader { public static class ShadersCreatorTool { private const string TEMPLATE_EXTENSION = ".allIn13DTemplate"; private const string STENCIL_BLOCK_TEMPLATE_NAME = "StencilBlock"; private static string[] TEMPLATES_NAMES = new string[] { "AllIn13DShaderOutline_NoShadowCaster_Template", "AllIn13DShaderOutline_Template", "AllIn13DShader_NoShadowCaster_Template", }; private static string[] TEMPLATE_TAGS = new string[] { "COMMON_PROPERTIES", "BASE_PASS", "FORWARD_ADD_PASS", "SHADOW_CASTER_PASS", "CUSTOM_EDITOR", "BASE_PASS_URP", "SHADOW_CASTER_PASS_URP", "DEPTH_ONLY_PASS_URP", "DEPTH_NORMALS_PASS_URP", "META_PASS_URP", }; private const string REGEX_CORE = @"\/\*<{0}_START>\*\/\s*([\t\r\ ]*(?:.*\n)*)[\t\r\ ]*\s+\/\*<{0}_END>\*\/"; private const string TAG_FORMAT = "<{0}>"; public static void BuildShaderFiles() { Shader mainShader = Shader.Find(Constants.SHADER_FULL_NAME_ALLIN13D); string mainShaderPath = AssetDatabase.GetAssetPath(mainShader); string shaderFileText = File.ReadAllText(mainShaderPath); string stencilBlockPath = Path.Combine(Constants.TEMPLATES_FOLDER, STENCIL_BLOCK_TEMPLATE_NAME) + TEMPLATE_EXTENSION; string stencilBlockContent = File.ReadAllText(stencilBlockPath); for (int i = 0; i < TEMPLATES_NAMES.Length; i++) { string templatePath = Path.Combine(Constants.TEMPLATES_FOLDER, TEMPLATES_NAMES[i]) + TEMPLATE_EXTENSION; string templateText = File.ReadAllText(templatePath); string newShaderFileText = SearchAndReplaceTemplateTags(shaderFileText, templateText); if (TEMPLATES_NAMES[i] == "AllIn13DShaderOutline_NoShadowCaster_Template" || TEMPLATES_NAMES[i] == "AllIn13DShaderOutline_Template") { newShaderFileText = newShaderFileText.Replace(@"/**/", stencilBlockContent); } string newShaderFileName = TEMPLATES_NAMES[i].Replace("_Template", ""); string newShaderPath = Path.Combine(Constants.SHADERS_GENERIC_FOLDER_PATH, newShaderFileName + ".shader"); newShaderFileText = EditorUtils.UnifyEOL(newShaderFileText); File.WriteAllText(newShaderPath, newShaderFileText); } AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); } private static string SearchAndReplaceTemplateTags(string shaderFileText, string templateText) { string res = templateText; for (int i = 0; i < TEMPLATE_TAGS.Length; i++) { string tagData = GetDataByTag(shaderFileText, TEMPLATE_TAGS[i]); res = OverrideTagWithData(TEMPLATE_TAGS[i], tagData, res); } return res; } private static string GetDataByTag(string shaderFileTex, string tag) { string res = string.Empty; string regex = string.Format(REGEX_CORE, tag); MatchCollection matchCollection = Regex.Matches(shaderFileTex, regex); if(matchCollection.Count > 0) { res = matchCollection[0].Groups[1].Value.TrimStart().TrimEnd(); } return res; } private static string OverrideTagWithData(string tag, string data, string targetFileTxt) { string res = targetFileTxt; string formattedTag = string.Format(TAG_FORMAT, tag); res = res.Replace(formattedTag, data); return res; } } }