static public TCP2_Config CreateFromFile(string text) { string[] lines = text.Split(new string[]{"\n","\r\n"}, System.StringSplitOptions.RemoveEmptyEntries); TCP2_Config config = new TCP2_Config(); //Flags ParseBlock currentBlock = ParseBlock.None; for(int i = 0; i < lines.Length; i++) { string line = lines[i]; if(line.StartsWith("//")) continue; string[] data = line.Split(new string[]{"\t"}, System.StringSplitOptions.RemoveEmptyEntries); if(line.StartsWith("#")) { currentBlock = ParseBlock.None; switch(data[0]) { case "#filename": config.Filename = data[1]; break; case "#shadername": config.ShaderName = data[1]; break; case "#features": currentBlock = ParseBlock.Features; break; case "#flags": currentBlock = ParseBlock.Flags; break; default: Debug.LogWarning("[TCP2 Shader Config] Unrecognized tag: " + data[0] + "\nline " + (i+1)); break; } } else { if(data.Length > 1) { bool enabled = false; bool.TryParse(data[1], out enabled); if(enabled) { if(currentBlock == ParseBlock.Features) config.Features.Add(data[0]); else if(currentBlock == ParseBlock.Flags) config.Flags.Add(data[0]); else Debug.LogWarning("[TCP2 Shader Config] Unrecognized line while parsing : " + line + "\nline " + (i+1)); } } } } return config; }
protected override void ForceValue(TCP2_Config config) { var selectedValue = GetSelectedValue(config); if (selectedValue < 0) { selectedValue = defaultValue; } if (forceValue && Enabled(config) && !config.HasKeyword(keyword)) { config.SetKeyword(keyword, values[selectedValue]); } }
protected override void OnEnabledChangedState(TCP2_Config config, bool newState) { var feature = -1; if (newState) { feature = GetSelectedFeature(config); if (feature < 0) { feature = 0; } } ToggleSelectedFeature(config, feature); }
static private bool NeedCustomLighting(TCP2_Config config) { bool specmask = HasFeatures(config, "SPECULAR_MASK"); bool anisotropic = HasFeatures(config, "SPECULAR_ANISOTROPIC"); bool texthreshold = HasFeatures(config, "TEXTURED_THRESHOLD"); bool occlusion = HasFeatures(config, "OCCLUSION"); bool indshadows = HasFeatures(config, "INDEPENDENT_SHADOWS"); bool sketch = HasFeatures(config, "SKETCH", "SKETCH_GRADIENT"); bool lightmap = HasFeatures(config, "LIGHTMAP"); bool dsbWrapLight = HasFeatures(config, "DISABLE_WRAPPED_LIGHTING"); bool rim_lightmask = HasFeatures(config, "RIM_LIGHTMASK"); bool color_mult = HasFeatures(config, "COLOR_MULTIPLIERS"); return(dsbWrapLight || specmask || anisotropic || occlusion || texthreshold || indshadows || sketch || lightmap || rim_lightmask || color_mult); }
private void LoadCurrentConfig(TCP2_Config config, bool loadConfigTemplate = true) { mCurrentConfig = config; mDirtyConfig = false; if (sAutoNames) { mCurrentConfig.AutoNames(); } mCurrentHash = mCurrentConfig.ToHash(); if (loadConfigTemplate) { Template.TryLoadTextAsset(mCurrentConfig); } }
public void FeaturesGUI(TCP2_Config config) { if (this.uiFeatures == null) { EditorGUILayout.HelpBox("Couldn't parse the features from the Template.", MessageType.Error); return; } int length = this.uiFeatures.Length; for (int i = 0; i < length; i++) { this.uiFeatures[i].DrawGUI(config); } }
protected override void DrawGUI(Rect position, TCP2_Config config) { var feature = GetSelectedFeature(config); if (feature < 0) { feature = 0; } EditorGUI.BeginChangeCheck(); feature = EditorGUI.Popup(position, feature, labels); if (EditorGUI.EndChangeCheck()) { ToggleSelectedFeature(config, feature); } }
private void ToggleSelectedFeature(TCP2_Config config, int selectedFeature) { for (var i = 0; i < features.Length; i++) { var enable = (i == selectedFeature); config.ToggleFeature(features[i], enable); } if (toggles != null) { foreach (var t in toggles) { config.ToggleFeature(t, selectedFeature > 0); } } }
static private string GetShaderTarget(TCP2_Config config) { return((config.shaderTarget / 10f).ToString("0.0")); /* * bool tessellate = HasFeatures(config, "DX11_TESSELLATION"); * bool forcesm2 = HasFeatures(config, "FORCE_SM2"); * * if(forcesm2) * return "2.0"; * else if(tessellate) * return "5.0"; * else * return "3.0"; */ }
static private string GetExistingShaderPath(TCP2_Config config, Shader existingShader) { //Override OutputPath if Shader already exists, to make sure we replace the original shader file string unityPath = AssetDatabase.GetAssetPath(existingShader); unityPath = unityPath.Replace(".shader", ""); //remove extension unityPath = Path.GetDirectoryName(unityPath); if (config.Filename.Contains("/")) { string filenamePath = Path.GetDirectoryName(config.Filename); unityPath = unityPath.Replace(filenamePath, ""); //remove subdirectories } unityPath = unityPath.Substring(6); //get only directory without leading "Assets" if (!unityPath.EndsWith("/")) unityPath = unityPath + "/"; return unityPath; }
static private bool GetMaskDependency(TCP2_Config config, string maskType) { switch(maskType) { case "SPEC_MASK": return HasFeatures(config, "SPECULAR", "SPECULAR_ANISOTROPIC"); case "REFL_MASK": return HasFeatures(config, "REFLECTION"); case "MASK_MC": return HasFeatures(config, "MATCAP"); case "SPEC_SHIN_MASK": return HasFeatures(config, "SPECULAR", "SPECULAR_ANISOTROPIC"); case "DETAIL_MASK": return HasFeatures(config, "DETAIL_TEX"); case "RIM_MASK": return HasFeatures(config, "RIM","RIM_OUTLINE"); case "EMISSION_MASK": return HasFeatures(config, "EMISSION"); case "SS_MASK": return HasFeatures(config, "SUBSURFACE_SCATTERING"); case "COLORMASK": return true; } return false; }
public void FeaturesGUI(TCP2_Config config) { if (uiFeatures == null) { EditorGUILayout.HelpBox("Couldn't parse the features from the Template.", MessageType.Error); return; } //Make the template accessible to UIFeatures (so that DropDown can iterate and know if any features inside are modified) CurrentTemplate = this; var length = uiFeatures.Length; for (var i = 0; i < length; i++) { uiFeatures[i].DrawGUI(config); } }
public static TCP2_Config CreateFromShader(Shader shader) { var shaderImporter = ShaderImporter.GetAtPath(AssetDatabase.GetAssetPath(shader)) as ShaderImporter; var config = new TCP2_Config(); config.ShaderName = shader.name; config.Filename = Path.GetFileName(AssetDatabase.GetAssetPath(shader)).Replace(".shader", ""); config.isModifiedExternally = false; var valid = config.ParseUserData(shaderImporter); if (valid) { return(config); } return(null); }
private void LoadCurrentConfigFromShader(Shader shader) { ShaderImporter shaderImporter = ShaderImporter.GetAtPath(AssetDatabase.GetAssetPath(shader)) as ShaderImporter; string[] features; string[] flags; string[] customData; Dictionary <string, string> keywords; TCP2_ShaderGeneratorUtils.ParseUserData(shaderImporter, out features, out flags, out keywords, out customData); if (features != null && features.Length > 0 && features[0] == "USER") { mCurrentConfig = new TCP2_Config(); mCurrentConfig.ShaderName = shader.name; mCurrentConfig.Filename = System.IO.Path.GetFileName(AssetDatabase.GetAssetPath(shader)); mCurrentConfig.Features = new List <string>(features); mCurrentConfig.Flags = (flags != null) ? new List <string>(flags) : new List <string>(); mCurrentConfig.Keywords = (keywords != null) ? new Dictionary <string, string>(keywords) : new Dictionary <string, string>(); mCurrentShader = shader; mConfigChoice = mUserShadersLabels.IndexOf(shader.name); mDirtyConfig = false; AutoNames(); mCurrentHash = mCurrentConfig.ToHash(); mIsModified = false; if (customData != null && customData.Length > 0) { ulong timestamp; if (ulong.TryParse(customData[0], out timestamp)) { if (shaderImporter.assetTimeStamp != timestamp) { mIsModified = true; } } } } else { EditorApplication.Beep(); this.ShowNotification(new GUIContent("Invalid shader loaded: it doesn't seem to have been generated by the TCP2 Shader Generator!")); mCurrentShader = null; NewShader(); } }
static private string GetShaderTarget(TCP2_Config config) { bool tessellate = HasFeatures(config, "DX11_TESSELLATION"); bool forcesm2 = HasFeatures(config, "FORCE_SM2"); if (forcesm2) { return("2.0"); } else if (tessellate) { return("5.0"); } else { return("3.0"); } }
protected override void DrawGUI(Rect position, TCP2_Config config) { var feature = Highlighted(config); EditorGUI.BeginChangeCheck(); feature = EditorGUI.Toggle(position, feature); if (EditorGUI.EndChangeCheck()) { config.ToggleFeature(keyword, feature); if (toggles != null) { foreach (var t in toggles) { config.ToggleFeature(t, feature); } } } }
protected override void DrawGUI(Rect position, TCP2_Config config) { EditorGUILayout.BeginHorizontal(); TCP2_GUI.HelpButton("Shader Target"); TCP2_GUI.SubHeader("Shader Target", "Defines the shader target level to compile for", config.shaderTarget != 30, LABEL_WIDTH - 24f); var newTarget = EditorGUILayout.IntPopup(config.shaderTarget, #if UNITY_5_4_OR_NEWER new[] { "2.0", "2.5", "3.0", "3.5", "4.0", "5.0" }, new[] { 20, 25, 30, 35, 40, 50 }); #else new string[] { "2.0", "3.0", "4.0", "5.0" }, new int[] { 20, 30, 40, 50 }); #endif if (newTarget != config.shaderTarget) { config.shaderTarget = newTarget; } EditorGUILayout.EndHorizontal(); }
//-------------------------------------------------------------------------------------------------- // SHADER GENERATION private static string GetIncludePrefix(TCP2_Config config) { //Folder if (!config.Filename.Contains("/")) { return(""); } var prefix = ""; foreach (var c in config.Filename) { if (c == '/') { prefix += "../"; } } return(prefix); }
protected override void DrawGUI(Rect position, TCP2_Config config) { //Check if any feature within that Foldout are enabled, and show different color if so var hasToggledFeatures = false; var i = Array.IndexOf(ShaderGeneratorTemplate.CurrentTemplate.uiFeatures, this); if (i >= 0) { for (i++; i < ShaderGeneratorTemplate.CurrentTemplate.uiFeatures.Length; i++) { var uiFeature = ShaderGeneratorTemplate.CurrentTemplate.uiFeatures[i]; if (uiFeature is UIFeature_DropDownEnd) { break; } hasToggledFeatures |= uiFeature.Highlighted(config) && uiFeature.Enabled(config); } } var color = GUI.color; GUI.color *= 0.95f; EditorGUILayout.BeginVertical(EditorStyles.helpBox); GUI.color = color; EditorGUI.BeginChangeCheck(); foldout = TCP2_GUI.HeaderFoldoutHighlight(foldout, guiContent, hasToggledFeatures); FoldoutStack.Push(foldout); if (EditorGUI.EndChangeCheck()) { UpdatePersistentState(); if (Event.current.alt || Event.current.control) { var state = foldout; foreach (var dd in AllDropDowns) { dd.foldout = state; dd.UpdatePersistentState(); } } } }
//Try to load a Template according to a config type and/or file public void TryLoadTextAsset(TCP2_Config config = null) { string configFile = config != null ? config.templateFile : null; //Append file extension if necessary if (!string.IsNullOrEmpty(configFile) && !configFile.EndsWith(".txt")) { configFile = configFile + ".txt"; } TextAsset loadedTextAsset = null; if (!string.IsNullOrEmpty(configFile)) { TextAsset conf = LoadTextAsset(configFile); if (conf != null) { loadedTextAsset = conf; if (loadedTextAsset != null) { SetTextAsset(loadedTextAsset); return; } } } //New name as of 2.3 loadedTextAsset = LoadTextAsset("TCP2_ShaderTemplate_Default.txt"); if (loadedTextAsset != null) { SetTextAsset(loadedTextAsset); return; } //Old legacy name loadedTextAsset = LoadTextAsset("TCP2_User_Unity5.txt"); if (loadedTextAsset != null) { SetTextAsset(loadedTextAsset); return; } }
static private string GetLightingFunction(TCP2_Config config) { bool customLighting = HasFeatures(config, "CUSTOM_LIGHTING"); if (customLighting) { return("ToonyColorsCustom"); } bool specular = HasFeatures(config, "SPECULAR", "SPECULAR_ANISOTROPIC"); if (specular) { return("ToonyColorsSpec"); } else { return("ToonyColors"); } }
private void LoadCurrentConfigFromShader(Shader shader) { mCurrentConfig = TCP2_Config.CreateFromShader(shader); if (mCurrentConfig != null) { mCurrentShader = shader; mConfigChoice = mUserShadersLabels.IndexOf(shader.name); mDirtyConfig = false; mCurrentHash = mCurrentConfig.ToHash(); //Load appropriate template Template.TryLoadTextAsset(mCurrentConfig); } else { EditorApplication.Beep(); this.ShowNotification(new GUIContent("Invalid shader loaded: it doesn't seem to have been generated by the TCP2 Shader Generator!")); mCurrentShader = null; NewShader(); } }
//------------------------------------------------- //Convert Config to ShaderImporter UserData static public string ToUserData(this TCP2_Config config, string[] customData) { string userData = ""; if(!config.Features.Contains("USER")) userData = "USER,"; foreach(string feature in config.Features) if(feature.Contains("USER")) userData += string.Format("{0},", feature); else userData += string.Format("F{0},", feature); foreach(string flag in config.Flags) userData += string.Format("f{0},", flag); foreach(KeyValuePair<string,string> kvp in config.Keywords) userData += string.Format("K{0}:{1},", kvp.Key, kvp.Value); foreach(string custom in customData) userData += string.Format("c{0},", custom); userData = userData.TrimEnd(','); return userData; }
static private bool GetMaskDependency(TCP2_Config config, string maskType) { switch (maskType) { case "SPEC_MASK": return(HasFeatures(config, "SPECULAR", "SPECULAR_ANISOTROPIC")); case "REFL_MASK": return(HasFeatures(config, "REFLECTION")); case "MASK_MC": return(HasFeatures(config, "MATCAP")); case "SPEC_SHIN_MASK": return(HasFeatures(config, "SPECULAR", "SPECULAR_ANISOTROPIC")); case "DETAIL_MASK": return(HasFeatures(config, "DETAIL_TEX")); case "RIM_MASK": return(HasFeatures(config, "RIM", "RIM_OUTLINE")); case "ILLUMIN_MASK": return(HasFeatures(config, "ILLUMINATION")); case "COLORMASK": return(true); } return(false); }
public static Shader Compile(TCP2_Config config, string template, float progress, bool overwritePrompt, bool modifiedPrompt) { //UI if(progress >= 0f) EditorUtility.DisplayProgressBar("Hold On", "Generating Shader: " + config.ShaderName, progress); //Generate source string source = config.GenerateShaderSource(template); if(string.IsNullOrEmpty(source)) { Debug.LogError("[TCP2 Shader Generator] Can't save Shader: source is null or empty!"); return null; } //Save to disk Shader shader = SaveShader(config, source, overwritePrompt, modifiedPrompt); //UI if(progress >= 0f) EditorUtility.ClearProgressBar(); return shader; }
//Generate the source code for the shader as a string private static string GenerateShaderSource(this TCP2_Config config, TCP2_ShaderGenerator.ShaderGeneratorTemplate template, Shader existingShader = null) { if (config == null) { var error = "[TCP2 Shader Generator] Config file is null"; Debug.LogError(error); return(error); } if (template == null) { var error = "[TCP2 Shader Generator] Template is null"; Debug.LogError(error); return(error); } if (template.textAsset == null || string.IsNullOrEmpty(template.textAsset.text)) { var error = "[TCP2 Shader Generator] Template string is null or empty"; Debug.LogError(error); return(error); } //------------------------------------------------ // SHADER PARAMETERS //Masks bool mask1 = false, mask2 = false, mask3 = false, vcolors_mask = false, mainTex_mask = false; var mask1features = ""; var mask2features = ""; var mask3features = ""; //Enable Masks according to their dependencies (new system using Template) foreach (var kvp in config.Keywords) { if (kvp.Value == "mask1") { var maskEnabled = template.GetMaskDependency(kvp.Key, config); mask1 |= maskEnabled; if (maskEnabled) { mask1features += template.GetMaskDisplayName(kvp.Key) + ","; } } else if (kvp.Value == "mask2") { var maskEnabled = template.GetMaskDependency(kvp.Key, config); mask2 |= maskEnabled; if (maskEnabled) { mask2features += template.GetMaskDisplayName(kvp.Key) + ","; } } else if (kvp.Value == "mask3") { var maskEnabled = template.GetMaskDependency(kvp.Key, config); mask3 |= maskEnabled; if (maskEnabled) { mask3features += template.GetMaskDisplayName(kvp.Key) + ","; } } else if (kvp.Value == "IN.color" || kvp.Value == "vcolors") { vcolors_mask |= template.GetMaskDependency(kvp.Key, config); } else if (kvp.Value == "mainTex") { mainTex_mask |= template.GetMaskDependency(kvp.Key, config); } } //Only enable Independent UVs if relevant Mask is actually enabled foreach (var kvp in config.Keywords) { if (kvp.Key == "UV_mask1") { config.ToggleFeature("UVMASK1", (kvp.Value == "Independent UV" || kvp.Value == "Independent UV0") && mask1); config.ToggleFeature("UVMASK1_UV2", kvp.Value == "Independent UV1" && mask1); } else if (kvp.Key == "UV_mask2") { config.ToggleFeature("UVMASK2", (kvp.Value == "Independent UV" || kvp.Value == "Independent UV0") && mask2); config.ToggleFeature("UVMASK2_UV2", kvp.Value == "Independent UV1" && mask2); } else if (kvp.Key == "UV_mask3") { config.ToggleFeature("UVMASK3", (kvp.Value == "Independent UV" || kvp.Value == "Independent UV0") && mask3); config.ToggleFeature("UVMASK3_UV2", kvp.Value == "Independent UV1" && mask3); } } mask1features = mask1features.TrimEnd(','); mask2features = mask2features.TrimEnd(','); mask3features = mask3features.TrimEnd(','); config.ToggleFeature("MASK1", mask1); config.ToggleFeature("MASK2", mask2); config.ToggleFeature("MASK3", mask3); config.ToggleFeature("VCOLORS_MASK", vcolors_mask); config.ToggleFeature("MASK_MAINTEX", mainTex_mask); //--- var keywords = new Dictionary <string, string>(config.Keywords); var flags = new List <string>(config.Flags); var features = new List <string>(config.Features); //Unity version #if UNITY_5_4_OR_NEWER TCP2_Utils.AddIfMissing(features, "UNITY_5_4"); #endif #if UNITY_5_5_OR_NEWER TCP2_Utils.AddIfMissing(features, "UNITY_5_5"); #endif #if UNITY_2017_1_OR_NEWER TCP2_Utils.AddIfMissing(features, "UNITY_2017_1"); #endif #if UNITY_2018_1_OR_NEWER TCP2_Utils.AddIfMissing(features, "UNITY_2018_1"); #endif #if UNITY_2018_2_OR_NEWER TCP2_Utils.AddIfMissing(features, "UNITY_2018_2"); #endif //Masks keywords.Add("MASK1", mask1features); keywords.Add("MASK2", mask2features); keywords.Add("MASK3", mask3features); //Shader name keywords.Add("SHADER_NAME", config.ShaderName); //Include path var include = GetIncludePrefix(config) + GetIncludeRelativePath(config, existingShader).TrimEnd('/'); keywords.Add("INCLUDE_PATH", include); //Shader Model target (old templates) if (!keywords.ContainsKey("SHADER_TARGET")) { var target = GetShaderTarget(config); keywords.Add("SHADER_TARGET", target); if (config.shaderTarget == 20) { TCP2_Utils.AddIfMissing(features, "FORCE_SM2"); } } //Generate Surface parameters var strFlags = ArrayToString(flags.ToArray(), " "); keywords.Add("SURF_PARAMS", strFlags); //------------------------------------------------ // PARSING & GENERATION var sb = new StringBuilder(); var templateLines = template.textAsset.text.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None); var depth = -1; var stack = new List <bool>(); var done = new List <bool>(); //Parse template file string line = null; for (var i = 0; i < templateLines.Length; i++) { line = templateLines[i]; //Comment if (line.StartsWith("#")) { //Meta if (line.StartsWith("#CONFIG=")) { config.configType = line.Substring(8).TrimEnd().ToLower(); } //Features UI if (line.StartsWith("#FEATURES")) { while (i < templateLines.Length) { i++; if (templateLines[i] == "#END") { break; } } continue; } //Keywords if (line.StartsWith("#KEYWORDS")) { while (i < templateLines.Length) { i++; if (templateLines[i] == "#END") { break; } var error = ProcessKeywords(templateLines[i], config, ref features, ref flags, ref keywords, ref i, ref depth, ref stack, ref done); if (!string.IsNullOrEmpty(error)) { return(error); } } //Update Surface parameters strFlags = ArrayToString(flags.ToArray(), " "); if (keywords.ContainsKey("SURF_PARAMS")) { keywords["SURF_PARAMS"] = strFlags; } else { keywords.Add("SURF_PARAMS", strFlags); } } //Debugging if (line.StartsWith("#break")) { Debug.Log("[TCP2] Parse Break @ " + i); } continue; } //Line break if (string.IsNullOrEmpty(line) && ((depth >= 0 && stack[depth]) || depth < 0)) { sb.AppendLine(line); continue; } //Conditions if (line.Contains("///")) { var error = ProcessCondition(line, ref features, ref i, ref depth, ref stack, ref done); if (!string.IsNullOrEmpty(error)) { return(error); } } //Regular line else { //Replace keywords line = ReplaceKeywords(line, keywords); //Append line if inside valid condition block if ((depth >= 0 && stack[depth]) || depth < 0) { sb.AppendLine(line); } } } if (depth >= 0) { Debug.LogWarning("[TCP2 Shader Generator] Missing " + (depth + 1) + " ending '///' tags"); } var sourceCode = sb.ToString(); //Normalize line endings sourceCode = sourceCode.Replace("\r\n", "\n"); return(sourceCode); }
public static Shader Compile(TCP2_Config config, Shader existingShader, TCP2_ShaderGenerator.ShaderGeneratorTemplate template, float progress, bool overwritePrompt) { //UI if (progress >= 0f) { EditorUtility.DisplayProgressBar("Hold On", "Generating Shader: " + config.ShaderName, progress); } //Generate source string source = config.GenerateShaderSource(template, existingShader); if (string.IsNullOrEmpty(source)) { Debug.LogError("[TCP2 Shader Generator] Can't save Shader: source is null or empty!"); return(null); } //Save to disk var shader = SaveShader(config, existingShader, source, overwritePrompt, config.isModifiedExternally); if (config.configType == "terrain") { //Generate Base shader var baseConfig = config.Copy(); baseConfig.Filename = baseConfig.Filename + "_Base"; baseConfig.ShaderName = "Hidden/" + baseConfig.ShaderName + "-Base"; baseConfig.Features.Add("TERRAIN_BASE"); source = baseConfig.GenerateShaderSource(template, existingShader); if (string.IsNullOrEmpty(source)) { Debug.LogError("[TCP2 Shader Generator] Can't save Terrain Base Shader: source is null or empty!"); } else { SaveShader(baseConfig, existingShader, source, false, false); } //Generate AddPass shader var addPassConfig = config.Copy(); addPassConfig.Filename = addPassConfig.Filename + "_AddPass"; addPassConfig.ShaderName = "Hidden/" + addPassConfig.ShaderName + "-AddPass"; addPassConfig.Features.Add("TERRAIN_ADDPASS"); addPassConfig.Flags.Add("decal:add"); source = addPassConfig.GenerateShaderSource(template, existingShader); if (string.IsNullOrEmpty(source)) { Debug.LogError("[TCP2 Shader Generator] Can't save Terrain AddPass Shader: source is null or empty!"); } else { SaveShader(addPassConfig, existingShader, source, false, false); } } //UI if (progress >= 0f) { EditorUtility.ClearProgressBar(); } return(shader); }
//-------------------------------------------------------------------------------------------------- // GENERATION public static Shader Compile(TCP2_Config config, Shader existingShader, TCP2_ShaderGenerator.ShaderGeneratorTemplate template, bool showProgressBar = true, bool overwritePrompt = true) { return(Compile(config, existingShader, template, showProgressBar ? 0f : -1f, overwritePrompt)); }
private static string GetIncludeFile(TCP2_Config config) { return "TCP2_Include.cginc"; }
private static bool GetMaskDependency(TCP2_Config config, string maskType) { switch(maskType) { case "SPEC_MASK": return HasFeatures(config, "SPECULAR", "SPECULAR_ANISOTROPIC"); case "REFL_MASK": return HasFeatures(config, "REFLECTION"); case "MASK_MC": return HasFeatures(config, "MATCAP"); case "SPEC_SHIN_MASK": return HasFeatures(config, "SPECULAR", "SPECULAR_ANISOTROPIC"); case "DETAIL_MASK": return HasFeatures(config, "DETAIL_TEX"); case "RIM_MASK": return HasFeatures(config, "RIM","RIM_OUTLINE"); case "ILLUMIN_MASK": return HasFeatures(config, "ILLUMINATION"); case "COLORMASK": return true; } return false; }
private void CopyShader() { mCurrentShader = null; mConfigChoice = 0; mIsModified = false; TCP2_Config newConfig = new TCP2_Config(); newConfig.Features = mCurrentConfig.Features; newConfig.Flags = mCurrentConfig.Flags; newConfig.Keywords = mCurrentConfig.Keywords; newConfig.ShaderName = mCurrentConfig.ShaderName + " Copy"; newConfig.Filename = mCurrentConfig.Filename + " Copy"; LoadCurrentConfig(newConfig); }
private static string GetShaderTarget(TCP2_Config config) { return((config.shaderTarget / 10f).ToString("0.0")); }
public static bool HasFeatures(TCP2_Config config, bool anyFeature, params string[] features) { return HasFeatures(config.Features, anyFeature, features); }
private static string GetLightingFunction(TCP2_Config config) { bool customLighting = HasFeatures(config, "CUSTOM_LIGHTING"); if(customLighting) return "ToonyColorsCustom"; bool specular = HasFeatures(config, "SPECULAR", "SPECULAR_ANISOTROPIC"); if(specular) return "ToonyColorsSpec"; else return "ToonyColors"; }
private static string GetSurfaceOutput(TCP2_Config config) { return "SurfaceOutput"; }
public static Shader Compile(TCP2_Config config, string template, bool showProgressBar = true, bool overwritePrompt = true, bool modifiedPrompt = false) { return Compile(config, template, showProgressBar ? 0f : -1f, overwritePrompt, modifiedPrompt); }
public static string GetKeyword(TCP2_Config config, string key) { return GetKeyword(config.Keywords, key); }
private static bool NeedCustomAmbient(TCP2_Config config) { bool occlusion = HasFeatures(config, "OCCLUSION"); bool cubeambient = HasFeatures(config, "CUBE_AMBIENT"); bool dirambient = HasFeatures(config, "DIRAMBIENT"); return cubeambient || occlusion || dirambient; }
//-------------------------------------------------------------------------------------------------- // IO //Save .shader file private static Shader SaveShader(TCP2_Config config, Shader existingShader, string sourceCode, bool overwritePrompt, bool modifiedPrompt) { if (string.IsNullOrEmpty(config.Filename)) { Debug.LogError("[TCP2 Shader Generator] Can't save Shader: filename is null or empty!"); return(null); } //Save file var outputPath = OutputPath; var filename = config.Filename; //Get existing shader exact path if (existingShader != null) { outputPath = GetExistingShaderPath(config, existingShader); /* * if(config.Filename.Contains("/")) * { * filename = config.Filename.Substring(config.Filename.LastIndexOf('/')+1); * } */ } var systemPath = Application.dataPath + outputPath; if (!Directory.Exists(systemPath)) { Directory.CreateDirectory(systemPath); } var fullPath = systemPath + filename + ".shader"; var overwrite = true; if (overwritePrompt && File.Exists(fullPath)) { overwrite = EditorUtility.DisplayDialog("TCP2 : Shader Generation", "The following shader already exists:\n\n" + fullPath + "\n\nOverwrite?", "Yes", "No"); } if (modifiedPrompt) { overwrite = EditorUtility.DisplayDialog("TCP2 : Shader Generation", "The following shader seems to have been modified externally or manually:\n\n" + fullPath + "\n\nOverwrite anyway?", "Yes", "No"); } if (overwrite) { var directory = Path.GetDirectoryName(fullPath); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } //Write file to disk File.WriteAllText(fullPath, sourceCode, Encoding.UTF8); AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); //Import (to compile shader) var assetPath = fullPath.Replace(Application.dataPath, "Assets"); var shader = AssetDatabase.LoadAssetAtPath(assetPath, typeof(Shader)) as Shader; if (SelectGeneratedShader) { Selection.objects = new Object[] { shader }; } //Set ShaderImporter userData var shaderImporter = ShaderImporter.GetAtPath(assetPath) as ShaderImporter; if (shaderImporter != null) { //Get file hash to verify if it has been manually altered afterwards var shaderHash = GetShaderContentHash(shaderImporter); //Use hash if available, else use timestamp var customDataList = new List <string>(); customDataList.Add(!string.IsNullOrEmpty(shaderHash) ? shaderHash : shaderImporter.assetTimeStamp.ToString()); customDataList.Add(config.GetShaderTargetCustomData()); var configTypeCustomData = config.GetConfigTypeCustomData(); if (configTypeCustomData != null) { customDataList.Add(configTypeCustomData); } customDataList.Add(config.GetConfigFileCustomData()); var userData = config.ToUserData(customDataList.ToArray()); shaderImporter.userData = userData; //Needed to save userData in .meta file AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.Default); } else { Debug.LogWarning("[TCP2 Shader Generator] Couldn't find ShaderImporter.\nMetadatas will be missing from the shader file."); } return(shader); } return(null); }
//-------------------------------------------------------------------------------------------------- // UTILS public static bool HasFeatures(TCP2_Config config, params string[] features) { return HasFeatures(config, true, features); }
private static string GetShaderTarget(TCP2_Config config) { bool tessellate = HasFeatures(config, "DX11_TESSELLATION"); bool forcesm2 = HasFeatures(config, "FORCE_SM2"); if(forcesm2) return "2.0"; else if(tessellate) return "5.0"; else return "3.0"; }
private static bool NeedFinalColorFunction(TCP2_Config config) { return false; }
private void LoadCurrentConfig(TCP2_Config config) { mCurrentConfig = config; mDirtyConfig = false; if(mAutoNames) { AutoNames(); } mCurrentHash = mCurrentConfig.ToHash(); }
private static bool NeedVertexFunction(TCP2_Config config) { bool vFunc = HasFeatures(config, "VERTEX_FUNC"); bool anisotropic = HasFeatures(config, "SPECULAR_ANISOTROPIC"); bool matcap = HasFeatures(config, "MATCAP"); bool sketch = HasFeatures(config, "SKETCH", "SKETCH_GRADIENT"); bool rimdir = HasFeatures(config, "RIMDIR"); bool rim = HasFeatures(config, "RIM", "RIM_OUTLINE"); bool rimvertex = HasFeatures(config, "RIM_VERTEX"); bool bump = HasFeatures(config, "BUMP"); bool cstamb = HasFeatures(config, "CUSTOM_AMBIENT"); return vFunc || matcap || sketch || (rimvertex && rim) || (bump && rimdir && rim) || anisotropic || cstamb; }
private void LoadCurrentConfigFromShader(Shader shader) { ShaderImporter shaderImporter = ShaderImporter.GetAtPath(AssetDatabase.GetAssetPath(shader)) as ShaderImporter; string[] features; string[] flags; string[] customData; Dictionary<string,string> keywords; TCP2_ShaderGeneratorUtils.ParseUserData(shaderImporter, out features, out flags, out keywords, out customData); if(features != null && features.Length > 0 && features[0] == "USER") { mCurrentConfig = new TCP2_Config(); mCurrentConfig.ShaderName = shader.name; mCurrentConfig.Filename = System.IO.Path.GetFileName(AssetDatabase.GetAssetPath(shader)); mCurrentConfig.Features = new List<string>(features); mCurrentConfig.Flags = (flags != null) ? new List<string>(flags) : new List<string>(); mCurrentConfig.Keywords = (keywords != null) ? new Dictionary<string,string>(keywords) : new Dictionary<string,string>(); mCurrentShader = shader; mConfigChoice = mUserShadersLabels.IndexOf(shader.name); mDirtyConfig = false; AutoNames(); mCurrentHash = mCurrentConfig.ToHash(); mIsModified = false; if(customData != null && customData.Length > 0) { foreach(string data in customData) { //Hash if(data.Length > 0 && data[0] == 'h') { string dataHash = data; string fileHash = TCP2_ShaderGeneratorUtils.GetShaderContentHash(shaderImporter); if(!string.IsNullOrEmpty(fileHash) && dataHash != fileHash) { mIsModified = true; } } //Timestamp else { ulong timestamp; if(ulong.TryParse(data, out timestamp)) { if(shaderImporter.assetTimeStamp != timestamp) { mIsModified = true; } } } } } } else { EditorApplication.Beep(); this.ShowNotification(new GUIContent("Invalid shader loaded: it doesn't seem to have been generated by the TCP2 Shader Generator!")); mCurrentShader = null; NewShader(); } }
//-------------------------------------------------------------------------------------------------- // GENERATION static public Shader Compile(TCP2_Config config, Shader existingShader, string template, bool showProgressBar = true, bool overwritePrompt = true, bool modifiedPrompt = false) { return(Compile(config, existingShader, template, showProgressBar ? 0f : -1f, overwritePrompt, modifiedPrompt)); }
static public string GetKeyword(TCP2_Config config, string key) { return(GetKeyword(config.Keywords, key)); }
private static bool NeedCustomLighting(TCP2_Config config) { bool specmask = HasFeatures(config, "SPECULAR_MASK"); bool anisotropic = HasFeatures(config, "SPECULAR_ANISOTROPIC"); bool texthreshold = HasFeatures(config, "TEXTURED_THRESHOLD"); bool occlusion = HasFeatures(config, "OCCLUSION"); bool indshadows = HasFeatures(config, "INDEPENDENT_SHADOWS"); bool sketch = HasFeatures(config, "SKETCH", "SKETCH_GRADIENT"); bool lightmap = HasFeatures(config, "LIGHTMAP"); return specmask || anisotropic || occlusion || texthreshold || indshadows || sketch || lightmap; }
//-------------------------------------------------------------------------------------------------- // PRIVATE - SHADER GENERATION private static string GetIncludePrefix(TCP2_Config config) { //Folder if(!config.Filename.Contains("/")) return ""; string prefix = ""; foreach(char c in config.Filename) if(c == '/') prefix += "../"; return prefix; }
//-------------------------------------------------------------------------------------------------- // IO //Save .shader file private static Shader SaveShader(TCP2_Config config, string sourceCode, bool overwritePrompt, bool modifiedPrompt) { if(string.IsNullOrEmpty(config.Filename)) { Debug.LogError("[TCP2 Shader Generator] Can't save Shader: filename is null or empty!"); return null; } //Save file string path = Application.dataPath + OUTPUT_PATH; if(!System.IO.Directory.Exists(path)) { System.IO.Directory.CreateDirectory(path); } string fullPath = path + config.Filename + ".shader"; bool overwrite = true; if(overwritePrompt && System.IO.File.Exists(fullPath)) { overwrite = EditorUtility.DisplayDialog("TCP2 : Shader Generation", "The following shader already exists:\n\n" + fullPath + "\n\nOverwrite?", "Yes", "No"); } if(modifiedPrompt) { overwrite = EditorUtility.DisplayDialog("TCP2 : Shader Generation", "The following shader seems to have been modified externally or manually:\n\n" + fullPath + "\n\nOverwrite anyway?", "Yes", "No"); } if(overwrite) { string directory = System.IO.Path.GetDirectoryName(path + config.Filename); if(!System.IO.Directory.Exists(directory)) { System.IO.Directory.CreateDirectory(directory); } //Write file to disk System.IO.File.WriteAllText(path + config.Filename + ".shader", sourceCode, System.Text.Encoding.UTF8); AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); //Import (to compile shader) string assetPath = "Assets" + OUTPUT_PATH + config.Filename + ".shader"; Shader shader = AssetDatabase.LoadAssetAtPath(assetPath, typeof(Shader)) as Shader; if(SelectGeneratedShader) { Selection.objects = new Object[]{ shader }; } //Set ShaderImporter userData ShaderImporter shaderImporter = ShaderImporter.GetAtPath(assetPath) as ShaderImporter; if(shaderImporter != null) { //Get file hash to verify if it has been manually altered afterwards string shaderHash = GetShaderContentHash(shaderImporter); //Use hash if available, else use timestamp string[] customData = new string[]{ !string.IsNullOrEmpty(shaderHash) ? shaderHash : shaderImporter.assetTimeStamp.ToString() }; string userData = config.ToUserData( customData ); shaderImporter.userData = userData; //Needed to save userData in .meta file AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.Default); } else { Debug.LogWarning("[TCP2 Shader Generator] Couldn't find ShaderImporter.\nMetadatas will be missing from the shader file."); } return shader; } return null; }