//-------------------------------------------------------------------------------------------------- // 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) { //Set default textures string[] names = new string[] { "_NoTileNoiseTex", "_Ramp" }; Texture[] textures = new Texture[] { AssetDatabase.LoadAssetAtPath <Texture2D>(AssetDatabase.GUIDToAssetPath("af5515bfe14f1af4a9b8b3bf306b9261")), AssetDatabase.LoadAssetAtPath <Texture2D>(AssetDatabase.GUIDToAssetPath("ccad9b0732473ee4e95de81e50e9050f")) }; shaderImporter.SetDefaultTextures(names, textures); //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); }
static public TCP2_Config CreateFromShader(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") { var config = new TCP2_Config(); config.ShaderName = shader.name; config.Filename = System.IO.Path.GetFileName(AssetDatabase.GetAssetPath(shader)); config.Features = new List <string>(features); config.Flags = (flags != null) ? new List <string>(flags) : new List <string>(); config.Keywords = (keywords != null) ? new Dictionary <string, string>(keywords) : new Dictionary <string, string>(); config.AutoNames(); //mCurrentShader = shader; //mConfigChoice = mUserShadersLabels.IndexOf(shader.name); //mDirtyConfig = false; //AutoNames(); //mCurrentHash = mCurrentConfig.ToHash(); config.isModifiedExternally = 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) { config.isModifiedExternally = true; } } //Timestamp else { ulong timestamp; if (ulong.TryParse(data, out timestamp)) { if (shaderImporter.assetTimeStamp != timestamp) { config.isModifiedExternally = true; } } } //Shader Model target if (data.StartsWith("SM:")) { config.shaderTarget = int.Parse(data.Substring(3)); } //Configuration Type if (data.StartsWith("CT:")) { config.configType = data.Substring(3); } //Configuration File if (data.StartsWith("CF:")) { config.templateFile = data.Substring(3); } } } return(config); } else { return(null); } }
//-------------------------------------------------------------------------------------------------- // IO //Save .shader file static private 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) { string[] customData = new string[] { 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); }
void OnGUI() { sGUIEnabled = GUI.enabled; EditorGUILayout.BeginHorizontal(); TCP2_GUI.HeaderBig("TOONY COLORS PRO 2 - SHADER GENERATOR"); TCP2_GUI.HelpButton("Shader Generator"); EditorGUILayout.EndHorizontal(); TCP2_GUI.Separator(); float lW = EditorGUIUtility.labelWidth; EditorGUIUtility.labelWidth = 105f; //Avoid refreshing Template meta at every Repaint EditorGUILayout.BeginHorizontal(); TextAsset _tmpTemplate = EditorGUILayout.ObjectField("Template:", Template.textAsset, typeof(TextAsset), false) as TextAsset; if (_tmpTemplate != Template.textAsset) { Template.SetTextAsset(_tmpTemplate); } //Load template if (loadTemplateMenu != null) { if (GUILayout.Button("Load ▼", EditorStyles.miniButton, GUILayout.ExpandWidth(false))) { loadTemplateMenu.ShowAsContext(); } } /* * if(GUILayout.Button("Reload", EditorStyles.miniButton, GUILayout.ExpandWidth(false))) * { * Template.Reload(); * } */ EditorGUILayout.EndHorizontal(); //Template not found if (Template == null || Template.textAsset == null) { EditorGUILayout.HelpBox("Couldn't find template file!\n\nVerify that the file 'TCP2_ShaderTemplate_Default.txt' is in your project.\nPlease reimport the pack if you can't find it!", MessageType.Error); return; } //Infobox for custom templates if (!string.IsNullOrEmpty(Template.templateInfo)) { TCP2_GUI.HelpBoxLayout(Template.templateInfo, MessageType.Info); } if (!string.IsNullOrEmpty(Template.templateWarning)) { TCP2_GUI.HelpBoxLayout(Template.templateWarning, MessageType.Warning); } TCP2_GUI.Separator(); //If current shader is unsaved, show yellow color Color gColor = GUI.color; GUI.color = mDirtyConfig ? gColor * unsavedChangesColor : GUI.color; EditorGUI.BeginChangeCheck(); mCurrentShader = EditorGUILayout.ObjectField("Current Shader:", mCurrentShader, typeof(Shader), false) as Shader; if (EditorGUI.EndChangeCheck()) { if (mCurrentShader != null) { LoadCurrentConfigFromShader(mCurrentShader); } } EditorGUILayout.BeginHorizontal(); GUILayout.Space(EditorGUIUtility.labelWidth + 4); if (mDirtyConfig) { var guiContent = new GUIContent("Unsaved changes"); var rect = GUILayoutUtility.GetRect(guiContent, EditorStyles.helpBox, GUILayout.Height(16)); rect.y -= 2; GUI.Label(rect, guiContent, EditorStyles.helpBox); } GUILayout.FlexibleSpace(); using (new EditorGUI.DisabledScope(mCurrentShader == null)) { if (GUILayout.Button("Copy", EditorStyles.miniButtonLeft, GUILayout.Width(60f), GUILayout.Height(16))) { CopyShader(); } } if (GUILayout.Button("Load ▼", EditorStyles.miniButtonMid, GUILayout.Width(60f), GUILayout.Height(16))) { loadShadersMenu.ShowAsContext(); } if (GUILayout.Button("New", EditorStyles.miniButtonRight, GUILayout.Width(60f), GUILayout.Height(16))) { NewShader(); } GUILayout.Space(18); //leave space to align with the Object Field box EditorGUILayout.EndHorizontal(); GUI.color = gColor; if (mCurrentConfig == null) { NewShader(); } if (mCurrentConfig.isModifiedExternally) { EditorGUILayout.HelpBox("It looks like this shader has been modified externally/manually. Updating it will overwrite the changes.", MessageType.Warning); } /* * if(mUserShaders != null && mUserShaders.Length > 0) * { * EditorGUI.BeginChangeCheck(); * int prevChoice = mConfigChoice; * Color gColor = GUI.color; * GUI.color = mDirtyConfig ? gColor * Color.yellow : GUI.color; * GUILayout.BeginHorizontal(); * mConfigChoice = EditorGUILayout.Popup("Load Shader:", mConfigChoice, mUserShadersLabels.ToArray()); * if(GUILayout.Button("◄", EditorStyles.miniButtonLeft, GUILayout.Width(22))) * { * mConfigChoice--; * if(mConfigChoice < 1) mConfigChoice = mUserShaders.Length; * } * if(GUILayout.Button("►", EditorStyles.miniButtonRight,GUILayout.Width(22))) * { * mConfigChoice++; * if(mConfigChoice > mUserShaders.Length) mConfigChoice = 1; * } * GUILayout.EndHorizontal(); * GUI.color = gColor; * if(EditorGUI.EndChangeCheck() && prevChoice != mConfigChoice) * { * bool load = true; * if(mDirtyConfig) * { * if(mCurrentShader != null) * load = EditorUtility.DisplayDialog("TCP2 : Shader Generation", "You have unsaved changes for the following shader:\n\n" + mCurrentShader.name + "\n\nDiscard the changes and load a new shader?", "Yes", "No"); * else * load = EditorUtility.DisplayDialog("TCP2 : Shader Generation", "You have unsaved changes.\n\nDiscard the changes and load a new shader?", "Yes", "No"); * } * * if(load) * { * //New Shader * if(mConfigChoice == 0) * { * NewShader(); * } * else * { * //Load selected Shader * Shader selectedShader = mUserShaders[mConfigChoice-1]; * mCurrentShader = selectedShader; * LoadCurrentConfigFromShader(mCurrentShader); * } * } * else * { * //Revert choice * mConfigChoice = prevChoice; * } * } * } */ EditorGUIUtility.labelWidth = lW; //Name & Filename TCP2_GUI.Separator(); GUI.enabled = (mCurrentShader == null); EditorGUI.BeginChangeCheck(); mCurrentConfig.ShaderName = EditorGUILayout.TextField(new GUIContent("Shader Name", "Path will indicate how to find the Shader in Unity's drop-down list"), mCurrentConfig.ShaderName); mCurrentConfig.ShaderName = Regex.Replace(mCurrentConfig.ShaderName, @"[^a-zA-Z0-9 _!/]", ""); if (EditorGUI.EndChangeCheck() && sAutoNames) { mCurrentConfig.AutoNames(); } GUI.enabled &= !sAutoNames; EditorGUILayout.BeginHorizontal(); mCurrentConfig.Filename = EditorGUILayout.TextField("File Name", mCurrentConfig.Filename); mCurrentConfig.Filename = Regex.Replace(mCurrentConfig.Filename, @"[^a-zA-Z0-9 _!/]", ""); GUILayout.Label(".shader", GUILayout.Width(50f)); EditorGUILayout.EndHorizontal(); GUI.enabled = sGUIEnabled; Space(); //######################################################################################################## // FEATURES TCP2_GUI.Header("FEATURES"); //Scroll view mScrollPosition = EditorGUILayout.BeginScrollView(mScrollPosition); EditorGUI.BeginChangeCheck(); if (Template.newSystem) { //New UI embedded into Template Template.FeaturesGUI(mCurrentConfig); if (mFirstHashPass) { mCurrentHash = mCurrentConfig.ToHash(); mFirstHashPass = false; } } else { EditorGUILayout.HelpBox("Old template versions aren't supported anymore.", MessageType.Warning); } #if DEBUG_MODE TCP2_GUI.SeparatorBig(); TCP2_GUI.SubHeaderGray("DEBUG MODE"); GUILayout.BeginHorizontal(); mDebugText = EditorGUILayout.TextField("Custom", mDebugText); if (GUILayout.Button("Add Feature", EditorStyles.miniButtonLeft, GUILayout.Width(80f))) { mCurrentConfig.Features.Add(mDebugText); } if (GUILayout.Button("Add Flag", EditorStyles.miniButtonRight, GUILayout.Width(80f))) { mCurrentConfig.Flags.Add(mDebugText); } GUILayout.EndHorizontal(); GUILayout.Label("Features:"); GUILayout.BeginHorizontal(); int count = 0; for (int i = 0; i < mCurrentConfig.Features.Count; i++) { if (count >= 3) { count = 0; GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); } count++; if (GUILayout.Button(mCurrentConfig.Features[i], EditorStyles.toolbarButton, GUILayout.ExpandWidth(false))) { mCurrentConfig.Features.RemoveAt(i); break; } } GUILayout.EndHorizontal(); GUILayout.Label("Flags:"); GUILayout.BeginHorizontal(); count = 0; for (int i = 0; i < mCurrentConfig.Flags.Count; i++) { if (count >= 3) { count = 0; GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); } count++; if (GUILayout.Button(mCurrentConfig.Flags[i], EditorStyles.toolbarButton, GUILayout.ExpandWidth(false))) { mCurrentConfig.Flags.RemoveAt(i); break; } } GUILayout.EndHorizontal(); GUILayout.Label("Keywords:"); GUILayout.BeginHorizontal(); count = 0; foreach (KeyValuePair <string, string> kvp in mCurrentConfig.Keywords) { if (count >= 3) { count = 0; GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); } count++; if (GUILayout.Button(kvp.Key + ":" + kvp.Value, EditorStyles.toolbarButton, GUILayout.ExpandWidth(false))) { mCurrentConfig.Keywords.Remove(kvp.Key); break; } } GUILayout.EndHorizontal(); //---------------------------------------------------------------- Space(); if (mCurrentShader != null) { if (mCurrentShaderImporter == null) { mCurrentShaderImporter = ShaderImporter.GetAtPath(AssetDatabase.GetAssetPath(mCurrentShader)) as ShaderImporter; } if (mCurrentShaderImporter != null && mCurrentShaderImporter.GetShader() == mCurrentShader) { mDebugExpandUserData = EditorGUILayout.Foldout(mDebugExpandUserData, "Shader UserData"); if (mDebugExpandUserData) { string[] userData = mCurrentShaderImporter.userData.Split(','); foreach (var str in userData) { GUILayout.Label(str); } } } } #endif //Update config if (EditorGUI.EndChangeCheck()) { int newHash = mCurrentConfig.ToHash(); if (newHash != mCurrentHash) { mDirtyConfig = true; } else { mDirtyConfig = false; } } //Scroll view EditorGUILayout.EndScrollView(); Space(); //GENERATE EditorGUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); GUI.color = mDirtyConfig ? gColor * unsavedChangesColor : GUI.color; if (GUILayout.Button(mCurrentShader == null ? "Generate Shader" : "Update Shader", GUILayout.Width(120f), GUILayout.Height(30f))) { if (Template == null) { EditorUtility.DisplayDialog("TCP2 : Shader Generation", "Can't generate shader: no Template file defined!\n\nYou most likely want to link the TCP2_User.txt file to the Template field in the Shader Generator.", "Ok"); return; } //Set config type if (Template.templateType != null) { mCurrentConfig.configType = Template.templateType; } //Set config file mCurrentConfig.templateFile = Template.textAsset.name; Shader generatedShader = TCP2_ShaderGeneratorUtils.Compile(mCurrentConfig, mCurrentShader, Template, true, !sOverwriteConfigs); ReloadUserShaders(); if (generatedShader != null) { mDirtyConfig = false; LoadCurrentConfigFromShader(generatedShader); } //Workaround to force the inspector to refresh, so that state is reset. //Needed in case of switching between specular/metallic and related //options, while the inspector is opened, so that it shows/hides the //relevant properties according to the changes. TCP2_MaterialInspector_SurfacePBS_SG.InspectorNeedsUpdate = true; } GUI.color = gColor; EditorGUILayout.EndHorizontal(); TCP2_GUI.Separator(); // OPTIONS TCP2_GUI.Header("OPTIONS"); GUILayout.BeginHorizontal(); sSelectGeneratedShader = GUILayout.Toggle(sSelectGeneratedShader, new GUIContent("Select Generated Shader", "Will select the generated file in the Project view"), GUILayout.Width(180f)); sAutoNames = GUILayout.Toggle(sAutoNames, new GUIContent("Automatic Name", "Will automatically generate the shader filename based on its UI name"), GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); sOverwriteConfigs = GUILayout.Toggle(sOverwriteConfigs, new GUIContent("Always overwrite shaders", "Overwrite shaders when generating/updating (no prompt)"), GUILayout.Width(180f)); sHideDisabled = GUILayout.Toggle(sHideDisabled, new GUIContent("Hide disabled fields", "Hide properties settings when they cannot be accessed"), GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUI.BeginChangeCheck(); TCP2_ShaderGeneratorUtils.CustomOutputDir = GUILayout.Toggle(TCP2_ShaderGeneratorUtils.CustomOutputDir, new GUIContent("Custom Output Directory:", "Will save the generated shaders in a custom directory within the Project"), GUILayout.Width(165f)); GUI.enabled &= TCP2_ShaderGeneratorUtils.CustomOutputDir; if (TCP2_ShaderGeneratorUtils.CustomOutputDir) { TCP2_ShaderGeneratorUtils.OutputPath = EditorGUILayout.TextField("", TCP2_ShaderGeneratorUtils.OutputPath); if (GUILayout.Button("Select...", EditorStyles.miniButton, GUILayout.ExpandWidth(false))) { string outputPath = TCP2_Utils.OpenFolderPanel_ProjectPath("Choose custom output directory for TCP2 generated shaders"); if (!string.IsNullOrEmpty(outputPath)) { TCP2_ShaderGeneratorUtils.OutputPath = outputPath; } } } else { EditorGUILayout.TextField("", TCP2_ShaderGeneratorUtils.OUTPUT_PATH); } if (EditorGUI.EndChangeCheck()) { ReloadUserShaders(); } GUI.enabled = sGUIEnabled; EditorGUILayout.EndHorizontal(); EditorGUI.BeginChangeCheck(); sLoadAllShaders = GUILayout.Toggle(sLoadAllShaders, new GUIContent("Reload Shaders from all Project", "Load shaders from all your Project folders instead of just Toony Colors Pro 2.\nEnable it if you move your generated shader files outside of the default TCP2 Generated folder."), GUILayout.ExpandWidth(false)); if (EditorGUI.EndChangeCheck()) { ReloadUserShaders(); } TCP2_ShaderGeneratorUtils.SelectGeneratedShader = sSelectGeneratedShader; }
//-------------------------------------------------------------------------------------------------- // IO //Save .shader file static private 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 string outputPath = OutputPath; if (existingShader != null) { outputPath = GetExistingShaderPath(config, existingShader); } string systemPath = Application.dataPath + outputPath; if (!Directory.Exists(systemPath)) { Directory.CreateDirectory(systemPath); } string fullPath = systemPath + config.Filename + ".shader"; bool 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) { string directory = Path.GetDirectoryName(systemPath + config.Filename); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } //Write file to disk File.WriteAllText(systemPath + config.Filename + ".shader", sourceCode, System.Text.Encoding.UTF8); AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); //Import (to compile shader) string assetPath = "Assets" + outputPath + 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 List <string> customDataList = new List <string>(); customDataList.Add(!string.IsNullOrEmpty(shaderHash) ? shaderHash : shaderImporter.assetTimeStamp.ToString()); customDataList.Add(config.GetShaderTargetCustomData()); string configTypeCustomData = config.GetConfigTypeCustomData(); if (configTypeCustomData != null) { customDataList.Add(configTypeCustomData); } customDataList.Add(config.GetConfigFileCustomData()); string 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); }
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(); } }
// Create a material instance of a given shader and configure textures and such void CreateMaterial(Shader shader) { string shaderPath = AssetDatabase.GetAssetPath(shader); string shaderDirectory = Path.GetDirectoryName(shaderPath); string shaderParentPath = Path.GetDirectoryName(Path.GetDirectoryName(shaderPath)); string shaderName = shader.name.Substring("Shade/".Length); string materialPath = Path.Combine(shaderParentPath, shaderName); Material material = AssetDatabase.LoadAssetAtPath <Material>(materialPath + ".mat"); if (material == null) { material = new Material(shader); AssetDatabase.CreateAsset(material, materialPath + ".mat"); } material.shader = shader; // Find the Graph.json file for this shader, find any Texture nodes and properly configure the associated material properties for them TextAsset shaderGraphAsset = AssetDatabase.LoadAssetAtPath <TextAsset>(Path.Combine(shaderDirectory, "Graph.json")); ShaderGraph graph = JsonUtility.FromJson <ShaderGraph>(shaderGraphAsset.text); ShaderImporter shaderImporter = ShaderImporter.GetAtPath(shaderPath) as ShaderImporter; string[] textureTypes = { "Texture", "Gradient", "Bake", "Tiler" }; foreach (ShaderNode n in graph.nodes) { if (n.options.userLabel != null) { string lowercaseName = Char.ToLowerInvariant(n.options.userLabel[0]) + n.options.userLabel.Substring(1); string propertyName = "_" + lowercaseName.Replace(" ", ""); if (Array.Exists(textureTypes, element => element == n.name)) { string textureName = n.options.value != null ? n.options.value : n.options.userLabel; Texture2D tex = AssetDatabase.LoadAssetAtPath <Texture2D>(Path.Combine(shaderDirectory, textureName + ".png")); if (tex != null) { material.SetTexture(propertyName, tex); shaderImporter.SetDefaultTextures(new[] { propertyName }, new[] { tex }); string texturePath = AssetDatabase.GetAssetPath(tex); TextureImporter importer = (TextureImporter)AssetImporter.GetAtPath(texturePath); if (n.options.wrapMode != null) { switch (n.options.wrapMode) { case "repeat": importer.wrapMode = TextureWrapMode.Repeat; break; case "clamp": importer.wrapMode = TextureWrapMode.Clamp; break; case "mirror": importer.wrapMode = TextureWrapMode.Mirror; break; } } else { importer.wrapMode = TextureWrapMode.Clamp; } if (n.options.filterMode != null) { switch (n.options.filterMode) { case "point": importer.filterMode = FilterMode.Point; break; case "linear": importer.filterMode = n.options.generateMipmaps ? FilterMode.Trilinear : FilterMode.Bilinear; break; } } importer.textureType = n.options.isNormalMap ? TextureImporterType.NormalMap : TextureImporterType.Default; importer.SaveAndReimport(); } } } } }