Files
2026-03-04 09:37:33 +08:00

190 lines
4.3 KiB
C#

using System;
using UnityEngine;
namespace RootMotion.FinalIK
{
[Serializable]
public class IKMappingLimb : IKMapping
{
[Serializable]
public enum BoneMapType
{
Parent = 0,
Bone1 = 1,
Bone2 = 2,
Bone3 = 3
}
public Transform parentBone;
public Transform bone1;
public Transform bone2;
public Transform bone3;
[Range(0f, 1f)]
public float maintainRotationWeight;
[Range(0f, 1f)]
public float weight = 1f;
[NonSerialized]
public bool updatePlaneRotations = true;
private BoneMap boneMapParent = new BoneMap();
private BoneMap boneMap1 = new BoneMap();
private BoneMap boneMap2 = new BoneMap();
private BoneMap boneMap3 = new BoneMap();
public override bool IsValid(IKSolver solver, ref string message)
{
if (!base.IsValid(solver, ref message))
{
return false;
}
if (!BoneIsValid(bone1, solver, ref message))
{
return false;
}
if (!BoneIsValid(bone2, solver, ref message))
{
return false;
}
if (!BoneIsValid(bone3, solver, ref message))
{
return false;
}
return true;
}
public BoneMap GetBoneMap(BoneMapType boneMap)
{
switch (boneMap)
{
case BoneMapType.Parent:
if (parentBone == null)
{
Warning.Log("This limb does not have a parent (shoulder) bone", bone1);
}
return boneMapParent;
case BoneMapType.Bone1:
return boneMap1;
case BoneMapType.Bone2:
return boneMap2;
default:
return boneMap3;
}
}
public void SetLimbOrientation(Vector3 upper, Vector3 lower)
{
boneMap1.defaultLocalTargetRotation = Quaternion.Inverse(Quaternion.Inverse(bone1.rotation) * Quaternion.LookRotation(bone2.position - bone1.position, bone1.rotation * -upper));
boneMap2.defaultLocalTargetRotation = Quaternion.Inverse(Quaternion.Inverse(bone2.rotation) * Quaternion.LookRotation(bone3.position - bone2.position, bone2.rotation * -lower));
}
public IKMappingLimb()
{
}
public IKMappingLimb(Transform bone1, Transform bone2, Transform bone3, Transform parentBone = null)
{
SetBones(bone1, bone2, bone3, parentBone);
}
public void SetBones(Transform bone1, Transform bone2, Transform bone3, Transform parentBone = null)
{
this.bone1 = bone1;
this.bone2 = bone2;
this.bone3 = bone3;
this.parentBone = parentBone;
}
public void StoreDefaultLocalState()
{
if (parentBone != null)
{
boneMapParent.StoreDefaultLocalState();
}
boneMap1.StoreDefaultLocalState();
boneMap2.StoreDefaultLocalState();
boneMap3.StoreDefaultLocalState();
}
public void FixTransforms()
{
if (parentBone != null)
{
boneMapParent.FixTransform(position: false);
}
boneMap1.FixTransform(position: true);
boneMap2.FixTransform(position: false);
boneMap3.FixTransform(position: false);
}
public override void Initiate(IKSolverFullBody solver)
{
if (boneMapParent == null)
{
boneMapParent = new BoneMap();
}
if (boneMap1 == null)
{
boneMap1 = new BoneMap();
}
if (boneMap2 == null)
{
boneMap2 = new BoneMap();
}
if (boneMap3 == null)
{
boneMap3 = new BoneMap();
}
if (parentBone != null)
{
boneMapParent.Initiate(parentBone, solver);
}
boneMap1.Initiate(bone1, solver);
boneMap2.Initiate(bone2, solver);
boneMap3.Initiate(bone3, solver);
boneMap1.SetPlane(solver, boneMap1.transform, boneMap2.transform, boneMap3.transform);
boneMap2.SetPlane(solver, boneMap2.transform, boneMap3.transform, boneMap1.transform);
if (parentBone != null)
{
boneMapParent.SetLocalSwingAxis(boneMap1);
}
}
public void ReadPose()
{
boneMap1.UpdatePlane(updatePlaneRotations, position: true);
boneMap2.UpdatePlane(updatePlaneRotations, position: false);
weight = Mathf.Clamp(weight, 0f, 1f);
boneMap3.MaintainRotation();
}
public void WritePose(IKSolverFullBody solver, bool fullBody)
{
if (weight <= 0f)
{
return;
}
if (fullBody)
{
if (parentBone != null)
{
boneMapParent.Swing(solver.GetNode(boneMap1.chainIndex, boneMap1.nodeIndex).solverPosition, weight);
}
boneMap1.FixToNode(solver, weight);
}
boneMap1.RotateToPlane(solver, weight);
boneMap2.RotateToPlane(solver, weight);
boneMap3.RotateToMaintain(maintainRotationWeight * weight * solver.IKPositionWeight);
boneMap3.RotateToEffector(solver, weight);
}
}
}