public void OnEnable() { if (saveUMAData != null) { sourceUMA = saveUMAData; } if (treeState == null) { treeState = new TreeViewState(); } boneTreeView = new BoneTreeView(treeState); targetPose = target as UMABonePose; // inspectorLocked = ActiveEditorTracker.sharedTracker.isLocked; // ActiveEditorTracker.sharedTracker.isLocked = true; EditorApplication.update += this.OnUpdate; #if UNITY_2019_1_OR_NEWER SceneView.duringSceneGui += this.OnSceneGUI; #else SceneView.onSceneGUIDelegate += this.OnSceneGUI; #endif if (warningIcon == null) { warningIcon = EditorGUIUtility.FindTexture("console.warnicon.sml"); } // if (trashIcon == null) // { // trashIcon = EditorGUIUtility.FindTexture("TreeEditor.Trash"); // } }
void Update() { if (expressionSet == null) { return; } if (skeletonRoot == null) { return; } if (expressionPlayer == null) { expressionPlayer = gameObject.GetComponent <ExpressionPlayer>(); if (expressionPlayer == null) { if (Debug.isDebugBuild) { Debug.LogWarning("Couldn't find expression player to preview!"); } return; } } if (skeleton == null) { skeleton = new UMASkeleton(skeletonRoot); } expressionSet.RestoreBones(skeleton); float[] values = expressionPlayer.Values; for (int i = 0; i < values.Length; i++) { float weight = values[i]; UMABonePose pose = null; if (weight > 0) { pose = expressionSet.posePairs[i].primary; } else { weight = -weight; pose = expressionSet.posePairs[i].inverse; } if (pose == null) { continue; } pose.ApplyPose(skeleton, weight); } }
public static UMABonePose CreatePoseAsset(string assetFolder, string assetName) { if (!System.IO.Directory.Exists(assetFolder)) { System.IO.Directory.CreateDirectory(assetFolder); } UMABonePose asset = ScriptableObject.CreateInstance <UMABonePose>(); AssetDatabase.CreateAsset(asset, assetFolder + "/" + assetName + ".asset"); return(asset); }
public void OnEnable() { targetPose = target as UMABonePose; // inspectorLocked = ActiveEditorTracker.sharedTracker.isLocked; // ActiveEditorTracker.sharedTracker.isLocked = true; EditorApplication.update += this.OnUpdate; SceneView.onSceneGUIDelegate += this.OnSceneGUI; if (warningIcon == null) { warningIcon = EditorGUIUtility.FindTexture("console.warnicon.sml"); } // if (trashIcon == null) // { // trashIcon = EditorGUIUtility.FindTexture("TreeEditor.Trash"); // } }
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(); }
void OnGUI() { EditorGUIUtility.LookLikeControls(); 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(); }
void LateUpdate() { if (!initialized) { return; } if (umaData == null || umaData.skeleton == null) { return; } if (enableSaccades) { UpdateSaccades(); } if (enableBlinking) { UpdateBlinking(); } float[] values = Values; MecanimJoint mecanimMask = MecanimJoint.None; if (!overrideMecanimNeck) { mecanimMask |= MecanimJoint.Neck; } if (!overrideMecanimHead) { mecanimMask |= MecanimJoint.Head; } if (!overrideMecanimJaw) { mecanimMask |= MecanimJoint.Jaw; } if (!overrideMecanimEyes) { mecanimMask |= MecanimJoint.Eye; } if (overrideMecanimJaw) { umaData.skeleton.Restore(jawHash); } for (int i = 0; i < values.Length; i++) { if ((MecanimAlternate[i] & mecanimMask) != MecanimJoint.None) { continue; } float weight = values[i]; if (weight == 0f) { continue; } UMABonePose pose = null; if (weight > 0) { pose = expressionSet.posePairs[i].primary; } else { weight = -weight; pose = expressionSet.posePairs[i].inverse; } if ((weight > minWeight) && (pose != null)) { pose.ApplyPose(umaData.skeleton, weight); } } }
// 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); } }
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); } } } }
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--; } }
void LateUpdate() { if (!processing) { return; } if (!initialized) { return; } if (umaData == null || umaData.skeleton == null) { return; } if (_mainCameraTransform != null && useDisableDistance && (_mainCameraTransform.position - transform.position).sqrMagnitude > (disableDistance * disableDistance)) { return; } if (enableSaccades) { UpdateSaccades(); } if (enableBlinking) { UpdateBlinking(); } float[] values = Values; MecanimJoint mecanimMask = MecanimJoint.None; if (!overrideMecanimNeck) { mecanimMask |= MecanimJoint.Neck; } if (!overrideMecanimHead) { mecanimMask |= MecanimJoint.Head; } if (!overrideMecanimJaw) { mecanimMask |= MecanimJoint.Jaw; } if (!overrideMecanimEyes) { mecanimMask |= MecanimJoint.Eye; } if (!overrideMecanimHands) { mecanimMask |= MecanimJoint.Hands; } if (overrideMecanimJaw) { umaData.skeleton.Restore(jawHash); } if (LastValues == null || LastValues.Length < values.Length) { LastValues = new float[44]; saveValues(values); } for (int i = 0; i < values.Length; i++) { if (LastValues[i] != values[i]) { if (ExpressionChanged != null) { ExpressionChanged.Invoke(umaData, PoseNames[i], values[i]); } } if ((MecanimAlternate[i] & mecanimMask) != MecanimJoint.None) { continue; } float weight = values[i]; if (weight == 0f) { continue; } UMABonePose pose = null; if (weight > 0) { pose = expressionSet.posePairs[i].primary; } else { weight = -weight; pose = expressionSet.posePairs[i].inverse; } if ((weight > minWeight) && (pose != null)) { pose.ApplyPose(umaData.skeleton, weight); } } saveValues(values); }