private static Dictionary <string, string> GetJointMapForFigure(DazFigurePlatform figure) { Dictionary <string, string> map = new Dictionary <string, string>(); switch (figure) { case DazFigurePlatform.Genesis8: case DazFigurePlatform.Genesis3: ConfigureGenesisMapStandard(map); break; case DazFigurePlatform.Genesis2: ConfigureGenesisMapStandard(map); //todo account for Gen2 variances break; case DazFigurePlatform.Victoria: case DazFigurePlatform.Genesis: case DazFigurePlatform.Michael: case DazFigurePlatform.TheFreak: case DazFigurePlatform.Victoria4: case DazFigurePlatform.Victoria4Elite: case DazFigurePlatform.Michael4: case DazFigurePlatform.Michael4Elite: case DazFigurePlatform.Stephanie4: case DazFigurePlatform.Aiko4: default: //do nothing, let unity's excellent guesser handle it break; } return(map); }
private static IEnumerator ImportRoutine(string dtuPath, string fbxPath) { Daz3DBridge.CurrentToolbarMode = Daz3DBridge.ToolbarMode.History;//force into history mode during import Daz3DBridge.Progress = .03f; yield return(new WaitForEndOfFrame()); _map = new MaterialMap(dtuPath); while (!IrayShadersReady()) { yield return(new WaitForEndOfFrame()); } var dtu = new DTU(); var routine = ImportDTURoutine(dtuPath, (d => dtu = d), .8f); while (routine.MoveNext()) { yield return(new WaitForEndOfFrame()); } //ImportDTU(dtuPath); DazFigurePlatform platform = DiscoverFigurePlatform(dtu); Daz3DBridge.Progress = .9f; yield return(new WaitForEndOfFrame()); if (GenerateUnityPrefab) { GeneratePrefabFromFBX(fbxPath, platform); } Daz3DBridge.Progress = 1f; yield return(new WaitForEndOfFrame()); _map = null; Daz3DBridge.Progress = 0; yield break; }
private static void DescribeHumanJointsForFigure(ref HumanDescription description, DazFigurePlatform figure) { var map = GetJointMapForFigure(figure); HumanBone[] humanBones = new HumanBone[HumanTrait.BoneName.Length]; int mapIdx = 0; foreach (var humanBoneName in HumanTrait.BoneName) { if (map.ContainsKey(humanBoneName)) { HumanBone humanBone = new HumanBone(); humanBone.humanName = humanBoneName; humanBone.boneName = map[humanBoneName]; humanBone.limit.useDefaultValues = true; //todo get limits from dtu? humanBones[mapIdx++] = humanBone; } } description.human = humanBones; }
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; }