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() { 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--; } }