using System.Collections.Generic; using UnityEngine; [AddComponentMenu("Modifiers/Rope Deform")] public class MegaRopeDeform : MegaModifier { public float floorOff; public int NumMasses = 8; public MegaSoft2D soft = new MegaSoft2D(); public float timeStep = 0.01f; public float Mass = 10f; public MegaAxis axis = MegaAxis.Z; public AnimationCurve stiffnessCrv = new AnimationCurve(new Keyframe(0f, 1f), new Keyframe(1f, 1f)); public float stiffspring = 1f; public float stiffdamp = 0.1f; public float spring = 1f; public float damp = 1f; public float off; public bool init; public float SpringCompress = 1f; public bool BendSprings = true; public bool Constraints = true; public float DampingRatio = 0.5f; public int pconl; public int pconr; public bool DisplayDebug = true; public int drawsteps = 20; public float boxsize = 0.01f; public Transform left; public Transform right; public float weight; public float weightPos = 0.5f; public Vector2[] masspos; private int ax; private float minx; private float width; public override string ModName() { return "RopeDeform"; } public override string GetHelpURL() { return "?page_id=1524"; } public override Vector3 Map(int i, Vector3 p) { p = tm.MultiplyPoint3x4(p); float t = (p[ax] - minx) / width; Vector2 vector = Interp1a(t); p.y += vector.y + off * 0.01f; p[ax] = vector.x; return invtm.MultiplyPoint3x4(p); } public override bool ModLateUpdate(MegaModContext mc) { ax = (int)axis; minx = bbox.min[ax]; width = bbox.max[ax] - bbox.min[ax]; if (init || NumMasses != soft.masses.Count) { init = false; Init(); } AddWeight(); UpdateRope(); return Prepare(mc); } public override bool Prepare(MegaModContext mc) { return true; } public void Build(MegaModContext mc) { } public void UpdateRope() { if (soft != null) { soft.Update(); for (int i = 0; i < soft.masses.Count; i++) { masspos[i + 1] = soft.masses[i].pos; soft.masses[i].forcec = Vector2.zero; } masspos[0] = soft.masses[0].pos - (soft.masses[1].pos - soft.masses[0].pos); masspos[masspos.Length - 1] = soft.masses[soft.masses.Count - 1].pos + (soft.masses[soft.masses.Count - 1].pos - soft.masses[soft.masses.Count - 2].pos); if (left != null) { Vector3 vector = base.transform.worldToLocalMatrix.MultiplyPoint(left.position); soft.constraints[pconl].pos.x = vector[ax]; soft.constraints[pconl].pos.y = vector.y; } if (right != null) { Vector3 vector2 = base.transform.worldToLocalMatrix.MultiplyPoint(right.position); soft.constraints[pconr].pos.x = vector2[ax]; soft.constraints[pconr].pos.y = vector2.y; } } } public void Init() { if (soft.masses == null) { soft.masses = new List(); } soft.masses.Clear(); float num = Mass / (float)NumMasses; int index = (int)axis; Vector2 zero = Vector2.zero; damp = DampingRatio * 0.45f * (2f * Mathf.Sqrt(num * spring)); for (int i = 0; i < NumMasses; i++) { float t = (float)i / (float)(NumMasses - 1); zero.x = Mathf.Lerp(bbox.min[index], bbox.max[index], t); Mass2D item = new Mass2D(num, zero); soft.masses.Add(item); } masspos = new Vector2[soft.masses.Count + 2]; for (int j = 0; j < soft.masses.Count; j++) { masspos[j + 1] = soft.masses[j].pos; } if (soft.springs == null) { soft.springs = new List(); } soft.springs.Clear(); if (soft.constraints == null) { soft.constraints = new List(); } soft.constraints.Clear(); for (int k = 0; k < soft.masses.Count - 1; k++) { Spring2D spring2D = new Spring2D(k, k + 1, spring, damp, soft); spring2D.restLen *= SpringCompress; soft.springs.Add(spring2D); if (Constraints) { Constraint2D item2 = Constraint2D.CreateLenCon(k, k + 1, spring2D.restLen); soft.constraints.Add(item2); } } if (BendSprings) { int num2 = 2; for (int l = 0; l < soft.masses.Count - num2; l++) { float time = (float)l / (float)soft.masses.Count; Spring2D spring2D2 = new Spring2D(l, l + num2, stiffspring * stiffnessCrv.Evaluate(time), stiffdamp * stiffnessCrv.Evaluate(time), soft); soft.springs.Add(spring2D2); Constraint2D item3 = Constraint2D.CreateLenCon(l, l + num2, spring2D2.restLen); soft.constraints.Add(item3); } } zero.x = bbox.min[index]; zero.y = 0f; Constraint2D item4 = Constraint2D.CreatePointCon(0, zero); pconl = soft.constraints.Count; soft.constraints.Add(item4); zero.x = bbox.max[index]; item4 = Constraint2D.CreatePointCon(soft.masses.Count - 1, zero); pconr = soft.constraints.Count; soft.constraints.Add(item4); soft.DoConstraints(); } private void DrawSpline(int steps) { if (soft.masses == null || soft.masses.Count == 0) { return; } Vector3 vector = Interp1a(0f); if (ax == 2) { float x = vector.x; vector.x = vector.z; vector.z = x; } for (int i = 1; i <= steps; i++) { if ((i & 1) == 1) { Gizmos.color = Color.white; } else { Gizmos.color = Color.black; } float t = (float)i / (float)steps; Vector3 vector2 = Interp1a(t); if (ax == 2) { float x2 = vector2.x; vector2.x = vector2.z; vector2.z = x2; } Gizmos.DrawLine(vector, vector2); vector = vector2; } } public void OnDrawGizmos() { Display(); } private void Display() { Gizmos.matrix = base.transform.localToWorldMatrix; if (DisplayDebug && soft != null && soft.masses != null) { DrawSpline(drawsteps); Vector3 zero = Vector3.zero; Gizmos.color = Color.yellow; for (int i = 0; i < soft.masses.Count; i++) { if (ax == 0) { zero.x = soft.masses[i].pos.x; zero.y = soft.masses[i].pos.y; zero.z = 0f; } else { zero.z = soft.masses[i].pos.x; zero.y = soft.masses[i].pos.y; zero.x = 0f; } Gizmos.DrawCube(zero, Vector3.one * boxsize * 0.1f); } if (weightPos >= 0f && weightPos < 100f) { Gizmos.color = Color.blue; Vector2 vector = Interp1a(weightPos * 0.01f); if (ax == 0) { zero.x = vector.x; zero.y = vector.y; zero.z = 0f; } else { zero.z = vector.x; zero.y = vector.y; zero.x = 0f; } Gizmos.DrawCube(zero, Vector3.one * boxsize * 0.2f); } } Gizmos.matrix = Matrix4x4.identity; } public Vector2 Interp1(float t) { int num = soft.masses.Count - 3; int num2 = Mathf.Min(Mathf.FloorToInt(t * (float)num), num - 1); float num3 = t * (float)num - (float)num2; Vector2 pos = soft.masses[num2].pos; Vector2 pos2 = soft.masses[num2 + 1].pos; Vector2 pos3 = soft.masses[num2 + 2].pos; Vector2 pos4 = soft.masses[num2 + 3].pos; return 0.5f * ((-pos + 3f * pos2 - 3f * pos3 + pos4) * (num3 * num3 * num3) + (2f * pos - 5f * pos2 + 4f * pos3 - pos4) * (num3 * num3) + (-pos + pos3) * num3 + 2f * pos2); } public Vector2 Interp1a(float t) { int num = masspos.Length - 3; int num2 = Mathf.Min(Mathf.FloorToInt(t * (float)num), num - 1); float num3 = t * (float)num - (float)num2; Vector2 vector = masspos[num2]; Vector2 vector2 = masspos[num2 + 1]; Vector2 vector3 = masspos[num2 + 2]; Vector2 vector4 = masspos[num2 + 3]; return 0.5f * ((-vector + 3f * vector2 - 3f * vector3 + vector4) * (num3 * num3 * num3) + (2f * vector - 5f * vector2 + 4f * vector3 - vector4) * (num3 * num3) + (-vector + vector3) * num3 + 2f * vector2); } private void AddWeight() { if (weightPos >= 0f && weightPos < 100f) { float num = soft.masses.Count - 1; int num2 = (int)(num * weightPos * 0.01f); int index = num2 + 1; float num3 = num * weightPos * 0.01f - (float)num2; Vector3 vector = Vector2.zero; vector.y = weight * (1f - num3); soft.masses[num2].forcec = vector; vector.y = weight * num3; soft.masses[index].forcec = vector; } } public float GetPos(float alpha) { return Interp1a(alpha).y; } public Vector2 GetPos2(float alpha) { return Interp1a(alpha); } public Vector2 GetPos3(float v) { for (int i = 1; i < masspos.Length - 1; i++) { if (v > masspos[i].x && v < masspos[i + 1].x) { float num = (v - masspos[i].x) / (masspos[i + 1].x - masspos[i].x); Vector2 vector = masspos[i - 1]; Vector2 vector2 = masspos[i]; Vector2 vector3 = masspos[i + 1]; Vector2 vector4 = masspos[i + 2]; return 0.5f * ((-vector + 3f * vector2 - 3f * vector3 + vector4) * (num * num * num) + (2f * vector - 5f * vector2 + 4f * vector3 - vector4) * (num * num) + (-vector + vector3) * num + 2f * vector2); } } return Vector2.zero; } public Vector2 SetWeight(float v, float weight) { for (int i = 1; i < masspos.Length - 2; i++) { if (v > masspos[i].x && v < masspos[i + 1].x) { float num = (v - masspos[i].x) / (masspos[i + 1].x - masspos[i].x); Vector2 vector = masspos[i - 1]; Vector2 vector2 = masspos[i]; Vector2 vector3 = masspos[i + 1]; Vector2 vector4 = masspos[i + 2]; Vector2 zero = Vector2.zero; zero.y = weight * (1f - num); soft.masses[i - 1].forcec = zero; zero.y = weight * num; soft.masses[i].forcec = zero; return 0.5f * ((-vector + 3f * vector2 - 3f * vector3 + vector4) * (num * num * num) + (2f * vector - 5f * vector2 + 4f * vector3 - vector4) * (num * num) + (-vector + vector3) * num + 2f * vector2); } } return Vector2.zero; } }