using System; using UnityEngine; public abstract class IKCtrlData { public IKCtrlData(FullBodyIKCtrl ik_ctrl, Transform tgt_bone, bool use_old = false, bool attach_ik = false) { this.MyIKCtrl = ik_ctrl; this.UseOldIK = use_old; this.m_TargetBone = tgt_bone; this.m_AttachPointIK = attach_ik; string text = (!this.MyIKCtrl.TgtChara.boMAN) ? "Bip01" : "ManBip"; string name = this.m_TargetBone.name; Transform transform = this.MyIKCtrl.IKTgtRoot.Find(name); if (!transform) { transform = new GameObject(name).transform; transform.transform.SetParent(this.MyIKCtrl.IKTgtRoot, false); GameObject gameObject = new GameObject("IKTarget"); gameObject.transform.SetParent(transform.transform, false); this.m_IKTarget = gameObject.transform; } else { this.m_IKTarget = transform.Find("IKTarget"); } this.m_BoneTgtPair = new IKCtrlData.BoneTgtPair(this.TargetBone, this.m_IKTarget); this.IkCmoInit(); this.m_PointIKData.IKCtrl = ik_ctrl; this.m_RotateIKData.IKCtrl = ik_ctrl; } public IKCtrlData.IKSettingData PointIK { get { return this.m_PointIKData; } } public IKCtrlData.IKSettingData RotateIK { get { return this.m_RotateIKData; } } public TBody.IKCMO IKCmo { get { return this.m_IKCmo; } } public bool ForceIK { get { return this.m_ForceIK; } set { this.m_ForceIK = (this.m_ForceIKEnable && value); } } public IKCtrlData.PosRotPair BlendPosRot { get { return this.m_BlendPosRot; } } public bool IsIKExec { get { return this.m_PointIKData.IsIKExec || this.m_RotateIKData.IsIKExec || this.ForceIK; } } public bool IsIKExecTruth { get { return this.GetIKExecTruth(IKCtrlData.IKAttachType.NewPoint) || this.GetIKExecTruth(IKCtrlData.IKAttachType.Rotate); } } public bool IsWeightOver0 { get { return this.PositionWeight * this.m_PosWeightBase > 0f || this.RotationWeight * this.m_RotWeightBase > 0f; } } public bool OldIkExec { get { return this.m_PointIKData.IsIKExec && this.m_PointIKData.IsOldIK; } } public bool AttachPointIK { get { return this.m_AttachPointIK; } } public Transform IKTarget { get { return this.m_IKTarget; } } public IKCtrlData.Vec3Enable OffsetEnable { get { return this.m_OffsetEnable; } } public virtual Transform TargetBone { get { return this.m_TargetBone; } } public bool IsSelfIKAttach { get; protected set; } public Transform[] ChainBones { get { return this.m_ChainBones; } } public float PositionWeight { get { return this.PointIK.Weight; } set { this.PointIK.Weight = value; this.OnPostSetPositionWeight(value); } } public float RotationWeight { get { return this.RotateIK.Weight; } set { this.RotateIK.Weight = value; this.OnPostSetRotationWeight(value); } } public virtual bool NeedFullbodySolverUpdate { get { return false; } } public static bool operator true(IKCtrlData data) { return data != null; } public static bool operator false(IKCtrlData data) { return data == null; } public static bool operator !(IKCtrlData data) { return data == null; } private void IkCmoInit() { if (!this.UseOldIK) { return; } this.IKCmo.Init(this.TargetBone.parent.parent, this.TargetBone.parent, this.TargetBone, this.MyIKCtrl.TgtBody); } public void SetFlagTarget(IKCtrlData.IKAttachType attach_type, string name) { if (this.MyIKCtrl.TgtChara.boMAN) { this.GetFlagData(attach_type).Target = this.MyIKCtrl.TgtBody.GetBone(name); } else { this.GetFlagData(attach_type).Target = this.MyIKCtrl.GetSTFlagObj(name); } } public void SetIKSetting(IKCtrlData.IKAttachType attachType, IKCtrlData.IKExecTiming timing, Maid tgt_maid, int slot_no, string attach_name, Transform axis_bone, Vector3 f_vecOffset, bool do_animation = false) { this.SetIKSetting(attachType, timing, tgt_maid, slot_no, attach_name, axis_bone, null, f_vecOffset, do_animation); } public void SetIKSetting(IKCtrlData.IKAttachType attachType, IKCtrlData.IKExecTiming timing, Maid tgt_maid, Transform target, Vector3 f_vecOffset, bool do_animation = false) { this.SetIKSetting(attachType, timing, tgt_maid, -1, string.Empty, null, target, f_vecOffset, do_animation); } public void SetIKSetting(IKCtrlData.IKAttachType attachType, IKCtrlData.IKExecTiming timing, Transform target, Vector3 f_vecOffset, bool do_animation = false) { this.SetIKSetting(attachType, timing, null, -1, string.Empty, null, target, f_vecOffset, do_animation); } public void SetIKSetting(IKCtrlData.IKAttachType attachType, IKCtrlData.IKExecTiming timing, Maid tgt_maid, string bone_name, Transform target, Vector3 f_vecOffset, bool do_animation = false) { this.SetIKSetting(attachType, timing, tgt_maid, -1, bone_name, null, target, f_vecOffset, do_animation); } public virtual void SetIKSetting(IKCtrlData.IKAttachType attachType, IKCtrlData.IKExecTiming timing, Maid tgt_maid, int slot_no, string attach_name, Transform axis_bone, Transform target, Vector3 f_vecOffset, bool do_animation = false) { this.GetIKSettingData(attachType).ChangeIKType(attachType); if (this.GetIKSettingData(attachType).MyType != attachType) { return; } this.MyIKCtrl.IKActive = true; this.BlendPosRot.Copy(this.m_lastIKPosRot); this.m_AnimPosRotOffset.Reset(); this.m_FirstPosRotOffset.Reset(); this.m_FirstTgtPosRot.Reset(); if (!target && !string.IsNullOrEmpty(attach_name)) { this.IsSelfIKAttach |= (tgt_maid == this.MyIKCtrl.TgtChara); } this.GetIKSettingData(attachType).SetIKSetting(timing, tgt_maid, slot_no, attach_name, axis_bone, target, f_vecOffset, do_animation); this.GetFlagData(attachType).IsFlagChange(); } public virtual void SetPullState(bool pull_on) { } protected virtual void OnPostSetPositionWeight(float val) { } protected virtual void OnPostSetRotationWeight(float val) { } public virtual void TagetTransCpy() { this.m_BoneTgtPair.Copy(); float num = 0f; this.RotationWeight = num; this.PositionWeight = num; } public virtual void ApplyIKSetting() { if (this.ForceIK) { this.GetIKSettingData(IKCtrlData.IKAttachType.NewPoint).ChangeIKType(IKCtrlData.IKAttachType.NewPoint); } if (!this.MyIKCtrl.IsUpdateEnd) { this.m_EachOtherIK = false; this.ForceIK |= this.MyIKCtrl.AllForceIK; } this.ApplyIKSetting(this.GetIKSettingData(IKCtrlData.IKAttachType.NewPoint)); this.ApplyIKSetting(this.GetIKSettingData(IKCtrlData.IKAttachType.Rotate)); } private void ApplyIKSetting(IKCtrlData.IKSettingData data) { if (this.MyIKCtrl.IsUpdateLate) { return; } if (data.curTargetData.TgtChara && data.curTargetData.TgtChara != this.MyIKCtrl.TgtChara) { IKCtrlData ikdata = data.curTargetData.TgtChara.IKCtrl.GetIKData(data.curTargetData.Tgt_AttachName); if (ikdata != null && ikdata.IsIKExec) { IKCtrlData.IKSettingData iksettingData = ikdata.GetIKSettingData(data.MyType); this.m_EachOtherIK = this.IsEachBoneIK(iksettingData); } if (!data.curTargetData.TgtChara.body0.LateUpdateEnd && !this.MyIKCtrl.TgtBody.LateUpdateEnd) { this.MyIKCtrl.IsUpdateLate = true; if (data.curTargetData.TgtChara.IKCtrl.IsIKExec) { FullBodyIKCtrl ikctrl = data.curTargetData.TgtChara.IKCtrl; ikctrl.PostSolverUpdate = (Action)Delegate.Combine(ikctrl.PostSolverUpdate, new Action(this.MyIKCtrl.LateIKUpdate)); } else { TBody body = data.curTargetData.TgtChara.body0; body.OnLateUpdateEnd = (Action)Delegate.Combine(body.OnLateUpdateEnd, new Action(this.MyIKCtrl.LateIKUpdate)); } return; } } if (data.BlendType != IKCtrlData.IKBlendType.Not_Blend && data.BlendTime <= 0f) { data.BlendReset(false); } data.DoSetOffset = false; data.IsIKExec = true; Vector3 position = this.TargetBone.position; Quaternion rotation = this.TargetBone.rotation; if (this.GetFlagData(data.MyType).IsEnable) { if (!this.GetFlagData(data.MyType).BlendCtrlSelf) { IKCtrlData.IKExecTiming curExecTiming = data.changeFlagData.curExecTiming; this.MultiTgtDataToPosRot(data, IKCtrlData.IKExecTiming.Normal, curExecTiming, ref position, ref rotation); data.DoSetOffset = true; data.IsIKExec = true; } else { IKCtrlData.IKExecTiming lastExecTiming = data.changeFlagData.lastExecTiming; if (this.GetFlagData(data.MyType).IsFlagChange()) { IKCtrlData.IKTargetData tgtData = data.GetTgtData(lastExecTiming); data.BlendReset(true); data.curTargetData.SetLastTarget(tgtData.Tgt_AttachName, tgtData.TgtChara, tgtData.Target, tgtData.TgtOffset); data.CheckBlendType(true); if (data.MyType == IKCtrlData.IKAttachType.Rotate) { this.BlendPosRot.rot = this.m_lastIKPosRot.rot; } else { this.BlendPosRot.pos = this.m_lastIKPosRot.pos; } this.SetIKPosRot(data, ref position, ref rotation, false, IKCtrlData.IKExecTiming.Normal); } else { this.SetIKPosRot(data, ref position, ref rotation, false, IKCtrlData.IKExecTiming.Normal); } } } else { this.SetIKPosRot(data, ref position, ref rotation, false, IKCtrlData.IKExecTiming.Normal); } if (data.IsIKExec) { if (data.FirstFrame && !data.BlendNow) { if (data.IsPointAttach) { this.m_FirstTgtPosRot.pos = position; } else { this.m_FirstTgtPosRot.rot = rotation; } } this.SetTargetTransform(data, position, rotation); if (this.m_EachOtherIK && !data.curTargetData.TgtChara.IKCtrl.IsUpdateEnd) { if (data.IsPointAttach) { this.PositionWeight *= 0.5f; } else { this.RotationWeight *= 0.5f; } } if (data.DoAnimation && !data.BlendNow) { if (!data.DoSetPosRot) { Transform targetBone = this.TargetBone; if (data.IsPointAttach) { if (!data.FirstFrame) { this.IKTarget.position += targetBone.position - this.m_FirstTgtPosRot.pos - this.m_FirstPosRotOffset.pos; } else { this.m_FirstPosRotOffset.pos = targetBone.position - this.m_FirstTgtPosRot.pos; } } else if (!data.FirstFrame) { this.IKTarget.rotation *= targetBone.rotation * Quaternion.Inverse(this.m_FirstTgtPosRot.rot) * Quaternion.Inverse(this.m_FirstPosRotOffset.rot); } else { this.m_FirstPosRotOffset.rot = targetBone.rotation * Quaternion.Inverse(this.m_FirstTgtPosRot.rot); } } } else { this.m_AnimPosRotOffset.Reset(); } if (!data.BlendNow) { data.FirstFrame = false; } if (data.curTargetData.IsTgtAxis) { KasaiUtility.DrawAxis(position, rotation, 0.125f); } if (!data.DoSetPosRot && data.BlendType != IKCtrlData.IKBlendType.Not_Blend) { data.ElapsedTime += Time.deltaTime; if (data.ElapsedTime >= data.BlendTime) { data.BlendReset(false); } } data.DoSetPosRot = true; } } private void SetIKPosRot(IKCtrlData.IKSettingData setting_data, ref Vector3 pos, ref Quaternion rot, bool include_offset = false, IKCtrlData.IKExecTiming flag_type = IKCtrlData.IKExecTiming.Normal) { this.SetIKPosRot(setting_data, setting_data.GetTgtData(flag_type), ref pos, ref rot, include_offset); } private void SetIKPosRot(IKCtrlData.IKSettingData setting_data, IKCtrlData.IKTargetData tgt_data, ref Vector3 pos, ref Quaternion rot, bool include_offset = false) { if (tgt_data.Target != null) { pos = tgt_data.Target.position; rot = tgt_data.Target.rotation; } else if (tgt_data.Tgt_AttachName != string.Empty) { if (this.MyIKCtrl.TgtBody.goSlot[tgt_data.Tgt_AttachSlot].morph != null) { if (tgt_data.TgtChara != null && tgt_data.TgtChara.body0 != null) { tgt_data.TgtChara.body0.SkinMeshUpdateOnce(); Vector3 vector; tgt_data.TgtChara.body0.goSlot[tgt_data.Tgt_AttachSlot].morph.GetAttachPoint(tgt_data.Tgt_AttachName, out pos, out rot, out vector, false); if (setting_data.MyType == IKCtrlData.IKAttachType.NewPoint && tgt_data.AxisTgt) { rot = tgt_data.AxisTgt.rotation; } } else { setting_data.IsIKExec = false; tgt_data.Tgt_AttachName = string.Empty; } } } else if (this.ForceIK) { pos = this.m_IKTarget.position; rot = this.m_IKTarget.rotation; } else if (setting_data.BlendType == IKCtrlData.IKBlendType.IK_To_Detach) { pos = this.BlendPosRot.pos; rot = this.BlendPosRot.rot; } else { setting_data.IsIKExec = false; } if (setting_data.IsIKExec && include_offset) { if (setting_data.IsPointAttach) { Vector3 start = pos; switch (this.posOffsetType) { case IKCtrlData.PosOffsetType.OffsetTarget: pos += rot * tgt_data.TgtOffset; break; case IKCtrlData.PosOffsetType.OffsetWorld: pos += tgt_data.TgtOffset; break; case IKCtrlData.PosOffsetType.OffsetBone: pos -= this.TargetBone.rotation * tgt_data.TgtOffset; break; } Debug.DrawLine(start, pos, Color.white); } else { rot *= Quaternion.Euler(tgt_data.TgtOffset); } } } protected bool IsEachBoneIK(IKCtrlData.IKSettingData data) { return data.IsIKExec && data.curTargetData.Target == this.TargetBone; } private void MultiTgtDataToPosRot(IKCtrlData.IKSettingData data, IKCtrlData.IKExecTiming from, IKCtrlData.IKExecTiming to, ref Vector3 pos, ref Quaternion rot) { IKCtrlData.IKTargetData tgtData = data.GetTgtData(from); IKCtrlData.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.MyType).GetBlendValue(from, to); if (data.IsPointAttach) { if (!tgtData.ExistTgt) { this.m_PosWeightBase = ((!tgtData2.ExistTgt) ? 0f : blendValue); } else { this.m_PosWeightBase = 1f; } pos = Vector3.Lerp(a, b, blendValue); } else { if (!tgtData.ExistTgt) { this.m_RotWeightBase = ((!tgtData2.ExistTgt) ? 0f : blendValue); } else { this.m_RotWeightBase = 1f; } rot = Quaternion.Lerp(a2, b2, blendValue); } } protected virtual void SetTargetTransform(IKCtrlData.IKSettingData data, Vector3 pos, Quaternion rot) { IKCtrlData.IKTargetData curTargetData = data.curTargetData; switch (data.MyType) { case IKCtrlData.IKAttachType.Point: pos += this.m_AnimPosRotOffset.pos; Debug.DrawLine(pos, pos + rot * Vector3.forward * 0.2f, Color.cyan); if (!data.DoSetOffset) { this.IkCmoPorc(pos, data.curTargetData.TgtOffset); } else { this.IkCmoPorc(pos, Vector3.zero); } break; case IKCtrlData.IKAttachType.Rotate: rot *= this.m_AnimPosRotOffset.rot; if (!data.DoSetOffset) { rot *= Quaternion.Euler(data.curTargetData.TgtOffset); } rot = Quaternion.Euler(this.GetIKEnable(data.MyType).GetEnable(this.TargetBone.eulerAngles, rot.eulerAngles, false)); this.m_IKTarget.rotation = rot; if (data.BlendType == IKCtrlData.IKBlendType.IK_To_IK) { this.m_IKTarget.rotation = Quaternion.Lerp(this.BlendPosRot.rot, this.m_IKTarget.rotation, data.BlendWeight); this.RotationWeight = this.m_RotWeightBase; } else if (data.BlendType == IKCtrlData.IKBlendType.IK_To_Detach) { this.RotationWeight = this.m_RotWeightBase * (1f - data.BlendWeight); } else { this.RotationWeight = this.m_RotWeightBase * data.BlendWeight; } break; case IKCtrlData.IKAttachType.NewPoint: pos += this.m_AnimPosRotOffset.pos; if (!data.DoSetOffset) { Vector3 start = pos; switch (this.posOffsetType) { case IKCtrlData.PosOffsetType.OffsetTarget: pos += rot * curTargetData.TgtOffset; break; case IKCtrlData.PosOffsetType.OffsetWorld: pos += curTargetData.TgtOffset; break; case IKCtrlData.PosOffsetType.OffsetBone: pos -= this.TargetBone.rotation * curTargetData.TgtOffset; break; } Debug.DrawLine(start, pos, Color.white); } pos = this.GetIKEnable(data.MyType).GetEnable(this.TargetBone.position, pos, false); this.m_IKTarget.position = pos; if (data.BlendType == IKCtrlData.IKBlendType.IK_To_IK) { this.m_IKTarget.position = Vector3.Lerp(this.BlendPosRot.pos, this.m_IKTarget.position, data.BlendWeight); this.PositionWeight = this.m_PosWeightBase; } else if (data.BlendType == IKCtrlData.IKBlendType.IK_To_Detach) { this.PositionWeight = this.m_PosWeightBase * (1f - data.BlendWeight); } else { this.PositionWeight = this.m_PosWeightBase * data.BlendWeight; } break; } data.DoSetOffset = true; } private void IkCmoPorc(Vector3 tgt, Vector3 vechand_offset) { if (!this.UseOldIK) { return; } for (int i = 0; i < 3; i++) { this.IKCmo.Porc(this.TargetBone.parent.parent, this.TargetBone.parent, this.TargetBone, tgt, vechand_offset, this); } } public virtual void Update() { } public virtual void LateUpdate() { this.SaveLastBonePosRot(); this.GetIKSettingData(IKCtrlData.IKAttachType.NewPoint).DoSetPosRot = (this.GetIKSettingData(IKCtrlData.IKAttachType.Rotate).DoSetPosRot = false); } public virtual void SaveLastBonePosRot() { this.m_lastIKPosRot.Copy(this.m_TargetBone); } public virtual void Detach(IKCtrlData.IKAttachType attachType) { this.ForceIK = false; this.m_BoneTgtPair.PosOffset = Vector3.zero; this.IsSelfIKAttach = false; this.BlendPosRot.Copy(this.m_lastIKPosRot); this.GetFlagData(attachType).Reset(); this.GetIKSettingData(attachType).Detach(); } public IKCtrlData.IKSettingData GetIKSettingData(IKCtrlData.IKAttachType attach_type) { if (attach_type == IKCtrlData.IKAttachType.Rotate) { return this.m_RotateIKData; } return this.m_PointIKData; } public IKCtrlData.ChangeFlagData GetFlagData(IKCtrlData.IKAttachType attach_type) { return this.GetIKSettingData(attach_type).changeFlagData; } public IKCtrlData.IKTargetData GetTargetData(IKCtrlData.IKAttachType attach_type) { return this.GetIKSettingData(attach_type).curTargetData; } public IKCtrlData.IKTargetData GetTargetData(IKCtrlData.IKAttachType attach_type, IKCtrlData.IKExecTiming exec_timing) { return this.GetIKSettingData(attach_type).GetTgtData(exec_timing); } private bool IsIKTargetChara(IKCtrlData.IKAttachType attach_type, Maid chara) { IKCtrlData.IKSettingData iksettingData = this.GetIKSettingData(attach_type); foreach (IKCtrlData.IKExecTiming timing in (IKCtrlData.IKExecTiming[])Enum.GetValues(typeof(IKCtrlData.IKExecTiming))) { IKCtrlData.IKTargetData tgtData = iksettingData.GetTgtData(timing); if (tgtData.TgtChara == chara) { return true; } } return false; } public bool IsIKTargetChara(Maid chara) { return this.IsIKTargetChara(IKCtrlData.IKAttachType.NewPoint, chara) || this.IsIKTargetChara(IKCtrlData.IKAttachType.Rotate, chara); } public IKCtrlData.Vec3Enable GetIKEnable(IKCtrlData.IKAttachType attach_type) { return this.GetIKSettingData(attach_type).offsetEnable; } public bool GetIKExecTruth(IKCtrlData.IKAttachType attach_type) { IKCtrlData.IKSettingData iksettingData = (attach_type != IKCtrlData.IKAttachType.Rotate) ? this.PointIK : this.RotateIK; float num = (attach_type != IKCtrlData.IKAttachType.Rotate) ? this.PositionWeight : this.RotationWeight; bool flag = iksettingData.IsIKExec && num > 0f; if (iksettingData.changeFlagData.IsEnable) { flag &= (iksettingData.changeFlagData.GetFlagValue() > 0f); } return flag; } [SerializeField] [Header("位置IK")] private IKCtrlData.IKSettingData m_PointIKData = new IKCtrlData.IKSettingData(IKCtrlData.IKAttachType.NewPoint); [SerializeField] [Header("回転IK")] private IKCtrlData.IKSettingData m_RotateIKData = new IKCtrlData.IKSettingData(IKCtrlData.IKAttachType.Rotate); private TBody.IKCMO m_IKCmo = new TBody.IKCMO(); private IKCtrlData.PosRotPair m_BlendPosRot = new IKCtrlData.PosRotPair(); [SerializeField] [Space] private IKCtrlData.PosRotPair m_AnimPosRotOffset = new IKCtrlData.PosRotPair(); private IKCtrlData.PosRotPair m_FirstPosRotOffset = new IKCtrlData.PosRotPair(); [SerializeField] private bool m_AttachPointIK; [SerializeField] private Transform m_TargetBone; [SerializeField] private Transform m_IKTarget; [SerializeField] private bool m_DrawLine = true; private IKCtrlData.BoneTgtPair m_BoneTgtPair; protected IKCtrlData.PosRotPair m_FirstTgtPosRot = new IKCtrlData.PosRotPair(); protected IKCtrlData.PosRotPair m_lastIKPosRot = new IKCtrlData.PosRotPair(); [SerializeField] [Range(0f, 1f)] protected float m_PosWeightBase = 1f; [SerializeField] [Range(0f, 1f)] protected float m_RotWeightBase = 1f; [SerializeField] protected bool m_ForceIK; protected bool m_ForceIKEnable; protected bool m_EachOtherIK; protected IKCtrlData.Vec3Enable m_OffsetEnable = new IKCtrlData.Vec3Enable(); [Space] public IKCtrlData.PosOffsetType posOffsetType; public readonly FullBodyIKCtrl MyIKCtrl; public readonly bool UseOldIK; protected Transform[] m_ChainBones; public enum IKAttachType { Point, Rotate, NewPoint } public enum IKBlendType { Detach_To_IK, IK_To_IK, IK_To_Detach, Not_Blend } public enum PosOffsetType { OffsetTarget, OffsetWorld, OffsetBone } public enum IKExecTiming { Normal, FlagPositive, FlagNegative = -1 } [Serializable] public class Vec3Enable { public bool AnyDisable { 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 Recet() { this.EnableX = (this.EnableY = (this.EnableZ = true)); } public void Copy(IKCtrlData.Vec3Enable cpy) { this.EnableX = cpy.EnableX; this.EnableY = cpy.EnableY; this.EnableZ = cpy.EnableZ; } public string OffEnableToStr() { if (!this.AnyDisable) { 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 = true; public bool EnableY = true; public bool EnableZ = true; } [Serializable] public class PosRotPair { public void Reset() { this.pos = Vector3.zero; this.rot = new Quaternion(0f, 0f, 0f, 1f); } public void Copy(IKCtrlData.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 DrawAxis() { KasaiUtility.DrawAxis(this.pos, this.rot, 0.0625f); } public Vector3 pos = Vector3.zero; public Quaternion rot = new Quaternion(0f, 0f, 0f, 1f); } public class BoneTgtPair { public BoneTgtPair(Transform bone, Transform target) { this.Bone = bone; this.Target = target; } public void Copy() { this.Target.position = this.Bone.position + this.PosOffset; this.Target.rotation = this.Bone.rotation; } public readonly Transform Bone; public readonly Transform Target; public Vector3 PosOffset = Vector3.zero; } [Serializable] public class ChangeFlagData { public bool IsEnable { get { return this.Target != null; } } public IKCtrlData.IKExecTiming lastExecTiming { get; private set; } public IKCtrlData.IKExecTiming curExecTiming { get { if (this.GetFlagValue() > 0f) { return IKCtrlData.IKExecTiming.FlagPositive; } if (this.GetFlagValue() < 0f) { return IKCtrlData.IKExecTiming.FlagNegative; } return IKCtrlData.IKExecTiming.Normal; } } public float GetFlagValue() { if (!this.Target) { return 0f; } return Vector3.Dot(this.Target.localPosition, this.Axis) / this.OnValue; } public float GetBlendValue(IKCtrlData.IKExecTiming from, IKCtrlData.IKExecTiming to) { if (from == to) { return 1f; } return Mathf.InverseLerp((float)from, (float)to, this.GetFlagValue()); } public bool IsFlagChange() { if (!this.Target) { return false; } IKCtrlData.IKExecTiming lastExecTiming = this.lastExecTiming; this.lastExecTiming = this.curExecTiming; return lastExecTiming != this.lastExecTiming; } public void Reset() { this.Target = null; this.lastExecTiming = IKCtrlData.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 IKTargetData(bool is_for_point) { this.IsForPointTarget = is_for_point; } public string lastAttachName { get { return this.m_LastAttachName; } } public Transform lastTarget { get { return this.m_LastTarget; } } public Maid lastTgtChara { get { return this.m_LastTgtChara; } } public Vector3 lastOffset { get { return this.m_LastOffset; } } public bool ExistTgt { get { return this.Target != null || !string.IsNullOrEmpty(this.Tgt_AttachName); } } public bool IsEachOtherIK(bool check_update = false) { return this.TgtChara && this.TgtChara.IKCtrl.IsIKExec && this.TgtChara.IKCtrl.IsUpdateEnd == check_update; } public void SaveLastTarget() { this.m_LastAttachName = this.Tgt_AttachName; this.m_LastTgtChara = this.TgtChara; this.m_LastTarget = this.Target; this.m_LastOffset = this.TgtOffset; } public void SetLastTarget(string attach_name, Maid maid, Transform target, Vector3 offset) { this.m_LastAttachName = attach_name; this.m_LastTgtChara = maid; this.m_LastTarget = target; this.m_LastOffset = offset; } public void SetIKSetting(Maid tgt_maid, int slot_no, string attach_name, Transform axis_bone, Transform target, Vector3 f_vecOffset) { this.SetLastTarget(this.Tgt_AttachName, this.TgtChara, this.Target, this.TgtOffset); this.TgtChara = tgt_maid; this.Tgt_AttachSlot = slot_no; this.Tgt_AttachName = attach_name; this.Target = target; this.AxisTgt = axis_bone; if (this.IsForPointTarget) { this.TgtOffset = f_vecOffset; } else { this.TgtOffset = KasaiUtility.AngleRimmit360(f_vecOffset); } this.IsIKExec = true; } public void Detach() { this.SetLastTarget(this.Tgt_AttachName, this.TgtChara, this.Target, this.TgtOffset); this.TgtChara = null; this.Tgt_AttachSlot = -1; this.Tgt_AttachName = string.Empty; this.Target = null; this.AxisTgt = null; this.TgtOffset = Vector3.zero; } private string m_LastAttachName = string.Empty; private Transform m_LastTarget; private Maid m_LastTgtChara; private Vector3 m_LastOffset = Vector3.zero; public Transform Target; public Vector3 TgtOffset; public int Tgt_AttachSlot = -1; public string Tgt_AttachName = string.Empty; public Maid TgtChara; public bool IsTgtAxis; public bool IsIKExec; public Transform AxisTgt; public readonly bool IsForPointTarget; } [Serializable] public class IKSettingData { public IKSettingData(IKCtrlData.IKAttachType type) { this.MyType = type; this.BlendType = IKCtrlData.IKBlendType.Not_Blend; this.m_NormalTgtData = new IKCtrlData.IKTargetData(this.IsPointAttach); this.m_FlagPositiveTgtData = new IKCtrlData.IKTargetData(this.IsPointAttach); this.m_FlagNegativeTgtData = new IKCtrlData.IKTargetData(this.IsPointAttach); } public IKCtrlData.Vec3Enable offsetEnable { get { return this.m_OffsetEnable; } } public IKCtrlData.ChangeFlagData changeFlagData { get { return this.m_ChangeFlagData; } } public IKCtrlData.IKTargetData curTargetData { get { IKCtrlData.IKExecTiming curExecTiming = this.changeFlagData.curExecTiming; if (curExecTiming == IKCtrlData.IKExecTiming.FlagPositive) { return this.m_FlagPositiveTgtData; } if (curExecTiming != IKCtrlData.IKExecTiming.FlagNegative) { return this.m_NormalTgtData; } return this.m_FlagNegativeTgtData; } } public float BlendTime { get { return (!this.IKCtrl) ? -1f : this.IKCtrl.BlendTime; } } public IKCtrlData.IKAttachType MyType { get; private set; } public IKCtrlData.IKBlendType BlendType { get; private set; } public bool DoIKBlend { get { return this.m_DoIKBlend && this.BlendTime > 0f; } } public bool IsPointAttach { get { return this.MyType != IKCtrlData.IKAttachType.Rotate; } } public bool NeedBlend { get { return this.BlendTime > 0f && this.BlendType != IKCtrlData.IKBlendType.Not_Blend; } } public float BlendWeight { get { return (!this.NeedBlend || !this.DoIKBlend) ? 1f : Mathf.Clamp01(this.ElapsedTime / this.BlendTime); } } public bool BlendNow { get { return this.NeedBlend && this.ElapsedTime < this.BlendTime; } } public bool IsOldIK { get { return this.MyType == IKCtrlData.IKAttachType.Point; } } public void ChangeIKType(IKCtrlData.IKAttachType type) { if (this.MyType == IKCtrlData.IKAttachType.Rotate) { return; } this.MyType = type; } public void CheckBlendType(bool check_time = true) { this.BlendType = IKCtrlData.IKBlendType.IK_To_IK; this.m_DoIKBlend = true; float num = Vector3.Distance(this.curTargetData.lastOffset, this.curTargetData.TgtOffset); if (this.curTargetData.lastTarget) { if (!this.curTargetData.Target && string.IsNullOrEmpty(this.curTargetData.Tgt_AttachName)) { this.BlendType = IKCtrlData.IKBlendType.IK_To_Detach; } else if (this.curTargetData.Target) { this.m_DoIKBlend = (this.curTargetData.lastTarget != this.curTargetData.Target || num > 0.01f); } } else if (!string.IsNullOrEmpty(this.curTargetData.lastAttachName)) { if (string.IsNullOrEmpty(this.curTargetData.Tgt_AttachName) && !this.curTargetData.Target) { this.BlendType = IKCtrlData.IKBlendType.IK_To_Detach; } else if (!this.curTargetData.Target) { this.m_DoIKBlend = (this.curTargetData.lastAttachName != this.curTargetData.Tgt_AttachName || this.curTargetData.lastTgtChara != this.curTargetData.TgtChara || num > 0.01f); } } else { this.BlendType = IKCtrlData.IKBlendType.Detach_To_IK; if (!this.curTargetData.Target && string.IsNullOrEmpty(this.curTargetData.Tgt_AttachName)) { this.BlendType = IKCtrlData.IKBlendType.Not_Blend; this.m_DoIKBlend = false; } } } public void BlendReset(bool elpsed_only = false) { this.ElapsedTime = 0f; if (!elpsed_only) { this.m_DoIKBlend = false; this.BlendType = IKCtrlData.IKBlendType.Not_Blend; } } public IKCtrlData.IKTargetData GetTgtData(IKCtrlData.IKExecTiming timing) { if (timing == IKCtrlData.IKExecTiming.FlagPositive) { return this.m_FlagPositiveTgtData; } if (timing != IKCtrlData.IKExecTiming.FlagNegative) { return this.m_NormalTgtData; } return this.m_FlagNegativeTgtData; } public void SetIKSetting(IKCtrlData.IKExecTiming timing, Maid tgt_chara, int slot_no, string attach_name, Transform axis_bone, Transform target, Vector3 f_vecOffset, bool do_animation) { this.BlendReset(false); this.DoAnimation = do_animation; this.IsIKExec = true; this.FirstFrame = true; this.GetTgtData(timing).SetIKSetting(tgt_chara, slot_no, attach_name, axis_bone, target, f_vecOffset); this.CheckBlendType(true); this.m_ChangeFlagData.IsFlagChange(); } public void Detach() { this.BlendReset(false); this.m_NormalTgtData.Detach(); this.m_FlagPositiveTgtData.Detach(); this.m_FlagNegativeTgtData.Detach(); this.CheckBlendType(true); this.m_ChangeFlagData.Reset(); this.DoSetOffset = false; this.DoSetPosRot = false; this.DoAnimation = false; this.IsIKExec = false; this.FirstFrame = false; } [SerializeField] [Header("通常時のターゲットデータ")] private IKCtrlData.IKTargetData m_NormalTgtData; [SerializeField] [Header("フラグ値が0以上のときのターゲットデータ")] private IKCtrlData.IKTargetData m_FlagPositiveTgtData; [SerializeField] [Header("フラグ値が0以下のときのターゲットデータ")] private IKCtrlData.IKTargetData m_FlagNegativeTgtData; [SerializeField] [Space] private IKCtrlData.Vec3Enable m_OffsetEnable = new IKCtrlData.Vec3Enable(); [SerializeField] private IKCtrlData.ChangeFlagData m_ChangeFlagData = new IKCtrlData.ChangeFlagData(); private bool m_DoIKBlend; public bool IsIKExec; public float ElapsedTime; [Range(0f, 1f)] public float Weight; [HideInInspector] public bool FirstFrame; public bool DoAnimation; [HideInInspector] public bool DoSetPosRot; [HideInInspector] public bool DoSetOffset; [HideInInspector] public FullBodyIKCtrl IKCtrl; } }