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;
        }