//Locate the StylizedWater Substance material in the project private void FindSubstance() { string[] assets = AssetDatabase.FindAssets("t:ProceduralMaterial StylizedWater"); string assetPath = AssetDatabase.GUIDToAssetPath(assets[0]); SubstanceImporter si = AssetImporter.GetAtPath(assetPath) as SubstanceImporter; //Substance .sbsar container ProceduralMaterial[] substanceContainer = si.GetMaterials(); //Look for the substance instance matching the material name we're looking for foreach (ProceduralMaterial substanceInstance in substanceContainer) { if (substanceInstance.name == "StylizedWater") { substance = substanceInstance; //Gotcha si.SetGenerateAllOutputs(substance, true); //Debug.Log("[Stylized Water] Succesfully located \"StylizedWater\" Substance in project."); } } if (!substance) { Debug.LogError("[Stylized Water] The \"StylizedWater\" Substance material could not be located in the project. Was it removed or renamed?"); } }
//Looks for the FAE_WindVectors substance in the project public void FindSubstance() { //Substance already assigned, no need to find it if (windSubstance) { return; } string[] assets = AssetDatabase.FindAssets("t:ProceduralMaterial FAE_WindVectors"); string assetPath = AssetDatabase.GUIDToAssetPath(assets[0]); SubstanceImporter si = AssetImporter.GetAtPath(assetPath) as SubstanceImporter; //Substance .sbsar container ProceduralMaterial[] substanceContainer = si.GetMaterials(); //Look for the substance instance matching the material name we're looking for foreach (ProceduralMaterial substanceInstance in substanceContainer) { if (substanceInstance.name == "FAE_WindVectors") { windSubstance = substanceInstance; //Gotcha GetSubstanceOutput(); } } //Debug.Log("Found substance: " + windSubstance.name); }
public static Material LoadSubstanceMaterialWithName(string materialPath, string substanceName) { Material material = LoadUnityMaterial(materialPath); #if UNITY_2017_4_OR_NEWER || UNITY_2018_1_OR_NEWER Debug.LogErrorFormat("Houdini Engine for Unity does not support the new Substance plugin as of yet!"); #elif UNITY_EDITOR if (material != null) { string assetPath = HEU_AssetDatabase.GetAssetPath(material); SubstanceImporter substanceImporter = AssetImporter.GetAtPath(assetPath) as SubstanceImporter; ProceduralMaterial[] proceduralMaterials = substanceImporter.GetMaterials(); for(int i = 0; i < proceduralMaterials.Length; ++i) { if(proceduralMaterials[i].name.Equals(substanceName)) { material = proceduralMaterials[i]; break; } } } #endif if(material != null) { Debug.LogFormat("Loaded Substance material with name {0} from path {1}.", substanceName, materialPath); } else { Debug.LogWarningFormat("Failed to load Substance material with name {0} from path {1}.", substanceName, materialPath); } return material; }
public static Material LoadSubstanceMaterialWithIndex(string materialPath, int substanceMaterialIndex) { Material material = LoadUnityMaterial(materialPath); #if UNITY_2017_4_OR_NEWER || UNITY_2018_1_OR_NEWER Debug.LogErrorFormat("Houdini Engine for Unity does not support the new Substance plugin as of yet!"); #elif UNITY_EDITOR if (material != null) { string assetPath = HEU_AssetDatabase.GetAssetPath(material); SubstanceImporter substanceImporter = AssetImporter.GetAtPath(assetPath) as SubstanceImporter; if(substanceMaterialIndex >= 0 && substanceMaterialIndex < substanceImporter.GetMaterialCount()) { material = substanceImporter.GetMaterials()[substanceMaterialIndex]; } } #endif if (material != null) { Debug.LogFormat("Loaded Substance material with index {0} from path {1}.", substanceMaterialIndex, materialPath); } else { Debug.LogWarningFormat("Failed to load Substance material with index {0} from path {1}.", substanceMaterialIndex, materialPath); } return material; }
public static Dictionary <string, List <string> > GatherProceduralMaterials() { Dictionary <string, List <string> > materials = new Dictionary <string, List <string> >(); //search for materials foreach (var obj in Selection.objects) { string path = AssetDatabase.GetAssetPath(obj); if (obj is ProceduralMaterial) { if (!materials.Keys.Contains(path)) { materials.Add(path, new List <string>() { obj.name }); } else { if (!materials[path].Contains(obj.name)) { materials[path].Add(obj.name); } } } else if (obj is SubstanceArchive) { SubstanceImporter substanceImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(obj)) as SubstanceImporter; // Get the substance importer to change the settings var importerMats = substanceImporter.GetMaterials(); foreach (var mat in importerMats) { if (!materials.Keys.Contains(path)) { materials.Add(path, new List <string>() { mat.name }); } else { if (!materials[path].Contains(mat.name)) { materials[path].Add(mat.name); } } } } } Debug.Log("Substance Baker : Found " + materials.Count.ToString() + " materials"); return(materials); }
public static void ApplySettings(BakerProfile profile) { var materials = GatherProceduralMaterials(); for (int i = 0; i < materials.Count; i++) { SubstanceImporter substanceImporter = AssetImporter.GetAtPath(materials.ElementAt(i).Key) as SubstanceImporter; // Get the substance importer to change the settings var proceduralMaterials = substanceImporter.GetMaterials(); //Get all the materials within that particular sbsar foreach (ProceduralMaterial proceduralMaterial in proceduralMaterials) //For each procedural material in the sbsar... { if (materials.ElementAt(i).Value.Contains(proceduralMaterial.name)) { ApplySettings(profile, proceduralMaterial, substanceImporter); } } Resources.UnloadUnusedAssets(); } }
void Start() { Assert.IsNotNull(m_TargetGameObject); m_Renderer = m_TargetGameObject.GetComponent <Renderer>(); Assert.IsNotNull(m_Renderer); Object[] obj_array = Resources.LoadAll("SubstanceArch", typeof(UnityEditor.SubstanceArchive)); foreach (Object obj in obj_array) { SubstanceArchive sbs = obj as SubstanceArchive; // https://forum.unity.com/threads/substance-proceduralmaterial-to-material-possible.200767/ string fromPath = AssetDatabase.GetAssetPath(sbs.GetInstanceID()); SubstanceImporter fromImporter = AssetImporter.GetAtPath(fromPath) as SubstanceImporter; int fromMaterialCount = fromImporter.GetMaterialCount(); ProceduralMaterial[] fromMaterials = fromImporter.GetMaterials(); foreach (ProceduralMaterial proc in fromMaterials) { m_ProcMaterialList.Add(proc); } } Debug.Log("m_ProcMaterialArray.Length = " + m_ProcMaterialList.Count); /* * m_ProcMaterialArray = * Resources.FindObjectsOfTypeAll( typeof( ProceduralMaterial ) ) as ProceduralMaterial[]; * Debug.Log( "m_ProcMaterialArray.Length = " + m_ProcMaterialArray.Length ); * foreach ( ProceduralMaterial proc_mat in m_ProcMaterialArray ) * { * Debug.Log( "proc_mat.name = " + proc_mat.name ); * } */ /* * m_Texture = * Resources.Load("ground_rock_face/resources/ground_rock_face_basecolor") as Texture2D; * Debug.Log( "m_Texture.name = " + m_Texture.name ); */ StartCoroutine("ChangeProcMaterial"); }
private void getSubstance(Material mat) { if (mat == null) { Debug.LogError("StylizedWater: No material assigned to MeshRenderer component!"); return; } if (mat.GetTexture("_Shadermap")) { string[] assets; string substanceName = mat.GetTexture("_Shadermap").name.Replace("_shadermap", ""); //eg StylizedWater_frozen_shadermap to StylizedWater_frozen assets = AssetDatabase.FindAssets("t:ProceduralMaterial " + substanceName); string assetPath = AssetDatabase.GUIDToAssetPath(assets[0]); SubstanceImporter si = AssetImporter.GetAtPath(assetPath) as SubstanceImporter; //Substance .sbsar container ProceduralMaterial[] substanceContainer = si.GetMaterials(); //Look for the substance instance matching the material name we're looking for foreach (ProceduralMaterial substanceInstance in substanceContainer) { if (substanceInstance.name == substanceName) { substance = substanceInstance; //Gotcha } } //Debug.Log("Found substance using " + material.name + ". Result: " + substance.name); } else { Debug.LogError("StylizedWater: Shadermap is not assigned to the current material, cannot locate associated Substance without it."); return; } }
public ProceduralMaterial RetrieveProceduralMaterial() { ProceduralMaterial result = null; string[] pathParts = m_ResourcePath.Split('/'); if (pathParts.Length >= 2) { string sbsarRawName = pathParts[pathParts.Length - 2].Replace(".sbsar", ""); string pmRawName = pathParts[pathParts.Length - 1]; string[] foundAssets = AssetDatabase.FindAssets("t:SubstanceArchive " + sbsarRawName); foreach (string sbsarGUID in foundAssets) { string sbsarPath = AssetDatabase.GUIDToAssetPath(sbsarGUID); SubstanceImporter si = AssetImporter.GetAtPath(sbsarPath) as SubstanceImporter; foreach (ProceduralMaterial pm in si.GetMaterials()) { Utils.Log(pm.name); if (result == null) { result = pm; } else if (pm.name == pmRawName) { result = pm; } } } Utils.Log("Trying to find ProceduralMaterial named " + sbsarRawName + "/" + pmRawName + "... " + (result == null ? " not found!" : "found: " + result.name)); } return(result); }
void OnGUI() { if (size == 0) { size = 1; } size = EditorGUILayout.IntField("Substances", size); if (substances == null) { substances = new SubstanceArchive[size]; } if (substances.Length != size) { SubstanceArchive[] cache = substances; substances = new SubstanceArchive[size]; for (int i = 0; i < (cache.Length > size ? size : cache.Length); i++) { substances[i] = cache[i]; } } for (int i = 0; i < size; i++) { substances[i] = EditorGUILayout.ObjectField("Substance " + (i + 1), substances[i], typeof(SubstanceArchive), false) as SubstanceArchive; } if (GUILayout.Button("Extract")) { for (int subs = 0; subs < size; subs++) { SubstanceArchive substance = substances[subs]; if (substance == null) { continue; } string substancePath = AssetDatabase.GetAssetPath(substance.GetInstanceID()); SubstanceImporter substanceImporter = AssetImporter.GetAtPath(substancePath) as SubstanceImporter; int substanceMaterialCount = substanceImporter.GetMaterialCount(); ProceduralMaterial[] substanceMaterials = substanceImporter.GetMaterials(); if (substanceMaterialCount <= 0) { continue; } string basePath = substancePath.Replace("/" + substance.name + ".sbsar", ""); if (!Directory.Exists(basePath + "/" + substance.name)) { AssetDatabase.CreateFolder(basePath, substance.name); AssetDatabase.ImportAsset(basePath + "/" + substance.name); } if (!Directory.Exists("EXPORT_HERE")) { Directory.CreateDirectory("EXPORT_HERE"); } System.Type substanceImporterType = typeof(SubstanceImporter); MethodInfo exportBitmaps = substanceImporterType.GetMethod("ExportBitmaps", BindingFlags.Instance | BindingFlags.Public); if (null == exportBitmaps) { return; } foreach (ProceduralMaterial substanceMaterial in substanceMaterials) { substanceMaterial.isReadable = true;//@zpj bool generateAllOutputs = substanceImporter.GetGenerateAllOutputs(substanceMaterial); if (!Directory.Exists(basePath + "/" + substance.name + "/" + substanceMaterial.name)) { AssetDatabase.CreateFolder(basePath + "/" + substance.name, substanceMaterial.name); AssetDatabase.ImportAsset(basePath + "/" + substance.name + "/" + substanceMaterial.name); } string materialPath = basePath + "/" + substance.name + "/" + substanceMaterial.name + "/"; Material newMaterial = new Material(substanceMaterial.shader); newMaterial.CopyPropertiesFromMaterial(substanceMaterial); AssetDatabase.CreateAsset(newMaterial, materialPath + substanceMaterial.name + ".mat"); AssetDatabase.ImportAsset(materialPath + substanceMaterial.name + ".mat"); substanceImporter.SetGenerateAllOutputs(substanceMaterial, true); exportBitmaps.Invoke(substanceImporter, new object[] { substanceMaterial, @"EXPORT_HERE", false }); if (!generateAllOutputs) { substanceImporter.SetGenerateAllOutputs(substanceMaterial, false); } string[] exportedTextures = Directory.GetFiles("EXPORT_HERE"); if (exportedTextures.Length > 0) { string TmpfilePath = string.Empty; foreach (string exportedTexture in exportedTextures) { TmpfilePath = materialPath + exportedTexture.Replace("EXPORT_HERE", ""); if (File.Exists(TmpfilePath)) { File.Delete(TmpfilePath); //Debug.Log(TmpfilePath); } File.Move(exportedTexture, TmpfilePath); } } AssetDatabase.Refresh(); int propertyCount = ShaderUtil.GetPropertyCount(newMaterial.shader); Texture[] materialTextures = substanceMaterial.GetGeneratedTextures(); if ((materialTextures.Length <= 0) || (propertyCount <= 0)) { continue; } Texture newTmpTexture = new Texture(); foreach (ProceduralTexture materialTexture in materialTextures) { string newTexturePath = materialPath + materialTexture.name + ".tga";// (Clone) string astmpe = Application.dataPath + newTexturePath.Substring(6); if (!File.Exists(astmpe)) { newTexturePath = materialPath + materialTexture.name + " (Clone).tga"; astmpe = Application.dataPath + newTexturePath.Substring(6); if (!File.Exists(astmpe)) { Debug.LogError(newTexturePath + "not exist"); } } Texture newTextureAsset = (Texture)AssetDatabase.LoadAssetAtPath(newTexturePath, typeof(Texture)); if (null != newTextureAsset) { try { for (int i = 0; i < propertyCount; i++) { if (ShaderUtil.GetPropertyType(newMaterial.shader, i) == ShaderUtil.ShaderPropertyType.TexEnv) { string propertyName = ShaderUtil.GetPropertyName(newMaterial.shader, i); newTmpTexture = newMaterial.GetTexture(propertyName); //Debug.Log(newTmpTexture.name + " and " + propertyName + " new assset " + newTextureAsset.name); if (null != newTmpTexture && (newTmpTexture.name == newTextureAsset.name || newTmpTexture.name + " (Clone)" == newTextureAsset.name)) { newMaterial.SetTexture(propertyName, newTextureAsset); } } } } catch (System.Exception ex) { Debug.Log(ex.Message); } } ProceduralOutputType outType = materialTexture.GetProceduralOutputType(); if (materialTexture.GetProceduralOutputType() == ProceduralOutputType.Normal) { TextureImporter textureImporter = AssetImporter.GetAtPath(newTexturePath) as TextureImporter; if (null != textureImporter) { textureImporter.textureType = TextureImporterType.Bump; } AssetDatabase.ImportAsset(newTexturePath); } } } if (Directory.Exists("EXPORT_HERE")) { Directory.Delete("EXPORT_HERE"); } } } }
public static void ExportAllSubstancesInDirectory(string dir) { string unity_assets_path = Application.dataPath; string unity_export_texture_dir = Path.Combine(Path.Combine(unity_assets_path, "Textures"), dir); string overload_editor_root_dir = OverloadLevelConverter.FindEditorRootFolder(); string overload_texture_export_dir = Path.Combine(overload_editor_root_dir, dir + "Textures"); int export_count = 0; string[] files = Directory.GetFiles(unity_export_texture_dir, "*.sbsar", SearchOption.AllDirectories); int total_files = files.Length; int files_processed = 0; try { foreach (string filename in files) { // Get a usable path for LoadAsset string unity_asset_location = Path.Combine("Assets", OverloadLevelEditor.Utility.GetRelativeFilenameFromDirectory(unity_assets_path, filename)).Replace('\\', '/'); // Show progress so far float prog_perc = (float)files_processed / (float)total_files; ++files_processed; if (EditorUtility.DisplayCancelableProgressBar("Exporting Substances", unity_asset_location, prog_perc)) { Debug.LogWarning("User cancelled Substance export"); break; } SubstanceImporter sub_imp = (SubstanceImporter)AssetImporter.GetAtPath(unity_asset_location); int sub_imp_count = sub_imp.GetMaterialCount(); if (sub_imp_count <= 0) { continue; } // In order to call GetPixels32 the material must be set to Raw format and only Raw // Fixup those that need to be fixed, and then restore them back. var materials_to_restore_settings = new Dictionary <string, SubstanceTextureSettings>(); ProceduralMaterial[] proc_mats = sub_imp.GetMaterials(); foreach (ProceduralMaterial proc_mat in proc_mats) { int maxTextureWidth; int maxTextureHeight; int textureFormat; int loadBehavior; bool res = sub_imp.GetPlatformTextureSettings(proc_mat.name, string.Empty, out maxTextureWidth, out maxTextureHeight, out textureFormat, out loadBehavior); if (!res) { Debug.LogError(string.Format("Failed to read platform settings for '{0}'", proc_mat.name)); continue; } if (textureFormat == (int)SubstanceTextureFormat.Raw) { continue; } // Convert to Raw format materials_to_restore_settings.Add(proc_mat.name, new SubstanceTextureSettings() { mat = proc_mat, maxTextureWidth = maxTextureWidth, maxTextureHeight = maxTextureHeight, textureFormat = textureFormat, loadBehavior = loadBehavior }); sub_imp.SetPlatformTextureSettings(proc_mat, string.Empty, maxTextureWidth, maxTextureHeight, (int)SubstanceTextureFormat.Raw, loadBehavior); } if (materials_to_restore_settings.Count != 0) { AssetDatabase.ImportAsset(unity_asset_location); sub_imp = (SubstanceImporter)AssetImporter.GetAtPath(unity_asset_location); proc_mats = sub_imp.GetMaterials(); } try { foreach (ProceduralMaterial proc_mat in proc_mats) { proc_mat.isReadable = true; proc_mat.RebuildTexturesImmediately(); if (proc_mat.isProcessing) { Debug.LogError(string.Format("{0} is still processing", proc_mat.name)); continue; } Texture[] mat_texs = proc_mat.GetGeneratedTextures(); if (mat_texs.Length <= 0) { continue; } string material_name = proc_mat.name; // Only look for the Diffuse texture foreach (ProceduralTexture mat_tex in mat_texs.Where(m => m.name.EndsWith("_Diffuse", System.StringComparison.InvariantCultureIgnoreCase))) { // Copy the texture into a Texture2D, then write that out Texture2D new_tex = new Texture2D(mat_tex.width, mat_tex.height); new_tex.anisoLevel = mat_tex.anisoLevel; new_tex.filterMode = mat_tex.filterMode; new_tex.mipMapBias = mat_tex.mipMapBias; new_tex.wrapMode = mat_tex.wrapMode; Color32[] pixels = mat_tex.GetPixels32(0, 0, mat_tex.width, mat_tex.height); for (int i = 0; i < pixels.Length; i++) { pixels[i].a = 255; } new_tex.SetPixels32(pixels); new_tex.Apply(); // Scale down to 512x512 before final export TextureScale.Bilinear(new_tex, 512, 512); string new_tex_name = Path.Combine(overload_texture_export_dir, material_name + ".png"); File.WriteAllBytes(new_tex_name, new_tex.EncodeToPNG()); export_count += 1; } } } finally { if (materials_to_restore_settings.Count != 0) { // Restore settings foreach (var kvp in materials_to_restore_settings) { //var name = kvp.Key; var settings = kvp.Value; sub_imp.SetPlatformTextureSettings(settings.mat, string.Empty, settings.maxTextureWidth, settings.maxTextureHeight, settings.textureFormat, settings.loadBehavior); } AssetDatabase.ImportAsset(unity_asset_location); } } } } finally { EditorUtility.ClearProgressBar(); Debug.Log("Finished exporting " + export_count.ToString() + " diffuse textures to " + overload_texture_export_dir); } }
private void PickMaterials() { TerrainObject to = currentSelect.GetComponent <TerrainObject>(); if (to.material != null && to.material.HasProperty("_Control") && to.material.HasProperty("_Splat0") && to.material.HasProperty("_Splat1")) { EditorGUILayout.Space(); InitPencil(); GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); GUILayout.BeginHorizontal("box", GUILayout.Width(340)); GUILayout.FlexibleSpace(); _selectProcedural = GUILayout.SelectionGrid(_selectProcedural, _textures, 6, "gridlist", GUILayout.Width(340), GUILayout.Height(60)); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.Box(PGUIStyle.BorderColor0, GUILayout.ExpandWidth(true), GUILayout.Height(1)); GUILayout.Label("Add / Replace / Substrances Update", PGUIStyle.nodeLabelBold); EditorGUILayout.BeginVertical(); EditorGUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); GUILayout.BeginHorizontal(GUILayout.Width(340), GUILayout.Height(20)); for (int i = 0; i < 4; i++) { if (to.material.HasProperty("_Splat" + i)) { if (GUILayout.Button(PResourceManager.LoadTexture("Terrain/up.png"), GUILayout.Width(53))) { if (_procedualAdd == null && _materialAdd == null && _procedual != null) { _procedualAdd = _procedual; } if (_procedualAdd != null) { to.material.SetTexture("_Splat" + i, _procedualAdd.GetTexture("_MainTex")); if (to.material.HasProperty("_BumpSpat" + i)) { to.material.SetTexture("_BumpSplat" + i, _procedualAdd.GetTexture("_BumpMap")); } } else if (_materialAdd != null) { to.material.SetTexture("_Splat" + i, _materialAdd); } _selectProcedural = i; _procedualAdd = null; _materialAdd = null; editData.InitSelection(); } } } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.Space(5); GUILayout.Box(PGUIStyle.BorderColor0, GUILayout.ExpandWidth(true), GUILayout.Height(1)); GUILayout.Space(5); string _assetName = AssetDatabase.GetAssetPath(to.material.GetTexture("_Splat" + _selectProcedural)); SubstanceImporter importer = AssetImporter.GetAtPath(_assetName) as SubstanceImporter; if (importer != null) { ProceduralMaterial[] _promats = importer.GetMaterials(); foreach (ProceduralMaterial t in _promats) { if (t.name + "Diffuse" == to.material.GetTexture("_Splat" + _selectProcedural).name) { _procedual = t; } } GUILayout.Space(5); GUILayout.Box(PGUIStyle.BorderColor0, GUILayout.ExpandWidth(true), GUILayout.Height(1)); } else { _procedual = null; } EditorGUILayout.Space(); EditorGUILayout.Space(); GUILayout.Space(5); GUILayout.BeginHorizontal(); GUILayout.Label("Material Type", GUILayout.Width(100)); _materialType = (TerrianMaterialType) EditorGUILayout.EnumPopup("", _materialType, GUILayout.Width(240)); GUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); if (_materialType != TerrianMaterialType.Classic) { GUILayout.Label("Substances to add:"); _materialAdd = null; _procedualAdd = EditorGUILayout.ObjectField(_procedualAdd, typeof(ProceduralMaterial), true, GUILayout.Width(220)) as ProceduralMaterial; } else { GUILayout.Label("Texture to add:"); _procedualAdd = null; _materialAdd = EditorGUILayout.ObjectField(_materialAdd, typeof(Texture2D), true, GUILayout.Width(220)) as Texture; } GUILayout.FlexibleSpace(); EditorGUILayout.EndVertical(); EditorGUILayout.Space(); EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); if (_procedual != null) { GUILayout.Label("Modify", PGUIStyle.nodeLabelBold); EditorGUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); _scrollPos = EditorGUILayout.BeginScrollView(_scrollPos, GUILayout.Width(350), GUILayout.Height(296)); Substance(); EditorGUILayout.EndScrollView(); GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); } else { ClassicMaterial(); } } else { GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); GUILayout.Label("Please, select the Pure Terrain Object", PGUIStyle.nodeLabelBold); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); } }