public static void CreateDecalPrefab(string materialPath, Material decalMaterial, float size) { #if HDRP string assetPath = materialPath.Substring(0, materialPath.IndexOf("/Materials/")); string materialName = Path.GetFileName(materialPath); string prefabName = materialName.Replace(".mat", ""); string prefabPath = MegascansUtilities.ValidateFolderCreate(assetPath, "Prefabs"); GameObject g = new GameObject(); g.AddComponent <UnityEngine.Experimental.Rendering.HDPipeline.DecalProjectorComponent>(); g.name = prefabName; UnityEngine.Experimental.Rendering.HDPipeline.DecalProjectorComponent decalProjector = g.GetComponent <UnityEngine.Experimental.Rendering.HDPipeline.DecalProjectorComponent>(); decalProjector.material = decalMaterial; #if UNITY_2018_3 || UNITY_2019 decalProjector.size = new Vector3(size, size, size); #endif string finalName = prefabPath + "/" + prefabName + "_Decal" + ".prefab"; UnityEngine.Object pf = null; try { pf = AssetDatabase.LoadAssetAtPath(finalName, typeof(UnityEngine.Object)); } catch (Exception ex) { Debug.Log("Error verifying prefab."); Debug.Log(ex); } if (!pf) { PrefabUtility.CreatePrefab(finalName, g); } else { PrefabUtility.ReplacePrefab(g, pf, ReplacePrefabOptions.ReplaceNameBased); } DestroyImmediate(g); #endif }
public static Material CreateMaterial(string mPath, string name, string shaderName) { string path = MegascansUtilities.FixPath(mPath); /// Unity doesn't allow you to create objects in directories which don't exist. /// So in this function, we create any and all necessary subdirectories that are required. /// We return the final subdirectory, which is used later in the asset creation too. //first, create the user specified path from the importer settings. string[] pathParts = MegascansUtilities.FixSlashes(path).Split('/'); string defPath = "Assets"; if (pathParts.Length > 0) { for (int i = 0; i < pathParts.Length; ++i) { defPath = MegascansUtilities.ValidateFolderCreate(defPath, pathParts[i]); } } defPath = defPath + "/" + name + ".mat"; Material terrainMaterial = new Material(Shader.Find(shaderName)); AssetDatabase.CreateAsset(terrainMaterial, defPath); AssetDatabase.Refresh(); return(terrainMaterial); }
void ProcessTextures(JObject objectList) { texPath = MegascansUtilities.ValidateFolderCreate(path, "Textures"); matPath = Path.Combine(MegascansUtilities.ValidateFolderCreate(path, "Materials"), folderNamingConvention); if (!(plant && hasBillboardLODOnly)) { MegascansUtilities.UpdateProgressBar(1.0f, "Processing Asset " + assetName, "Creating material..."); finalMat = MegascansMaterialUtils.CreateMaterial(shaderType, matPath, isAlembic, dispType, texPack); ImportAllTextures(finalMat, (JArray)objectList["components"]); ImportAllTextures(finalMat, (JArray)objectList["packedTextures"]); } if (plant && hasBillboardLOD) { texPath = MegascansUtilities.ValidateFolderCreate(texPath, "Billboard"); matPath += "_Billboard"; MegascansUtilities.UpdateProgressBar(1.0f, "Processing Asset " + assetName, "Creating material..."); billboardMat = MegascansMaterialUtils.CreateMaterial(shaderType, matPath, isAlembic, dispType, texPack); ImportAllTextures(billboardMat, (JArray)objectList["components-billboard"]); ImportAllTextures(billboardMat, (JArray)objectList["packed-billboard"]); } }
/// <summary> /// Returns the final directory for our asset, creating subfolders where necessary in the 'Assets' directory. /// </summary> string ConstructPath(JObject objectList) { /// Make sure path is "Assets/...." not "D:/Unity Projects/My Project/Assets/...." otherwise the AssetDatabase cannot write files to it. /// Lastly I also match the path with the Application DataPath in order to make sure this is the right path selected from the Bridge. AssetDatabase.Refresh(); string defPath = ""; bool addNextPathPart = false; if ((string)objectList["exportPath"] != "") { path = (string)objectList["exportPath"]; } else { defPath = "Assets"; addNextPathPart = true; } string[] pathParts = MegascansUtilities.FixSlashes(path).Split('/'); List <string> finalPathParts = new List <string> (); foreach (string part in pathParts) { if (part == "Assets" && !addNextPathPart) { addNextPathPart = true; } if (addNextPathPart) { finalPathParts.Add(part); } } if (!addNextPathPart) { return(null); } //First, create the user specified path from the importer settings. if (finalPathParts.Count > 0) { for (int i = 0; i < finalPathParts.Count; i++) { defPath = MegascansUtilities.ValidateFolderCreate(defPath, finalPathParts[i]); //FixSlashes(Path.Combine(defPath, finalPathParts[i]));//ValidateFolderCreate(defPath, finalPathParts[i]); } } if (!AssetDatabase.IsValidFolder(defPath)) { return(null); } //then create check to see if the asset type subfolder exists, create it if it doesn't. defPath = MegascansUtilities.ValidateFolderCreate(defPath, MegascansUtilities.GetAssetType((string)objectList["path"])); defPath = MegascansUtilities.ValidateFolderCreate(defPath, folderNamingConvention); return(defPath); }
void ImportAllTextures(Material mat, JArray texturesList) { try { List <string> typesOfTexturesAvailable = new List <string>(); for (int i = 0; i < texturesList.Count; i++) { typesOfTexturesAvailable.Add((string)texturesList[i]["type"]); } string destTexPath; Texture2D tex; for (int i = 0; i < texturesList.Count; i++) { mapName = (string)texturesList[i]["type"]; MegascansUtilities.UpdateProgressBar(1.0f, "Processing Asset " + assetName, "Importing texture: " + mapName); if ((string)texturesList[i]["type"] == "albedo" || ((string)texturesList[i]["type"] == "diffuse" && !typesOfTexturesAvailable.Contains("albedo"))) { destTexPath = Path.Combine(texPath, (string)texturesList[i]["nameOverride"]); MegascansTextureProcessor texPrcsr = new MegascansTextureProcessor((string)texturesList[i]["path"], destTexPath); tex = texPrcsr.ImportTexture(); mat.SetTexture("_MainTex", tex); mat.SetTexture("_BaseColorMap", tex); if (shaderType == 1) { mat.SetTexture("_BaseMap", tex); mat.SetColor("_BaseColor", Color.white); } if (MegascansUtilities.AlbedoHasOpacity((JObject)texturesList[i]["channelsData"])) { float alphaCutoff = 0.33f; texPrcsr.AdjustAlphaCutoff(); if (shaderType > 0) { mat.SetFloat("_AlphaClip", 1); mat.SetFloat("_Cutoff", 0.1f); mat.SetFloat("_Mode", 1); mat.SetFloat("_Cull", 0); mat.EnableKeyword("_ALPHATEST_ON"); } else { mat.SetInt("_AlphaCutoffEnable", 1); mat.SetFloat("_AlphaCutoff", alphaCutoff); mat.SetInt("_DoubleSidedEnable", 1); mat.SetOverrideTag("RenderType", "TransparentCutout"); mat.SetInt("_ZTestGBuffer", (int)UnityEngine.Rendering.CompareFunction.Equal); mat.SetInt("_CullMode", (int)UnityEngine.Rendering.CullMode.Off); mat.SetInt("_CullModeForward", (int)UnityEngine.Rendering.CullMode.Back); mat.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); mat.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); mat.SetInt("_ZWrite", 1); mat.renderQueue = 2450; mat.SetInt("_ZTestGBuffer", (int)UnityEngine.Rendering.CompareFunction.Equal); mat.EnableKeyword("_ALPHATEST_ON"); mat.EnableKeyword("_DOUBLESIDED_ON"); mat.DisableKeyword("_BLENDMODE_ALPHA"); mat.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); } } } else if ((string)texturesList[i]["type"] == "specular") { if (texPack > 0) { destTexPath = Path.Combine(texPath, (string)texturesList[i]["nameOverride"]); MegascansTextureProcessor texPrcsr = new MegascansTextureProcessor((string)texturesList[i]["path"], destTexPath); tex = texPrcsr.ImportTexture(); mat.SetTexture("_SpecGlossMap", tex); mat.SetTexture("_SpecularColorMap", tex); mat.SetColor("_SpecColor", new UnityEngine.Color(1.0f, 1.0f, 1.0f)); mat.SetColor("_SpecularColor", new UnityEngine.Color(1.0f, 1.0f, 1.0f)); mat.SetFloat("_WorkflowMode", 0); mat.SetFloat("_MaterialID", 4); mat.EnableKeyword("_METALLICSPECGLOSSMAP"); mat.EnableKeyword("_SPECGLOSSMAP"); mat.EnableKeyword("_SPECULAR_SETUP"); mat.EnableKeyword("_SPECULARCOLORMAP"); mat.EnableKeyword("_MATERIAL_FEATURE_SPECULAR_COLOR"); } } else if ((string)texturesList[i]["type"] == "masks") { if (texPack < 1 || shaderType < 1) { destTexPath = Path.Combine(texPath, (string)texturesList[i]["nameOverride"]); MegascansTextureProcessor texPrcsr = new MegascansTextureProcessor((string)texturesList[i]["path"], destTexPath, false, false); tex = texPrcsr.ImportTexture(); mat.SetTexture("_MaskMap", tex); mat.SetTexture("_MetallicGlossMap", tex); mat.EnableKeyword("_MASKMAP"); mat.SetFloat("_MaterialID", 1); mat.EnableKeyword("_METALLICSPECGLOSSMAP"); mat.EnableKeyword("_METALLICGLOSSMAP"); bool hasMetalness; bool hasAO; bool hasGloss; MegascansUtilities.MaskMapComponents((JObject)texturesList[i]["channelsData"], out hasMetalness, out hasAO, out hasGloss); if (!hasMetalness) { mat.SetFloat("_Metallic", 1.0f); } if (hasAO) { mat.SetTexture("_OcclusionMap", tex); mat.EnableKeyword("_OCCLUSIONMAP"); } } } else if ((string)texturesList[i]["type"] == "normal") { string normalMapPath = (string)texturesList[i]["path"]; if (activeLOD == "high" && !normalMapPath.Contains("NormalBump")) { for (int x = 0; x < 10; x++) { string n = normalMapPath.Replace("_LOD" + x.ToString(), "Bump"); if (File.Exists(n)) { normalMapPath = n; break; } } if (normalMapPath.Contains("NormalBump")) { continue; } } destTexPath = Path.Combine(texPath, (string)texturesList[i]["nameOverride"]); MegascansTextureProcessor texPrcsr = new MegascansTextureProcessor(normalMapPath, destTexPath, true, false); tex = texPrcsr.ImportTexture(); mat.SetTexture("_BumpMap", tex); mat.SetTexture("_NormalMap", tex); mat.EnableKeyword("_NORMALMAP_TANGENT_SPACE"); mat.EnableKeyword("_NORMALMAP"); } else if ((string)texturesList[i]["type"] == "ao" && texPack > 0) { destTexPath = Path.Combine(texPath, (string)texturesList[i]["nameOverride"]); MegascansTextureProcessor texPrcsr = new MegascansTextureProcessor((string)texturesList[i]["path"], destTexPath, false, false); tex = texPrcsr.ImportTexture(); mat.SetTexture("_OcclusionMap", tex); mat.EnableKeyword("_OCCLUSIONMAP"); } else if ((string)texturesList[i]["type"] == "displacement") { if (dispType > 0) { destTexPath = Path.Combine(texPath, (string)texturesList[i]["nameOverride"]); MegascansTextureProcessor texPrcsr = new MegascansTextureProcessor((string)texturesList[i]["path"], destTexPath, false, false); tex = texPrcsr.ImportTexture(); mat.SetTexture("_HeightMap", tex); mat.SetTexture("_ParallaxMap", tex); mat.EnableKeyword("_DISPLACEMENT_LOCK_TILING_SCALE"); if (shaderType == 0) { mat.EnableKeyword("_HEIGHTMAP"); } if (dispType == 1) { mat.EnableKeyword("_VERTEX_DISPLACEMENT"); mat.EnableKeyword("_VERTEX_DISPLACEMENT_LOCK_OBJECT_SCALE"); } else if (dispType == 2) { mat.EnableKeyword("_PARALLAXMAP"); mat.EnableKeyword("_PIXEL_DISPLACEMENT"); mat.EnableKeyword("_PIXEL_DISPLACEMENT_LOCK_OBJECT_SCALE"); } } } else if ((string)texturesList[i]["type"] == "translucency") { destTexPath = Path.Combine(texPath, (string)texturesList[i]["nameOverride"]); MegascansTextureProcessor texPrcsr = new MegascansTextureProcessor((string)texturesList[i]["path"], destTexPath); tex = texPrcsr.ImportTexture(); mat.SetTexture("_SubsurfaceMaskMap", tex); mat.EnableKeyword("_SUBSURFACE_MASK_MAP"); mat.SetInt("_DiffusionProfile", 1); mat.SetFloat("_EnableSubsurfaceScattering", 1); if (!typesOfTexturesAvailable.Contains("transmission")) { mat.SetTexture("_ThicknessMap", tex); mat.EnableKeyword("_THICKNESSMAP"); } if (plant) { mat.SetInt("_DiffusionProfile", 2); mat.SetFloat("_CoatMask", 0.0f); mat.SetInt("_EnableWind", 1); mat.EnableKeyword("_VERTEX_WIND"); } MegascansMaterialUtils.AddSSSSettings(mat, shaderType); } else if ((string)texturesList[i]["type"] == "transmission") { destTexPath = Path.Combine(texPath, (string)texturesList[i]["nameOverride"]); MegascansTextureProcessor texPrcsr = new MegascansTextureProcessor((string)texturesList[i]["path"], destTexPath, false, false); tex = texPrcsr.ImportTexture(); mat.SetTexture("_ThicknessMap", tex); mat.EnableKeyword("_THICKNESSMAP"); mat.SetInt("_DiffusionProfile", 2); MegascansMaterialUtils.AddSSSSettings(mat, shaderType); } else if (importAllTextures) { mapName = (string)texturesList[i]["type"]; string mapPath = (string)texturesList[i]["path"]; string otherTexFolder = MegascansUtilities.ValidateFolderCreate(texPath, "Others"); destTexPath = Path.Combine(otherTexFolder, (string)texturesList[i]["nameOverride"]); MegascansTextureProcessor texPrcsr = new MegascansTextureProcessor(mapPath, destTexPath); tex = texPrcsr.ImportTexture(); } } } catch (Exception ex) { Debug.Log("Exception::MegascansImporter::ImportAllTextures:: " + ex.ToString()); MegascansUtilities.HideProgressBar(); } }
/// <summary> /// Returns the final directory for our asset, creating subfolders where necessary in the 'Assets' directory. /// </summary> /// <param name="jsonPath"></param> /// <returns></returns> string ConstructPath(JObject objectList) { /// /// Unity doesn't allow you to create objects in directories which don't exist. /// So in this function, we create any and all necessary subdirectories that are required. /// We return the final subdirectory, which is used later in the asset creation too. /// A ton of project path validation /// Make sure path is "Assets/...." not "D:/Unity Projects/My Project/Assets/...." otherwise the AssetDatabase cannot write files to it. /// Lastly I also match the path with the Application DataPath in order to make sure this is the right path selected from the Bridge. /// AssetDatabase.Refresh(); string defPath = ""; bool addNextPathPart = false; if ((string)objectList["exportPath"] != "") { path = (string)objectList["exportPath"]; } else { defPath = "Assets"; addNextPathPart = true; } string[] pathParts = MegascansUtilities.FixSlashes(path).Split('/'); List <string> finalPathParts = new List <string> (); foreach (string part in pathParts) { if (part == "Assets" && !addNextPathPart) { addNextPathPart = true; } if (addNextPathPart) { finalPathParts.Add(part); } } if (!addNextPathPart) { return(null); } //First, create the user specified path from the importer settings. if (finalPathParts.Count > 0) { for (int i = 0; i < finalPathParts.Count; i++) { defPath = MegascansUtilities.ValidateFolderCreate(defPath, finalPathParts[i]); //FixSlashes(Path.Combine(defPath, finalPathParts[i]));//ValidateFolderCreate(defPath, finalPathParts[i]); } } if (!AssetDatabase.IsValidFolder(defPath)) { return(null); } //then create check to see if the asset type subfolder exists, create it if it doesn't. defPath = MegascansUtilities.ValidateFolderCreate(defPath, MegascansUtilities.GetAssetType((string)objectList["path"])); GetAssetFolderName(objectList); string finalFolderName = finalName.Replace("$mapName", "").Replace("$resolution", "").Replace("$lod", "").Replace("$variation", ""); defPath = MegascansUtilities.ValidateFolderCreate(defPath, finalFolderName); return(defPath); }
/// <summary> /// Process textures from Megascans asset import. /// </summary> /// <param name="textureComponents"></param> /// <returns></returns> void ProcessTextures(JArray textureComponents) { //create a subdirectory for textures. texPath = MegascansUtilities.ValidateFolderCreate(path, "Textures"); texPath += "/" + finalName.Replace(" ", "_").Replace("$lod", "").Replace("$variation", "").Replace("$resolution", assetResolution); matPath = MegascansUtilities.ValidateFolderCreate(path, "Materials"); matPath += "/" + finalName.Replace(" ", "_").Replace("$mapName", "").Replace("$resolution", "").Replace("$lod", "").Replace("$variation", ""); //Attempt to store all the paths we might need to get our textures. //It's quicker to do this, than create an array and loop through it continually using a lot of if-statements later on. string albedo = null; string opacity = null; string normals = null; string metallic = null; string specular = null; string AO = null; string gloss = null; string displacement = null; string roughness = null; string translucency = null; //Search the JSON array for each texture type, leave it null if it doesn't exist. This is important as we use the null check later. for (int i = 0; i < textureComponents.Count; ++i) { albedo = (string)textureComponents[i]["type"] == "albedo" ? (string)textureComponents[i]["path"] : albedo; albedo = (albedo == null && (string)textureComponents[i]["type"] == "diffuse") ? (string)textureComponents[i]["path"] : albedo; opacity = (string)textureComponents[i]["type"] == "opacity" ? (string)textureComponents[i]["path"] : opacity; normals = (string)textureComponents[i]["type"] == "normal" ? (string)textureComponents[i]["path"] : normals; metallic = (string)textureComponents[i]["type"] == "metalness" ? (string)textureComponents[i]["path"] : metallic; specular = (string)textureComponents[i]["type"] == "specular" ? (string)textureComponents[i]["path"] : specular; AO = (string)textureComponents[i]["type"] == "ao" ? (string)textureComponents[i]["path"] : AO; gloss = (string)textureComponents[i]["type"] == "gloss" ? (string)textureComponents[i]["path"] : gloss; displacement = (string)textureComponents[i]["type"] == "displacement" ? (string)textureComponents[i]["path"] : displacement; roughness = (string)textureComponents[i]["type"] == "roughness" ? (string)textureComponents[i]["path"] : roughness; translucency = (string)textureComponents[i]["type"] == "translucency" ? (string)textureComponents[i]["path"] : translucency; } //make sure we never try to import the high poly normalmap... if (normals != null) { for (int i = 0; i < 6; ++i) { string ld = "_LOD" + i.ToString(); string n = normals.Replace("Bump", ld); if (File.Exists(n)) { normals = n; break; } } } if (!(assetType > 1 && plant && hasBillboardLODOnly)) { finalMat = ReadWriteAllTextures(albedo, opacity, normals, metallic, specular, AO, gloss, displacement, roughness, translucency); } if (assetType > 1 && plant && hasBillboardLOD) { #if UNITY_EDITOR_WIN string[] pathParts = albedo.Split('\\'); #endif #if UNITY_EDITOR_OSX string[] pathParts = albedo.Split('/'); #endif string[] nameParts = pathParts[pathParts.Length - 1].Split('_'); albedo = albedo == null ? null : albedo.Replace("Atlas", "Billboard").Replace(nameParts[0], "Billboard"); opacity = opacity == null ? null : opacity.Replace("Atlas", "Billboard").Replace(nameParts[0], "Billboard"); normals = normals == null ? null : normals.Replace("Atlas", "Billboard").Replace(nameParts[0], "Billboard"); metallic = metallic == null ? null : metallic.Replace("Atlas", "Billboard").Replace(nameParts[0], "Billboard"); specular = specular == null ? null : specular.Replace("Atlas", "Billboard").Replace(nameParts[0], "Billboard"); AO = AO == null ? null : AO.Replace("Atlas", "Billboard").Replace(nameParts[0], "Billboard"); gloss = gloss == null ? null : gloss.Replace("Atlas", "Billboard").Replace(nameParts[0], "Billboard"); displacement = displacement == null ? null : displacement.Replace("Atlas", "Billboard").Replace(nameParts[0], "Billboard"); roughness = roughness == null ? null : roughness.Replace("Atlas", "Billboard").Replace(nameParts[0], "Billboard"); translucency = translucency == null ? null : translucency.Replace("Atlas", "Billboard").Replace(nameParts[0], "Billboard"); texPath = MegascansUtilities.FixSpaces(new string[] { texPath, "Billboard" }); matPath = MegascansUtilities.FixSpaces(new string[] { matPath, "Billboard" }); billboardMat = ReadWriteAllTextures(albedo, opacity, normals, metallic, specular, AO, gloss, displacement, roughness, translucency); } }
/// <summary> /// Process textures from Megascans asset import. /// </summary> /// <param name="textureComponents"></param> /// <returns></returns> void ProcessTextures(JArray textureComponents, JArray texBBData) { //create a subdirectory for textures. string tempTexName = finalName.Replace(" ", "_").Replace("$lod", "").Replace("$variation", "").Replace("$resolution", assetResolution); texPath = Path.Combine(MegascansUtilities.ValidateFolderCreate(path, "Textures"), tempTexName); string tempMatName = finalName.Replace(" ", "_").Replace("$mapName", "").Replace("$resolution", "").Replace("$lod", "").Replace("$variation", ""); matPath = Path.Combine(MegascansUtilities.ValidateFolderCreate(path, "Materials"), tempMatName); //Attempt to store all the paths we might need to get our textures. //It's quicker to do this, than create an array and loop through it continually using a lot of if-statements later on. string albedo = null; string opacity = null; string normals = null; string metallic = null; string specular = null; string AO = null; string gloss = null; string displacement = null; string roughness = null; string translucency = null; string transmission = null; //Search the JSON array for each texture type, leave it null if it doesn't exist. This is important as we use the null check later. for (int i = 0; i < textureComponents.Count; ++i) { albedo = (string)textureComponents[i]["type"] == "albedo" ? (string)textureComponents[i]["path"] : albedo; albedo = (albedo == null && (string)textureComponents[i]["type"] == "diffuse") ? (string)textureComponents[i]["path"] : albedo; opacity = (string)textureComponents[i]["type"] == "opacity" ? (string)textureComponents[i]["path"] : opacity; normals = (string)textureComponents[i]["type"] == "normal" ? (string)textureComponents[i]["path"] : normals; metallic = (string)textureComponents[i]["type"] == "metalness" ? (string)textureComponents[i]["path"] : metallic; specular = (string)textureComponents[i]["type"] == "specular" ? (string)textureComponents[i]["path"] : specular; AO = (string)textureComponents[i]["type"] == "ao" ? (string)textureComponents[i]["path"] : AO; gloss = (string)textureComponents[i]["type"] == "gloss" ? (string)textureComponents[i]["path"] : gloss; displacement = (string)textureComponents[i]["type"] == "displacement" ? (string)textureComponents[i]["path"] : displacement; roughness = (string)textureComponents[i]["type"] == "roughness" ? (string)textureComponents[i]["path"] : roughness; translucency = (string)textureComponents[i]["type"] == "translucency" ? (string)textureComponents[i]["path"] : translucency; transmission = (string)textureComponents[i]["type"] == "transmission" ? (string)textureComponents[i]["path"] : transmission; } //make sure we never try to import the high poly normalmap... if (normals != null) { for (int i = 0; i < 6; ++i) { string ld = "_LOD" + i.ToString(); string n = normals.Replace("Bump", ld); if (File.Exists(n)) { normals = n; break; } } } if (!(assetType > 1 && plant && hasBillboardLODOnly)) { finalMat = ReadWriteAllTextures(albedo, opacity, normals, metallic, specular, AO, gloss, displacement, roughness, translucency, transmission); } if (importAllTextures) { for (int i = 0; i < textureComponents.Count; ++i) { string type = (string)textureComponents[i]["type"]; if (!importedTextures.Contains(type)) { ImportTexture(type, (string)textureComponents[i]["path"]); } } } if (assetType > 1 && plant && hasBillboardLOD) { //Search the JSON array for each texture type, leave it null if it doesn't exist. This is important as we use the null check later. for (int i = 0; i < texBBData.Count; ++i) { albedo = (string)texBBData[i]["type"] == "albedo" ? (string)texBBData[i]["path"] : albedo; albedo = (albedo == null && (string)texBBData[i]["type"] == "diffuse") ? (string)texBBData[i]["path"] : albedo; opacity = (string)texBBData[i]["type"] == "opacity" ? (string)texBBData[i]["path"] : opacity; normals = (string)texBBData[i]["type"] == "normal" ? (string)texBBData[i]["path"] : normals; metallic = (string)texBBData[i]["type"] == "metalness" ? (string)texBBData[i]["path"] : metallic; specular = (string)texBBData[i]["type"] == "specular" ? (string)texBBData[i]["path"] : specular; AO = (string)texBBData[i]["type"] == "ao" ? (string)texBBData[i]["path"] : AO; gloss = (string)texBBData[i]["type"] == "gloss" ? (string)texBBData[i]["path"] : gloss; displacement = (string)texBBData[i]["type"] == "displacement" ? (string)texBBData[i]["path"] : displacement; roughness = (string)texBBData[i]["type"] == "roughness" ? (string)texBBData[i]["path"] : roughness; translucency = (string)texBBData[i]["type"] == "translucency" ? (string)texBBData[i]["path"] : translucency; transmission = (string)texBBData[i]["type"] == "transmission" ? (string)texBBData[i]["path"] : transmission; } texPath = MegascansUtilities.FixSpaces(new string[] { texPath, "Billboard" }); matPath = MegascansUtilities.FixSpaces(new string[] { matPath, "Billboard" }); billboardMat = ReadWriteAllTextures(albedo, opacity, normals, metallic, specular, AO, gloss, displacement, roughness, translucency, transmission); if (importAllTextures) { for (int i = 0; i < texBBData.Count; ++i) { string type = (string)texBBData[i]["type"]; if (!importedTextures.Contains(type)) { ImportTexture(type, (string)texBBData[i]["path"]); } } } } }
/// <summary> /// Creates prefabs for the 3D Scatter assets. /// </summary> /// <param name="hasBillboard"></param> /// <returns></returns> public static void CreatePrefabsScatter(PrefabData prefabData) { try { string prefabPath = MegascansUtilities.ValidateFolderCreate(prefabData.assetPath, "Prefabs"); int numberOfVariations = MegascansUtilities.GetMeshChildrenCount(prefabData.importedGeometryPaths3D); List <GameObject> prefabObjects = new List <GameObject>(); for (int i = 0; i < numberOfVariations; i++) { string prefabName = prefabData.finalAssetName.Replace("$mapName", "").Replace("$resolution", "").Replace("$lod", "").Replace("$variation", ""); string varName = "Var" + (i + 1).ToString(); prefabName = prefabName.Contains("$variation") ? prefabName.Replace("$variation", "Var" + varName) : prefabName + varName; //Setting up prefab gameobject GameObject prefabGameObject = new GameObject(); prefabGameObject.name = prefabName; prefabGameObject.isStatic = true; if (prefabData.setupLODs) { prefabGameObject.AddComponent <LODGroup>(); prefabGameObject.GetComponent <LODGroup>().fadeMode = (LODFadeMode)prefabData.lodFadeMode; //Casting lod fade mode to enum. prefabGameObject.GetComponent <LODGroup>().animateCrossFading = true; } List <LOD> lodsForPrefab = new List <LOD>(); int numberOfFiles = prefabData.importedGeometryPaths3D.Count; List <float> lodHeights = MegascansUtilities.getLODHeightList(numberOfFiles); //Instantiate all the meshes in the scene, add them to the material/collider to them. for (int x = 0; (x < numberOfFiles && x < 8); x++) { UnityEngine.Object loadedGeometry = AssetDatabase.LoadAssetAtPath <UnityEngine.Object>(prefabData.importedGeometryPaths3D[x]); //Highpoly mesh check. if (loadedGeometry.name.ToLower().Contains("highpoly") && !prefabData.highpoly) { continue; } GameObject geometryObject = Instantiate(loadedGeometry) as GameObject; Renderer[] r; if (prefabData.isAlembic) //if the instantiated mesh is an alembic asset. { //Get all variations in a LOD List <Transform> varsInLOD = new List <Transform>(); foreach (Transform var in geometryObject.transform) { varsInLOD.Add(var); } //Delete all the other variations in the LOD object for (int y = 0; y < varsInLOD.Count; y++) { //If variation does not match one currently being processed. if (y != i) { DestroyImmediate(varsInLOD[y].gameObject); } } //Parent the child gameobject (geometry) to the prefab game object. geometryObject.transform.parent = prefabGameObject.transform; geometryObject.transform.localPosition = Vector3.zero; geometryObject.name = geometryObject.name.Replace("(Clone)", ""); r = geometryObject.GetComponentsInChildren <Renderer>(); } else//if the instantiated mesh is a scatter type asset. { //Get all variations in a LOD List <Transform> varsInLOD = new List <Transform>(); foreach (Transform var in geometryObject.transform) { varsInLOD.Add(var); } //Delete all the other variations in the LOD object for (int y = 0; y < varsInLOD.Count; y++) { //If variation does not match one currently being processed. if (y != i) { DestroyImmediate(varsInLOD[y].gameObject); } } //Parent the child gameobject (geometry) to the prefab game object. geometryObject.transform.parent = prefabGameObject.transform; geometryObject.transform.localPosition = Vector3.zero; geometryObject.name = geometryObject.name.Replace("(Clone)", ""); r = geometryObject.GetComponentsInChildren <Renderer>(); } foreach (Renderer ren in r) { ren.material = prefabData.finalMat; //Apply highpoly material if the mesh was highpoly and highpoly filter is enabled. if (loadedGeometry.name.ToLower().Contains("highpoly") && prefabData.highpoly) { ren.material = prefabData.highpolyMat; #if UNITY_EDITOR_OSX ren.material = prefabData.finalMat; #endif } //Apply collision if (prefabData.setupCollision) { ren.gameObject.AddComponent <MeshCollider>().sharedMesh = ren.gameObject.GetComponent <MeshFilter>().sharedMesh; } } if (prefabData.setupLODs) { lodsForPrefab.Add(new LOD(lodHeights[0], r)); lodHeights.RemoveAt(0); } else { break; } } //Set LODs in the LOD group if (prefabData.setupLODs) { prefabGameObject.GetComponent <LODGroup>().SetLODs(lodsForPrefab.ToArray()); prefabGameObject.GetComponent <LODGroup>().RecalculateBounds(); } //Prefab saving string prefLocation = prefabPath + "/" + prefabName + ".prefab"; prefLocation = prefLocation.Replace("(Clone)", ""); GameObject prefabObject = SavePrefab(prefabGameObject, prefLocation, prefabData.addAssetToScene); if (prefabObject) { prefabObjects.Add(prefabObject); } } //Setting up variation holder gameobject GameObject scatterParent = new GameObject(prefabData.assetName); scatterParent.isStatic = true; foreach (GameObject variation in prefabObjects) { variation.transform.parent = scatterParent.transform; } } catch (Exception ex) { Debug.Log("Exception::MegascansMeshUtils::3D Asset Prefab:: " + ex.ToString()); MegascansUtilities.HideProgressBar(); } }
/// <summary> /// Creates prefabs from the newer assets on bridge, has an option for billboard materials on plants. /// </summary> /// <param name="hasBillboard"></param> /// <returns></returns> public static void CreatePrefab3DPlant(PrefabData prefabData) { try { string prefabPath = MegascansUtilities.ValidateFolderCreate(prefabData.assetPath, "Prefabs"); string tempPrefabName = prefabData.finalAssetName.Replace("$mapName", "").Replace("$resolution", "").Replace("$lod", ""); List <GameObject> prefabObjects = new List <GameObject>(); for (int i = 0; i < prefabData.importedGeometryPaths3DPlant.Count; i++) { string variation = "Var" + (i + 1).ToString(); string prefabName = tempPrefabName.Contains("$variation") ? tempPrefabName.Replace("$variation", variation) : tempPrefabName + "_" + variation; //Prefab saving //Setting up prefab gameobject GameObject prefabGameObject = new GameObject(); prefabGameObject.name = prefabName; prefabGameObject.isStatic = true; if (prefabData.setupLODs) { prefabGameObject.AddComponent <LODGroup>(); prefabGameObject.GetComponent <LODGroup>().fadeMode = (LODFadeMode)prefabData.lodFadeMode; //Casting lod fade mode to enum. prefabGameObject.GetComponent <LODGroup>().animateCrossFading = true; } List <LOD> lodsForPrefab = new List <LOD>(); int numberOfFiles = prefabData.importedGeometryPaths3DPlant[i].Count; List <float> lodHeights = MegascansUtilities.getLODHeightList(numberOfFiles); //Instantiate all the meshes in the scene, add them to the material/collider to them. for (int x = 0; (x < numberOfFiles && x < 8); x++) { UnityEngine.Object loadedGeometry = AssetDatabase.LoadAssetAtPath <UnityEngine.Object>(prefabData.importedGeometryPaths3DPlant[i][x]); //Highpoly mesh check. if (loadedGeometry.name.ToLower().Contains("highpoly") && !prefabData.highpoly) { continue; } GameObject geometryObject = Instantiate(loadedGeometry) as GameObject; Renderer[] r; //Parent all the objects to the prefab game object. if (geometryObject.transform.childCount > 0 && !prefabData.isAlembic) { r = new Renderer[geometryObject.transform.childCount]; for (int j = 0; j < geometryObject.transform.childCount; ++j) { //Parent the child gameobject (geometry) to the prefab game object. GameObject geometryChildObject = geometryObject.transform.GetChild(j).gameObject; //Cache a reference to the child gameobject of the geometry. geometryChildObject.transform.parent = prefabGameObject.transform; geometryChildObject.transform.localPosition = Vector3.zero; geometryChildObject.name = geometryChildObject.name.Replace("(Clone)", ""); r[j] = geometryChildObject.GetComponent <Renderer>(); } //Destroy the empty parent container which was holding the meshes. DestroyImmediate(geometryObject); } else if (prefabData.isAlembic) //if the instantiated mesh is an alembic asset. { //Parent the child gameobject (geometry) to the prefab game object. geometryObject.transform.parent = prefabGameObject.transform; geometryObject.transform.localPosition = Vector3.zero; geometryObject.name = geometryObject.name.Replace("(Clone)", ""); r = geometryObject.GetComponentsInChildren <Renderer>(); } else //if the instantiated mesh does not have any children { r = new Renderer[1]; //Parent the child gameobject (geometry) to the prefab game object. geometryObject.transform.parent = prefabGameObject.transform; geometryObject.transform.localPosition = Vector3.zero; geometryObject.name = geometryObject.name.Replace("(Clone)", ""); r[0] = geometryObject.GetComponent <Renderer>(); } foreach (Renderer ren in r) { ren.material = prefabData.finalMat; //Apply highpoly material if the mesh was highpoly and highpoly filter is enabled. if (loadedGeometry.name.ToLower().Contains("highpoly") && prefabData.highpoly) { ren.material = prefabData.highpolyMat; #if UNITY_EDITOR_OSX ren.material = prefabData.finalMat; #endif } //Billboard material application if (prefabData.hasBillboardLOD && x == (numberOfFiles - 1)) { ren.material = prefabData.billboardMat; } //Apply collision if (prefabData.setupCollision) { ren.gameObject.AddComponent <MeshCollider>().sharedMesh = ren.gameObject.GetComponent <MeshFilter>().sharedMesh; } } if (prefabData.setupLODs) { lodsForPrefab.Add(new LOD(lodHeights[0], r)); lodHeights.RemoveAt(0); } else { break; } } //Set LODs in the LOD group if (prefabData.setupLODs) { prefabGameObject.GetComponent <LODGroup>().SetLODs(lodsForPrefab.ToArray()); prefabGameObject.GetComponent <LODGroup>().RecalculateBounds(); } //Prefab saving string prefLocation = prefabPath + "/" + prefabName + ".prefab"; prefLocation = prefLocation.Replace("(Clone)", ""); GameObject prefabObject = SavePrefab(prefabGameObject, prefLocation, prefabData.addAssetToScene); if (prefabObject) { prefabObjects.Add(prefabObject); } } //Setting up variation holder gameobject GameObject plantsParent = new GameObject(prefabData.assetName); plantsParent.isStatic = true; foreach (GameObject variation in prefabObjects) { variation.transform.parent = plantsParent.transform; } } catch (Exception ex) { Debug.Log("Exception::MegascansMeshUtils::3D Plant Prefab:: " + ex.ToString()); MegascansUtilities.HideProgressBar(); } }
/// <summary> /// Import meshes, start from highest LOD and import the chain. /// </summary> public static void ProcessMeshes(JObject assetJson, string assetFolderPath, bool highpoly, bool hasVariations, PrefabData prefabData) { try { bool createPrefabs = EditorPrefs.GetBool("QuixelDefaultSetupPrefabs", true); bool importLODs = EditorPrefs.GetBool("QuixelDefaultImportLODs", true); bool setupLODs = EditorPrefs.GetBool("QuixelDefaultSetupLOD", true); prefabData.setupLODs = (importLODs && setupLODs); //Only do LOD setup if lower lods were imported and LOD grouping is enabled. //get mesh components from the current object. Also, meshComps.Count can give us the number of variations ;) JArray meshComps = (JArray)assetJson["meshList"]; JArray lodList = (JArray)assetJson["lodList"]; string activeLOD = (string)assetJson["activeLOD"]; string minLOD = (string)assetJson["minLOD"]; string modelsFolderPath = MegascansUtilities.ValidateFolderCreate(assetFolderPath, "Models"); if (hasVariations) { List <List <string> > importedGeometryPaths3DPlant = new List <List <string> >(); for (int i = 1; i <= meshComps.Count; i++) { List <string> importedGeometryPaths = new List <string>(); bool lodMatched = false; // This flag helps to import the lower lods once the active lod is found. foreach (JObject mesh in lodList) { if ((int)mesh["variation"] == i) { string currentLOD = (string)mesh["lod"]; if (lodMatched || currentLOD == activeLOD || highpoly) { lodMatched = true; if ((currentLOD == "high") && !highpoly) { continue; } //get the path of the highest LOD to be imported. string sourcePath = (string)mesh["path"]; string destPath = Path.Combine(modelsFolderPath, (string)mesh["nameOverride"]); ImportMesh(sourcePath, destPath); importedGeometryPaths.Add(destPath); if (!importLODs) { break; } } } } importedGeometryPaths3DPlant.Add(importedGeometryPaths); } prefabData.importedGeometryPaths3DPlant = importedGeometryPaths3DPlant; if (createPrefabs) { CreatePrefab3DPlant(prefabData); } } else { List <string> importedGeometryPaths3D = new List <string>(); bool lodMatched = false; // This flag helps to import the lower lods once the active lod is found. foreach (JObject mesh in lodList) { string currentLOD = (string)mesh["lod"]; if (lodMatched || (currentLOD == activeLOD) || highpoly) { lodMatched = true; if ((currentLOD == "high") && !highpoly) { continue; } //get the path of the highest LOD to be imported. string sourcePath = (string)mesh["path"]; string destPath = Path.Combine(modelsFolderPath, (string)mesh["nameOverride"]); ImportMesh(sourcePath, destPath); importedGeometryPaths3D.Add(destPath); if (!importLODs) { break; } } } prefabData.importedGeometryPaths3D = importedGeometryPaths3D; if (createPrefabs) { if (MegascansUtilities.isScatterAsset(assetJson, importedGeometryPaths3D)) { CreatePrefabsScatter(prefabData); } else { CreatePrefab3D(prefabData); } } } } catch (Exception ex) { Debug.Log("Exception::MegascansMeshUtils::Processing Meshes:: " + ex.ToString()); MegascansUtilities.HideProgressBar(); } }
/// <summary> /// Generates prefabs from imported meshes. /// Used for normal 3D assets /// </summary> public static void CreatePrefab3D(PrefabData prefabData) { try { string prefabPath = MegascansUtilities.ValidateFolderCreate(prefabData.assetPath, "Prefabs"); string prefabName = prefabData.modelNamingConvention; //Setting up prefab gameobject GameObject prefabGameObject = new GameObject(); prefabGameObject.name = prefabName; prefabGameObject.isStatic = true; if (prefabData.setupLODs) { prefabGameObject.AddComponent <LODGroup>(); prefabGameObject.GetComponent <LODGroup>().fadeMode = (LODFadeMode)prefabData.lodFadeMode; //Casting lod fade mode to enum. prefabGameObject.GetComponent <LODGroup>().animateCrossFading = true; } List <LOD> lodsForPrefab = new List <LOD>(); int numberOfFiles = prefabData.importedGeometryPaths3D.Count; List <float> lodHeights = MegascansUtilities.getLODHeightList(numberOfFiles); //Instantiate all the meshes in the scene, add them to the material/collider to them. for (int x = 0; (x < numberOfFiles && x < 8); x++) { UnityEngine.Object loadedGeometry = AssetDatabase.LoadAssetAtPath <UnityEngine.Object>(prefabData.importedGeometryPaths3D[x]); //Highpoly mesh check. if (loadedGeometry.name.ToLower().Contains("highpoly") && !prefabData.highpoly) { continue; } GameObject geometryObject = Instantiate(loadedGeometry) as GameObject; Renderer[] r; //Parent all the objects to the prefab game object. if (geometryObject.transform.childCount > 0 && !prefabData.isAlembic) { r = new Renderer[geometryObject.transform.childCount]; for (int j = 0; j < geometryObject.transform.childCount; ++j) { //Parent the child gameobject (geometry) to the prefab game object. GameObject geometryChildObject = geometryObject.transform.GetChild(j).gameObject; //Cache a reference to the child gameobject of the geometry. geometryChildObject.transform.parent = prefabGameObject.transform; geometryChildObject.transform.localPosition = Vector3.zero; geometryChildObject.name = geometryChildObject.name.Replace("(Clone)", ""); r[j] = geometryChildObject.GetComponentInChildren <Renderer>(); } //Destroy the empty parent container which was holding the meshes. DestroyImmediate(geometryObject); } else if (prefabData.isAlembic) //if the instantiated mesh is an alembic asset. { //Parent the child gameobject (geometry) to the prefab game object. geometryObject.transform.parent = prefabGameObject.transform; geometryObject.transform.localPosition = Vector3.zero; geometryObject.name = geometryObject.name.Replace("(Clone)", ""); r = geometryObject.GetComponentsInChildren <Renderer>(); } else //if the instantiated mesh does not have any children { //Parent the child gameobject (geometry) to the prefab game object. geometryObject.transform.parent = prefabGameObject.transform; geometryObject.transform.localPosition = Vector3.zero; geometryObject.name = geometryObject.name.Replace("(Clone)", ""); r = geometryObject.GetComponentsInChildren <Renderer>(); } foreach (Renderer ren in r) { ren.material = prefabData.finalMat; //Apply collision if (prefabData.setupCollision) { ren.gameObject.AddComponent <MeshCollider>().sharedMesh = ren.gameObject.GetComponent <MeshFilter>().sharedMesh; } } if (prefabData.setupLODs) { lodsForPrefab.Add(new LOD(lodHeights[0], r)); lodHeights.RemoveAt(0); } else //We only set the prefab with 1 LOD if setup LODs is unchecked. { break; } } //Set LODs in the LOD group if (prefabData.setupLODs) { prefabGameObject.GetComponent <LODGroup>().SetLODs(lodsForPrefab.ToArray()); prefabGameObject.GetComponent <LODGroup>().RecalculateBounds(); } //Prefab saving string prefLocation = prefabPath + "/" + prefabName + ".prefab"; prefLocation = prefLocation.Replace("(Clone)", ""); SavePrefab(prefabGameObject, prefLocation, prefabData.addAssetToScene); } catch (Exception ex) { Debug.Log("Exception::MegascansMeshUtils::3D Asset Prefab:: " + ex.ToString()); MegascansUtilities.HideProgressBar(); } }
/// <summary> /// Generates prefabs from imported meshes. /// Used for normal 3D assets /// </summary> public static void CreatePrefab3D(PrefabData prefabData) { try { string prefabPath = MegascansUtilities.ValidateFolderCreate(prefabData.assetPath, "Prefabs"); string prefabName = prefabData.finalAssetName.Replace("$mapName", "").Replace("$resolution", "").Replace("$lod", "").Replace("$variation", ""); //Setting up prefab gameobject GameObject prefabGameObject = new GameObject(); prefabGameObject.name = prefabName; prefabGameObject.AddComponent <LODGroup>(); prefabGameObject.GetComponent <LODGroup>().fadeMode = (LODFadeMode)prefabData.lodFadeMode; //Casting lod fade mode to enum. prefabGameObject.GetComponent <LODGroup>().animateCrossFading = true; prefabGameObject.isStatic = true; float lodHeight = 1.0f; List <LOD> lodsForPrefab = new List <LOD>(); int numberOfFiles = prefabData.importedGeometryPaths3D.Count; //Instantiate all the meshes in the scene, add them to the material/collider to them. for (int x = 0; x < numberOfFiles; x++) { UnityEngine.Object loadedGeometry = AssetDatabase.LoadAssetAtPath <UnityEngine.Object>(prefabData.importedGeometryPaths3D[x]); //Highpoly mesh check. if (loadedGeometry.name.ToLower().Contains("highpoly") && !prefabData.highpoly) { continue; } GameObject geometryObject = Instantiate(loadedGeometry) as GameObject; Renderer[] r; //Parent all the objects to the prefab game object. if (geometryObject.transform.childCount > 0 && !prefabData.isAlembic) { r = new Renderer[geometryObject.transform.childCount]; for (int j = 0; j < geometryObject.transform.childCount; ++j) { //Parent the child gameobject (geometry) to the prefab game object. GameObject geometryChildObject = geometryObject.transform.GetChild(j).gameObject; //Cache a reference to the child gameobject of the geometry. geometryChildObject.transform.parent = prefabGameObject.transform; geometryChildObject.transform.localPosition = Vector3.zero; geometryChildObject.name = geometryChildObject.name.Replace("(Clone)", ""); //Get reference to the renderer components to apply material later. r[j] = geometryChildObject.GetComponentInChildren <Renderer>(); } //Destroy the empty parent container which was holding the meshes. DestroyImmediate(geometryObject); } else if (prefabData.isAlembic) //if the instantiated mesh is an alembic asset. { //Parent the child gameobject (geometry) to the prefab game object. geometryObject.transform.parent = prefabGameObject.transform; geometryObject.transform.localPosition = Vector3.zero; geometryObject.name = geometryObject.name.Replace("(Clone)", ""); //Get reference to the renderer components to apply material later. r = geometryObject.GetComponentsInChildren <Renderer>(); } else //if the instantiated mesh does not have any children { //Parent the child gameobject (geometry) to the prefab game object. geometryObject.transform.parent = prefabGameObject.transform; geometryObject.transform.localPosition = Vector3.zero; geometryObject.name = geometryObject.name.Replace("(Clone)", ""); //Get reference to the renderer component to apply material later. r = geometryObject.GetComponentsInChildren <Renderer>(); } foreach (Renderer ren in r) { ren.material = prefabData.finalMat; //Apply highpoly material if the mesh was highpoly and highpoly filter is enabled. if (loadedGeometry.name.ToLower().Contains("highpoly") && prefabData.highpoly) { ren.material = prefabData.highpolyMat; #if UNITY_EDITOR_OSX ren.material = prefabData.finalMat; #endif } //Apply collision if (prefabData.setupCollision) { ren.gameObject.AddComponent <MeshCollider>().sharedMesh = ren.gameObject.GetComponent <MeshFilter>().sharedMesh; } } if (numberOfFiles > 2) { lodHeight *= ((x + 1) >= (numberOfFiles / 2)) ? 0.75f : 0.5f; } else { lodHeight *= (x + 1) < 1 ? 0.75f : 0.15f; } lodsForPrefab.Add(new LOD(lodHeight, r)); } //Set LODs in the LOD group prefabGameObject.GetComponent <LODGroup>().SetLODs(lodsForPrefab.ToArray()); prefabGameObject.GetComponent <LODGroup>().RecalculateBounds(); //Prefab saving string prefLocation = prefabPath + "/" + prefabName + ".prefab"; prefLocation = prefLocation.Replace("(Clone)", ""); SavePrefab(prefabGameObject, prefLocation, prefabData.addAssetToScene); } catch (Exception ex) { Debug.Log("Exception::MegascansMeshUtils::3D Asset Prefab:: " + ex.ToString()); MegascansUtilities.HideProgressBar(); } }