PO/Library/PackageCache/com.unity.2d.animation@5.0.7/IK/Runtime/IKChain2D.cs

209 lines
6.7 KiB
C#

using System;
using UnityEngine.Scripting.APIUpdating;
using UnityEngine.Serialization;
namespace UnityEngine.U2D.IK
{
/// <summary>
/// Class for storing data for a 2D IK Chain.
/// </summary>
[MovedFrom("UnityEngine.Experimental.U2D.IK")]
[Serializable]
public class IKChain2D
{
[SerializeField][FormerlySerializedAs("m_Target")]
private Transform m_EffectorTransform;
[SerializeField][FormerlySerializedAs("m_Effector")]
private Transform m_TargetTransform;
[SerializeField]
private int m_TransformCount;
[SerializeField]
private Transform[] m_Transforms;
[SerializeField]
private Quaternion[] m_DefaultLocalRotations;
[SerializeField]
private Quaternion[] m_StoredLocalRotations;
protected float[] m_Lengths;
/// <summary>
/// Get Set the Unity Transform used as IK Effector.
/// </summary>
public Transform effector
{
get { return m_EffectorTransform; }
set { m_EffectorTransform = value; }
}
/// <summary>
/// Get Set the Unity Transform used as IK Target.
/// </summary>
public Transform target
{
get { return m_TargetTransform; }
set { m_TargetTransform = value; }
}
/// <summary>
/// Get the Unity Transforms that are in the IK Chain.
/// </summary>
public Transform[] transforms
{
get { return m_Transforms; }
}
/// <summary>
/// Get the root Unity Transform for the IK Chain.
/// </summary>
public Transform rootTransform
{
get
{
if (m_Transforms != null && transformCount > 0 && m_Transforms.Length == transformCount)
return m_Transforms[0];
return null;
}
}
private Transform lastTransform
{
get
{
if (m_Transforms != null && transformCount > 0 && m_Transforms.Length == transformCount)
return m_Transforms[transformCount - 1];
return null;
}
}
/// <summary>
/// Get and Set the number of Unity Transforms in the IK Chain.
/// </summary>
public int transformCount
{
get { return m_TransformCount; }
set { m_TransformCount = Mathf.Max(0, value); }
}
/// <summary>
/// Returns true if the IK Chain is valid. False otherwise.
/// </summary>
public bool isValid
{
get { return Validate(); }
}
/// <summary>
/// Gets the length of the IK Chain.
/// </summary>
public float[] lengths
{
get
{
if(isValid)
{
PrepareLengths();
return m_Lengths;
}
return null;
}
}
private bool Validate()
{
if (effector == null)
return false;
if (transformCount == 0)
return false;
if (m_Transforms == null || m_Transforms.Length != transformCount)
return false;
if (m_DefaultLocalRotations == null || m_DefaultLocalRotations.Length != transformCount)
return false;
if (m_StoredLocalRotations == null || m_StoredLocalRotations.Length != transformCount)
return false;
if (rootTransform == null)
return false;
if (lastTransform != effector)
return false;
if (target && IKUtility.IsDescendentOf(target, rootTransform))
return false;
return true;
}
/// <summary>
/// Initialize the IK Chain.
/// </summary>
public void Initialize()
{
if (effector == null || transformCount == 0 || IKUtility.GetAncestorCount(effector) < transformCount - 1)
return;
m_Transforms = new Transform[transformCount];
m_DefaultLocalRotations = new Quaternion[transformCount];
m_StoredLocalRotations = new Quaternion[transformCount];
var currentTransform = effector;
int index = transformCount - 1;
while (currentTransform && index >= 0)
{
m_Transforms[index] = currentTransform;
m_DefaultLocalRotations[index] = currentTransform.localRotation;
currentTransform = currentTransform.parent;
--index;
}
}
private void PrepareLengths()
{
var currentTransform = effector;
int index = transformCount - 1;
if (m_Lengths == null || m_Lengths.Length != transformCount - 1)
m_Lengths = new float[transformCount - 1];
while (currentTransform && index >= 0)
{
if (currentTransform.parent && index > 0)
m_Lengths[index - 1] = (currentTransform.position - currentTransform.parent.position).magnitude;
currentTransform = currentTransform.parent;
--index;
}
}
/// <summary>
/// Restores IK Chain to it's default pose.
/// </summary>
/// <param name="targetRotationIsConstrained">True to constrain the target rotation. False otherwise.</param>
public void RestoreDefaultPose(bool targetRotationIsConstrained)
{
var count = targetRotationIsConstrained ? transformCount : transformCount-1;
for (int i = 0; i < count; ++i)
m_Transforms[i].localRotation = m_DefaultLocalRotations[i];
}
/// <summary>
/// Explicitly stores the local rotation
/// </summary>
public void StoreLocalRotations()
{
for (int i = 0; i < m_Transforms.Length; ++i)
m_StoredLocalRotations[i] = m_Transforms[i].localRotation;
}
/// <summary>
/// Blend between Forward Kinematics and Inverse Kinematics.
/// </summary>
/// <param name="finalWeight">Weight for blend</param>
/// <param name="targetRotationIsConstrained">True to constrain target rotation. False otherwise.</param>
public void BlendFkToIk(float finalWeight, bool targetRotationIsConstrained)
{
var count = targetRotationIsConstrained ? transformCount : transformCount-1;
for (int i = 0; i < count; ++i)
m_Transforms[i].localRotation = Quaternion.Slerp(m_StoredLocalRotations[i], m_Transforms[i].localRotation, finalWeight);
}
}
}