static void _process_model(string character_name, string folder, string filename) { //var abs_folder = Application.dataPath + "/" + folder; folder = "Assets/" + folder; var asset = AssetDatabase.LoadAssetAtPath <GameObject>(folder + "/" + filename); // Create a game object in the hierarchy. var holder = GameObject.Find("Mixamo"); if (holder == null) { holder = new GameObject("Mixamo"); } //var model = GameObject.Instantiate(asset, holder.transform); var model = (GameObject)PrefabUtility.InstantiatePrefab(asset, UnityEngine.SceneManagement.SceneManager.GetActiveScene()); model.transform.parent = holder.transform; model.name = character_name; // Collect all the materials. var meshes = asset.GetComponentsInChildren <SkinnedMeshRenderer>(); bool has_eyes = false; var material_set = new HashSet <Material>(); foreach (var mesh in meshes) { var obj_name = mesh.name; // Sometimes Adobe Fuse model has an "Eyes" object *or* and "Eyelashes" object // and the one it doesn't have is called "default". if (obj_name == "Eyes") { has_eyes = true; } foreach (var mat in mesh.sharedMaterials) { material_set.Add(mat); } } // Create materials list var materials = new List <Material>(); foreach (var m in material_set) { materials.Add(m); } // Create Eyes and Eyelashes materials from the Body material. var body_mat = materials.Find(m => m.name.Contains("_Body")); var mat_prefix = body_mat.name.Split('_')[0]; if (body_mat != null) { var bodyPath = folder + "/Materials/" + body_mat.name + ".mat"; var eyePath = folder + "/Materials/" + mat_prefix + "_Eyes_Diffuse.mat"; var eyelashesPath = folder + "/Materials/" + mat_prefix + "_Eyelashes_Diffuse.mat"; AssetDatabase.CopyAsset(bodyPath, eyePath); AssetDatabase.CopyAsset(bodyPath, eyelashesPath); materials.Add(AssetDatabase.LoadAssetAtPath <Material>(eyePath)); materials.Add(AssetDatabase.LoadAssetAtPath <Material>(eyelashesPath)); } // Rename the "default" object to the correct value. { var default_object = model.transform.Find("default"); if (default_object != null) { if (has_eyes) { default_object.name = "Eyelashes"; } else { default_object.name = "Eyes"; } } } // Set materials for Eyes and Eyelashes objects. model.transform.Find("Eyes").GetComponent <SkinnedMeshRenderer>().material = materials.Find(m => m.name.Contains("_Eyes")); model.transform.Find("Eyelashes").GetComponent <SkinnedMeshRenderer>().material = materials.Find(m => m.name.Contains("_Eyelashes")); // Configure each material. foreach (var m in materials) { foreach (var part in _parts) { if (!m.name.Contains(part.Name)) { continue; } // Set rendering mode. m.SetFloat("_Mode", (float)part.BlendMode); // Set textures. Use Body for Eyes and Eyelashes. var tp = part.Name; if (part.Name == "_Eyes" || part.Name == "_Eyelashes") { tp = "_Body"; } m.SetTexture("_MainTex", AssetDatabase.LoadAssetAtPath <Texture>(folder + "/Textures/" + mat_prefix + tp + "_BaseColor.png")); m.SetTexture("_MetallicGlossMap", AssetDatabase.LoadAssetAtPath <Texture>(folder + "/Textures/" + mat_prefix + tp + "_MetallicAndSmoothness.png")); m.SetTexture("_BumpMap", AssetDatabase.LoadAssetAtPath <Texture>(folder + "/Textures/" + mat_prefix + tp + "_Normal.png")); m.SetTexture("_OcclusionMap", AssetDatabase.LoadAssetAtPath <Texture>(folder + "/Textures/" + mat_prefix + tp + "_AmbientOcclusion.png")); // Configure the part parameters. m.SetFloat("_GlossMapScale", part.GlossScale); m.SetFloat("_BumpScale", part.BumpScale); if (part.BlendMode == BlendMode.Cutout) { m.SetFloat("_Cutoff", part.CutoffAlpha); } // Find which parameters are which... //m.SetFloat("_Glossiness", 0.1f); //m.SetFloat("_GlossMapScale", 0.2f); //m.SetFloat("_SmoothnessTextureChannel", 0.3f); //m.SetFloat("_Metallic", 0.4f); //m.SetFloat("_SpecularHighlights", 0.5f); //m.SetFloat("_GlossyReflections", 0.6f); } } // Create prefab to hold changes. var old_model = model; var prefab = PrefabUtility.CreatePrefab(folder + "/" + character_name + ".prefab", old_model); // Recreate the instance from the new prefab. model = (GameObject)PrefabUtility.InstantiatePrefab(prefab, UnityEngine.SceneManagement.SceneManager.GetActiveScene()); model.transform.parent = holder.transform; // Remove the original prefab. GameObject.DestroyImmediate(old_model); // Must do this so that the changes are immediately visible in the editor. foreach (var m in materials) { MaterialUpdater.MaterialChanged(m, MaterialUpdater.WorkflowMode.Metallic); } // Select the new game object. _expand_hierarchy_object(holder); Selection.activeGameObject = model; }
static void _process_model(string character_name, string folder, string filename) { //var abs_folder = Application.dataPath + "/" + folder; folder = "Assets/" + folder; var asset = AssetDatabase.LoadAssetAtPath <GameObject>(folder + "/" + filename); // Create a game object in the hierarchy. var holder = GameObject.Find("Mixamo"); if (holder == null) { holder = new GameObject("Mixamo"); } //var model = GameObject.Instantiate(asset, holder.transform); var model = (GameObject)PrefabUtility.InstantiatePrefab(asset, UnityEngine.SceneManagement.SceneManager.GetActiveScene()); model.transform.parent = holder.transform; model.name = character_name; // Collect all the materials. var meshes = asset.GetComponentsInChildren <SkinnedMeshRenderer>(); bool has_eyes = meshes.Any(m => m.name == "Eyes"); // Rename the "default" object to the correct value. var default_object = model.transform.Find("default"); if (default_object != null) { if (has_eyes) { default_object.name = "Eyelashes"; } else { default_object.name = "Eyes"; } } var default_mesh = meshes.FirstOrDefault(m => m.name == "default")?.transform; if (default_mesh != null) { default_mesh.name = has_eyes ? "Eyelashes" : "Eyes"; Debug.Log("Here I am!" + has_eyes + " " + default_mesh.name); } var materials = new Dictionary <string, Material>(); bool body_mat_processed = false; AssetDatabase.CreateFolder(folder, "Materials"); foreach (var mesh in meshes) { // Sometimes Adobe Fuse model has an "Eyes" object *or* and "Eyelashes" object // and the one it doesn't have is called "default". //extract embedded materials and adjust mesh var shared_mats = new Material[mesh.sharedMaterials.Length]; for (var i = 0; i < mesh.sharedMaterials.Length; i++) { var mat = mesh.sharedMaterials[i]; if (mat.name == "Bodymat") { if (!body_mat_processed) { _extract_material(folder, mat, materials, "Eyesmat"); _extract_material(folder, mat, materials, "Eyelashesmat"); body_mat_processed = true; } if (mesh.name == "Eyes" || mesh.name == "Eyelashes") { shared_mats[i] = materials[mesh.name + "mat"]; continue; } } _extract_material(folder, mat, materials); shared_mats[i] = materials[mat.name]; } // directly applying shared_mats to the current mesh seems to be delayed and misses the last item // just update the model directly model.transform.Find(mesh.name).GetComponent <SkinnedMeshRenderer>().sharedMaterials = shared_mats; } foreach (var part in _parts) { var material_name = part.Name + "mat"; if (!materials.ContainsKey(material_name)) { continue; } var m = materials[material_name]; // Set rendering mode. m.SetFloat("_Mode", (float)part.BlendMode); // Set textures. Use Body for Eyes and Eyelashes. var tp = "_" + part.Name; if (part.Name == "Eyes" || part.Name == "Eyelashes") { tp = "_Body"; } var texBase = AssetDatabase.LoadAssetAtPath <Texture2D>(folder + "/Textures/" + character_name + tp + "_BaseColor.png"); m.SetTexture("_MainTex", texBase); m.SetTexture("_MetallicGlossMap", AssetDatabase.LoadAssetAtPath <Texture>(folder + "/Textures/" + character_name + tp + "_MetallicAndSmoothness.png")); m.SetTexture("_BumpMap", AssetDatabase.LoadAssetAtPath <Texture>(folder + "/Textures/" + character_name + tp + "_Normal.png")); m.SetTexture("_OcclusionMap", AssetDatabase.LoadAssetAtPath <Texture>(folder + "/Textures/" + character_name + tp + "_AmbientOcclusion.png")); // Override blend mode for non-alpha hair. // Override a transparent BlendMode if the texture is actually opaque-only. if (part.BlendMode == BlendMode.Fade || part.BlendMode == BlendMode.Transparent) { // Check texture type. switch (texBase.format) { // Ignore formats that have alpha. case TextureFormat.ARGB4444: case TextureFormat.RGBA32: case TextureFormat.ARGB32: case TextureFormat.RGBA4444: case TextureFormat.BGRA32: case TextureFormat.RGBAHalf: case TextureFormat.RGBAFloat: case TextureFormat.PVRTC_RGBA2: case TextureFormat.PVRTC_RGBA4: case TextureFormat.ETC2_RGBA8: case TextureFormat.ETC2_RGBA1: case TextureFormat.ASTC_RGBA_4x4: case TextureFormat.ASTC_RGBA_5x5: case TextureFormat.ASTC_RGBA_6x6: case TextureFormat.ASTC_RGBA_8x8: case TextureFormat.ASTC_RGBA_10x10: case TextureFormat.ASTC_RGBA_12x12: case TextureFormat.DXT5: // NOTE: DXT5 has alpha, DXT1 is usually non-alpha break; default: // Fall back to opaque. m.SetFloat("_Mode", (float)BlendMode.Opaque); break; } } // Configure the part parameters. m.SetFloat("_GlossMapScale", part.GlossScale); m.SetFloat("_BumpScale", part.BumpScale); if (part.BlendMode == BlendMode.Cutout) { m.SetFloat("_Cutoff", part.CutoffAlpha); } // Find which parameters are which... //m.SetFloat("_Glossiness", 0.1f); //m.SetFloat("_GlossMapScale", 0.2f); //m.SetFloat("_SmoothnessTextureChannel", 0.3f); //m.SetFloat("_Metallic", 0.4f); //m.SetFloat("_SpecularHighlights", 0.5f); //m.SetFloat("_GlossyReflections", 0.6f); } // Create prefab to hold changes. var old_model = model; var prefab = PrefabUtility.SaveAsPrefabAsset(old_model, folder + "/" + character_name + ".prefab"); // Recreate the instance from the new prefab. model = (GameObject)PrefabUtility.InstantiatePrefab(prefab, UnityEngine.SceneManagement.SceneManager.GetActiveScene()); model.transform.parent = holder.transform; // Remove the original prefab. GameObject.DestroyImmediate(old_model); // Must do this so that the changes are immediately visible in the editor. foreach (var m in materials.Values) { MaterialUpdater.MaterialChanged(m, MaterialUpdater.WorkflowMode.Metallic); } // Select the new game object. _expand_hierarchy_object(holder); Selection.activeGameObject = model; }