using System; using kt.ik; using kt.Utility; using UnityEngine; public abstract class AIKCtrl { public AIKCtrl(FullBodyIKMgr ik_mgr, FullBodyIKMgr.IKEffectorType effector_type) { this.myIKMgr = ik_mgr; this.effectorType = effector_type; this.Bone = ik_mgr.GetIKBone(effector_type); this.ChainBones = ik_mgr.GetChainBonesToInit(effector_type); string text = (!this.myIKMgr.chara.boMAN) ? "Bip01" : "ManBip"; string name = effector_type.ToString() + " IKTarget"; Transform transform = this.myIKMgr.ikTargetRoot.Find(name); if (!transform) { transform = new GameObject(name).transform; transform.SetParent(this.myIKMgr.ikTargetRoot, false); GameObject gameObject = new GameObject("IKTarget"); gameObject.transform.SetParent(transform, false); this.ConstraintTarget = gameObject.transform; } else { this.ConstraintTarget = transform.Find("IKTarget"); } this.MyBoneTgtPair = new AIKCtrl.BoneTgtPair(this.bone, this.ConstraintTarget); this.VirtualTarget = new GameObject("VirtualTarget").transform; this.VirtualTarget.transform.SetParent(transform, false); this.PointIKData.ikCtrl = ik_mgr; this.RotateIKData.ikCtrl = ik_mgr; if (this.IsUseOldIK) { this.IKCmo = new TBody.IKCMO(); this.IKCmo.Init(this.ChainBones[0], this.ChainBones[1], this.ChainBones[2], ik_mgr.body); } } public AIKCtrl.IKSettingData pointIKData { get { return this.PointIKData; } } public AIKCtrl.IKSettingData rotateIKData { get { return this.RotateIKData; } } protected virtual bool IsUseOldIK { get { return false; } } protected bool IsOldIKExec { get { bool flag = this.IsUseOldIK; flag &= this.pointIKData.isIKExec; return flag & this.pointIKData.attachType == AIKCtrl.IKAttachType.Point; } } public float blendTime { get { return this.myIKMgr.blendTime; } set { AIKCtrl.IKSettingData pointIKData = this.pointIKData; this.rotateIKData.blendTime = value; pointIKData.blendTime = value; } } public Transform bone { get { return this.Bone; } } public Transform constraintTarget { get { return this.ConstraintTarget; } } public Transform virtualTarget { get { return this.VirtualTarget; } } public bool isIKExec { get { return this.pointIKData.isIKExec || this.rotateIKData.isIKExec; } } public bool isIKExecNotWeight0 { get { return this.pointIKData.isIKExecNotWeight0 || this.rotateIKData.isIKExecNotWeight0; } } public virtual bool isNeedFullbodySolverUpdate { get { return false; } } public bool isNeedAttachTargetUpdatePreExec { get; protected set; } public Transform[] chainBones { get { return this.ChainBones; } } protected Transform ChainRoot { get { return this.chainBones[0]; } } public float positionWeight { get { return this.pointIKData.weight; } set { this.pointIKData.weight = value; this.OnPostSetPositionWeight(value); } } public float rotationWeight { get { return this.rotateIKData.weight; } set { this.rotateIKData.weight = value; this.OnPostSetRotationWeight(value); } } public bool isUpperBody { get; protected set; } public static bool operator true(AIKCtrl data) { return data != null; } public static bool operator false(AIKCtrl data) { return data == null; } public static bool operator !(AIKCtrl data) { return data == null; } public void SetFlagTarget(AIKCtrl.IKAttachType attach_type, string name) { if (this.myIKMgr.chara.boMAN) { this.GetFlagData(attach_type).target = this.myIKMgr.body.GetBone(name); } else { this.GetFlagData(attach_type).target = this.myIKMgr.GetSTFlagObj(name); } } public virtual void SetIKSetting(IKAttachParam param) { this.myIKMgr.isIKActive = true; AIKCtrl.IKSettingData iksettingData = this.GetIKSettingData(param.attachType); AIKCtrl.IKTargetData tgtData = iksettingData.GetTgtData(param.execTiming); if (iksettingData.attachType != AIKCtrl.IKAttachType.Rotate) { iksettingData.attachType = param.attachType; } iksettingData.blendTime = param.blendTime; iksettingData.offsetEnable = param.offsetEnable; if (this.myIKMgr.body.isMotionChange) { iksettingData.isSetFirstFramePosRot = false; } if (param.attachType == AIKCtrl.IKAttachType.NewPoint) { this.posOffsetType = param.posOffsetType; this.SetPullState(param.bodyPull); } this.BlendPosRot.Copy(this.LastIKPosRot); if (tgtData.targetChara) { this.myIKMgr.RemovePartner(tgtData.targetChara, true); } if (param.targetChara) { this.myIKMgr.AddPartner(param.targetChara, true); } iksettingData.SetIKSetting(param); this.myIKMgr.RemoveReservedDetach(this); this.isNeedAttachTargetUpdatePreExec |= (param.targetChara == this.myIKMgr.chara); } public virtual void SetPullState(bool pull_on) { } public void SetVirtualPosRot(AIKCtrl.PosRotPair posrot) { this.VirtualPosRot = posrot; } public virtual void TargetTransCpy() { this.MyBoneTgtPair.Copy(); float num = 0f; this.rotationWeight = num; this.positionWeight = num; } public virtual void ApplyIKSetting() { if (!this.myIKMgr.isUpdateEnd) { this.EachOtherIK = false; } this.ApplyIKSetting(this.GetIKSettingData(AIKCtrl.IKAttachType.NewPoint)); this.ApplyIKSetting(this.GetIKSettingData(AIKCtrl.IKAttachType.Rotate)); } private void ApplyIKSetting(AIKCtrl.IKSettingData data) { if (this.myIKMgr.isUpdateLate) { return; } if (data.curTargetData.targetChara && data.curTargetData.targetChara != this.myIKMgr.chara) { TBody body = data.curTargetData.targetChara.body0; if (body.fullBodyIK != null) { if (!string.IsNullOrEmpty(data.curTargetData.attachIKName)) { AIKCtrl ikctrl = body.fullBodyIK.GetIKCtrl(data.curTargetData.attachIKName); if (ikctrl != null && ikctrl.isIKExec) { AIKCtrl.IKSettingData iksettingData = ikctrl.GetIKSettingData(data.attachType); this.EachOtherIK = this.IsEachBoneIK(iksettingData); } } if (!this.IsIgnoreLateUpdateEnd && this.myIKMgr.ikExecOrder >= body.fullBodyIK.ikExecOrder && !body.isLateUpdateEnd && !this.myIKMgr.body.isLateUpdateEnd) { this.myIKMgr.isUpdateLate = true; if (body.fullBodyIK.isIKExec) { body.fullBodyIK.onPostSolverUpdate.Add(new Action(this.myIKMgr.LateIKUpdate), true); } else { body.onLateUpdateEnd.Add(new Action(this.myIKMgr.LateIKUpdate), true); } return; } } } if (!data.isBlendEnd && data.blendTime <= 0f) { data.BlendEnd(); } data.isOffsetSetEnd = false; data.isIKExec = true; Vector3 vector = this.bone.position; Quaternion quaternion = this.bone.rotation; float num = 1f; if (this.GetFlagData(data.attachType).isEnable) { if (!this.GetFlagData(data.attachType).blendCtrlSelf) { AIKCtrl.IKExecTiming curExecTiming = data.changeFlagData.curExecTiming; this.MultiTgtDataToPosRot(data, AIKCtrl.IKExecTiming.Normal, curExecTiming, ref vector, ref quaternion, ref num); data.isOffsetSetEnd = true; data.isIKExec = true; } else { AIKCtrl.IKExecTiming lastExecTiming = data.changeFlagData.lastExecTiming; if (this.GetFlagData(data.attachType).IsFlagChange()) { AIKCtrl.IKTargetData tgtData = data.GetTgtData(lastExecTiming); data.BlendReset(); data.curTargetData.SetLastTarget(tgtData.tgtAttachName, tgtData.targetChara, tgtData.target, tgtData.tgtOffset); data.CheckBlendType(); if (data.attachType == AIKCtrl.IKAttachType.Rotate) { this.BlendPosRot.rot = this.LastIKPosRot.rot; } else { this.BlendPosRot.pos = this.LastIKPosRot.pos; } this.SetIKPosRot(data, ref vector, ref quaternion, false, AIKCtrl.IKExecTiming.Normal); } else { this.SetIKPosRot(data, ref vector, ref quaternion, false, AIKCtrl.IKExecTiming.Normal); } } } else { this.SetIKPosRot(data, ref vector, ref quaternion, false, AIKCtrl.IKExecTiming.Normal); } if (data.isIKExec) { bool flag = this.EachOtherIK && !data.curTargetData.targetChara.fullBodyIK.isUpdateEnd; if (flag && data.isBlendNow) { if (data.isPointAttach) { vector = Vector3.Lerp(vector, this.bone.position, 0.5f); } else { quaternion = Quaternion.Lerp(quaternion, this.bone.rotation, 0.5f); } } if (data.isFirstFrame && !data.isSetFirstFramePosRot) { if (data.isPointAttach) { this.FirstBonePosRot.pos = this.bone.position; if (flag) { this.FirstTgtPosRot.pos = Vector3.Lerp(this.bone.position, vector, 0.5f); } else { this.FirstTgtPosRot.pos = vector; } } else { this.FirstBonePosRot.rot = this.bone.rotation; if (flag) { this.FirstTgtPosRot.rot = Quaternion.Lerp(this.bone.rotation, quaternion, 0.5f); } else { this.FirstTgtPosRot.rot = quaternion; } } } if (data.isPointAttach) { if (data.blendType == AIKCtrl.IKBlendType.IK_To_Detach) { this.positionWeight = num * (1f - data.blendWeight); } else if (data.blendType == AIKCtrl.IKBlendType.Detach_To_IK) { this.positionWeight = num * data.blendWeight; } else { this.positionWeight = num; } } else if (data.blendType == AIKCtrl.IKBlendType.IK_To_Detach) { this.rotationWeight = num * (1f - data.blendWeight); } else if (data.blendType == AIKCtrl.IKBlendType.Detach_To_IK) { this.rotationWeight = num * data.blendWeight; } else { this.rotationWeight = num; } this.SetTargetTransform(data, vector, quaternion); data.isSetFirstFramePosRot = (data.isFirstFrame && !data.isSetFirstFramePosRot); data.CheckFirstFrame(); if (data.curTargetData.isShowTgtAxis) { DebugUtility.DrawAxis(vector, quaternion, 0.125f); } if (!data.isPosRotSetEnd && !data.isBlendEnd) { data.elapsedTime += Time.deltaTime; if (data.elapsedTime >= data.blendTime) { data.BlendEnd(); } } data.isPosRotSetEnd = true; } } private void SetIKPosRot(AIKCtrl.IKSettingData setting_data, ref Vector3 pos, ref Quaternion rot, bool include_offset = false, AIKCtrl.IKExecTiming exec_timing = AIKCtrl.IKExecTiming.Normal) { this.SetIKPosRot(setting_data, setting_data.GetTgtData(exec_timing), ref pos, ref rot, include_offset); } private void SetIKPosRot(AIKCtrl.IKSettingData setting_data, AIKCtrl.IKTargetData tgt_data, ref Vector3 pos, ref Quaternion rot, bool include_offset = false) { setting_data.isIKExec = true; if (tgt_data.target != null) { if (tgt_data.target == this.virtualTarget) { Transform transform = this.myIKMgr.chara.transform; this.virtualTarget.rotation = transform.rotation * this.VirtualPosRot.rot; this.virtualTarget.position = transform.TransformPoint(this.VirtualPosRot.pos); } pos = tgt_data.target.position; rot = tgt_data.target.rotation; } else if (tgt_data.tgtAttachName != string.Empty) { if (this.myIKMgr.body.goSlot[tgt_data.tgtAttachSlot].morph != null) { if (tgt_data.targetChara != null && tgt_data.targetChara.body0 != null) { Vector3 vector; tgt_data.targetChara.body0.goSlot[tgt_data.tgtAttachSlot].morph.GetAttachPoint(tgt_data.tgtAttachName, out pos, out rot, out vector, false); if (setting_data.attachType == AIKCtrl.IKAttachType.NewPoint && tgt_data.axisTarget) { rot = tgt_data.axisTarget.rotation; } } else { setting_data.isIKExec = false; tgt_data.tgtAttachName = string.Empty; } } else { setting_data.isIKExec = false; } } else if (setting_data.blendType == AIKCtrl.IKBlendType.IK_To_Detach) { pos = this.GetBlendBasePos(); rot = this.GetBlendBaseRot(); } else { setting_data.isIKExec = false; } if (setting_data.isIKExec && include_offset) { Vector3 vector2 = tgt_data.tgtOffset; Vector3 vector3 = tgt_data.lastOffset; if (setting_data.isPointAttach) { Vector3 start = pos; AIKCtrl.PosOffsetType posOffsetType = this.posOffsetType; if (posOffsetType != AIKCtrl.PosOffsetType.OffsetBone) { if (posOffsetType == AIKCtrl.PosOffsetType.OffsetTarget) { vector2 = rot * vector2; vector3 = rot * vector3; } } else { vector2 = -(this.bone.rotation * vector2); vector3 = -(this.bone.rotation * vector3); } if (setting_data.blendType == AIKCtrl.IKBlendType.IK_To_IK && !setting_data.isTargetChange) { vector2 = Vector3.Lerp(vector3 + setting_data.lastAnmOffset, vector2, setting_data.blendWeight); } pos += vector2; Debug.DrawLine(start, pos, Color.white); } else { if (setting_data.blendType == AIKCtrl.IKBlendType.IK_To_IK && !setting_data.isTargetChange) { vector2 = Vector3.Lerp(tgt_data.lastOffset + setting_data.lastAnmOffset, vector2, setting_data.blendWeight); } rot *= Quaternion.Euler(vector2); } } } public Vector3 GetBlendBasePos() { if (this.BlendCalc == AIKCtrl.BlendCalcType.World) { return this.BlendPosRot.pos; } return this.ChainRoot.position + this.BlendPosRot.pos; } private Quaternion GetBlendBaseRot() { if (this.BlendCalc == AIKCtrl.BlendCalcType.World) { return this.BlendPosRot.rot; } return this.ChainRoot.rotation * this.BlendPosRot.rot; } protected bool IsEachBoneIK(AIKCtrl.IKSettingData data) { return data.isIKExec && data.curTargetData.target == this.bone; } private void MultiTgtDataToPosRot(AIKCtrl.IKSettingData data, AIKCtrl.IKExecTiming from, AIKCtrl.IKExecTiming to, ref Vector3 pos, ref Quaternion rot, ref float weight) { AIKCtrl.IKTargetData tgtData = data.GetTgtData(from); AIKCtrl.IKTargetData tgtData2 = data.GetTgtData(to); Vector3 a = pos; Quaternion a2 = rot; this.SetIKPosRot(data, tgtData, ref a, ref a2, true); Vector3 b = pos; Quaternion b2 = rot; this.SetIKPosRot(data, tgtData2, ref b, ref b2, true); float blendValue = this.GetFlagData(data.attachType).GetBlendValue(from, to); if (!tgtData.isExistTarget) { weight = ((!tgtData2.isExistTarget) ? 0f : blendValue); } else { weight = 1f; } if (data.isPointAttach) { pos = Vector3.Lerp(a, b, blendValue); } else { rot = Quaternion.Slerp(a2, b2, blendValue); } } protected virtual void SetTargetTransform(AIKCtrl.IKSettingData data, Vector3 pos, Quaternion rot) { AIKCtrl.IKTargetData curTargetData = data.curTargetData; Vector3 vector = curTargetData.tgtOffset; Vector3 vector2 = curTargetData.lastOffset; switch (data.attachType) { case AIKCtrl.IKAttachType.Point: Debug.DrawLine(pos, pos + rot * Vector3.forward * 0.2f, Color.cyan); if (!data.isOffsetSetEnd) { this.IkCmoPorc(pos, data.curTargetData.tgtOffset); } else { this.IkCmoPorc(pos, Vector3.zero); } break; case AIKCtrl.IKAttachType.NewPoint: if (!data.isOffsetSetEnd) { Vector3 start = pos; AIKCtrl.PosOffsetType posOffsetType = this.posOffsetType; if (posOffsetType != AIKCtrl.PosOffsetType.OffsetBone) { if (posOffsetType == AIKCtrl.PosOffsetType.OffsetTarget) { vector = rot * vector; vector2 = rot * vector2; } } else { vector = -(this.bone.rotation * vector); vector2 = -(this.bone.rotation * vector2); } if (data.blendType == AIKCtrl.IKBlendType.IK_To_IK && !data.isTargetChange) { vector = Vector3.Lerp(vector2 + data.lastAnmOffset, vector, data.blendWeight); } pos += vector; Debug.DrawLine(start, pos, Color.white); } pos = data.offsetEnable.GetEnable(this.bone.position, pos, false); this.ConstraintTarget.position = pos; if (data.blendType == AIKCtrl.IKBlendType.IK_To_IK && data.isTargetChange) { if (data.blendWeight < 0.5f) { this.ConstraintTarget.position = Vector3.Lerp(this.GetBlendBasePos(), this.bone.position, data.blendWeight / 0.5f); } else { this.ConstraintTarget.position = Vector3.Lerp(this.bone.position, this.ConstraintTarget.position, (data.blendWeight - 0.5f) / 0.5f); } } break; case AIKCtrl.IKAttachType.Rotate: if (!data.isOffsetSetEnd) { if (data.blendType == AIKCtrl.IKBlendType.IK_To_IK && !data.isTargetChange) { vector = Vector3.Lerp(curTargetData.lastOffset + data.lastAnmOffset, vector, data.blendWeight); } rot *= Quaternion.Euler(vector); } rot = Quaternion.Euler(data.offsetEnable.GetEnable(this.bone.eulerAngles, rot.eulerAngles, false)); this.ConstraintTarget.rotation = rot; if (data.blendType == AIKCtrl.IKBlendType.IK_To_IK && data.isTargetChange) { if (data.blendWeight < 0.5f) { this.ConstraintTarget.rotation = Quaternion.Slerp(this.GetBlendBaseRot(), this.bone.rotation, data.blendWeight / 0.5f); } else { this.ConstraintTarget.rotation = Quaternion.Slerp(this.bone.rotation, this.ConstraintTarget.rotation, (data.blendWeight - 0.5f) / 0.5f); } } break; } if (data.doAnimation && data.isBlendEnd) { if (data.isPointAttach) { data.anmOffset = this.bone.position - this.FirstBonePosRot.pos + (this.FirstTgtPosRot.pos - curTargetData.target.position); Debug.DrawRay(this.constraintTarget.position, data.anmOffset, Color.gray); this.constraintTarget.position += data.anmOffset; } else { Quaternion rhs = this.bone.rotation * Quaternion.Inverse(this.FirstBonePosRot.rot); this.constraintTarget.rotation *= rhs; data.anmOffset = rhs.eulerAngles; } } data.isOffsetSetEnd = true; } private void IkCmoPorc(Vector3 tgt, Vector3 vechand_offset) { if (!this.IsUseOldIK) { return; } for (int i = 0; i < 3; i++) { this.IKCmo.Porc(this.ChainBones[0], this.ChainBones[1], this.ChainBones[2], tgt, vechand_offset, this); } } public virtual void OnPostFullBodySolverUpdate() { } public virtual void OnPostIKUpdate() { this.SaveLastTargetPosRot(); this.pointIKData.isPosRotSetEnd = (this.rotateIKData.isPosRotSetEnd = false); } protected virtual void SaveLastTargetPosRot() { if (this.BlendCalc == AIKCtrl.BlendCalcType.World) { this.LastIKPosRot.Copy(this.constraintTarget); } else { this.LastIKPosRot.pos = this.constraintTarget.position - this.ChainRoot.position; this.LastIKPosRot.rot = this.ChainRoot.InverseTransformRotation(this.constraintTarget.rotation); } } public virtual void Detach() { this.isNeedAttachTargetUpdatePreExec = false; this.Detach(AIKCtrl.IKAttachType.NewPoint); this.Detach(AIKCtrl.IKAttachType.Rotate); this.BlendPosRot.Copy(this.LastIKPosRot); } protected void Detach(AIKCtrl.IKAttachType attachType) { AIKCtrl.IKSettingData iksettingData = this.GetIKSettingData(attachType); foreach (AIKCtrl.IKExecTiming exec_timing in (AIKCtrl.IKExecTiming[])Enum.GetValues(typeof(AIKCtrl.IKExecTiming))) { this.myIKMgr.RemovePartner(iksettingData.GetTgtData(exec_timing).targetChara, true); } this.GetFlagData(attachType).Reset(); iksettingData.Detach(); } public virtual void Reset() { } public void ResetDetach() { this.Reset(); this.Detach(); } public AIKCtrl.IKSettingData GetIKSettingData(AIKCtrl.IKAttachType attach_type) { if (attach_type == AIKCtrl.IKAttachType.Rotate) { return this.RotateIKData; } return this.PointIKData; } public AIKCtrl.ChangeFlagData GetFlagData(AIKCtrl.IKAttachType attach_type) { return this.GetIKSettingData(attach_type).changeFlagData; } public AIKCtrl.IKTargetData GetTargetData(AIKCtrl.IKAttachType attach_type) { return this.GetIKSettingData(attach_type).curTargetData; } public AIKCtrl.IKTargetData GetTargetData(AIKCtrl.IKAttachType attach_type, AIKCtrl.IKExecTiming exec_timing) { return this.GetIKSettingData(attach_type).GetTgtData(exec_timing); } private bool IsIKTargetChara(AIKCtrl.IKAttachType attach_type, Maid chara) { AIKCtrl.IKSettingData iksettingData = this.GetIKSettingData(attach_type); foreach (AIKCtrl.IKExecTiming exec_timing in (AIKCtrl.IKExecTiming[])Enum.GetValues(typeof(AIKCtrl.IKExecTiming))) { AIKCtrl.IKTargetData tgtData = iksettingData.GetTgtData(exec_timing); if (tgtData.targetChara == chara) { return true; } } return false; } public bool IsIKTargetChara(Maid chara) { return this.IsIKTargetChara(AIKCtrl.IKAttachType.NewPoint, chara) || this.IsIKTargetChara(AIKCtrl.IKAttachType.Rotate, chara); } public AIKCtrl.Vec3Enable GetIKEnable(AIKCtrl.IKAttachType attach_type) { return this.GetIKSettingData(attach_type).offsetEnable; } protected virtual void OnPostSetPositionWeight(float val) { } protected virtual void OnPostSetRotationWeight(float val) { } [SerializeField] [Header("位置IK")] private AIKCtrl.IKSettingData PointIKData = new AIKCtrl.IKSettingData(AIKCtrl.IKAttachType.NewPoint); [SerializeField] [Header("回転IK")] private AIKCtrl.IKSettingData RotateIKData = new AIKCtrl.IKSettingData(AIKCtrl.IKAttachType.Rotate); protected TBody.IKCMO IKCmo; protected AIKCtrl.PosRotPair BlendPosRot = default(AIKCtrl.PosRotPair); protected AIKCtrl.BlendCalcType BlendCalc; [SerializeField] [Header("ボーンとアタッチ用ターゲット")] private Transform Bone; public readonly FullBodyIKMgr.IKEffectorType effectorType; [SerializeField] private Transform ConstraintTarget; [SerializeField] private Transform VirtualTarget; private AIKCtrl.PosRotPair VirtualPosRot; private AIKCtrl.BoneTgtPair MyBoneTgtPair; protected AIKCtrl.PosRotPair FirstTgtPosRot = default(AIKCtrl.PosRotPair); protected AIKCtrl.PosRotPair FirstBonePosRot = default(AIKCtrl.PosRotPair); protected AIKCtrl.PosRotPair LastIKPosRot = default(AIKCtrl.PosRotPair); protected bool EachOtherIK; [Space] public AIKCtrl.PosOffsetType posOffsetType; public readonly FullBodyIKMgr myIKMgr; [SerializeField] [ReadOnly] protected Transform[] ChainBones; protected bool IsIgnoreLateUpdateEnd; public enum IKAttachType { Point, NewPoint, Rotate } public enum IKBlendType { Detach_To_IK, IK_To_IK, IK_To_Detach, Not_Blend } protected enum BlendCalcType { World, Local } public enum PosOffsetType { OffsetTarget, OffsetWorld, OffsetBone } public enum IKExecTiming { Normal, FlagPositive, FlagNegative = -1 } [Serializable] public struct Vec3Enable { public Vec3Enable(bool x_enable, bool y_enable, bool z_enable) { this.enableX = x_enable; this.enableY = y_enable; this.enableZ = z_enable; } public bool isAnyDisable { get { return !this.enableX || !this.enableY || !this.enableZ; } } public Vector3 GetEnable(Vector3 pos, bool inverse = false) { if (this.enableX == inverse) { pos.x = 0f; } if (this.enableY == inverse) { pos.y = 0f; } if (this.enableZ == inverse) { pos.z = 0f; } return pos; } public Vector3 GetEnable(Vector3 from, Vector3 to, bool inverse = false) { if (this.enableX == inverse) { to.x = from.x; } if (this.enableY == inverse) { to.y = from.y; } if (this.enableZ == inverse) { to.z = from.z; } return to; } public void Reset() { this.enableX = (this.enableY = (this.enableZ = true)); } public string OffEnableToStr() { if (!this.isAnyDisable) { return string.Empty; } string text = " disable="; if (!this.enableX) { text += "x"; } if (!this.enableY) { if (!this.enableX) { text += ","; } text += "y"; } if (!this.enableZ) { if (!this.enableX || !this.enableY) { text += ","; } text += "z"; } return text; } public bool enableX; public bool enableY; public bool enableZ; } [Serializable] public struct PosRotPair { public PosRotPair(Vector3 position, Quaternion rotation) { this.pos = position; this.rot = rotation; } public void Reset() { this.pos = Vector3.zero; this.rot = new Quaternion(0f, 0f, 0f, 1f); } public void Copy(AIKCtrl.PosRotPair pair) { this.pos = pair.pos; this.rot = pair.rot; } public void Copy(Transform transform) { this.pos = transform.position; this.rot = transform.rotation; } public void CopyLocal(Transform transform) { this.pos = transform.localPosition; this.rot = transform.localRotation; } public void DrawAxis() { DebugUtility.DrawAxis(this.pos, this.rot, 0.0625f); } public Vector3 pos; public Quaternion rot; } public struct BoneTgtPair { public BoneTgtPair(Transform bone, Transform target) { this.bone = bone; this.target = target; this.Copy(); } public void Copy() { this.target.position = this.bone.position; this.target.rotation = this.bone.rotation; } public readonly Transform bone; public readonly Transform target; } [Serializable] public class ChangeFlagData { public bool isEnable { get { return this.target != null; } } public AIKCtrl.IKExecTiming lastExecTiming { get; private set; } public AIKCtrl.IKExecTiming curExecTiming { get { if (this.GetFlagValue() > 0f) { return AIKCtrl.IKExecTiming.FlagPositive; } if (this.GetFlagValue() < 0f) { return AIKCtrl.IKExecTiming.FlagNegative; } return AIKCtrl.IKExecTiming.Normal; } } public float GetFlagValue() { if (!this.target) { return 0f; } return Vector3.Dot(this.target.localPosition, this.axis) / this.onValue; } public float GetBlendValue(AIKCtrl.IKExecTiming from, AIKCtrl.IKExecTiming to) { if (from == to) { return 1f; } return Mathf.InverseLerp((float)from, (float)to, this.GetFlagValue()); } public bool IsFlagChange() { if (!this.target) { return false; } AIKCtrl.IKExecTiming lastExecTiming = this.lastExecTiming; this.lastExecTiming = this.curExecTiming; return lastExecTiming != this.lastExecTiming; } public void Reset() { this.target = null; this.lastExecTiming = AIKCtrl.IKExecTiming.Normal; this.blendCtrlSelf = false; } public Transform target; public Vector3 axis = Vector3.forward; public float onValue = 0.1f; [HideInInspector] public bool blendCtrlSelf; } [Serializable] public class IKTargetData { public string lastAttachName { get; private set; } public Transform lastTarget { get; private set; } public Maid lastTgtChara { get; private set; } public Vector3 lastOffset { get; private set; } public bool isExistTarget { get { return this.target != null || !string.IsNullOrEmpty(this.tgtAttachName); } } public bool isTgtAttachPoint { get { return this.target == null && !string.IsNullOrEmpty(this.tgtAttachName); } } public bool IsEachOtherIK(bool check_update = false) { return this.targetChara && this.targetChara.body0.fullBodyIK.isIKExec && this.targetChara.body0.fullBodyIK.isUpdateEnd == check_update; } public void SaveLastTarget() { this.lastAttachName = this.tgtAttachName; this.lastTgtChara = this.targetChara; this.lastTarget = this.target; this.lastOffset = this.tgtOffset; } public void SetLastTarget(string attach_name, Maid maid, Transform target, Vector3 offset) { this.lastAttachName = attach_name; this.lastTgtChara = maid; this.lastTarget = target; this.lastOffset = offset; } public void SetIKSetting(IKAttachParam param, bool is_offset_rimmit = false) { this.SetLastTarget(this.tgtAttachName, this.targetChara, this.target, this.tgtOffset); this.targetChara = param.targetChara; this.tgtAttachSlot = param.slotNo; this.tgtAttachName = param.attachPointName; this.axisTarget = param.axisBone; this.target = param.attachTarget; this.attachIKName = param.attachIKName; if (!is_offset_rimmit) { this.tgtOffset = param.offset; } else { this.tgtOffset = MathUtility.AngleClamp180(param.offset); } this.isIKExec = true; } public void Detach() { this.SetLastTarget(this.tgtAttachName, this.targetChara, this.target, this.tgtOffset); this.targetChara = null; this.tgtAttachSlot = -1; this.tgtAttachName = string.Empty; this.target = null; this.axisTarget = null; this.tgtOffset = Vector3.zero; this.attachIKName = string.Empty; } public Transform target; public Vector3 tgtOffset; public int tgtAttachSlot = -1; public string tgtAttachName = string.Empty; public string attachIKName = string.Empty; public Maid targetChara; public bool isShowTgtAxis; public bool isIKExec; public Transform axisTarget; } [Serializable] public class IKSettingData { public IKSettingData(AIKCtrl.IKAttachType type) { this.attachType = type; this.blendType = AIKCtrl.IKBlendType.Not_Blend; this.offsetEnable.Reset(); } public bool isPointAttach { get { return this.attachType != AIKCtrl.IKAttachType.Rotate; } } public AIKCtrl.ChangeFlagData changeFlagData { get { return this.ChangeFlagData; } } public AIKCtrl.IKTargetData curTargetData { get { AIKCtrl.IKExecTiming curExecTiming = this.changeFlagData.curExecTiming; if (curExecTiming == AIKCtrl.IKExecTiming.FlagPositive) { return this.FlagPositiveTgtData; } if (curExecTiming != AIKCtrl.IKExecTiming.FlagNegative) { return this.NormalTgtData; } return this.FlagNegativeTgtData; } } public bool isIKExecNotWeight0 { get { return this.isIKExec && this.weight > 0f; } } public AIKCtrl.IKBlendType blendType { get; private set; } public bool isTargetChange { get; private set; } public bool isNeedBlend { get { return this.blendTime > 0f && !this.isBlendEnd; } } public float blendWeight { get { return Mathf.Clamp01(this.elapsedTime / this.blendTime); } } public bool isBlendNow { get { return this.isNeedBlend && this.elapsedTime < this.blendTime; } } public bool isBlendEnd { get; private set; } public bool isFirstFrame { get { return !this.isBlendNow && this.IsFirstFrame; } } public void CheckBlendType() { this.blendType = AIKCtrl.IKBlendType.IK_To_IK; bool flag = true; this.isTargetChange = false; float num = Vector3.Distance(this.curTargetData.lastOffset, this.curTargetData.tgtOffset); if (this.curTargetData.lastTarget) { if (!this.curTargetData.isExistTarget) { this.blendType = AIKCtrl.IKBlendType.IK_To_Detach; } else if (this.curTargetData.target) { flag = (this.isTargetChange = (this.curTargetData.lastTarget != this.curTargetData.target)); } else { flag = (this.isTargetChange = true); } flag |= (num > 0.01f || this.lastAnmOffset != Vector3.zero); } else if (!string.IsNullOrEmpty(this.curTargetData.lastAttachName)) { if (!this.curTargetData.isExistTarget) { this.blendType = AIKCtrl.IKBlendType.IK_To_Detach; } else if (!string.IsNullOrEmpty(this.curTargetData.tgtAttachName)) { flag = (this.isTargetChange = (this.curTargetData.lastAttachName != this.curTargetData.tgtAttachName || this.curTargetData.lastTgtChara != this.curTargetData.targetChara)); } else { flag = (this.isTargetChange = true); } flag |= (num > 0.1f || this.lastAnmOffset != Vector3.zero); } else { this.blendType = AIKCtrl.IKBlendType.Detach_To_IK; flag = (this.isTargetChange = this.curTargetData.isExistTarget); } if (!flag) { this.blendType = AIKCtrl.IKBlendType.Not_Blend; } } public void BlendReset() { this.elapsedTime = 0f; this.isBlendEnd = false; this.blendType = AIKCtrl.IKBlendType.Not_Blend; } public void BlendEnd() { this.elapsedTime = 0f; this.isBlendEnd = true; this.blendType = AIKCtrl.IKBlendType.Not_Blend; } public void SetBlendType(AIKCtrl.IKBlendType blend_type) { if (!this.isBlendEnd) { this.blendType = blend_type; } } public AIKCtrl.IKTargetData GetTgtData(AIKCtrl.IKExecTiming exec_timing) { if (exec_timing == AIKCtrl.IKExecTiming.FlagPositive) { return this.FlagPositiveTgtData; } if (exec_timing != AIKCtrl.IKExecTiming.FlagNegative) { return this.NormalTgtData; } return this.FlagNegativeTgtData; } public void SetIKSetting(IKAttachParam param) { this.BlendReset(); this.doAnimation = param.doAnimation; this.lastAnmOffset = this.anmOffset; this.anmOffset = Vector3.zero; this.isIKExec = true; this.IsFirstFrame = true; this.GetTgtData(param.execTiming).SetIKSetting(param, this.attachType == AIKCtrl.IKAttachType.Rotate); this.CheckBlendType(); this.ChangeFlagData.IsFlagChange(); } public void Detach() { this.BlendReset(); this.NormalTgtData.Detach(); this.FlagPositiveTgtData.Detach(); this.FlagNegativeTgtData.Detach(); this.CheckBlendType(); this.ChangeFlagData.Reset(); this.isOffsetSetEnd = false; this.isPosRotSetEnd = false; this.doAnimation = false; this.anmOffset = (this.lastAnmOffset = Vector3.zero); this.isIKExec = false; this.IsFirstFrame = false; this.isSetFirstFramePosRot = false; } public void CheckFirstFrame() { if (!this.isBlendNow) { this.IsFirstFrame = false; } } [HideInInspector] public FullBodyIKMgr ikCtrl; public AIKCtrl.IKAttachType attachType; [Header("各ターゲット情報")] [SerializeField] private AIKCtrl.IKTargetData NormalTgtData = new AIKCtrl.IKTargetData(); [SerializeField] private AIKCtrl.IKTargetData FlagPositiveTgtData = new AIKCtrl.IKTargetData(); [SerializeField] private AIKCtrl.IKTargetData FlagNegativeTgtData = new AIKCtrl.IKTargetData(); [Space] public AIKCtrl.Vec3Enable offsetEnable; [SerializeField] [Header("IKターゲットを切り替えのフラグ情報")] private AIKCtrl.ChangeFlagData ChangeFlagData = new AIKCtrl.ChangeFlagData(); [Header("実行してるか")] public bool isIKExec; public float blendTime = 0.5f; [Space] public float elapsedTime; private bool IsFirstFrame; public bool doAnimation; public Vector3 anmOffset = Vector3.zero; public Vector3 lastAnmOffset = Vector3.zero; [Space] [Range(0f, 1f)] public float weight; [HideInInspector] public bool isPosRotSetEnd; [HideInInspector] public bool isOffsetSetEnd; [HideInInspector] public bool isSetFirstFramePosRot; } }