protected void CreateBonePoseCallback(UMAData umaData) { UMA.PoseTools.UMABonePose bonePose = null; 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); } } Destroy(tempAvatarPreDNA); Destroy(tempAvatarPostDNA); // This can be very helpful for testing /* * bonePose.ApplyPose(skeletonPreDNA, 1.0f); */ EditorUtility.SetDirty(bonePose); AssetDatabase.SaveAssets(); // Set this asset as the converters pose asset selectedConverter.startingPose = bonePose; //make sure its fully applied selectedConverter.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?", "Remove DNA", "Keep DNA")) { UMAData.UMARecipe baseRecipeData = new UMAData.UMARecipe(); baseRaceRecipe.Load(baseRecipeData, activeUMA.context); baseRecipeData.ClearDna(); baseRaceRecipe.Save(baseRecipeData, activeUMA.context); } } }
void OnGUI() { Transform newSkeleton = EditorGUILayout.ObjectField("Rig Prefab", skeleton, typeof(Transform), true) as Transform; if (skeleton != newSkeleton) { skeleton = newSkeleton; boneComponents = new Dictionary <string, float>(); Transform[] transforms = UMABonePose.GetTransformsInPrefab(skeleton); foreach (Transform bone in transforms) { boneComponents.Add(bone.name, 1f); } } EditorGUILayout.Space(); EditorGUILayout.LabelField("Component Poses"); EditorGUI.indentLevel++; UMABonePose changedPose = null; UMABonePose deletedPose = null; float sliderVal = 0; List <string> activeBones = new List <string>(); foreach (KeyValuePair <UMABonePose, float> entry in poseComponents) { GUILayout.BeginHorizontal(); sliderVal = EditorGUILayout.Slider(entry.Key.name, entry.Value, 0f, 2f); if (sliderVal != entry.Value) { changedPose = entry.Key; } if (GUILayout.Button("-", GUILayout.Width(20f))) { deletedPose = entry.Key; } else { foreach (UMABonePose.PoseBone pose in entry.Key.poses) { if (!activeBones.Contains(pose.bone)) { activeBones.Add(pose.bone); } } } GUILayout.EndHorizontal(); } if (changedPose != null) { poseComponents[changedPose] = sliderVal; } if (deletedPose != null) { poseComponents.Remove(deletedPose); } GUILayout.BeginHorizontal(); newComponent = EditorGUILayout.ObjectField(newComponent, typeof(UMABonePose), false) as UMABonePose; GUI.enabled = (newComponent != null); if (GUILayout.Button("+", GUILayout.Width(30f))) { poseComponents.Add(newComponent, 1f); newComponent = null; } GUI.enabled = true; GUILayout.EndHorizontal(); EditorGUI.indentLevel--; EditorGUILayout.Space(); EditorGUILayout.LabelField("Component Bones"); EditorGUI.indentLevel++; foreach (string bone in activeBones) { GUILayout.BeginHorizontal(); if (boneComponents.ContainsKey(bone)) { boneComponents[bone] = EditorGUILayout.Slider(bone, boneComponents[bone], 0f, 2f); } GUILayout.EndHorizontal(); } EditorGUI.indentLevel--; GUILayout.BeginHorizontal(); if (GUILayout.Button("Left")) { foreach (string bone in activeBones) { if (bone.Contains("Left") || bone.Contains("left")) { boneComponents[bone] = 1f; } else if (bone.Contains("Right") || bone.Contains("right")) { boneComponents[bone] = 0f; } else { boneComponents[bone] = 0.5f; } } } if (GUILayout.Button("Right")) { foreach (string bone in activeBones) { if (bone.Contains("Left") || bone.Contains("left")) { boneComponents[bone] = 0f; } else if (bone.Contains("Right") || bone.Contains("right")) { boneComponents[bone] = 1f; } else { boneComponents[bone] = 0.5f; } } } if (GUILayout.Button("Mirror")) { foreach (string bone in activeBones) { boneComponents[bone] = Mathf.Max(1f - boneComponents[bone], 0f); } if (poseName.EndsWith("_L")) { poseName = poseName.Substring(0, poseName.Length - 1) + "R"; } else if (poseName.EndsWith("_R")) { poseName = poseName.Substring(0, poseName.Length - 1) + "L"; } } GUILayout.EndHorizontal(); EditorGUILayout.Space(); poseFolder = EditorGUILayout.ObjectField("Pose Folder", poseFolder, typeof(UnityEngine.Object), false) as UnityEngine.Object; EnforceFolder(ref poseFolder); GUILayout.BeginHorizontal(); poseName = EditorGUILayout.TextField("New Pose", poseName); if ((skeleton == null) || (poseFolder == null) || (poseComponents.Count < 1) || (poseName.Length < 1)) { GUI.enabled = false; } if (GUILayout.Button("Build", GUILayout.Width(60f))) { string folderPath = AssetDatabase.GetAssetPath(poseFolder); UMABonePose newPose = CreatePoseAsset(folderPath, poseName); Transform[] sourceBones = UMABonePose.GetTransformsInPrefab(skeleton); foreach (string bone in activeBones) { Transform source = System.Array.Find <Transform>(sourceBones, entry => entry.name == bone); if (source != null) { Vector3 position = source.localPosition; Quaternion rotation = source.localRotation; Vector3 scale = source.localScale; bool include = false; foreach (KeyValuePair <UMABonePose, float> entry in poseComponents) { float strength = entry.Value * boneComponents[bone]; if (strength > 0f) { foreach (UMABonePose.PoseBone pose in entry.Key.poses) { if (pose.bone == bone) { position += pose.position * strength; Quaternion posedRotation = rotation * pose.rotation; rotation = Quaternion.Slerp(rotation, posedRotation, strength); scale = Vector3.Slerp(scale, pose.scale, strength); } } include = true; } } if (include) { newPose.AddBone(source, position, rotation, scale); } } else { Debug.LogWarning("Bone not found in skeleton: " + bone); } } EditorUtility.SetDirty(newPose); AssetDatabase.SaveAssets(); } GUI.enabled = true; GUILayout.EndHorizontal(); }
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); } } } }
// This code is generally the same as used in the DynamicDNAConverterCustomizer // Probably worth breaking it out at some point and having it geenric protected void CreateBonePoseCallback(UMAData umaData) { avatarDNAisDirty = false; UMABonePose bonePose = ScriptableObject.CreateInstance <UMABonePose>(); UMAData umaPreDNA = tempAvatarPreDNA.GetComponent <UMADynamicAvatar>().umaData; UMAData umaPostDNA = tempAvatarPostDNA.GetComponent <UMADynamicAvatar>().umaData; UMADnaBase activeDNA = umaPostDNA.umaRecipe.GetDna(selectedDNAHash); UMASkeleton skeletonPreDNA = umaPreDNA.skeleton; UMASkeleton skeletonPostDNA = umaPostDNA.skeleton; if (poseSaveIndex < 0) { poseSaveName = startingPoseName; // Now that StartingPose has been generated // add the active DNA to the pre DNA avatar // UMA2.8+ Lots of converters can use the same DNA now //UMA2.8+ FixDNAPrefabs raceData.GetConverter(s) now returns IDNAConverter([]) IDNAConverter[] activeConverters = sourceUMA.umaRecipe.raceData.GetConverters(sourceUMA.umaRecipe.GetDna(selectedDNAHash)); //umaPreDNA.umaRecipe.raceData.dnaConverterList = new DnaConverterBehaviour[1]; //umaPreDNA.umaRecipe.raceData.dnaConverterList[0] = activeConverter; umaPreDNA.umaRecipe.raceData.dnaConverterList = activeConverters; umaPreDNA.umaRecipe.raceData.UpdateDictionary(); umaPreDNA.umaRecipe.EnsureAllDNAPresent(); umaPreDNA.Dirty(true, false, true); } 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); } } int activeDNACount = activeDNA.Count; for (int i = 0; i < activeDNACount; i++) { activeDNA.SetValue(i, 0.5f); } AssetDatabase.CreateAsset(bonePose, folderPath + "/" + poseSaveName + ".asset"); EditorUtility.SetDirty(bonePose); AssetDatabase.SaveAssets(); poseSaveIndex++; if (poseSaveIndex < activeDNACount) { poseSaveName = activeDNA.Names[poseSaveIndex] + "_0"; activeDNA.SetValue(poseSaveIndex, 0.0f); avatarDNAisDirty = true; } else if (poseSaveIndex < (activeDNACount * 2)) { int dnaIndex = poseSaveIndex - activeDNACount; poseSaveName = activeDNA.Names[dnaIndex] + "_1"; activeDNA.SetValue(dnaIndex, 1.0f); umaPostDNA.Dirty(); avatarDNAisDirty = true; } else { UMAUtils.DestroySceneObject(tempAvatarPreDNA); UMAUtils.DestroySceneObject(tempAvatarPostDNA); // Build a prefab DNA Converter and populate it with the morph set string assetName = "Morph Set"; string assetPath = AssetDatabase.GenerateUniqueAssetPath(folderPath + "/" + assetName + ".asset"); MorphSetDnaAsset asset = CustomAssetUtility.CreateAsset <MorphSetDnaAsset>(assetPath, false); SerializedObject serializedAsset = new SerializedObject(asset); SerializedProperty startingPose = serializedAsset.FindProperty("startingPose"); startingPose.objectReferenceValue = AssetDatabase.LoadAssetAtPath <UMABonePose>(folderPath + "/" + startingPoseName + ".asset"); SerializedProperty morphSetArray = serializedAsset.FindProperty("dnaMorphs"); morphSetArray.ClearArray(); for (int i = 0; i < activeDNACount; i++) { string posePairName = activeDNA.Names[i]; morphSetArray.InsertArrayElementAtIndex(i); SerializedProperty posePair = morphSetArray.GetArrayElementAtIndex(i); SerializedProperty dnaEntryName = posePair.FindPropertyRelative("dnaEntryName"); dnaEntryName.stringValue = posePairName; SerializedProperty zeroPose = posePair.FindPropertyRelative("poseZero"); zeroPose.objectReferenceValue = AssetDatabase.LoadAssetAtPath <UMABonePose>(folderPath + "/" + posePairName + "_0.asset"); SerializedProperty onePose = posePair.FindPropertyRelative("poseOne"); onePose.objectReferenceValue = AssetDatabase.LoadAssetAtPath <UMABonePose>(folderPath + "/" + posePairName + "_1.asset"); } serializedAsset.ApplyModifiedPropertiesWithoutUndo(); // Build a prefab DNA Converter and populate it with the morph set string prefabName = "Converter Prefab"; string prefabPath = AssetDatabase.GenerateUniqueAssetPath(folderPath + "/" + prefabName + ".prefab"); GameObject tempConverterPrefab = new GameObject(prefabName); MorphSetDnaConverterBehaviour converter = tempConverterPrefab.AddComponent <MorphSetDnaConverterBehaviour>(); SerializedObject serializedConverter = new SerializedObject(converter); SerializedProperty morphSet = serializedAsset.FindProperty("morphSet"); morphSet.objectReferenceValue = AssetDatabase.LoadAssetAtPath <MorphSetDnaAsset>(assetPath); serializedConverter.ApplyModifiedPropertiesWithoutUndo(); #if UNITY_2018_3_OR_NEWER PrefabUtility.SaveAsPrefabAsset(tempConverterPrefab, prefabPath); #else PrefabUtility.CreatePrefab(prefabPath, tempConverterPrefab); #endif DestroyImmediate(tempConverterPrefab, false); } }
void OnGUI() { sourceSkeleton = EditorGUILayout.ObjectField("Rig Prefab", sourceSkeleton, typeof(Transform), true) as Transform; poseFolder = EditorGUILayout.ObjectField("Pose Folder", poseFolder, typeof(UnityEngine.Object), false) as UnityEngine.Object; EnforceFolder(ref poseFolder); EditorGUILayout.Space(); // Single pose from skeleton if (skelOpen = EditorGUILayout.Foldout(skelOpen, "Rig Source")) { EditorGUI.indentLevel++; poseSkeleton = EditorGUILayout.ObjectField("Pose Rig", poseSkeleton, typeof(Transform), false) as Transform; skelPoseID = EditorGUILayout.TextField("ID", skelPoseID); if ((sourceSkeleton == null) || (poseSkeleton == null) || (skelPoseID == null) || (skelPoseID.Length < 1)) { GUI.enabled = false; } if (GUILayout.Button("Build Pose")) { string folderPath; if (poseFolder != null) { folderPath = AssetDatabase.GetAssetPath(poseFolder); } else { folderPath = AssetDatabase.GetAssetPath(poseAnimation); folderPath = folderPath.Substring(0, folderPath.LastIndexOf('/')); } UMABonePose bonePose = CreatePoseAsset(folderPath, skelPoseID); Transform[] sourceBones = UMABonePose.GetTransformsInPrefab(sourceSkeleton); Transform[] poseBones = UMABonePose.GetTransformsInPrefab(poseSkeleton); List <UMABonePose.PoseBone> poseList = new List <UMABonePose.PoseBone>(); foreach (Transform bone in poseBones) { Transform source = System.Array.Find <Transform>(sourceBones, entry => entry.name == bone.name); if (source) { if ((bone.localPosition != source.localPosition) || (bone.localRotation != source.localRotation) || (bone.localScale != source.localScale)) { UMABonePose.PoseBone poseB = new UMABonePose.PoseBone(); poseB.bone = bone.name; poseB.position = bone.localPosition - source.localPosition; poseB.rotation = bone.localRotation * Quaternion.Inverse(source.localRotation); poseB.scale = new Vector3(bone.localScale.x / source.localScale.x, bone.localScale.y / source.localScale.y, bone.localScale.z / source.localScale.z); poseList.Add(poseB); } } else { Debug.Log("Unmatched bone: " + bone.name); } } bonePose.poses = poseList.ToArray(); EditorUtility.SetDirty(bonePose); AssetDatabase.SaveAssets(); } GUI.enabled = true; EditorGUI.indentLevel--; } EditorGUILayout.Space(); // Multiple poses from animation frames if (animOpen = EditorGUILayout.Foldout(animOpen, "Animation Source")) { EditorGUI.indentLevel++; poseAnimation = EditorGUILayout.ObjectField("Pose Animation", poseAnimation, typeof(AnimationClip), false) as AnimationClip; if (poses == null) { poses = new List <AnimationPose>(); poses.Add(new AnimationPose()); } bool validPose = false; AnimationPose deletedPose = null; scrollPosition = GUILayout.BeginScrollView(scrollPosition); foreach (AnimationPose pose in poses) { GUILayout.BeginHorizontal(); EditorGUILayout.LabelField("ID", GUILayout.Width(50f)); pose.ID = EditorGUILayout.TextField(pose.ID); EditorGUILayout.LabelField("Frame", GUILayout.Width(60f)); pose.frame = EditorGUILayout.IntField(pose.frame, GUILayout.Width(50f)); if ((pose.ID != null) && (pose.ID.Length > 0)) { validPose = true; } if (GUILayout.Button("-", GUILayout.Width(20f))) { deletedPose = pose; validPose = false; break; } GUILayout.EndHorizontal(); } if (deletedPose != null) { poses.Remove(deletedPose); } GUILayout.EndScrollView(); GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (GUILayout.Button("+", GUILayout.Width(30f))) { poses.Add(new AnimationPose()); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if (GUILayout.Button("Load Pose Set")) { LoadPoseSet(); } if (!validPose) { GUI.enabled = false; } if (GUILayout.Button("Save Pose Set")) { SavePoseSet(); } GUI.enabled = true; GUILayout.EndHorizontal(); if ((sourceSkeleton == null) || (poseAnimation == null) || (!validPose)) { GUI.enabled = false; } if (GUILayout.Button("Build Poses")) { string folderPath; if (poseFolder != null) { folderPath = AssetDatabase.GetAssetPath(poseFolder); } else { folderPath = AssetDatabase.GetAssetPath(poseAnimation); folderPath = folderPath.Substring(0, folderPath.LastIndexOf('/')); } Transform[] sourceBones = UMABonePose.GetTransformsInPrefab(sourceSkeleton); EditorCurveBinding[] bindings = AnimationUtility.GetCurveBindings(poseAnimation); Dictionary <string, Vector3> positions = new Dictionary <string, Vector3>(); Dictionary <string, Quaternion> rotations = new Dictionary <string, Quaternion>(); Dictionary <string, Vector3> scales = new Dictionary <string, Vector3>(); foreach (AnimationPose pose in poses) { if ((pose.ID == null) || (pose.ID.Length < 1)) { Debug.LogWarning("Bad pose identifier, not building for frame: " + pose.frame); continue; } float time = (float)pose.frame / poseAnimation.frameRate; if ((time < 0f) || (time > poseAnimation.length)) { Debug.LogWarning("Bad frame number, not building for pose: " + pose.ID); continue; } positions.Clear(); rotations.Clear(); scales.Clear(); foreach (EditorCurveBinding binding in bindings) { if (binding.type == typeof(Transform)) { AnimationCurve curve = AnimationUtility.GetEditorCurve(poseAnimation, binding); float val = curve.Evaluate(time); Vector3 position; Quaternion rotation; Vector3 scale; switch (binding.propertyName) { case "m_LocalPosition.x": if (positions.TryGetValue(binding.path, out position)) { position.x = val; positions[binding.path] = position; } else { position = new Vector3(); position.x = val; positions.Add(binding.path, position); } break; case "m_LocalPosition.y": if (positions.TryGetValue(binding.path, out position)) { position.y = val; positions[binding.path] = position; } else { position = new Vector3(); position.y = val; positions.Add(binding.path, position); } break; case "m_LocalPosition.z": if (positions.TryGetValue(binding.path, out position)) { position.z = val; positions[binding.path] = position; } else { position = new Vector3(); position.z = val; positions.Add(binding.path, position); } break; case "m_LocalRotation.w": if (rotations.TryGetValue(binding.path, out rotation)) { rotation.w = val; rotations[binding.path] = rotation; } else { rotation = new Quaternion(); rotation.w = val; rotations.Add(binding.path, rotation); } break; case "m_LocalRotation.x": if (rotations.TryGetValue(binding.path, out rotation)) { rotation.x = val; rotations[binding.path] = rotation; } else { rotation = new Quaternion(); rotation.x = val; rotations.Add(binding.path, rotation); } break; case "m_LocalRotation.y": if (rotations.TryGetValue(binding.path, out rotation)) { rotation.y = val; rotations[binding.path] = rotation; } else { rotation = new Quaternion(); rotation.y = val; rotations.Add(binding.path, rotation); } break; case "m_LocalRotation.z": if (rotations.TryGetValue(binding.path, out rotation)) { rotation.z = val; rotations[binding.path] = rotation; } else { rotation = new Quaternion(); rotation.z = val; rotations.Add(binding.path, rotation); } break; case "m_LocalScale.x": if (scales.TryGetValue(binding.path, out scale)) { scale.x = val; scales[binding.path] = scale; } else { scale = new Vector3(); scale.x = val; scales.Add(binding.path, scale); } break; case "m_LocalScale.y": if (scales.TryGetValue(binding.path, out scale)) { scale.y = val; scales[binding.path] = scale; } else { scale = new Vector3(); scale.y = val; scales.Add(binding.path, scale); } break; case "m_LocalScale.z": if (scales.TryGetValue(binding.path, out scale)) { scale.z = val; scales[binding.path] = scale; } else { scale = new Vector3(); scale.z = val; scales.Add(binding.path, scale); } break; default: Debug.LogError("Unexpected property:" + binding.propertyName); break; } } } UMABonePose bonePose = CreatePoseAsset(folderPath, pose.ID); foreach (Transform bone in sourceBones) { string path = AnimationUtility.CalculateTransformPath(bone, sourceSkeleton.parent); Vector3 position; Quaternion rotation; Vector3 scale; if (!positions.TryGetValue(path, out position)) { position = bone.localPosition; } if (!rotations.TryGetValue(path, out rotation)) { rotation = bone.localRotation; } if (!scales.TryGetValue(path, out scale)) { scale = bone.localScale; } if ((bone.localPosition != position) || (bone.localRotation != rotation) || (bone.localScale != scale)) { bonePose.AddBone(bone, position, rotation, scale); } } EditorUtility.SetDirty(bonePose); } AssetDatabase.SaveAssets(); } GUI.enabled = true; EditorGUI.indentLevel--; } }