projectEli/Assets/NeoFPS/Core/Weapons/Shared/BaseWieldableStanceManager.cs
2022-11-06 20:28:33 -05:00

356 lines
13 KiB
C#

using System;
using UnityEngine;
namespace NeoFPS
{
public abstract class BaseWieldableStanceManager : MonoBehaviour
{
[SerializeField]
private Stance[] m_Stances = { };
private int m_CurrentStance = -1;
private IPoseHandler m_PoseHandler = null;
private Animator m_Animator = null;
private int m_Blockers = 0;
enum PositionBlend
{
Lerp,
EaseIn,
EaseOut,
EaseInOut,
SwingAcross,
SwingUp,
Spring,
Bounce,
Overshoot
}
enum RotationBlend
{
Lerp,
Slerp,
EaseIn,
EaseOut,
EaseInOut,
Spring,
Bounce,
Overshoot
}
[Serializable]
struct Stance
{
#pragma warning disable 0649
#if UNITY_EDITOR
public bool expanded;
#endif
[Tooltip("The name of the stance.")]
public string name;
[Tooltip("An optional name of a bool parameter in the weapon's animator.")]
public string animatorBoolKey;
[Tooltip("The position to move the weapon to in this stance.")]
public Vector3 position;
[Tooltip("The rotation of the weapon in this stance.")]
public Vector3 rotation;
[Tooltip("The easing method for blending between the source position and stance position on entering the stance.")]
public PositionBlend inPositionBlend;
[Tooltip("The easing method for blending between the source rotation and stance rotation on entering the stance.")]
public RotationBlend inRotationBlend;
[Tooltip("The time taken to enter the stance.")]
public float inTime;
[Tooltip("The easing method for blending between the stance position and idle position on exiting the stance.")]
public PositionBlend outPositionBlend;
[Tooltip("The easing method for blending between the stance rotation and Idle rotation on exiting the stance.")]
public RotationBlend outRotationBlend;
[Tooltip("The time taken to exit the stance.")]
public float outTime;
#pragma warning restore 0649
public int animatorBoolHash
{
get;
private set;
}
public void Awake()
{
if (!string.IsNullOrEmpty(animatorBoolKey))
animatorBoolHash = Animator.StringToHash(animatorBoolKey);
else
animatorBoolHash = -1;
}
public void OnValidate()
{
position.x = Mathf.Clamp(position.x, -1f, 1f);
position.y = Mathf.Clamp(position.y, -1f, 1f);
position.z = Mathf.Clamp(position.z, -1f, 1f);
rotation.x = Mathf.Clamp(rotation.x, -90f, 90f);
rotation.y = Mathf.Clamp(rotation.y, -90f, 90f);
rotation.z = Mathf.Clamp(rotation.z, -90f, 90f);
inTime = Mathf.Clamp(inTime, 0f, 10f);
outTime = Mathf.Clamp(outTime, 0f, 10f);
}
}
public string currentStance
{
get
{
if (m_CurrentStance == -1)
return string.Empty;
else
return m_Stances[m_CurrentStance].name;
}
}
public bool isBlocked
{
get { return m_Blockers > 0; }
}
protected virtual void OnValidate()
{
for (int i = 0; i < m_Stances.Length; ++i)
m_Stances[i].OnValidate();
}
protected virtual void Awake()
{
m_Animator = GetComponentInChildren<Animator>();
m_PoseHandler = GetComponent<IPoseHandler>();
if (m_PoseHandler == null)
Debug.LogError("WieldableStanceManager requires a component that implements IPoseHandler to function");
for (int i = 0; i < m_Stances.Length; ++i)
m_Stances[i].Awake();
}
protected virtual void OnDisable()
{
m_Blockers = 0;
ResetStance();
}
protected void AddBlocker()
{
++m_Blockers;
if (m_Blockers == 1)
TransitionOut(m_CurrentStance);
}
protected void RemoveBlocker()
{
--m_Blockers;
switch (m_Blockers)
{
case 0:
TransitionIn(m_CurrentStance);
break;
case -1:
m_Blockers = 0;
break;
}
}
void TransitionOut(int index)
{
if (index != -1)
{
// Get the position blend function
CustomPositionInterpolation positionInterpolation = null;
switch (m_Stances[index].outPositionBlend)
{
case PositionBlend.Lerp:
positionInterpolation = PoseTransitions.PositionLerp;
break;
case PositionBlend.EaseIn:
positionInterpolation = PoseTransitions.PositionEaseInQuadratic;
break;
case PositionBlend.EaseOut:
positionInterpolation = PoseTransitions.PositionEaseOutQuadratic;
break;
case PositionBlend.SwingAcross:
positionInterpolation = PoseTransitions.PositionSwingAcross;
break;
case PositionBlend.SwingUp:
positionInterpolation = PoseTransitions.PositionSwingUp;
break;
case PositionBlend.Spring:
positionInterpolation = PoseTransitions.PositionSpringIn;
break;
case PositionBlend.Bounce:
positionInterpolation = PoseTransitions.PositionBounceIn;
break;
case PositionBlend.Overshoot:
positionInterpolation = PoseTransitions.PositionOvershootIn;
break;
}
// Get the rotation blend function
CustomRotationInterpolation rotationInterpolation = null;
switch (m_Stances[index].outRotationBlend)
{
case RotationBlend.Lerp:
rotationInterpolation = PoseTransitions.RotationLerp;
break;
case RotationBlend.EaseIn:
rotationInterpolation = PoseTransitions.RotationEaseInQuadratic;
break;
case RotationBlend.EaseOut:
rotationInterpolation = PoseTransitions.RotationEaseOutQuadratic;
break;
case RotationBlend.Slerp:
rotationInterpolation = PoseTransitions.RotationSlerp;
break;
case RotationBlend.Spring:
rotationInterpolation = PoseTransitions.RotationSpringIn;
break;
case RotationBlend.Bounce:
rotationInterpolation = PoseTransitions.RotationBounceIn;
break;
case RotationBlend.Overshoot:
rotationInterpolation = PoseTransitions.RotationOvershootIn;
break;
}
// Apply the reset
m_PoseHandler.ResetPose(positionInterpolation, rotationInterpolation, m_Stances[index].outTime);
}
}
void TransitionIn(int index)
{
if (index != -1)
{
// Get the position blend function
CustomPositionInterpolation positionInterpolation = null;
switch (m_Stances[index].inPositionBlend)
{
case PositionBlend.Lerp:
positionInterpolation = PoseTransitions.PositionLerp;
break;
case PositionBlend.EaseIn:
positionInterpolation = PoseTransitions.PositionEaseInQuadratic;
break;
case PositionBlend.EaseOut:
positionInterpolation = PoseTransitions.PositionEaseOutQuadratic;
break;
case PositionBlend.SwingAcross:
positionInterpolation = PoseTransitions.PositionSwingAcross;
break;
case PositionBlend.SwingUp:
positionInterpolation = PoseTransitions.PositionSwingUp;
break;
case PositionBlend.Spring:
positionInterpolation = PoseTransitions.PositionSpringIn;
break;
case PositionBlend.Bounce:
positionInterpolation = PoseTransitions.PositionBounceIn;
break;
case PositionBlend.Overshoot:
positionInterpolation = PoseTransitions.PositionOvershootIn;
break;
}
// Get the rotation blend function
CustomRotationInterpolation rotationInterpolation = null;
switch (m_Stances[index].inRotationBlend)
{
case RotationBlend.Lerp:
rotationInterpolation = PoseTransitions.RotationLerp;
break;
case RotationBlend.EaseIn:
rotationInterpolation = PoseTransitions.RotationEaseInQuadratic;
break;
case RotationBlend.EaseOut:
rotationInterpolation = PoseTransitions.RotationEaseOutQuadratic;
break;
case RotationBlend.Slerp:
rotationInterpolation = PoseTransitions.RotationSlerp;
break;
case RotationBlend.Spring:
rotationInterpolation = PoseTransitions.RotationSpringIn;
break;
case RotationBlend.Bounce:
rotationInterpolation = PoseTransitions.RotationBounceIn;
break;
case RotationBlend.Overshoot:
rotationInterpolation = PoseTransitions.RotationOvershootIn;
break;
}
// Set pose
m_PoseHandler.SetPose(m_Stances[index].position, positionInterpolation, Quaternion.Euler(m_Stances[index].rotation), rotationInterpolation, m_Stances[index].inTime);
}
}
public void SetStance(string stanceName)
{
if (enabled)
{
if (stanceName == string.Empty)
{
if (m_CurrentStance != -1)
{
// Reset pose
if (m_PoseHandler != null && !isBlocked)
TransitionOut(m_CurrentStance);
// Reset animator bool parameter
if (m_Animator != null && m_Stances[m_CurrentStance].animatorBoolHash != -1)
m_Animator.SetBool(m_Stances[m_CurrentStance].animatorBoolHash, false);
// Set stance to idle
m_CurrentStance = -1;
}
}
else
{
for (int i = 0; i < m_Stances.Length; ++i)
{
if (m_Stances[i].name == stanceName)
{
if (m_CurrentStance != i)
{
if (m_PoseHandler != null && !isBlocked)
TransitionIn(i);
// Set animator bool parameter
if (m_Animator != null)
{
// Reset old
if (m_CurrentStance != -1 && m_Stances[m_CurrentStance].animatorBoolHash != -1)
m_Animator.SetBool(m_Stances[m_CurrentStance].animatorBoolHash, false);
// Set new
if (m_Stances[i].animatorBoolHash != -1)
m_Animator.SetBool(m_Stances[i].animatorBoolHash, true);
}
m_CurrentStance = i;
}
break;
}
}
}
}
}
public void ResetStance()
{
if (m_CurrentStance != -1)
{
// Reset pose
if (m_PoseHandler != null)
m_PoseHandler.ResetPose(0f);
// Reset animator bool parameter
if (m_Animator != null && m_Stances[m_CurrentStance].animatorBoolHash != -1)
m_Animator.SetBool(m_Stances[m_CurrentStance].animatorBoolHash, false);
// Set stance to idle
m_CurrentStance = -1;
}
}
}
}