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();
        }
Exemplo n.º 2
0
        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--;
            }
        }