208 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			208 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System.Collections.Generic;
 | 
						|
using UnityEngine;
 | 
						|
 | 
						|
namespace Passer.Humanoid {
 | 
						|
 | 
						|
    [System.Serializable]
 | 
						|
    public class PoseMixer {
 | 
						|
        public List<MixedPose> mixedPoses = new List<MixedPose>();
 | 
						|
        [System.NonSerialized]
 | 
						|
        public int currentPoseIx;
 | 
						|
        [System.NonSerialized]
 | 
						|
        public int detectedPoseIx;
 | 
						|
        public enum PoseMode {
 | 
						|
            Set,
 | 
						|
            Detect
 | 
						|
        }
 | 
						|
        public PoseMode poseMode;
 | 
						|
        [System.NonSerialized]
 | 
						|
        public Pose detectedPose;
 | 
						|
 | 
						|
        // New version without currentPose
 | 
						|
        public void SetPoseValue(int newCurrentPoseIx, float value = 1) {
 | 
						|
            MixedPose currentPose = mixedPoses[newCurrentPoseIx];
 | 
						|
            if (currentPoseIx != newCurrentPoseIx && currentPose != null && !currentPose.additive) {
 | 
						|
                currentPoseIx = newCurrentPoseIx;
 | 
						|
 | 
						|
                for (int i = 0; i < mixedPoses.Count; i++) {
 | 
						|
                    MixedPose mixedPose = mixedPoses[i];
 | 
						|
                    if (mixedPose.value > 0 && i != currentPoseIx)
 | 
						|
                        mixedPose.previousValue = mixedPose.value;
 | 
						|
                    else
 | 
						|
                        mixedPose.previousValue = 0;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            if (currentPose != null) {
 | 
						|
                currentPose.value = value;
 | 
						|
 | 
						|
                if (!currentPose.additive) {
 | 
						|
                    float invValue = 1 - value;
 | 
						|
                    for (int j = 0; j < mixedPoses.Count; j++) {
 | 
						|
                        MixedPose mixedPose = mixedPoses[j];
 | 
						|
                        if (mixedPose.previousValue != 0)
 | 
						|
                            mixedPose.value = invValue * mixedPose.previousValue;
 | 
						|
                    }
 | 
						|
                    //foreach (MixedPose mixedPose in mixedPoses) {
 | 
						|
                    //    if (mixedPose.previousValue != 0)
 | 
						|
                    //        mixedPose.value = invValue * mixedPose.previousValue;
 | 
						|
                    //}
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
        }
 | 
						|
 | 
						|
        public void SetPoseValue(Pose newCurrentPose, float value = 1) {
 | 
						|
            if (newCurrentPose == null)
 | 
						|
                return;
 | 
						|
 | 
						|
            int poseIx = GetPoseIx(newCurrentPose);
 | 
						|
            if (value == 0 && poseIx == currentPoseIx) {
 | 
						|
                Remove(newCurrentPose);
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            SetPoseValue(poseIx, value);
 | 
						|
        }
 | 
						|
 | 
						|
        public virtual MixedPose Add() {
 | 
						|
            MixedPose newMixedPose = new MixedPose() {
 | 
						|
                pose = ScriptableObject.CreateInstance<Pose>()
 | 
						|
            };
 | 
						|
            mixedPoses.Add(newMixedPose);
 | 
						|
            return newMixedPose;
 | 
						|
        }
 | 
						|
 | 
						|
        public MixedPose Add(Pose _pose) {
 | 
						|
            MixedPose foundMixedPose = mixedPoses.Find(mixedPose => mixedPose.pose == _pose);
 | 
						|
            if (foundMixedPose != null)
 | 
						|
                return foundMixedPose;
 | 
						|
            MixedPose newMixedPose = new MixedPose() {
 | 
						|
                pose = _pose
 | 
						|
            };
 | 
						|
            mixedPoses.Add(newMixedPose);
 | 
						|
            return newMixedPose;
 | 
						|
        }
 | 
						|
        public void Remove(Pose _pose) {
 | 
						|
            mixedPoses.RemoveAll(mixedPose => mixedPose.pose == _pose);
 | 
						|
        }
 | 
						|
 | 
						|
        public int GetPoseIx(Pose _pose) {
 | 
						|
            int ix = mixedPoses.FindIndex(mixedPose => mixedPose.pose == _pose);
 | 
						|
            if (ix != -1)
 | 
						|
                return ix;
 | 
						|
            MixedPose newMixedPose = new MixedPose() {
 | 
						|
                pose = _pose
 | 
						|
            };
 | 
						|
            mixedPoses.Add(newMixedPose);
 | 
						|
            // position is last position;
 | 
						|
            return mixedPoses.Count - 1;
 | 
						|
        }
 | 
						|
        public MixedPose GetEditedPose() {
 | 
						|
            foreach (MixedPose mixedPose in mixedPoses) {
 | 
						|
                if (mixedPose.pose != null && mixedPose.isEdited)
 | 
						|
                    return mixedPose;
 | 
						|
            }
 | 
						|
            return null;
 | 
						|
        }
 | 
						|
 | 
						|
        public void ShowPose(HumanoidControl humanoid) {
 | 
						|
            foreach (MixedPose mixedPose in mixedPoses) {
 | 
						|
                if (mixedPose != null && mixedPose.pose != null)
 | 
						|
                    mixedPose.pose.Show(humanoid, mixedPose.value);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        public void ShowPose(HumanoidControl humanoid, Side showSide) {
 | 
						|
            detectedPoseIx = -1;
 | 
						|
            float bestScore = -1;
 | 
						|
 | 
						|
            if (poseMode == PoseMode.Set)
 | 
						|
                ResetAffectedBones(humanoid, showSide);
 | 
						|
            int i = 0;
 | 
						|
            foreach (MixedPose mixedPose in mixedPoses) {
 | 
						|
                if (poseMode == PoseMode.Set && mixedPose != null && mixedPose.pose != null) {
 | 
						|
                    mixedPose.pose.ShowAdditive(humanoid, showSide, mixedPose.value);
 | 
						|
                }
 | 
						|
                mixedPose.UpdateScore(humanoid, showSide);
 | 
						|
                if (mixedPose.score > bestScore) {
 | 
						|
                    detectedPoseIx = i;
 | 
						|
                    bestScore = mixedPose.score;
 | 
						|
                    detectedPose = mixedPose.pose;
 | 
						|
                }
 | 
						|
                i++;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        public void ResetAffectedBones(HumanoidControl humanoid, Side showSide) {
 | 
						|
            foreach (MixedPose mixedPose in mixedPoses) {
 | 
						|
                if (mixedPose != null && mixedPose.pose != null && mixedPose.pose.bonePoses != null) {
 | 
						|
 | 
						|
                    foreach (BonePose bonePose in mixedPose.pose.bonePoses) {
 | 
						|
                        HumanoidTarget.TargetedBone targetedBone = humanoid.GetBone(showSide, bonePose.boneRef.sideBoneId);
 | 
						|
                        if (targetedBone == null || targetedBone.target.transform == null)
 | 
						|
                            continue;
 | 
						|
 | 
						|
                        if (bonePose.setTranslation)
 | 
						|
                            targetedBone.target.transform.position = targetedBone.TargetBasePosition();
 | 
						|
                        if (bonePose.setRotation)
 | 
						|
                            targetedBone.target.transform.rotation = targetedBone.TargetBaseRotation();
 | 
						|
                        if (bonePose.setRotation)
 | 
						|
                            targetedBone.target.transform.localScale = Vector3.one;
 | 
						|
                    }
 | 
						|
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        public void Cleanup() {
 | 
						|
            mixedPoses.RemoveAll(mixedPose => mixedPose.pose == null);
 | 
						|
        }
 | 
						|
 | 
						|
        public string[] GetPoseNames() {
 | 
						|
            string[] poseNames = new string[mixedPoses.Count];//.Length];
 | 
						|
            for (int i = 0; i < poseNames.Length; i++) {
 | 
						|
                if (mixedPoses[i].pose == null)
 | 
						|
                    poseNames[i] = "";
 | 
						|
                else
 | 
						|
                    poseNames[i] = mixedPoses[i].pose.name;
 | 
						|
            }
 | 
						|
            return poseNames;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    [System.Serializable]
 | 
						|
    public class MixedPose {
 | 
						|
        /// <summary>
 | 
						|
        /// The pose itself
 | 
						|
        /// </summary>
 | 
						|
        public Pose pose;
 | 
						|
        /// <summary>
 | 
						|
        /// The current value of the pose
 | 
						|
        /// </summary>
 | 
						|
        public float value;
 | 
						|
        /// <summary>
 | 
						|
        /// This is an additive pose
 | 
						|
        /// </summary>
 | 
						|
        public bool additive;
 | 
						|
        /// <summary>
 | 
						|
        /// The value of the pose when it became the previous pose
 | 
						|
        /// </summary>
 | 
						|
        [System.NonSerialized]
 | 
						|
        public float previousValue;
 | 
						|
        /// <summary>
 | 
						|
        /// Pose is in editing mode
 | 
						|
        /// </summary>
 | 
						|
        public bool isEdited;
 | 
						|
        /// <summary> Score indicating how much the current pose matched this pose</summary>
 | 
						|
        [System.NonSerialized]
 | 
						|
        public float score;
 | 
						|
 | 
						|
        public void UpdateScore(HumanoidControl humanoid, Side side) {
 | 
						|
            if (pose == null)
 | 
						|
                return;
 | 
						|
 | 
						|
            score = pose.GetScore(humanoid, side);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 |