using System; using System.Collections.Generic; using kt.Physics; using kt.Utility; using RootMotion.FinalIK; using UnityEngine; public abstract class ALimbIKCtrl : AIKCtrl { public ALimbIKCtrl(FullBodyIKMgr ik_mgr, FBIKChain chain, IKMappingLimb ik_mapping, FullBodyIKMgr.IKEffectorType effector_type) : base(ik_mgr, effector_type) { ALimbIKCtrl $this = this; this.chain = chain; this.ikMapping = ik_mapping; this.OrijinPull = this.chain.pull; this.ColliderMeta = base.constraintTarget.parent.gameObject.AddComponent(); this.ColliderMeta.effectorType = this.effectorType; if (this.myIKMgr.body.IsCrcBody) { ik_mgr.colliderLoader.onPostLoad.Add(delegate { $this.ColliderMeta.colliderList = ik_mgr.colliderLoader.GetColliderList(effector_type); $this.colliderEnable = false; }, false); } GameObject gameObject = new GameObject(effector_type.ToString() + "_IKPlaneCollider"); gameObject.transform.SetParent(this.myIKMgr.planeColliderTrans, false); this.floorCollider = gameObject.AddComponent(); this.floorCollider.planeStatus.direction = MathUtility.VectorType.Y; this.floorCollider.enabled = true; this.wallCollider = gameObject.gameObject.AddComponent(); this.wallCollider.planeStatus.direction = MathUtility.VectorType.Z; this.wallCollider.enabled = false; this.myIKMgr.AddFloorCollider(this.floorCollider); this.myIKMgr.AddWallCollider(this.wallCollider); } protected List ColliderList { get { return this.ColliderMeta.colliderList; } } public abstract bool isLeft { get; } public abstract ALimbIKCtrl pairIK { get; } public override bool isNeedFullbodySolverUpdate { get { return (base.isIKExec && this.IsPullBody) || (this.isNeedCorrect && this.correctType == ALimbIKCtrl.BorderCorrectType.HalfBody); } } public bool isNeedCorrect { get; protected set; } public bool colliderEnable { get { return this.ColliderMeta.enabled; } set { this.ColliderMeta.enabled = value; } } public NativePlaneCollider floorCollider { get; protected set; } public NativePlaneCollider wallCollider { get; protected set; } public NativeMaidPropCollider limbCapsule { get; protected set; } public override void Reset() { base.Reset(); this.correctType = ALimbIKCtrl.BorderCorrectType.Bone; this.colliderEnable = false; this.HitCheckLimbList.Clear(); this.isOldHitCheck = false; } public override void SetPullState(bool pull_on) { this.IsPullBody = pull_on; if (pull_on) { this.chain.pull = this.OrijinPull; } else { this.chain.pull = 0.1f; } } public void AddHitCheckLimb(ALimbIKCtrl limb) { if (!this.HitCheckLimbList.Contains(limb)) { this.HitCheckLimbList.Add(limb); } } public override void TargetTransCpy() { base.TargetTransCpy(); if (base.isUpperBody) { this.ikMapping.weight = 0f; } } public override void ApplyIKSetting() { this.isNeedCorrect = false; this.SolvedBonePos = base.bone.position; base.ApplyIKSetting(); if (!base.isIKExec) { this.SetTargetTransformNoExec(); } if (this.correctType == ALimbIKCtrl.BorderCorrectType.HalfBody) { this.HitCheck(); } if (base.isUpperBody) { this.ikMapping.weight = Mathf.Max(this.ikMapping.weight, Mathf.Max(base.positionWeight, base.rotationWeight)); } } protected virtual void SetTargetTransformNoExec() { } public virtual void HitCheck() { if (this.myIKMgr.body.IsCrcBody) { this.CheckLimbCapsule(); } this.CheckPlaneCollider(); } private void CheckLimbCapsule() { using (HashSet.Enumerator enumerator = this.HitCheckLimbList.GetEnumerator()) { while (enumerator.MoveNext()) { ALimbIKCtrl limb = enumerator.Current; ALimbIKCtrl $this = this; if (this.myIKMgr.ikExecOrder >= limb.myIKMgr.ikExecOrder && !limb.myIKMgr.body.isLateUpdateEnd && !this.myIKMgr.body.isLateUpdateEnd) { if (limb.myIKMgr.isIKExec) { limb.myIKMgr.onPostSolverUpdate.Add(delegate { $this.CheckLimbCapsule(limb); }, true); } else { limb.myIKMgr.body.onLateUpdateEnd.Add(delegate { $this.CheckLimbCapsule(limb); }, true); } } else { this.CheckLimbCapsule(limb); } } } } private void CheckLimbCapsule(ALimbIKCtrl limb) { NativeMaidPropCollider limbCapsule = limb.limbCapsule; if (!limbCapsule) { return; } for (int i = 0; i < 4; i++) { Vector3 b; if (!limbCapsule.Collide(this.limbCapsule, out b)) { break; } Vector3 vector = base.bone.position + b; Transform bone = this.ChainParentCtrl.bone; Debug.DrawLine(base.bone.position, vector, Color.red); bone.rotation = Quaternion.FromToRotation(base.bone.position - bone.position, vector - bone.position) * bone.rotation; } } private void CheckPlaneCollider() { if (this.correctType != ALimbIKCtrl.BorderCorrectType.HalfBody) { bool flag = false; Vector3 offset = Vector3.zero; if (this.ChainParentCtrl != null && this.ChainParentCtrl.isNeedCorrect) { flag |= this.CheckPlaneCollider(this.floorCollider); flag |= this.CheckPlaneCollider(this.wallCollider); offset = this.SolvedBonePos - base.bone.position; } if (!flag) { flag |= this.CheckPlaneCollider(this.floorCollider, offset, null); flag |= this.CheckPlaneCollider(this.wallCollider, offset, null); } } else { this.CheckPlaneCollider(this.floorCollider, base.constraintTarget); this.CheckPlaneCollider(this.wallCollider, base.constraintTarget); } } private bool CheckPlaneCollider(NativePlaneCollider plane_collider) { return this.CheckPlaneCollider(plane_collider, Vector3.zero, null); } private bool CheckPlaneCollider(NativePlaneCollider plane_collider, Transform target_trs) { return this.CheckPlaneCollider(plane_collider, Vector3.zero, target_trs); } private bool CheckPlaneCollider(NativePlaneCollider plane_collider, Vector3 offset, Transform copy_trs = null) { if (!plane_collider.enabled || !this.colliderEnable) { return false; } Vector3 zero = Vector3.zero; bool flag = false; if (this.isOldHitCheck) { for (int i = 0; i < 4; i++) { Vector3 position = base.bone.position; bool flag2 = plane_collider.Collide(ref position, 0f); flag = (flag || flag2); if (!flag2) { break; } if (this.ChainParentCtrl) { Debug.DrawLine(this.ChainParentCtrl.bone.position, base.bone.position, Color.gray, 0f, false); } this.DoPlaneCorrect(position - base.bone.position); } if (flag && this.ChainParentCtrl != null) { Debug.DrawLine(this.ChainParentCtrl.bone.position, base.bone.position, Color.magenta); } } else if (this.ColliderList != null) { foreach (ANativeColliderBase anativeColliderBase in this.ColliderList) { if (anativeColliderBase && anativeColliderBase.enabled) { Vector3 localPosition = anativeColliderBase.transform.localPosition; Quaternion localRotation = anativeColliderBase.transform.localRotation; if (copy_trs && copy_trs != base.bone) { Vector3 position2 = base.bone.InverseTransformPoint(anativeColliderBase.transform.position); Quaternion rhs = Quaternion.Inverse(base.bone.rotation) * anativeColliderBase.transform.rotation; anativeColliderBase.transform.position = copy_trs.TransformPoint(position2); anativeColliderBase.transform.rotation = copy_trs.rotation * rhs; } else { anativeColliderBase.transform.position += offset; } for (int j = 0; j < 4; j++) { bool flag3 = plane_collider.Collide(anativeColliderBase, out zero); flag = (flag || flag3); if (!flag3) { break; } if (this.ChainParentCtrl) { Debug.DrawLine(this.ChainParentCtrl.bone.position, base.bone.position, Color.gray, 0f, false); } anativeColliderBase.transform.localPosition = localPosition; anativeColliderBase.transform.localRotation = localRotation; this.DoPlaneCorrect(zero); } anativeColliderBase.transform.localPosition = localPosition; anativeColliderBase.transform.localRotation = localRotation; } } if (flag && this.ChainParentCtrl != null) { Debug.DrawLine(this.ChainParentCtrl.bone.position, base.bone.position, Color.magenta); } } return flag; } protected virtual void DoPlaneCorrect(Vector3 normal) { switch (this.correctType) { case ALimbIKCtrl.BorderCorrectType.Bone: { Vector3 vector = base.bone.position + normal; Debug.DrawLine(base.bone.position, vector); if (this.ChainParentCtrl != null) { AIKCtrl.PosRotPair posRotPair = default(AIKCtrl.PosRotPair); if (this.ChainChildCtrl) { posRotPair.Copy(this.ChainChildCtrl.bone); } Quaternion rotation = base.bone.rotation; Transform bone = this.ChainParentCtrl.bone; Vector3 fromDirection = base.bone.position - bone.position; Vector3 toDirection = vector - bone.position; bone.rotation = Quaternion.FromToRotation(fromDirection, toDirection) * bone.rotation; base.bone.rotation = rotation; if (this.ChainChildCtrl) { fromDirection = this.ChainChildCtrl.bone.position - base.bone.position; toDirection = posRotPair.pos - base.bone.position; base.bone.rotation = Quaternion.FromToRotation(fromDirection, toDirection) * base.bone.rotation; this.ChainChildCtrl.bone.rotation = posRotPair.rot; } this.isNeedCorrect = true; } break; } case ALimbIKCtrl.BorderCorrectType.HalfBody: if (!base.GetIKSettingData(AIKCtrl.IKAttachType.NewPoint).isIKExec) { base.GetIKSettingData(AIKCtrl.IKAttachType.NewPoint).isIKExec = true; } if (base.positionWeight == 0f) { base.positionWeight = 1f; } base.constraintTarget.position += normal; break; case ALimbIKCtrl.BorderCorrectType.Chara: this.myIKMgr.bodyOffsetCtrl.AddPosOffset(normal); break; case ALimbIKCtrl.BorderCorrectType.WithPartner: this.myIKMgr.bodyOffsetCtrl.AddPosOffset(normal); foreach (Maid maid in this.myIKMgr.partnerList) { maid.body0.fullBodyIK.bodyOffsetCtrl.AddPosOffset(normal); } break; } } public bool ForceCollidePlaneCollider(ALimbIKCtrl.BorderCorrectType correct_type, NativePlaneCollider collider) { bool colliderEnable = this.colliderEnable; this.colliderEnable = true; ALimbIKCtrl.BorderCorrectType borderCorrectType = this.correctType; this.correctType = correct_type; bool result = this.CheckPlaneCollider(collider); this.correctType = borderCorrectType; this.colliderEnable = colliderEnable; return result; } public override void OnPostFullBodySolverUpdate() { this.SolvedBonePos = base.bone.position; } public override void OnPostIKUpdate() { if (base.isIKExec && this.correctType != ALimbIKCtrl.BorderCorrectType.HalfBody) { this.HitCheck(); } base.OnPostIKUpdate(); } private const int COLIDER_CHECK_COUNT = 4; public ALimbIKCtrl.BorderCorrectType correctType; private IKColliderMeta ColliderMeta; public readonly FBIKChain chain; public readonly IKMappingLimb ikMapping; protected float OrijinPull = -1f; protected ALimbIKCtrl ChainParentCtrl; protected ALimbIKCtrl ChainChildCtrl; protected bool IsPullBody = true; private Vector3 SolvedBonePos; private HashSet HitCheckLimbList = new HashSet(); [HideInInspector] public bool isOldHitCheck; public enum BorderCorrectType { Bone, HalfBody, Chara, WithPartner, All } }