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) { } } }