Files
Ultimate-Fishing-Simulator-…/Assets/Scripts/Assembly-CSharp/RootMotion/FinalIK/IKSolverLimb.cs
2026-03-04 09:37:33 +08:00

266 lines
6.6 KiB
C#

using System;
using UnityEngine;
namespace RootMotion.FinalIK
{
[Serializable]
public class IKSolverLimb : IKSolverTrigonometric
{
[Serializable]
public enum BendModifier
{
Animation = 0,
Target = 1,
Parent = 2,
Arm = 3,
Goal = 4
}
[Serializable]
public struct AxisDirection
{
public Vector3 direction;
public Vector3 axis;
public float dot;
public AxisDirection(Vector3 direction, Vector3 axis)
{
this.direction = direction.normalized;
this.axis = axis.normalized;
dot = 0f;
}
}
public AvatarIKGoal goal;
public BendModifier bendModifier;
[Range(0f, 1f)]
public float maintainRotationWeight;
[Range(0f, 1f)]
public float bendModifierWeight = 1f;
public Transform bendGoal;
private bool maintainBendFor1Frame;
private bool maintainRotationFor1Frame;
private Quaternion defaultRootRotation;
private Quaternion parentDefaultRotation;
private Quaternion bone3RotationBeforeSolve;
private Quaternion maintainRotation;
private Quaternion bone3DefaultRotation;
private Vector3 _bendNormal;
private Vector3 animationNormal;
private AxisDirection[] axisDirectionsLeft = new AxisDirection[4];
private AxisDirection[] axisDirectionsRight = new AxisDirection[4];
private AxisDirection[] axisDirections
{
get
{
if (goal == AvatarIKGoal.LeftHand)
{
return axisDirectionsLeft;
}
return axisDirectionsRight;
}
}
public void MaintainRotation()
{
if (base.initiated)
{
maintainRotation = bone3.transform.rotation;
maintainRotationFor1Frame = true;
}
}
public void MaintainBend()
{
if (base.initiated)
{
animationNormal = bone1.GetBendNormalFromCurrentRotation();
maintainBendFor1Frame = true;
}
}
protected override void OnInitiateVirtual()
{
defaultRootRotation = root.rotation;
if (bone1.transform.parent != null)
{
parentDefaultRotation = Quaternion.Inverse(defaultRootRotation) * bone1.transform.parent.rotation;
}
if (bone3.rotationLimit != null)
{
bone3.rotationLimit.Disable();
}
bone3DefaultRotation = bone3.transform.rotation;
Vector3 vector = Vector3.Cross(bone2.transform.position - bone1.transform.position, bone3.transform.position - bone2.transform.position);
if (vector != Vector3.zero)
{
bendNormal = vector;
}
animationNormal = bendNormal;
StoreAxisDirections(ref axisDirectionsLeft);
StoreAxisDirections(ref axisDirectionsRight);
}
protected override void OnUpdateVirtual()
{
if (IKPositionWeight > 0f)
{
bendModifierWeight = Mathf.Clamp(bendModifierWeight, 0f, 1f);
maintainRotationWeight = Mathf.Clamp(maintainRotationWeight, 0f, 1f);
_bendNormal = bendNormal;
bendNormal = GetModifiedBendNormal();
}
if (maintainRotationWeight * IKPositionWeight > 0f)
{
bone3RotationBeforeSolve = (maintainRotationFor1Frame ? maintainRotation : bone3.transform.rotation);
maintainRotationFor1Frame = false;
}
}
protected override void OnPostSolveVirtual()
{
if (IKPositionWeight > 0f)
{
bendNormal = _bendNormal;
}
if (maintainRotationWeight * IKPositionWeight > 0f)
{
bone3.transform.rotation = Quaternion.Slerp(bone3.transform.rotation, bone3RotationBeforeSolve, maintainRotationWeight * IKPositionWeight);
}
}
public IKSolverLimb()
{
}
public IKSolverLimb(AvatarIKGoal goal)
{
this.goal = goal;
}
private void StoreAxisDirections(ref AxisDirection[] axisDirections)
{
axisDirections[0] = new AxisDirection(Vector3.zero, new Vector3(-1f, 0f, 0f));
axisDirections[1] = new AxisDirection(new Vector3(0.5f, 0f, -0.2f), new Vector3(-0.5f, -1f, 1f));
axisDirections[2] = new AxisDirection(new Vector3(-0.5f, -1f, -0.2f), new Vector3(0f, 0.5f, -1f));
axisDirections[3] = new AxisDirection(new Vector3(-0.5f, -0.5f, 1f), new Vector3(-1f, -1f, -1f));
}
private Vector3 GetModifiedBendNormal()
{
float num = bendModifierWeight;
if (num <= 0f)
{
return bendNormal;
}
switch (bendModifier)
{
case BendModifier.Animation:
if (!maintainBendFor1Frame)
{
MaintainBend();
}
maintainBendFor1Frame = false;
return Vector3.Lerp(bendNormal, animationNormal, num);
case BendModifier.Parent:
{
if (bone1.transform.parent == null)
{
return bendNormal;
}
Quaternion quaternion = bone1.transform.parent.rotation * Quaternion.Inverse(parentDefaultRotation);
return Quaternion.Slerp(Quaternion.identity, quaternion * Quaternion.Inverse(defaultRootRotation), num) * bendNormal;
}
case BendModifier.Target:
{
Quaternion b = IKRotation * Quaternion.Inverse(bone3DefaultRotation);
return Quaternion.Slerp(Quaternion.identity, b, num) * bendNormal;
}
case BendModifier.Arm:
{
if (bone1.transform.parent == null)
{
return bendNormal;
}
if (goal == AvatarIKGoal.LeftFoot || goal == AvatarIKGoal.RightFoot)
{
if (!Warning.logged)
{
LogWarning("Trying to use the 'Arm' bend modifier on a leg.");
}
return bendNormal;
}
Vector3 normalized = (IKPosition - bone1.transform.position).normalized;
normalized = Quaternion.Inverse(bone1.transform.parent.rotation * Quaternion.Inverse(parentDefaultRotation)) * normalized;
if (goal == AvatarIKGoal.LeftHand)
{
normalized.x = 0f - normalized.x;
}
for (int i = 1; i < axisDirections.Length; i++)
{
axisDirections[i].dot = Mathf.Clamp(Vector3.Dot(axisDirections[i].direction, normalized), 0f, 1f);
axisDirections[i].dot = Interp.Float(axisDirections[i].dot, InterpolationMode.InOutQuintic);
}
Vector3 vector2 = axisDirections[0].axis;
for (int j = 1; j < axisDirections.Length; j++)
{
vector2 = Vector3.Slerp(vector2, axisDirections[j].axis, axisDirections[j].dot);
}
if (goal == AvatarIKGoal.LeftHand)
{
vector2.x = 0f - vector2.x;
vector2 = -vector2;
}
Vector3 vector3 = bone1.transform.parent.rotation * Quaternion.Inverse(parentDefaultRotation) * vector2;
if (num >= 1f)
{
return vector3;
}
return Vector3.Lerp(bendNormal, vector3, num);
}
case BendModifier.Goal:
{
if (bendGoal == null)
{
if (!Warning.logged)
{
LogWarning("Trying to use the 'Goal' Bend Modifier, but the Bend Goal is unassigned.");
}
return bendNormal;
}
Vector3 vector = Vector3.Cross(bendGoal.position - bone1.transform.position, IKPosition - bone1.transform.position);
if (vector == Vector3.zero)
{
return bendNormal;
}
if (num >= 1f)
{
return vector;
}
return Vector3.Lerp(bendNormal, vector, num);
}
default:
return bendNormal;
}
}
}
}