/// <summary> /// Upgrades a DynamicDNAConverter Prefab to a new ConverterController asset and replaces any usage of the old asset. Stores the original asset in a relative 'Legacy' folder. /// </summary> /// <returns>Returns the path of the new converterController asset</returns> public DynamicDNAConverterController DoUpgrade() { var DCBPath = AssetDatabase.GetAssetPath(this.gameObject); //In Unity 2018.3+ this asset may be being inspected in its own Prefab scene (rather than via customizer). //If that is the case we need to get the path differently #if UNITY_2018_3_OR_NEWER var prefabStage = UnityEditor.Experimental.SceneManagement.PrefabStageUtility.GetPrefabStage(this.gameObject); if (prefabStage != null) { DCBPath = prefabStage.prefabAssetPath; } #endif if (string.IsNullOrEmpty(DCBPath)) { Debug.LogWarning("Upgrade could not be completed. Could not get asset path for the DNAConverterBehaviour to upgrade"); return(null); } var newControllerName = this.name.Replace("DynamicDNAConverterBehaviour", "").Replace("DynamicDNAConverter", "").Replace("DNAConverterBehaviour", "").Replace("ConverterBehaviour", "").Replace("Legacy", ""); if (_converterController != null) { Debug.LogWarning("Upgrading " + this.gameObject.name + " failed because it already references a previously converted version. If you need to Upgrade again please inspect this assets 'Legacy Settings' and click 'Revert To Legacy Settings'"); return(null); } DynamicDNAConverterController newController = null; DynamicDNAPlugin skelModsPlug = null; DynamicDNAPlugin startingPosePlug = null; newControllerName += "DNAConverterController"; var path = DCBPath; path = path.Replace("/" + Path.GetFileName(path), ""); var assetPathAndName = AssetDatabase.GenerateUniqueAssetPath(path + "/" + newControllerName + ".asset"); newController = DynamicDNAConverterController.CreateDynamicDNAConverterControllerAsset(assetPathAndName, false); if (newController == null) { //bail if the converterController was not created Debug.LogWarning("DynamicDNAConverterBehaviour BackupAndUpgrade failed because it was unable to create the new ConverterController."); return(null); } //Add skeletonModifiers if (_skeletonModifiers.Count > 0) { skelModsPlug = newController.AddPlugin(typeof(SkeletonDNAConverterPlugin)); if (!((SkeletonDNAConverterPlugin)skelModsPlug).ImportSettings(this.gameObject, 0)) { Debug.LogWarning("Your SkeletonModifiers did not import correctly into the new plugin. Please try importing then manually"); } } //Add startingPose if (_startingPose != null) { startingPosePlug = newController.AddPlugin(typeof(BonePoseDNAConverterPlugin)); if (((BonePoseDNAConverterPlugin)startingPosePlug).ImportSettings(this.gameObject, 0)) { Debug.LogWarning("Your StartingPose did not import correctly into the new plugin. Please try importing it manually"); } } //Import the rest of our data newController.ImportConverterBehaviourData(this); //Set this last because the backwards compatible public properties get values from it if its set _converterController = newController; EditorUtility.SetDirty(newController); if (skelModsPlug != null) { EditorUtility.SetDirty(skelModsPlug); } if (startingPosePlug != null) { EditorUtility.SetDirty(startingPosePlug); } //Find and replace the usage of this FindAndReplaceUsage(newController); //If this asset is not inside a 'LegacyDNA' folder move it inside one //We need to keep the old one because downloaded content may still require it //The RaceDatas and SlotDataAssets will warn the user if they are using a legacy DynamicDNAConverterBehaviour var DCBFilename = System.IO.Path.GetFileName(DCBPath); string moveAssetResult = ""; #pragma warning disable 0219 string newDCBPath = DCBPath; #pragma warning restore if (DCBPath.IndexOf("LegacyDNA" + "/" + DCBFilename) == -1) { var DCBDir = System.IO.Path.GetDirectoryName(DCBPath); if (!AssetDatabase.IsValidFolder(DCBDir + "/" + "LegacyDNA")) { AssetDatabase.CreateFolder(DCBDir, "LegacyDNA"); } if (DCBFilename.IndexOf("Legacy") == -1) { DCBFilename = System.IO.Path.GetFileNameWithoutExtension(DCBPath) + " Legacy" + System.IO.Path.GetExtension(DCBPath); } moveAssetResult = AssetDatabase.MoveAsset(DCBPath, DCBDir + "/" + "LegacyDNA" + "/" + DCBFilename); if (string.IsNullOrEmpty(moveAssetResult)) { newDCBPath = DCBDir + "/" + "LegacyDNA" + "/" + DCBFilename; } } if (!string.IsNullOrEmpty(moveAssetResult)) { Debug.LogWarning(moveAssetResult); } #if UNITY_2018_3_OR_NEWER //If this happenned in a prefab stage (rather than via customizer) it wont save the prefab with the added converterController so if (prefabStage != null) { PrefabUtility.SaveAsPrefabAsset(this.gameObject, newDCBPath); } #endif EditorUtility.SetDirty(this.gameObject); AssetDatabase.SaveAssets(); return(_converterController); }
private void CreateBonePoseCallback(UMAData umaData) { UMA.PoseTools.UMABonePose bonePose = CreatePoseAsset("", bonePoseSaveName); //I dont think this should have ever overwritten the existing one /*if (selectedConverter.startingPose == null) * { * bonePose = CreatePoseAsset("", bonePoseSaveName); * } * else * { * bonePose = selectedConverter.startingPose; * bonePose.poses = new UMABonePose.PoseBone[1]; * }*/ UMASkeleton skeletonPreDNA = tempAvatarPreDNA.GetComponent <UMADynamicAvatar>().umaData.skeleton; UMASkeleton skeletonPostDNA = tempAvatarPostDNA.GetComponent <UMADynamicAvatar>().umaData.skeleton; Transform transformPreDNA; Transform transformPostDNA; bool transformDirty; int parentHash; foreach (int boneHash in skeletonPreDNA.BoneHashes) { skeletonPreDNA.TryGetBoneTransform(boneHash, out transformPreDNA, out transformDirty, out parentHash); skeletonPostDNA.TryGetBoneTransform(boneHash, out transformPostDNA, out transformDirty, out parentHash); if ((transformPreDNA == null) || (transformPostDNA == null)) { Debug.LogWarning("Bad bone hash in skeleton: " + boneHash); continue; } if (!LocalTransformsMatch(transformPreDNA, transformPostDNA)) { bonePose.AddBone(transformPreDNA, transformPostDNA.localPosition, transformPostDNA.localRotation, transformPostDNA.localScale); } } UMAUtils.DestroySceneObject(tempAvatarPreDNA); UMAUtils.DestroySceneObject(tempAvatarPostDNA); // This can be very helpful for testing /* * bonePose.ApplyPose(skeletonPreDNA, 1.0f); */ EditorUtility.SetDirty(bonePose); AssetDatabase.SaveAssets(); if (_applyAndResetOnCreateBP) { DynamicDNAConverterController converterController = (selectedConverter is DynamicDNAConverterController) ? (selectedConverter as DynamicDNAConverterController) : null; DynamicDNAConverterBehaviour converterBehaviour = (selectedConverter is DynamicDNAConverterBehaviour) ? (selectedConverter as DynamicDNAConverterBehaviour) : null; //UMA2.8+ fixDNAPrefabs Removed the converterBehaviour.ConverterController field, it should be directly assigned to the Races/Slots now //if (converterBehaviour.ConverterController != null) // converterController = converterBehaviour.ConverterController; if (converterController != null) { //find the first BonePoseDNAConverterPlugin and add the pose to it var existingBPCPs = converterController.GetPlugins(typeof(BonePoseDNAConverterPlugin)); BonePoseDNAConverterPlugin thisBPCP; if (existingBPCPs.Count > 0) { thisBPCP = existingBPCPs[0] as BonePoseDNAConverterPlugin; //Turn off any other starting poses? for (int i = 0; i < existingBPCPs.Count; i++) { for (int bi = 0; bi < (existingBPCPs[i] as BonePoseDNAConverterPlugin).poseDNAConverters.Count; bi++) { (existingBPCPs[i] as BonePoseDNAConverterPlugin).poseDNAConverters[bi].startingPoseWeight = 0f; } } } else { //if there isn't one create it thisBPCP = converterController.AddPlugin(typeof(BonePoseDNAConverterPlugin)) as BonePoseDNAConverterPlugin; } thisBPCP.poseDNAConverters.Add(new BonePoseDNAConverterPlugin.BonePoseDNAConverter(bonePose, 1f)); Debug.Log(bonePose.name + " added as a starting pose to " + thisBPCP.name); } else if (converterBehaviour != null) { // Set this asset as the converters pose asset converterBehaviour.startingPose = bonePose; //make sure its fully applied converterBehaviour.startingPoseWeight = 1f; } // Reset all the DNA values for target Avatar to default UMADnaBase[] targetDNA = activeUMA.umaData.GetAllDna(); foreach (UMADnaBase dnaEntry in targetDNA) { for (int i = 0; i < dnaEntry.Values.Length; i++) { dnaEntry.SetValue(i, 0.5f); } } // Optionally clear the DNA from the base recipe, // since it's now included in the new starting pose UMARecipeBase baseRaceRecipe = activeUMA.umaData.umaRecipe.GetRace().baseRaceRecipe; if (baseRaceRecipe != null) { if (EditorUtility.DisplayDialog("Base Recipe Cleanup", "Starting Pose created. Remove DNA from base recipe of active race? Choose 'RemoveDNA' if your intention is to replace modifications made by a recipes starting DNA values with the created pose.", "Remove DNA", "Keep DNA")) { UMAData.UMARecipe baseRecipeData = new UMAData.UMARecipe(); baseRaceRecipe.Load(baseRecipeData, activeUMA.context); baseRecipeData.ClearDna(); baseRaceRecipe.Save(baseRecipeData, activeUMA.context); } } } }