using System; using System.Collections.Generic; using UnityEngine; public class DynamicMuneBone : MonoBehaviour, IDynamicBone { public bool isLeft { get; private set; } private float MuneSize { get { return this.GetMaidPropRatio(MPN.MuneL); } } public float muneSizeNormalized { get { return this.GetMaidPropNormalized(MPN.MuneL); } } private float MuneUpDown { get { return Mathf.Lerp(30f, -30f, this.GetMaidPropNormalized(MPN.MuneUpDown)) * this.MuneSize; } } private float MuneYori { get { float num = Mathf.Lerp(12.5f, -12.5f, this.GetMaidPropNormalized(MPN.MuneYori)) * (float)((!this.isLeft) ? -1 : 1); return num * this.MuneSize; } } private float MuneDir { get { return Mathf.Lerp(-25f, 25f, this.GetMaidPropNormalized(MPN.MuneDir)); } } private float MuneYawarakaNormalized { get { return this.GetMaidPropNormalized(MPN.MuneYawaraka); } } private Transform Spine { get { return base.transform.parent; } } public DynamicMuneYureBone muneYureBone { get { return this.MuneYureBone; } } public bool isDynamicReset { get; private set; } public float dynamicWeight { get { return this.DynamicWeight; } set { this.DynamicWeight = Mathf.Clamp01(value); } } private bool IsSubYureEnable { get { return this.Maid.body0.boVisible_NIP; } } public void Init(Maid maid, bool is_left) { this.Maid = maid; this.isLeft = is_left; this.SetUpMunePropValueDic(MPN.MuneL); this.SetUpMunePropValueDic(MPN.MuneYori); this.SetUpMunePropValueDic(MPN.MuneUpDown); this.SetUpMunePropValueDic(MPN.MuneDir); this.SetUpMunePropValueDic(MPN.MuneYawaraka); this.SetUpMunePropValueDic(MPN.MuneLong); this.NotDynamicRot = (this.DefaultLocalRot = base.transform.localRotation); this.MuneSub = base.transform.Find(base.transform.name + "_sub"); this.NotDynamicMuneSubRot = (this.DefaultMuneSubLocalRot = this.MuneSub.localRotation); this.DynamicPos = this.GetTargetPos(); this.LastMuneYawarakaVal = this.MuneYawarakaNormalized; Transform transform = this.MuneSub.Find(base.transform.name + "_scale"); this.MuneYureBone = transform.gameObject.AddComponent(); this.MuneYureBone.Init(this); base.enabled = false; this.isDynamicReset = false; } private void SetUpMunePropValueDic(MPN mpn) { this.MunePropValueDic[mpn] = this.Maid.GetProp(mpn).value; } private void OnDestroy() { this.UnInit(); } public void UnInit() { if (this.Maid && this.Maid.body0) { this.Maid.body0.RemoveDynamicBone(this); } this.MuneYureBone.UnInit(); } public void ApplyMuneProp(MPN mpn, float val) { if (!this.MunePropValueDic.ContainsKey(mpn)) { return; } this.MunePropValueDic[mpn] = Mathf.FloorToInt(val * 100f); } public void PreUpdate() { if (!base.enabled) { return; } base.transform.localRotation = this.NotDynamicRot; this.MuneSub.localRotation = this.NotDynamicMuneSubRot; Transform transform = base.transform; Vector3 one = Vector3.one; this.MuneSub.localScale = one; transform.localScale = one; this.MuneYureBone.PreUpdate(); base.transform.localRotation = this.DefaultLocalRot; base.transform.Rotate(0f, this.MuneYori, this.MuneUpDown); this.NotDynamicRot = base.transform.localRotation; if (this.isDynamicOn) { float a = Mathf.Lerp(180f, 120f, this.muneSizeNormalized); float b = Mathf.Lerp(180f, 160f, Mathf.Clamp01(this.muneSizeNormalized / 0.5f)); float num = Mathf.Lerp(a, b, this.GetMaidPropNormalized(MPN.MuneUpDown)); num += 40f * Mathf.Abs(Vector3.Dot(this.Spine.up, Vector3.down)) * this.muneSizeNormalized; this.MuneSub.localRotation = Quaternion.Euler(Vector3.forward * (num + this.MuneDir)); } else { this.MuneSub.localRotation = this.DefaultMuneSubLocalRot; } this.NotDynamicMuneSubRot = this.MuneSub.localRotation; this.MuneYureBone.CalcMuneEditMove(); this.MuneYureBone.SetWeight((float)((!this.IsSubYureEnable) ? 0 : 1)); } public void PhysicsReset() { this.isDynamicReset = true; this.MuneYureBone.PhysicsReset(); } public void DynamicUpdate() { if (!base.enabled) { return; } if (this.isDynamicOn) { this.Stiffness = this.GetStiffness(); this.Mass = this.MassLerp.GetValue(Mathf.Clamp01((this.MuneYawarakaNormalized - 0.5f) / 0.5f)); this.Mass = Mathf.Lerp(1f, this.Mass, Mathf.Clamp01(this.muneSizeNormalized / 0.5f)); this.Damping = this.DampingLerp.GetValue(Mathf.Clamp01((this.MuneYawarakaNormalized - 0.5f) / 0.5f)); this.Damping = Mathf.Lerp(1f, this.Damping, Mathf.Clamp01(this.muneSizeNormalized / 0.5f)); if (this.IsGravityVariable) { float value = Vector3.Dot(this.Spine.right, Vector3.down); float num = Vector3.Dot(this.Spine.up, Vector3.down); bool flag = num < 0f; float d = Mathf.Lerp(this.GravityYLandScape, this.GravityYFaceUpDown, Mathf.Abs(num)); float a = Mathf.Sin(180f * this.GetMaidPropNormalized(MPN.MuneYori) * 0.017453292f); float num2; if (flag) { num2 = Mathf.Clamp01(this.GetMaidPropNormalized(MPN.MuneYori) / 0.5f); } else { num2 = 1f - Mathf.Clamp01(this.GetMaidPropNormalized(MPN.MuneYori) / 0.5f); } float num3 = Mathf.Lerp(a, num2, Mathf.Abs(num)); this.Gravity = Vector3.Lerp(Vector3.down * this.GravityYMin, Vector3.down * d, (1f - Mathf.Clamp01(value)) * num3); if (flag) { Vector3 vector = Vector3.zero; if (this.isLeft) { vector = this.Spine.rotation * Vector3.forward; } else { vector = this.Spine.rotation * Vector3.back; } vector.y = 0f; vector *= this.GravityXSupine * Mathf.Abs(num) * num2; this.Gravity += vector; } } else { this.Gravity = Vector3.down * 0.01f; } Vector3 targetPos = this.GetTargetPos(); Vector3 vector2 = (targetPos - this.DynamicPos) * this.Stiffness; vector2 += this.Gravity; Vector3 a2 = vector2 / this.Mass; this.Velocity += a2 * (1f - this.Damping); if (this.MuneYawarakaNormalized != this.LastMuneYawarakaVal || this.dynamicWeight != this.LastDynamicWeight || this.isDynamicReset) { vector2 = Vector3.zero; a2 = Vector3.zero; this.Velocity = Vector3.zero; if (this.isDynamicReset) { this.DynamicPos = targetPos; } this.isDynamicReset = true; } Vector3 a3 = this.DynamicPos + vector2 + this.Velocity; if (Vector3.Dot((a3 - base.transform.position).normalized, base.transform.rotation * Vector3.left) < Mathf.Cos(this.RimmitAngle * 0.017453292f)) { vector2 *= this.RimmitOverBias; this.Velocity *= this.RimmitOverBias; } this.DynamicPos += vector2; this.DynamicPos += this.Velocity; float num4 = (this.MuneYawarakaNormalized < 0.5f) ? (this.MuneYawarakaNormalized / 0.5f) : 1f; this.DynamicPos = Vector3.Lerp(targetPos, this.DynamicPos, num4 * this.dynamicWeight * Mathf.Clamp01(this.muneSizeNormalized / 0.5f)); base.transform.rotation = Quaternion.FromToRotation(base.transform.rotation * Vector3.left, this.DynamicPos - base.transform.position) * base.transform.rotation; float magnitude = (this.DynamicPos - targetPos).magnitude; float num5 = -0.2f; float num6 = 0.3f; Vector3 zero = Vector3.zero; zero.x = 1f + magnitude * num6; zero.y = 1f + -magnitude * num5; zero.z = 1f + -magnitude * num5; base.transform.localScale = zero; if (this.MuneXScaling) { Vector3 localScale = base.transform.localScale; Vector3 localScale2 = this.MuneSub.localScale; float num7 = Vector3.Dot(this.Spine.rotation * Vector3.down, Vector3.down) * this.muneSizeNormalized; float num8; float num9; float b; if (num7 > 0f) { num8 = num7 * Vector3.Dot(base.transform.rotation * Vector3.right, Vector3.down); num9 = num7 * Vector3.Dot(this.MuneSub.rotation * Vector3.left, Vector3.down); b = this.GravityXScalingSupine; } else { num7 = Mathf.Abs(num7); num8 = num7 * Vector3.Dot(base.transform.rotation * Vector3.left, Vector3.down); num9 = num7 * Vector3.Dot(this.MuneSub.rotation * Vector3.right, Vector3.down); b = this.GravityXScalingProne; } float num10 = Mathf.Sin(180f * this.GetMaidPropNormalized(MPN.MuneLong) * 0.017453292f); localScale.x *= Mathf.Lerp(1f, b, num8 * num10); localScale2.x *= Mathf.Lerp(1f, b, num9 * num10); base.transform.localScale = localScale; this.MuneSub.localScale = localScale2; } if (this.isDynamicReset) { this.isDynamicReset = false; } } else { this.isDynamicReset = true; } this.MuneYureBone.DynamicUpdate(); this.LastDynamicWeight = this.dynamicWeight; this.LastMuneYawarakaVal = this.MuneYawarakaNormalized; } private float GetStiffness() { DynamicMuneBone.MathLerpPair mathLerpPair = (!this.IsSubYureEnable) ? this.StiffnessBraLerp : this.StiffnessLerp; float t = Mathf.Pow(this.muneSizeNormalized, (!this.IsSubYureEnable) ? 0.7f : 0.5f); return mathLerpPair.GetValue(t); } private Vector3 GetTargetPos() { return base.transform.position + base.transform.rotation * Vector3.left * this.TargetDistance; } private float GetMaidPropNormalized(MPN mpn) { if (!this.MunePropValueDic.ContainsKey(mpn)) { Debug.LogErrorFormat("MPN:{0}は不正です。胸に関するMPNのみ指定してください", new object[] { mpn }); return 0f; } int min = this.Maid.GetProp(mpn).min; int max = this.Maid.GetProp(mpn).max; return Mathf.InverseLerp((float)min, (float)max, (float)this.MunePropValueDic[mpn]); } private float GetMaidPropRatio(MPN mpn) { if (!this.MunePropValueDic.ContainsKey(mpn)) { Debug.LogErrorFormat("MPN:{0}は不正です。胸に関するMPNのみ指定してください", new object[] { mpn }); return 0f; } return (float)this.MunePropValueDic[mpn] / 100f; } private const float MUNE_YORI_VAL = 12.5f; private const float MUNE_UPDAWN_VAL = 30f; private const float MUNE_DIR_VAL = 25f; private const float MUNESUB_FALLDOWN_ROT = 40f; private Dictionary MunePropValueDic = new Dictionary(); private Maid Maid; private float LastMuneYawarakaVal; private Quaternion DefaultLocalRot; private Transform MuneSub; private Quaternion DefaultMuneSubLocalRot; private Quaternion NotDynamicRot; private Quaternion NotDynamicMuneSubRot; [SerializeField] [Range(0f, 1f)] private float TargetDistance = 0.7f; private Vector3 DynamicPos; private Vector3 Velocity = Vector3.zero; [Header("剛性(揺れ幅)に関するパラメータ")] [SerializeField] private DynamicMuneBone.MathLerpPair StiffnessLerp = new DynamicMuneBone.MathLerpPair(0.22f, 0.055f); [SerializeField] private DynamicMuneBone.MathLerpPair StiffnessBraLerp = new DynamicMuneBone.MathLerpPair(0.27f, 0.07f); [SerializeField] [Range(0f, 1f)] private float Stiffness; [Header("振り子運動の質量に関するパラメータ")] [SerializeField] private DynamicMuneBone.MathLerpPair MassLerp = new DynamicMuneBone.MathLerpPair(0.4f, 1.5f); [SerializeField] [Range(0.4f, 1.5f)] private float Mass = 0.4f; [Header("減衰力(揺れを抑制する力)に関するパラメータ")] [SerializeField] private DynamicMuneBone.MathLerpPair DampingLerp = new DynamicMuneBone.MathLerpPair(0.3f, 0.01f); [SerializeField] [Range(0.01f, 1f)] private float Damping = 0.3f; [SerializeField] [Header("重量可変か")] private bool IsGravityVariable = true; [SerializeField] [Header("下にかかる重力の最小値")] [Range(0f, 0.1f)] private float GravityYMin = 0.01f; [SerializeField] [Header("体を横にしたときに下にかかる重力")] [Range(0f, 0.1f)] private float GravityYLandScape = 0.03f; [SerializeField] [Header("体を仰向けorうつ伏せにしたときに下にかかる重力")] [Range(0f, 0.1f)] private float GravityYFaceUpDown = 0.02f; [SerializeField] [Header("仰向けになったとき横方向にかかる重力の値")] [Range(0f, 0.1f)] private float GravityXSupine = 0.02f; [SerializeField] [Space] private Vector3 Gravity = Vector3.down * 0.01f; [Space] [SerializeField] [Range(0f, 90f)] private float RimmitAngle = 72f; [SerializeField] [Range(0f, 1f)] private float RimmitOverBias = 0.8f; private DynamicMuneYureBone MuneYureBone; [SerializeField] [Header("物理が有効か")] public bool isDynamicOn = true; [SerializeField] [Header("物理の適用度")] [Range(0f, 1f)] private float DynamicWeight = 1f; private float LastDynamicWeight = 1f; [Header("重力による胸潰れのパラメータ")] [SerializeField] private bool MuneXScaling = true; [SerializeField] [Range(0f, 1f)] private float GravityXScalingSupine = 0.75f; [SerializeField] [Range(1f, 2f)] private float GravityXScalingProne = 1.15f; [Serializable] private struct MathLerpPair { public MathLerpPair(float t0, float t1) { this.t0Value = t0; this.t1Value = t1; } public float GetValue(float t) { return Mathf.Lerp(this.t0Value, this.t1Value, t); } public float t0Value; public float t1Value; } }