Files
2026-03-04 10:03:45 +08:00

131 lines
3.0 KiB
C#

using UnityEngine;
namespace RootMotion.FinalIK
{
public abstract class RotationLimit : MonoBehaviour
{
public Vector3 axis = Vector3.forward;
[HideInInspector]
public Quaternion defaultLocalRotation;
private bool initiated;
private bool applicationQuit;
private bool defaultLocalRotationSet;
public Vector3 secondaryAxis => new Vector3(axis.y, axis.z, axis.x);
public Vector3 crossAxis => Vector3.Cross(axis, secondaryAxis);
public bool defaultLocalRotationOverride { get; private set; }
public void SetDefaultLocalRotation()
{
defaultLocalRotation = base.transform.localRotation;
defaultLocalRotationSet = true;
defaultLocalRotationOverride = false;
}
public void SetDefaultLocalRotation(Quaternion localRotation)
{
defaultLocalRotation = localRotation;
defaultLocalRotationSet = true;
defaultLocalRotationOverride = true;
}
public Quaternion GetLimitedLocalRotation(Quaternion localRotation, out bool changed)
{
if (!initiated)
{
Awake();
}
Quaternion quaternion = Quaternion.Inverse(defaultLocalRotation) * localRotation;
Quaternion q = LimitRotation(quaternion);
q = Quaternion.Normalize(q);
changed = q != quaternion;
if (!changed)
{
return localRotation;
}
return defaultLocalRotation * q;
}
public bool Apply()
{
bool changed = false;
base.transform.localRotation = GetLimitedLocalRotation(base.transform.localRotation, out changed);
return changed;
}
public void Disable()
{
if (initiated)
{
base.enabled = false;
return;
}
Awake();
base.enabled = false;
}
protected abstract Quaternion LimitRotation(Quaternion rotation);
private void Awake()
{
if (!defaultLocalRotationSet)
{
SetDefaultLocalRotation();
}
if (axis == Vector3.zero)
{
Debug.LogError("Axis is Vector3.zero.");
}
initiated = true;
}
private void LateUpdate()
{
Apply();
}
public void LogWarning(string message)
{
Warning.Log(message, base.transform);
}
protected static Quaternion Limit1DOF(Quaternion rotation, Vector3 axis)
{
return Quaternion.FromToRotation(rotation * axis, axis) * rotation;
}
protected static Quaternion LimitTwist(Quaternion rotation, Vector3 axis, Vector3 orthoAxis, float twistLimit)
{
twistLimit = Mathf.Clamp(twistLimit, 0f, 180f);
if (twistLimit >= 180f)
{
return rotation;
}
Vector3 normal = rotation * axis;
Vector3 tangent = orthoAxis;
Vector3.OrthoNormalize(ref normal, ref tangent);
Vector3 tangent2 = rotation * orthoAxis;
Vector3.OrthoNormalize(ref normal, ref tangent2);
Quaternion quaternion = Quaternion.FromToRotation(tangent2, tangent) * rotation;
if (twistLimit <= 0f)
{
return quaternion;
}
return Quaternion.RotateTowards(quaternion, rotation, twistLimit);
}
protected static float GetOrthogonalAngle(Vector3 v1, Vector3 v2, Vector3 normal)
{
Vector3.OrthoNormalize(ref normal, ref v1);
Vector3.OrthoNormalize(ref normal, ref v2);
return Vector3.Angle(v1, v2);
}
}
}