Pascal Serrarens de12c36220 First commit
2022-01-11 16:51:37 +01:00

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