public static IEnumerator ImportDTURoutine(string path, Action <DTU> dtuOut, float progressLimit) { Debug.Log("ImportDTU for " + path); FoldAll(); ImportEventRecord record = new ImportEventRecord(); EventQueue.Enqueue(record); var dtu = DTUConverter.ParseDTUFile(path); dtuOut(dtu); var dtuObject = AssetDatabase.LoadAssetAtPath <UnityEngine.Object>(path); record.AddToken("Imported DTU file: " + path); record.AddToken(dtuObject.name, dtuObject, ENDLINE); //UnityEngine.Debug.Log("DTU: " + dtu.AssetName + " contains: " + dtu.Materials.Count + " materials"); record.AddToken("Generated materials: "); float progressIncrement = (progressLimit - Daz3DBridge.Progress) / dtu.Materials.Count; for (int i = 0; i < dtu.Materials.Count; i++) { var dtuMat = dtu.Materials[i]; var material = dtu.ConvertToUnity(dtuMat); _map.AddMaterial(material); record.AddToken(material.name, material); Daz3DBridge.Progress = Mathf.MoveTowards(Daz3DBridge.Progress, progressLimit, progressIncrement); yield return(new WaitForEndOfFrame()); } record.AddToken(" based on DTU file.", null, ENDLINE); Daz3DBridge bridge = EditorWindow.GetWindow(typeof(Daz3DBridge)) as Daz3DBridge; if (bridge == null) { var consoleType = Type.GetType("ConsoleWindow,UnityEditor.dll"); bridge = EditorWindow.CreateWindow <Daz3DBridge>(new[] { consoleType }); } bridge?.Focus(); //just a safeguard to keep the history data at a managable size (100 records) while (EventQueue.Count > 100) { EventQueue.Dequeue(); } yield break; }
public static void ImportDTU(string path) { Debug.Log("ImportDTU for " + path); FoldAll(); ImportEventRecord record = new ImportEventRecord(); EventQueue.Enqueue(record); var dtu = DTUConverter.ParseDTUFile(path); var dtuObject = AssetDatabase.LoadAssetAtPath <UnityEngine.Object>(path); record.AddToken("Imported DTU file: " + path); record.AddToken(dtuObject.name, dtuObject, ENDLINE); //UnityEngine.Debug.Log("DTU: " + dtu.AssetName + " contains: " + dtu.Materials.Count + " materials"); record.AddToken("Generated materials: "); foreach (var dtuMat in dtu.Materials) { var material = dtu.ConvertToUnity(dtuMat); _map.AddMaterial(material); record.AddToken(material.name, material); } record.AddToken(" based on DTU file.", null, ENDLINE); Daz3DBridge bridge = EditorWindow.GetWindow(typeof(Daz3DBridge)) as Daz3DBridge; if (bridge == null) { var consoleType = Type.GetType("ConsoleWindow,UnityEditor.dll"); bridge = EditorWindow.CreateWindow <Daz3DBridge>(new[] { consoleType }); } bridge?.Focus(); //just a safeguard to keep the history data at a managable size (100 records) while (EventQueue.Count > 100) { EventQueue.Dequeue(); } }
public static void GeneratePrefabFromFBX(string fbxPath, DazFigurePlatform platform) { var fbxPrefab = AssetDatabase.LoadAssetAtPath <GameObject>(fbxPath); if (fbxPrefab == null) { Debug.LogWarning("no FBX model prefab found at " + fbxPath); return; } if (PrefabUtility.GetPrefabAssetType(fbxPrefab) != PrefabAssetType.Model) { Debug.LogWarning(fbxPath + " is not a model prefab "); return; } System.Reflection.MethodInfo resetPose = null; System.Reflection.MethodInfo xferPose = null; var avatarInstance = Instantiate(fbxPrefab); avatarInstance.name = "AvatarInstance"; if (AutomateMecanimAvatarMappings) { var record = new ImportEventRecord(); ModelImporter importer = GetAtPath(fbxPath) as ModelImporter; if (importer) { var description = importer.humanDescription; DescribeHumanJointsForFigure(ref description, platform); importer.humanDescription = description; importer.avatarSetup = ModelImporterAvatarSetup.CreateFromThisModel; // Genesis 8 is modeled in A-pose, so we correct to T-pose before configuring avatar joints //using Unity's internal MakePoseValid method, which does a perfect job if (platform == DazFigurePlatform.Genesis8 && false) { //use reflection to access AvatarSetupTool; var setupToolType = Type.GetType("UnityEditor.AvatarSetupTool,UnityEditor.dll"); var boneWrapperType = Type.GetType("UnityEditor.AvatarSetupTool+BoneWrapper,UnityEditor.dll"); if (boneWrapperType != null && setupToolType != null) { var existingMappings = new Dictionary <string, string>(); var human = description.human; for (var i = 0; i < human.Length; ++i) { existingMappings[human[i].humanName] = human[i].boneName; } var getModelBones = setupToolType.GetMethod("GetModelBones"); var getHumanBones = setupToolType.GetMethod("GetHumanBones", new[] { typeof(Dictionary <string, string>), typeof(Dictionary <Transform, bool>) }); var makePoseValid = setupToolType.GetMethod("MakePoseValid"); resetPose = setupToolType.GetMethod("CopyPose"); xferPose = setupToolType.GetMethod("TransferPoseToDescription"); if (getModelBones != null && getHumanBones != null && makePoseValid != null) { record.AddToken("Corrected Avatar Setup T-pose for Genesis8 figure: ", null); record.AddToken(fbxPrefab.name, fbxPrefab, ENDLINE); var modelBones = (Dictionary <Transform, bool>)getModelBones.Invoke(null, new object[] { avatarInstance.transform, false, null }); var humanBones = (ICollection <object>)getHumanBones.Invoke(null, new object[] { existingMappings, modelBones }); // a little dance to populate array of Unity's internal BoneWrapper type var humanBonesArray = new object[humanBones.Count]; humanBones.CopyTo(humanBonesArray, 0); Array destinationArray = Array.CreateInstance(boneWrapperType, humanBones.Count); Array.Copy(humanBonesArray, destinationArray, humanBones.Count); //This mutates the transforms (modelBones) via Bonewrapper class makePoseValid.Invoke(null, new[] { destinationArray }); } } } AssetDatabase.WriteImportSettingsIfDirty(fbxPath); AssetDatabase.ImportAsset(fbxPath, ImportAssetOptions.ForceUpdate); // i think this might unT-pose the gen8 skeleton instance if (resetPose != null && xferPose != null) { SerializedObject modelImporterObj = new SerializedObject(importer); var skeleton = modelImporterObj?.FindProperty("m_HumanDescription.m_Skeleton"); if (skeleton != null) { resetPose.Invoke(null, new object[] { avatarInstance, fbxPrefab }); //xferPose.Invoke(null, new object[] { skeleton, avatarInstance.transform }); } } DestroyImmediate(avatarInstance); record.AddToken("Automated Mecanim avatar setup for " + fbxPrefab.name + ": "); //a little dance to get the avatar just reimported var allAvatars = Resources.FindObjectsOfTypeAll(typeof(Avatar)); var avatar = Array.Find(allAvatars, element => element.name.StartsWith(fbxPrefab.name)); if (avatar) { record.AddToken(avatar.name, avatar, ENDLINE); } } else { Debug.LogWarning("Could not acquire importer for " + fbxPath + " ...could not automatically configure humanoid avatar."); record.AddToken("Could not acquire importer for " + fbxPath + " ...could not automatically configure humanoid avatar.", null, ENDLINE); } EventQueue.Enqueue(record); } //remap the materials var workingInstance = Instantiate(fbxPrefab); workingInstance.name = "Daz3d_" + fbxPrefab.name; var renderers = workingInstance.GetComponentsInChildren <Renderer>(); if (renderers?.Length == 0) { Debug.LogWarning("no renderers found for material remapping"); return; } var modelPath = AssetDatabase.GetAssetPath(fbxPrefab); if (ReplaceMaterials) { foreach (var renderer in renderers) { var dict = new Dictionary <Material, Material>(); if (renderer.name.ToLower().Contains("eyelashes")) { renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; } foreach (var keyMat in renderer.sharedMaterials) { var key = keyMat.name; key = Daz3D.Utilities.ScrubKey(key); Material nuMat = null; if (_map != null && _map.Map.ContainsKey(key)) { nuMat = _map.Map[key];// the preferred uber/iRay based material generated by the DTUConverter } else if (s_StandardMaterialCollection.ContainsKey(key)) { nuMat = new Material(s_StandardMaterialCollection[key]); //FixupStandardBasedMaterial(ref nuMat, fbxPrefab, keyMat.name, data); } else { var shader = Shader.Find("HDRP/Lit"); if (shader == null) { Debug.LogWarning("couldn't find HDRP/Lit shader"); continue; } nuMat = new Material(shader); nuMat.CopyPropertiesFromMaterial(keyMat); // just copy the textures, colors and scalars that are appropriate given the base material type //DazMaterialPropertiesInfo info = new DazMaterialPropertiesInfo(); //CustomizeMaterial(ref nuMat, info); var matPath = Path.GetDirectoryName(modelPath); matPath = Path.Combine(matPath, fbxPrefab.name + "Daz3D_Materials"); matPath = AssetDatabase.GenerateUniqueAssetPath(matPath); if (!Directory.Exists(matPath)) { Directory.CreateDirectory(matPath); } //Debug.Log("obj path " + path); AssetDatabase.CreateAsset(nuMat, matPath + "/Daz3D_" + keyMat.name + ".mat"); } dict.Add(keyMat, nuMat); } //remap the meshes in the fbx prefab to the value materials in dict var count = renderer.sharedMaterials.Length; var copy = new Material[count]; //makes a copy for (int i = 0; i < count; i++) { var key = renderer.sharedMaterials[i]; //Debug.Log("remapping: " + renderer.sharedMaterials[i].name + " to " + dict[key].name); copy[i] = dict[key];//fill copy } renderer.sharedMaterials = copy;//overwrite sharedMaterials, because set indexer assigns to a copy } } //write the prefab to the asset database // Make sure the file name is unique, in case an existing Prefab has the same name. var nuPrefabPathPath = Path.GetDirectoryName(modelPath); nuPrefabPathPath = Path.Combine(nuPrefabPathPath, fbxPrefab.name + "_Prefab"); nuPrefabPathPath = AssetDatabase.GenerateUniqueAssetPath(nuPrefabPathPath); if (!Directory.Exists(nuPrefabPathPath)) { Directory.CreateDirectory(nuPrefabPathPath); } nuPrefabPathPath += "/Daz3D_" + fbxPrefab.name + ".prefab"; // For future refreshment var component = workingInstance.AddComponent <Daz3DInstance>(); component.SourceFBX = fbxPrefab; // Create the new Prefab. var prefab = PrefabUtility.SaveAsPrefabAssetAndConnect(workingInstance, nuPrefabPathPath, InteractionMode.AutomatedAction); Selection.activeGameObject = prefab; //now, seek other instance(s) in the scene having been sourced from this fbx asset var otherInstances = FindObjectsOfType <Daz3DInstance>(); int foundCount = 0; var resultingInstance = workingInstance; if (ReplaceSceneInstances) { foreach (var otherInstance in otherInstances) { if (otherInstance == component)//ignore this working instance { continue; } if (otherInstance.SourceFBX != fbxPrefab)//ignore instances of other assets { continue; } //for any found that flag ReplaceOnImport, delete that instance and replace with a copy of //this one, at their respective transforms if (otherInstance.ReplaceOnImport) { foundCount++; var xform = otherInstance.transform; var replacementInstance = PrefabUtility.InstantiatePrefab(prefab, xform.parent) as GameObject; replacementInstance.transform.position = xform.position; replacementInstance.transform.rotation = xform.rotation; //var replacementInstance = Instantiate(prefab, xform.position, xform.rotation, xform.parent); //PrefabUtility.RevertPrefabInstance(replacementInstance, InteractionMode.AutomatedAction); DestroyImmediate(otherInstance.gameObject); resultingInstance = replacementInstance; } } } //if no prior instances found, then don't destroy this instance //since it appears to be the first one to arrive if (foundCount > 0) { DestroyImmediate(workingInstance); } ImportEventRecord pfbRecord = new ImportEventRecord(); pfbRecord.AddToken("Created Unity Prefab: "); pfbRecord.AddToken(prefab.name, prefab); pfbRecord.AddToken(" and an instance in the scene: "); pfbRecord.AddToken(resultingInstance.name, resultingInstance, ENDLINE); EventQueue.Enqueue(pfbRecord); //highlight/select the object in the scene view Selection.activeGameObject = resultingInstance; }