namespace UnityEngine.Animations.Rigging
{
///
/// The TwoBoneIK constraint job.
///
[Unity.Burst.BurstCompile]
public struct TwoBoneIKConstraintJob : IWeightedAnimationJob
{
/// The transform handle for the root transform.
public ReadWriteTransformHandle root;
/// The transform handle for the mid transform.
public ReadWriteTransformHandle mid;
/// The transform handle for the tip transform.
public ReadWriteTransformHandle tip;
/// The transform handle for the hint transform.
public ReadOnlyTransformHandle hint;
/// The transform handle for the target transform.
public ReadOnlyTransformHandle target;
/// The offset applied to the target transform if maintainTargetPositionOffset or maintainTargetRotationOffset is enabled.
public AffineTransform targetOffset;
/// The weight for which target position has an effect on IK calculations. This is a value in between 0 and 1.
public FloatProperty targetPositionWeight;
/// The weight for which target rotation has an effect on IK calculations. This is a value in between 0 and 1.
public FloatProperty targetRotationWeight;
/// The weight for which hint transform has an effect on IK calculations. This is a value in between 0 and 1.
public FloatProperty hintWeight;
/// The main weight given to the constraint. This is a value in between 0 and 1.
public FloatProperty jobWeight { get; set; }
///
/// Defines what to do when processing the root motion.
///
/// The animation stream to work on.
public void ProcessRootMotion(AnimationStream stream) { }
///
/// Defines what to do when processing the animation.
///
/// The animation stream to work on.
public void ProcessAnimation(AnimationStream stream)
{
float w = jobWeight.Get(stream);
if (w > 0f)
{
AnimationRuntimeUtils.SolveTwoBoneIK(
stream, root, mid, tip, target, hint,
targetPositionWeight.Get(stream) * w,
targetRotationWeight.Get(stream) * w,
hintWeight.Get(stream) * w,
targetOffset
);
}
else
{
AnimationRuntimeUtils.PassThrough(stream, root);
AnimationRuntimeUtils.PassThrough(stream, mid);
AnimationRuntimeUtils.PassThrough(stream, tip);
}
}
}
///
/// This interface defines the data mapping for the TwoBoneIK constraint.
///
public interface ITwoBoneIKConstraintData
{
/// The root transform of the two bones hierarchy.
Transform root { get; }
/// The mid transform of the two bones hierarchy.
Transform mid { get; }
/// The tip transform of the two bones hierarchy.
Transform tip { get; }
/// The IK target transform.
Transform target { get; }
/// The IK hint transform.
Transform hint { get; }
/// This is used to maintain the offset of the tip position to the target position.
bool maintainTargetPositionOffset { get; }
/// This is used to maintain the offset of the tip rotation to the target rotation.
bool maintainTargetRotationOffset { get; }
/// The path to the target position weight property in the constraint component.
string targetPositionWeightFloatProperty { get; }
/// The path to the target rotation weight property in the constraint component.
string targetRotationWeightFloatProperty { get; }
/// The path to the hint weight property in the constraint component.
string hintWeightFloatProperty { get; }
}
///
/// The TwoBoneIK constraint job binder.
///
/// The constraint data type
public class TwoBoneIKConstraintJobBinder : AnimationJobBinder
where T : struct, IAnimationJobData, ITwoBoneIKConstraintData
{
///
/// Creates the animation job.
///
/// The animated hierarchy Animator component.
/// The constraint data.
/// The constraint component.
/// Returns a new job interface.
public override TwoBoneIKConstraintJob Create(Animator animator, ref T data, Component component)
{
var job = new TwoBoneIKConstraintJob();
job.root = ReadWriteTransformHandle.Bind(animator, data.root);
job.mid = ReadWriteTransformHandle.Bind(animator, data.mid);
job.tip = ReadWriteTransformHandle.Bind(animator, data.tip);
job.target = ReadOnlyTransformHandle.Bind(animator, data.target);
if (data.hint != null)
job.hint = ReadOnlyTransformHandle.Bind(animator, data.hint);
job.targetOffset = AffineTransform.identity;
if (data.maintainTargetPositionOffset)
job.targetOffset.translation = data.tip.position - data.target.position;
if (data.maintainTargetRotationOffset)
job.targetOffset.rotation = Quaternion.Inverse(data.target.rotation) * data.tip.rotation;
job.targetPositionWeight = FloatProperty.Bind(animator, component, data.targetPositionWeightFloatProperty);
job.targetRotationWeight = FloatProperty.Bind(animator, component, data.targetRotationWeightFloatProperty);
job.hintWeight = FloatProperty.Bind(animator, component, data.hintWeightFloatProperty);
return job;
}
///
/// Destroys the animation job.
///
/// The animation job to destroy.
public override void Destroy(TwoBoneIKConstraintJob job)
{
}
}
}