using System; using System.Collections.Generic; using kt.Physics; using kt.Utility; using RootMotion.FinalIK; using UnityEngine; [Serializable] public class HandFootIKCtrl : ALimbIKCtrl { public HandFootIKCtrl(IKEffector effector, FBIKChain chain, IKMappingLimb ik_mapping, FullBodyIKMgr ik_ctrl, FullBodyIKMgr.IKEffectorType effector_type) : base(ik_ctrl, chain, ik_mapping, effector_type) { this.effector = effector; this.effector.target = base.constraintTarget; base.isUpperBody = (effector_type == FullBodyIKMgr.IKEffectorType.Hand_L || effector_type == FullBodyIKMgr.IKEffectorType.Hand_R); this.NoPullBodyIK = base.constraintTarget.parent.gameObject.AddComponent(); this.NoPullBodyIK.solver.SetChain(base.chainBones[0], base.chainBones[1], base.chainBones[2], base.chainBones[0]); this.NoPullBodyIK.solver.target = base.constraintTarget; this.NoPullBodyIK.solver.bendModifier = IKSolverLimb.BendModifier.Goal; this.NoPullBodyIK.solver.maintainRotationWeight = ik_mapping.maintainRotationWeight; this.NoPullBodyIK.enabled = false; switch (effector_type) { case FullBodyIKMgr.IKEffectorType.Hand_R: this.NoPullBodyIK.solver.goal = AvatarIKGoal.RightHand; break; default: switch (effector_type) { case FullBodyIKMgr.IKEffectorType.Foot_R: this.NoPullBodyIK.solver.goal = AvatarIKGoal.RightFoot; break; case FullBodyIKMgr.IKEffectorType.Foot_L: this.NoPullBodyIK.solver.goal = AvatarIKGoal.LeftFoot; break; } break; case FullBodyIKMgr.IKEffectorType.Hand_L: this.NoPullBodyIK.solver.goal = AvatarIKGoal.LeftHand; break; } if (!base.isUpperBody) { if (!this.myIKMgr.body.IsCrcBody && this.myIKMgr.chara.boMAN) { return; } string str = (this.effectorType != FullBodyIKMgr.IKEffectorType.Foot_L) ? "Bip01 R " : "Bip01 L "; Transform bone = this.myIKMgr.body.GetBone(str + "Toe0"); Transform bone2 = this.myIKMgr.body.GetBone(str + "Toe1"); Transform bone3 = this.myIKMgr.body.GetBone(str + "Toe2"); this.ToeBoneLocalAngleDic = new Dictionary(); this.ToeBoneLocalAngleDic[bone] = bone.localEulerAngles; this.ToeBoneLocalAngleDic[bone2] = bone2.localEulerAngles; this.ToeBoneLocalAngleDic[bone3] = bone3.localEulerAngles; if (this.isLeft) { base.limbCapsule = this.myIKMgr.body.limbColliderMgr.GetCollider(LimbColliderMgr.LimbType.Calf_L); } else { base.limbCapsule = this.myIKMgr.body.limbColliderMgr.GetCollider(LimbColliderMgr.LimbType.Calf_R); } } else if (this.isLeft) { base.limbCapsule = this.myIKMgr.body.limbColliderMgr.GetCollider(LimbColliderMgr.LimbType.Forearm_L); } else { base.limbCapsule = this.myIKMgr.body.limbColliderMgr.GetCollider(LimbColliderMgr.LimbType.Forearm_R); } } public override ALimbIKCtrl pairIK { get { FullBodyIKMgr.IKEffectorType effector_type; if (base.isUpperBody) { effector_type = ((!this.isLeft) ? FullBodyIKMgr.IKEffectorType.Hand_L : FullBodyIKMgr.IKEffectorType.Hand_R); } else { effector_type = ((!this.isLeft) ? FullBodyIKMgr.IKEffectorType.Foot_L : FullBodyIKMgr.IKEffectorType.Foot_R); } return this.myIKMgr.GetIKCtrl(effector_type); } } public override bool isLeft { get { return this.effectorType == FullBodyIKMgr.IKEffectorType.Hand_L || this.effectorType == FullBodyIKMgr.IKEffectorType.Foot_L; } } protected override bool IsUseOldIK { get { return this.effectorType == FullBodyIKMgr.IKEffectorType.Hand_L || this.effectorType == FullBodyIKMgr.IKEffectorType.Hand_R; } } public override bool isNeedFullbodySolverUpdate { get { return base.isNeedFullbodySolverUpdate && base.pointIKData.attachType != AIKCtrl.IKAttachType.Point; } } public ShoulderThighIKCtrl shoulderThighCtrl { get; private set; } public ElbowKneeIKCtrl elbowKneeCtrl { get; private set; } public void SetChain(ElbowKneeIKCtrl elbowknee_data, ShoulderThighIKCtrl shoulderthigh_data) { this.elbowKneeCtrl = elbowknee_data; this.ChainParentCtrl = elbowknee_data; this.shoulderThighCtrl = shoulderthigh_data; this.NoPullBodyIK.solver.bendGoal = elbowknee_data.constraintTarget; } public override void TargetTransCpy() { base.TargetTransCpy(); this.effector.positionWeight = 0f; this.effector.rotationWeight = 0f; this.NoPullBodyIK.solver.IKPositionWeight = 0f; this.NoPullBodyIK.solver.IKRotationWeight = 0f; this.NoPullBodyIK.solver.bendModifierWeight = 0f; } protected override void SetTargetTransform(AIKCtrl.IKSettingData data, Vector3 pos, Quaternion rot) { base.SetTargetTransform(data, pos, rot); if (!data.isPointAttach || data.attachType == AIKCtrl.IKAttachType.Point) { return; } this.CalcElbowKneeTgtPosRot(); } private void CalcElbowKneeTgtPosRot() { Transform constraintTarget = this.shoulderThighCtrl.constraintTarget; Transform constraintTarget2 = this.elbowKneeCtrl.constraintTarget; this.elbowKneeCtrl.rotationWeight = base.positionWeight; Vector3 fromDirection = base.bone.position - this.elbowKneeCtrl.bone.position; Vector3 toDirection = base.constraintTarget.position - constraintTarget2.position; constraintTarget2.rotation = Quaternion.FromToRotation(fromDirection, toDirection) * constraintTarget2.rotation; if (this.elbowKneeCtrl.pointIKData.isIKExecNotWeight0) { return; } Vector3 position = base.bone.InverseTransformPoint(this.elbowKneeCtrl.bone.position); Vector3 vector = base.constraintTarget.TransformPoint(position); Vector3 vector2 = base.constraintTarget.position - vector; Vector3 vector3 = vector - constraintTarget.position; float f = Vector3.Dot(vector2.normalized, vector3.normalized); float num = Mathf.Acos(f) * 57.29578f; if (float.IsNaN(num)) { num = 0f; } float t = Mathf.Clamp01(num / this.BendFadeBorder); Vector3 vector4 = base.constraintTarget.position - constraintTarget.position; float num2 = Vector3.Dot(vector - constraintTarget.position, vector4.normalized); if (float.IsNaN(num2)) { num2 = 0f; } Vector3 vector5 = constraintTarget.position + vector4.normalized * num2; Vector3 a = constraintTarget2.rotation * Vector3.up * 0.01f; Vector3 b = (vector - vector5) * this.BendStlength; Vector3 b2 = Vector3.Lerp(a, b, t); if (base.pointIKData.blendType == AIKCtrl.IKBlendType.IK_To_Detach) { constraintTarget2.position = Vector3.Lerp(this.elbowKneeCtrl.bone.position, vector5 + b2, base.positionWeight); } else { constraintTarget2.position = vector5 + b2; } this.SetElbowKneePositionWeight(base.positionWeight); } private void SetElbowKneePositionWeight(float val) { if (this.IsPullBody) { this.elbowKneeCtrl.positionWeight = val; } else { this.NoPullBodyIK.solver.bendModifierWeight = val; } } protected override void SetTargetTransformNoExec() { if (this.elbowKneeCtrl.positionWeight > 0f) { base.positionWeight = this.elbowKneeCtrl.positionWeight; base.constraintTarget.position += this.elbowKneeCtrl.constraintTarget.position - this.elbowKneeCtrl.bone.position; } if (this.elbowKneeCtrl.rotationWeight > 0f) { base.constraintTarget.position = this.elbowKneeCtrl.constraintTarget.TransformPoint(base.bone.localPosition); base.constraintTarget.rotation = this.elbowKneeCtrl.constraintTarget.rotation * base.bone.localRotation; } } protected override void DoPlaneCorrect(Vector3 normal) { ALimbIKCtrl.BorderCorrectType correctType = this.correctType; if (correctType != ALimbIKCtrl.BorderCorrectType.Bone) { if (correctType != ALimbIKCtrl.BorderCorrectType.HalfBody) { base.DoPlaneCorrect(normal); } else { base.DoPlaneCorrect(normal); this.shoulderThighCtrl.constraintTarget.position += normal; this.shoulderThighCtrl.positionWeight = base.positionWeight; this.elbowKneeCtrl.constraintTarget.position += normal; this.elbowKneeCtrl.positionWeight = base.positionWeight; } } else { Vector3 position = this.elbowKneeCtrl.bone.position; this.CorrectByElbowKnee(normal); if (this.elbowKneeCtrl.isNeedCorrect) { Vector3 position2 = base.bone.position; Vector3 fromDirection = this.elbowKneeCtrl.bone.position - this.shoulderThighCtrl.bone.position; Vector3 toDirection = position - this.shoulderThighCtrl.bone.position; this.shoulderThighCtrl.bone.rotation = Quaternion.FromToRotation(fromDirection, toDirection) * this.shoulderThighCtrl.bone.rotation; fromDirection = base.bone.position - this.elbowKneeCtrl.bone.position; toDirection = position2 - this.elbowKneeCtrl.bone.position; this.elbowKneeCtrl.bone.rotation = Quaternion.FromToRotation(fromDirection, toDirection) * this.elbowKneeCtrl.bone.rotation; } } } private void CorrectByElbowKnee(Vector3 normal) { Transform bone = this.shoulderThighCtrl.bone; Transform bone2 = this.elbowKneeCtrl.bone; Vector3 vector = base.bone.position + normal; Debug.DrawLine(base.bone.position, vector); float t = Mathf.Clamp01(Vector3.Dot(-bone.right, -bone2.right)); Vector3 bend_pos = Vector3.Lerp(bone2.position, bone2.position + normal, t); this.ForceNoPullBodyIKSolve(vector, base.bone.rotation, bend_pos); } private void ForceNoPullBodyIKSolve(Vector3 target_pos, Quaternion target_rot, Vector3 bend_pos) { AIKCtrl.PosRotPair posRotPair = default(AIKCtrl.PosRotPair); posRotPair.Copy(this.NoPullBodyIK.solver.target); IKSolverLimb solver = this.NoPullBodyIK.solver; solver.IKPositionWeight = (solver.IKRotationWeight = 1f); solver.target.position = target_pos; solver.target.rotation = target_rot; solver.bendModifierWeight = 1f; Vector3 position = solver.bendGoal.position; solver.bendGoal.position = bend_pos; solver.Update(); solver.target.position = posRotPair.pos; solver.target.rotation = posRotPair.rot; solver.bendGoal.position = position; } public override void HitCheck() { base.HitCheck(); if (this.pairIK.colliderEnable && this.myIKMgr.body.IsCrcBody) { NativePlaneCollider nativePlaneCollider; if (base.isUpperBody) { nativePlaneCollider = ((!this.isLeft) ? this.myIKMgr.upperCrossBorder.right : this.myIKMgr.upperCrossBorder.left); } else { nativePlaneCollider = ((!this.isLeft) ? this.myIKMgr.lowerCrossBorder.right : this.myIKMgr.lowerCrossBorder.left); } Vector3 position = base.bone.position; if (this.elbowKneeCtrl.ForceCollidePlaneCollider(ALimbIKCtrl.BorderCorrectType.Bone, nativePlaneCollider)) { Vector3 vector = position - base.bone.position; vector -= nativePlaneCollider.worldDirection * Vector3.Dot(vector, nativePlaneCollider.worldDirection); this.ForceNoPullBodyIKSolve(position, base.bone.rotation, this.elbowKneeCtrl.bone.position); } } } public override void OnPostFullBodySolverUpdate() { if (base.pointIKData.attachType == AIKCtrl.IKAttachType.Point) { return; } if (!base.isIKExec || this.IsPullBody) { base.OnPostFullBodySolverUpdate(); return; } this.NoPullBodyIK.solver.Update(); base.OnPostFullBodySolverUpdate(); } public override void OnPostIKUpdate() { if (!base.isUpperBody) { this.SetHighHeelAngle(); } base.OnPostIKUpdate(); } private void SetHighHeelAngle() { if (!this.myIKMgr.body.IsHiheel) { return; } float num = Mathf.Clamp01(Vector3.Dot(Vector3.up, base.bone.right)); float d = 25f * num; Vector3 localEulerAngles = base.bone.localEulerAngles; base.bone.localEulerAngles += Vector3.forward * d; if (MathUtility.AngleClamp180(base.bone.localEulerAngles.z) > 45f) { base.bone.localEulerAngles = new Vector3(localEulerAngles.x, localEulerAngles.y, 45f); } foreach (KeyValuePair keyValuePair in this.ToeBoneLocalAngleDic) { Transform key = keyValuePair.Key; Vector3 value = keyValuePair.Value; key.localEulerAngles = value - Vector3.forward * 25f; } } protected override void OnPostSetPositionWeight(float val) { if (base.pointIKData.attachType == AIKCtrl.IKAttachType.Point) { return; } if (this.IsPullBody) { this.effector.positionWeight = val; } else { this.NoPullBodyIK.solver.IKPositionWeight = val; } } protected override void OnPostSetRotationWeight(float val) { if (base.IsOldIKExec) { return; } if (this.IsPullBody) { this.effector.rotationWeight = val; } else { this.NoPullBodyIK.solver.IKRotationWeight = val; } } private const float HIGHHEEL_ANGLE = 25f; private const float ANGLEZ_RIMMIT = 45f; [SerializeField] [Space] [Range(1f, 90f)] private float BendFadeBorder = 30f; [SerializeField] [Range(1f, 2f)] private float BendStlength = 1.01f; public readonly IKEffector effector; private LimbIK NoPullBodyIK; private readonly Dictionary ToeBoneLocalAngleDic; }