namespace UnityEngine.Animations.Rigging { /// /// The ChainIK constraint data. /// [System.Serializable] public struct ChainIKConstraintData : IAnimationJobData, IChainIKConstraintData { internal const int k_MinIterations = 1; internal const int k_MaxIterations = 50; internal const float k_MinTolerance = 0f; internal const float k_MaxTolerance = 0.01f; [SerializeField] Transform m_Root; [SerializeField] Transform m_Tip; [SyncSceneToStream, SerializeField] Transform m_Target; [SyncSceneToStream, SerializeField, Range(0f, 1f)] float m_ChainRotationWeight; [SyncSceneToStream, SerializeField, Range(0f, 1f)] float m_TipRotationWeight; [NotKeyable, SerializeField, Range(k_MinIterations, k_MaxIterations)] int m_MaxIterations; [NotKeyable, SerializeField, Range(k_MinTolerance, k_MaxTolerance)] float m_Tolerance; [NotKeyable, SerializeField] bool m_MaintainTargetPositionOffset; [NotKeyable, SerializeField] bool m_MaintainTargetRotationOffset; /// public Transform root { get => m_Root; set => m_Root = value; } /// public Transform tip { get => m_Tip; set => m_Tip = value; } /// public Transform target { get => m_Target; set => m_Target = value; } /// The weight for which ChainIK target has an effect on chain (up to tip Transform). This is a value in between 0 and 1. public float chainRotationWeight { get => m_ChainRotationWeight; set => m_ChainRotationWeight = Mathf.Clamp01(value); } /// The weight for which ChainIK target has and effect on tip Transform. This is a value in between 0 and 1. public float tipRotationWeight { get => m_TipRotationWeight; set => m_TipRotationWeight = Mathf.Clamp01(value); } /// public int maxIterations { get => m_MaxIterations; set => m_MaxIterations = Mathf.Clamp(value, k_MinIterations, k_MaxIterations); } /// public float tolerance { get => m_Tolerance; set => m_Tolerance = Mathf.Clamp(value, k_MinTolerance, k_MaxTolerance); } /// public bool maintainTargetPositionOffset { get => m_MaintainTargetPositionOffset; set => m_MaintainTargetPositionOffset = value; } /// public bool maintainTargetRotationOffset { get => m_MaintainTargetRotationOffset; set => m_MaintainTargetRotationOffset = value; } /// string IChainIKConstraintData.chainRotationWeightFloatProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_ChainRotationWeight)); /// string IChainIKConstraintData.tipRotationWeightFloatProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_TipRotationWeight)); /// bool IAnimationJobData.IsValid() { if (m_Root == null || m_Tip == null || m_Target == null) return false; int count = 1; Transform tmp = m_Tip; while (tmp != null && tmp != m_Root) { tmp = tmp.parent; ++count; } return (tmp == m_Root && count > 2); } /// void IAnimationJobData.SetDefaultValues() { m_Root = null; m_Tip = null; m_Target = null; m_ChainRotationWeight = 1f; m_TipRotationWeight = 1f; m_MaxIterations = 15; m_Tolerance = 0.0001f; m_MaintainTargetPositionOffset = false; m_MaintainTargetRotationOffset = false; } } /// /// ChainIK constraint /// [DisallowMultipleComponent, AddComponentMenu("Animation Rigging/Chain IK Constraint")] [HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.3/manual/constraints/ChainIKConstraint.html")] public class ChainIKConstraint : RigConstraint< ChainIKConstraintJob, ChainIKConstraintData, ChainIKConstraintJobBinder > { /// protected override void OnValidate() { base.OnValidate(); m_Data.chainRotationWeight = Mathf.Clamp01(m_Data.chainRotationWeight); m_Data.tipRotationWeight = Mathf.Clamp01(m_Data.tipRotationWeight); m_Data.maxIterations = Mathf.Clamp( m_Data.maxIterations, ChainIKConstraintData.k_MinIterations, ChainIKConstraintData.k_MaxIterations ); m_Data.tolerance = Mathf.Clamp( m_Data.tolerance, ChainIKConstraintData.k_MinTolerance, ChainIKConstraintData.k_MaxTolerance ); } } }