using System; using System.Collections.Generic; using System.Linq; using RootMotion.FinalIK; using UnityEngine; public class FullBodyIKCtrl : MonoBehaviour { private HeightIKCtrlData m_MouthIKData { get { return (!this.m_strIKDataPair.ContainsKey("口")) ? null : ((HeightIKCtrlData)this.m_strIKDataPair["口"]); } } public Transform BodyTarget { get; private set; } public bool IsUpdateEnd { get; private set; } public BodyCtrlData BodyCtrlData { get { return this.m_BodyCtrlData; } } public TBody TgtBody { get { return this.m_TgtBody; } } public Maid TgtMaid { get { return this.m_TgtBody.maid; } } public FullBodyBipedIK FullbodyIK { get { return this.m_FullbodyIK; } } public Transform IKTgtRoot { get { return this.m_IKTgtRoot; } } public IKEffector BodyEffector { get { return this.m_FullbodyIK.solver.bodyEffector; } } public Dictionary strIKDataPair { get { return this.m_strIKDataPair; } } public bool IsIKExec { get { return this.m_strIKDataPair.Any((KeyValuePair ik) => ik.Value.IsIKExec) && this.IKActive; } } private void Update() { this.IsUpdateEnd = false; if (this.BodyCtrlData.IsIKExec && this.IKActive) { this.TgtMaid.SetPos(this.BodyCtrlData.OrijinMaidPos); if (this.BodyCtrlData.DoAllOffset) { GameMain.Instance.CharacterMgr.SetCharaAllPos(this.BodyCtrlData.OrijinAllPos); } } } private void OnDestroy() { if (this.m_IKTgtRoot) { UnityEngine.Object.Destroy(this.m_IKTgtRoot); } } private BodyCtrlData SafeAddBodyCtrlData(string key_str) { BodyCtrlData bodyCtrlData = new BodyCtrlData(this); if (this.m_strIKDataPair.ContainsKey(key_str)) { this.m_strIKDataPair[key_str] = bodyCtrlData; } else { this.m_strIKDataPair.Add(key_str, bodyCtrlData); } this.m_BodyCtrlData = bodyCtrlData; return (BodyCtrlData)this.m_strIKDataPair[key_str]; } private BipedIKCtrlData SafeAddFullbodyIKData(string key_str, IKEffector effector, FBIKChain chain, IKMappingLimb ik_mapping, IKEffector sub_effector, bool use_old = false) { BipedIKCtrlData value = new BipedIKCtrlData(effector, chain, ik_mapping, this, effector.bone, sub_effector, use_old); if (this.m_strIKDataPair.ContainsKey(key_str)) { this.m_strIKDataPair[key_str] = value; } else { this.m_strIKDataPair.Add(key_str, value); } this.m_FullbodyDataList.Add((BipedIKCtrlData)this.m_strIKDataPair[key_str]); return (BipedIKCtrlData)this.m_strIKDataPair[key_str]; } private CCDIKCtrlData SafeAddCCDIKData(string key_str, ref CCDIK ccd_ik, bool weight_fade, bool attach_ik, IKManager.BoneType boneType, bool affect_height) { if (ccd_ik) { UnityEngine.Object.DestroyImmediate(ccd_ik); } ccd_ik = this.IKTgtRoot.gameObject.AddComponent(); CCDIKCtrlData value = (!affect_height) ? new CCDIKCtrlData(ccd_ik, this.GetChainBonesToInit(boneType), this, weight_fade, attach_ik) : new HeightIKCtrlData(ccd_ik, this.GetChainBonesToInit(boneType), this, weight_fade, attach_ik); if (this.m_strIKDataPair.ContainsKey(key_str)) { this.m_strIKDataPair[key_str] = value; } else { this.m_strIKDataPair.Add(key_str, value); } this.m_CCDDataList.Add((CCDIKCtrlData)this.m_strIKDataPair[key_str]); return (CCDIKCtrlData)this.m_strIKDataPair[key_str]; } private FABRIKCtrlData SafeAddFABRIKData(string key_str, ref FABRIK fabr_ik, bool weight_fade, bool attach_ik, IKManager.BoneType boneType, bool affect_height) { if (fabr_ik) { UnityEngine.Object.DestroyImmediate(fabr_ik); } fabr_ik = this.IKTgtRoot.gameObject.AddComponent(); FABRIKCtrlData value = new FABRIKCtrlData(fabr_ik, this.GetChainBonesToInit(boneType), this, attach_ik); if (this.m_strIKDataPair.ContainsKey(key_str)) { this.m_strIKDataPair[key_str] = value; } else { this.m_strIKDataPair.Add(key_str, value); } this.m_FABRDataList.Add((FABRIKCtrlData)this.m_strIKDataPair[key_str]); return (FABRIKCtrlData)this.m_strIKDataPair[key_str]; } public void LateIKUpdate() { this.IKUpdate(); this.TgtBody.AutoTwist(); for (int i = 0; i < this.TgtBody.goSlot.Count; i++) { if (this.TgtBody.goSlot[i].obj != null) { this.TgtBody.goSlot[i].CopyTrans(); } this.TgtBody.goSlot[i].Update(); } } public void Init() { this.m_TgtBody = base.GetComponent(); if (!this.m_IKTgtRoot) { this.m_IKTgtRoot = new GameObject("IK Target Root").transform; this.m_IKTgtRoot.SetParent(this.m_TgtBody.m_trBones, false); } if (!this.TgtMaid.boMAN) { this.m_STRoot = this.m_TgtBody.m_trBones.Find("ST_Root"); } if (this.m_FullbodyIK) { UnityEngine.Object.DestroyImmediate(this.m_FullbodyIK); } this.m_FullbodyIK = this.m_IKTgtRoot.gameObject.AddComponent(); this.m_Mouth = new GameObject("Mouth").transform; this.m_Mouth.SetParent(this.TgtBody.trsHead, false); this.m_Mouth.localEulerAngles = new Vector3(-90f, 90f, 0f); if (!this.TgtMaid.boMAN) { this.m_NippleL = new GameObject("Nipple_L").transform; this.m_NippleL.SetParent(CMT.SearchObjName(this.TgtBody.m_trBones, "Mune_L_sub", true), false); this.m_NippleR = new GameObject("Nipple_R").transform; this.m_NippleR.SetParent(CMT.SearchObjName(this.TgtBody.m_trBones, "Mune_R_sub", true), false); } this.m_FullbodyDataList.Clear(); this.m_CCDDataList.Clear(); this.m_ForearmCalfIKList.Clear(); this.m_FABRDataList.Clear(); this.m_IKBoneDic = IKManager.CreateBoneDic(this.TgtMaid); this.m_FullbodyIK.references.root = this.m_TgtBody.m_trBones; this.m_FullbodyIK.references.pelvis = this.GetIKBone(IKManager.BoneType.Root); if (!this.TgtMaid.boMAN) { this.m_FullbodyIK.references.spine = new Transform[] { this.m_IKBoneDic[IKManager.BoneType.Spine0].Value.transform, this.m_IKBoneDic[IKManager.BoneType.Spine3].Value.transform }; } else { this.m_FullbodyIK.references.spine = new Transform[] { this.m_IKBoneDic[IKManager.BoneType.Spine0].Value.transform, this.m_IKBoneDic[IKManager.BoneType.Spine2].Value.transform }; } this.m_FullbodyIK.references.head = this.GetIKBone(IKManager.BoneType.Head); this.m_FullbodyIK.references.leftUpperArm = this.GetIKBone(IKManager.BoneType.UpperArm_L); this.m_FullbodyIK.references.leftForearm = this.GetIKBone(IKManager.BoneType.Forearm_L); this.m_FullbodyIK.references.leftHand = this.GetIKBone(IKManager.BoneType.Hand_L); this.m_FullbodyIK.references.rightUpperArm = this.GetIKBone(IKManager.BoneType.UpperArm_R); this.m_FullbodyIK.references.rightForearm = this.GetIKBone(IKManager.BoneType.Forearm_R); this.m_FullbodyIK.references.rightHand = this.GetIKBone(IKManager.BoneType.Hand_R); this.m_FullbodyIK.references.leftThigh = this.GetIKBone(IKManager.BoneType.Thigh_L); this.m_FullbodyIK.references.leftCalf = this.GetIKBone(IKManager.BoneType.Calf_L); this.m_FullbodyIK.references.leftFoot = this.GetIKBone(IKManager.BoneType.Foot_L); this.m_FullbodyIK.references.rightThigh = this.GetIKBone(IKManager.BoneType.Thigh_R); this.m_FullbodyIK.references.rightCalf = this.GetIKBone(IKManager.BoneType.Calf_R); this.m_FullbodyIK.references.rightFoot = this.GetIKBone(IKManager.BoneType.Foot_R); this.m_FullbodyIK.solver.SetToReferences(this.m_FullbodyIK.references, null); this.m_FullbodyIK.fixTransforms = false; foreach (IKEffector ikeffector in this.m_FullbodyIK.solver.effectors) { ikeffector.positionWeight = 0f; ikeffector.rotationWeight = 0f; } foreach (FBIKChain fbikchain in this.m_FullbodyIK.solver.chain) { fbikchain.bendConstraint.weight = 0f; } this.m_BodyCtrlData = this.SafeAddBodyCtrlData("体全体"); this.SafeAddFullbodyIKData("左手", this.m_FullbodyIK.solver.leftHandEffector, this.m_FullbodyIK.solver.leftArmChain, this.m_FullbodyIK.solver.leftArmMapping, this.m_FullbodyIK.solver.leftShoulderEffector, true); this.SafeAddFullbodyIKData("右手", this.m_FullbodyIK.solver.rightHandEffector, this.m_FullbodyIK.solver.rightArmChain, this.m_FullbodyIK.solver.rightArmMapping, this.m_FullbodyIK.solver.rightShoulderEffector, true); this.SafeAddFullbodyIKData("左足", this.m_FullbodyIK.solver.leftFootEffector, this.m_FullbodyIK.solver.leftLegChain, this.m_FullbodyIK.solver.leftLegMapping, this.m_FullbodyIK.solver.leftThighEffector, false); this.SafeAddFullbodyIKData("右足", this.m_FullbodyIK.solver.rightFootEffector, this.m_FullbodyIK.solver.rightLegChain, this.m_FullbodyIK.solver.rightLegMapping, this.m_FullbodyIK.solver.rightThighEffector, false); this.SafeAddCCDIKData("口", ref this.m_MouthIK, true, true, IKManager.BoneType.Mouth, true); this.m_ForearmCalfIKList.Add(this.SafeAddFABRIKData("右肘", ref this.m_ForearmRIK, false, true, IKManager.BoneType.Forearm_R, false)); this.m_ForearmCalfIKList.Add(this.SafeAddFABRIKData("左肘", ref this.m_ForearmLIK, false, true, IKManager.BoneType.Forearm_L, false)); this.m_ForearmCalfIKList.Add(this.SafeAddFABRIKData("右膝", ref this.m_CalfRIK, false, true, IKManager.BoneType.Calf_R, false)); this.m_ForearmCalfIKList.Add(this.SafeAddFABRIKData("左膝", ref this.m_CalfLIK, false, true, IKManager.BoneType.Calf_L, false)); if (!this.BodyTarget) { Transform transform = this.m_IKTgtRoot.Find(this.BodyEffector.bone.name); transform = new GameObject(this.BodyEffector.bone.name).transform; transform.SetParent(this.m_IKTgtRoot, false); this.BodyTarget = new GameObject("IKTarget").transform; this.BodyTarget.SetParent(transform, false); } this.BodyEffector.target = this.BodyTarget; this.m_FullbodyIK.enabled = false; } public void IKUpdate() { if (this.TgtMaid.boMAN) { this.m_Mouth.localPosition = new Vector3(-0.013f, 0.1115f, 0f); } else { this.AttachPointTransCpy(this.m_Mouth, "head", "歯", false); this.AttachPointTransCpy(this.m_NippleL, "body", "乳首左", false); this.AttachPointTransCpy(this.m_NippleR, "body", "乳首右", false); } this.BodyEffector.positionWeight = 0f; this.BodyTarget.position = this.BodyEffector.bone.position; this.DoHeightCover = false; this.IsUpdateLate = false; if (!this.IKActive) { return; } bool flag = false; foreach (IKCtrlData ikctrlData in this.m_strIKDataPair.Values) { ikctrlData.ApplyIKSetting(); flag |= ikctrlData.IsIKExec; } if (!this.IsUpdateLate && (flag || this.AllForceIK)) { this.SolverUpdate(); } } public void SolverUpdate() { this.IsUpdateEnd = true; Action postSolverUpdate = this.PostSolverUpdate; this.PostSolverUpdate = null; if (this.BodyCtrlData.IsIKExec) { this.BodyCtrlData.Update(); } bool flag = this.m_FullbodyDataList.Any((BipedIKCtrlData data) => data.IsIKExec && !data.OldIkExec); if (this.m_MouthIKData.IsIKExec) { this.m_MouthIKData.Update(); } flag |= (this.BodyEffector.positionWeight == 1f); if (flag) { Vector3 position = this.m_FullbodyIK.references.spine[0].InverseTransformPoint(this.m_FullbodyIK.references.spine[1].position); this.m_FullbodyIK.solver.Update(); if (this.GetIKData("右足").IsIKExec || this.GetIKData("左足").IsIKExec) { this.m_FullbodyIK.references.spine[1].position = this.m_FullbodyIK.references.spine[0].TransformPoint(position); } } for (int i = 0; i < this.m_ForearmCalfIKList.Count; i++) { if (this.m_ForearmCalfIKList[i].IsIKExec) { this.m_ForearmCalfIKList[i].Update(); } } foreach (IKCtrlData ikctrlData in this.m_strIKDataPair.Values) { ikctrlData.LateUpdate(); } if (postSolverUpdate != null) { postSolverUpdate(); } } public void AttachPointTransCpy(Transform trans, string slot_name, string attach_name, bool scale_cpy = false) { int slotNo = this.TgtBody.GetSlotNo(slot_name); if (this.TgtBody.goSlot[slotNo].morph == null) { return; } Vector3 position; Quaternion rotation; Vector3 localScale; this.TgtBody.goSlot[slotNo].morph.GetAttachPoint(attach_name, out position, out rotation, out localScale, false); trans.position = position; trans.rotation = rotation; if (scale_cpy) { trans.localScale = localScale; } } public Transform GetIKBone(IKManager.BoneType boneType) { return (!this.m_IKBoneDic.ContainsKey(boneType)) ? null : this.m_IKBoneDic[boneType].Value.transform; } public Transform[] GetChainBonesToInit(IKManager.BoneType boneType) { Transform[] result = new Transform[0]; switch (boneType) { case IKManager.BoneType.Forearm_R: result = new Transform[] { this.GetIKBone(IKManager.BoneType.Clavicle_R), this.GetIKBone(IKManager.BoneType.UpperArm_R), this.GetIKBone(IKManager.BoneType.Forearm_R) }; break; case IKManager.BoneType.Hand_R: result = new Transform[] { this.GetIKBone(IKManager.BoneType.UpperArm_R), this.GetIKBone(IKManager.BoneType.Forearm_R), this.GetIKBone(IKManager.BoneType.Hand_R) }; break; default: switch (boneType) { case IKManager.BoneType.Head: if (!this.TgtMaid.boMAN) { result = new Transform[] { this.GetIKBone(IKManager.BoneType.Spine0), this.GetIKBone(IKManager.BoneType.Spine1), this.GetIKBone(IKManager.BoneType.Spine2), this.GetIKBone(IKManager.BoneType.Spine3), this.GetIKBone(IKManager.BoneType.Neck), this.GetIKBone(IKManager.BoneType.Head) }; } else { result = new Transform[] { this.GetIKBone(IKManager.BoneType.Spine0), this.GetIKBone(IKManager.BoneType.Spine1), this.GetIKBone(IKManager.BoneType.Spine2), this.GetIKBone(IKManager.BoneType.Neck), this.GetIKBone(IKManager.BoneType.Head) }; } break; case IKManager.BoneType.Neck: if (!this.TgtMaid.boMAN) { result = new Transform[] { this.GetIKBone(IKManager.BoneType.Spine0), this.GetIKBone(IKManager.BoneType.Spine1), this.GetIKBone(IKManager.BoneType.Spine2), this.GetIKBone(IKManager.BoneType.Spine3), this.GetIKBone(IKManager.BoneType.Neck) }; } else { result = new Transform[] { this.GetIKBone(IKManager.BoneType.Spine0), this.GetIKBone(IKManager.BoneType.Spine1), this.GetIKBone(IKManager.BoneType.Spine2), this.GetIKBone(IKManager.BoneType.Neck) }; } break; default: switch (boneType) { case IKManager.BoneType.Mouth: if (!this.TgtMaid.boMAN) { result = new Transform[] { this.GetIKBone(IKManager.BoneType.Spine0), this.GetIKBone(IKManager.BoneType.Spine1), this.GetIKBone(IKManager.BoneType.Spine2), this.GetIKBone(IKManager.BoneType.Spine3), this.GetIKBone(IKManager.BoneType.Neck), this.GetIKBone(IKManager.BoneType.Head), this.GetIKBone(IKManager.BoneType.Mouth) }; } else { result = new Transform[] { this.GetIKBone(IKManager.BoneType.Spine0), this.GetIKBone(IKManager.BoneType.Spine1), this.GetIKBone(IKManager.BoneType.Spine2), this.GetIKBone(IKManager.BoneType.Neck), this.GetIKBone(IKManager.BoneType.Head), this.GetIKBone(IKManager.BoneType.Mouth) }; } break; case IKManager.BoneType.Nipple_L: if (!this.TgtMaid.boMAN) { result = new Transform[] { this.GetIKBone(IKManager.BoneType.Bust_L), this.GetIKBone(IKManager.BoneType.Bust_L_Sub), this.GetIKBone(IKManager.BoneType.Nipple_L) }; } break; case IKManager.BoneType.Nipple_R: if (!this.TgtMaid.boMAN) { result = new Transform[] { this.GetIKBone(IKManager.BoneType.Bust_R), this.GetIKBone(IKManager.BoneType.Bust_R_Sub), this.GetIKBone(IKManager.BoneType.Nipple_R) }; } break; } break; case IKManager.BoneType.Spine2: result = new Transform[] { this.GetIKBone(IKManager.BoneType.Spine0), this.GetIKBone(IKManager.BoneType.Spine1), this.GetIKBone(IKManager.BoneType.Spine2) }; break; case IKManager.BoneType.Spine3: if (!this.TgtMaid.boMAN) { result = new Transform[] { this.GetIKBone(IKManager.BoneType.Spine0), this.GetIKBone(IKManager.BoneType.Spine1), this.GetIKBone(IKManager.BoneType.Spine2), this.GetIKBone(IKManager.BoneType.Spine3) }; } break; } break; case IKManager.BoneType.Calf_R: result = new Transform[] { this.GetIKBone(IKManager.BoneType.Thigh_R), this.GetIKBone(IKManager.BoneType.Calf_R) }; break; case IKManager.BoneType.Foot_R: result = new Transform[] { this.GetIKBone(IKManager.BoneType.Thigh_R), this.GetIKBone(IKManager.BoneType.Calf_R), this.GetIKBone(IKManager.BoneType.Foot_R) }; break; case IKManager.BoneType.Forearm_L: result = new Transform[] { this.GetIKBone(IKManager.BoneType.Clavicle_L), this.GetIKBone(IKManager.BoneType.UpperArm_L), this.GetIKBone(IKManager.BoneType.Forearm_L) }; break; case IKManager.BoneType.Hand_L: result = new Transform[] { this.GetIKBone(IKManager.BoneType.UpperArm_L), this.GetIKBone(IKManager.BoneType.Forearm_L), this.GetIKBone(IKManager.BoneType.Hand_L) }; break; case IKManager.BoneType.Calf_L: result = new Transform[] { this.GetIKBone(IKManager.BoneType.Thigh_L), this.GetIKBone(IKManager.BoneType.Calf_L) }; break; case IKManager.BoneType.Foot_L: result = new Transform[] { this.GetIKBone(IKManager.BoneType.Thigh_L), this.GetIKBone(IKManager.BoneType.Calf_L), this.GetIKBone(IKManager.BoneType.Foot_L) }; break; } return result; } public IKCtrlData GetIKData(string tag_name) { if (this.m_strIKDataPair.ContainsKey(tag_name)) { return this.m_strIKDataPair[tag_name]; } return null; } public T GetIKData(string tag_name) where T : IKCtrlData { if (this.m_strIKDataPair.ContainsKey(tag_name) && this.m_strIKDataPair[tag_name] is T) { return this.m_strIKDataPair[tag_name] as T; } return (T)((object)null); } public Transform GetSTFlagObj(string name) { return this.m_STRoot.Find(name); } [SerializeField] private TBody m_TgtBody; [SerializeField] private Transform m_IKTgtRoot; [SerializeField] private Transform m_STRoot; [SerializeField] private FullBodyBipedIK m_FullbodyIK; private CCDIK m_MouthIK; private CCDIK m_MuneLIK; private CCDIK m_MuneRIK; private FABRIK m_ForearmLIK; private FABRIK m_ForearmRIK; private FABRIK m_CalfLIK; private FABRIK m_CalfRIK; private Dictionary> m_IKBoneDic = new Dictionary>(); [SerializeField] private BodyCtrlData m_BodyCtrlData; [SerializeField] private List m_FullbodyDataList = new List(); [SerializeField] private List m_CCDDataList = new List(); [SerializeField] private List m_FABRDataList = new List(); private Transform m_NippleL; private Transform m_NippleR; private Transform m_Mouth; private Dictionary m_strIKDataPair = new Dictionary(); private List m_ForearmCalfIKList = new List(); public bool IKActive = true; public bool DoHeightCover; public bool IsUpdateLate; public Action PostSolverUpdate; public bool AllForceIK; }