using System; using System.Collections.Generic; using UnityEngine; [Serializable] public class MegaSpline { public float length; public bool closed; public List knots = new List(); public List animations; public Vector3 offset = Vector3.zero; public Vector3 rotate = Vector3.zero; public Vector3 scale = Vector3.one; public bool reverse; public int outlineSpline = -1; public float outline; public bool constantSpeed; public int subdivs = 10; public MegaShapeEase twistmode; public MegaSplineAnim splineanim = new MegaSplineAnim(); public static MegaSpline Copy(MegaSpline src) { MegaSpline megaSpline = new MegaSpline(); megaSpline.closed = src.closed; megaSpline.offset = src.offset; megaSpline.rotate = src.rotate; megaSpline.scale = src.scale; megaSpline.length = src.length; megaSpline.knots = new List(); megaSpline.constantSpeed = src.constantSpeed; megaSpline.subdivs = src.subdivs; for (int i = 0; i < src.knots.Count; i++) { MegaKnot megaKnot = new MegaKnot(); megaKnot.p = src.knots[i].p; megaKnot.invec = src.knots[i].invec; megaKnot.outvec = src.knots[i].outvec; megaKnot.seglength = src.knots[i].seglength; megaKnot.length = src.knots[i].length; megaKnot.notlocked = src.knots[i].notlocked; megaSpline.knots.Add(megaKnot); } if (src.animations != null) { megaSpline.animations = new List(src.animations); } return megaSpline; } public float KnotDistance(int k, int k1) { if (k >= 0 && k <= knots.Count - 1 && k1 >= 0 && k1 <= knots.Count - 1) { return Vector3.Distance(knots[k].p, knots[k1].p); } return 0f; } public void AddKnot(Vector3 p, Vector3 invec, Vector3 outvec) { MegaKnot megaKnot = new MegaKnot(); megaKnot.p = p; megaKnot.invec = invec; megaKnot.outvec = outvec; knots.Add(megaKnot); } public void AddKnot(Vector3 p, Vector3 invec, Vector3 outvec, Matrix4x4 tm) { MegaKnot megaKnot = new MegaKnot(); megaKnot.p = tm.MultiplyPoint3x4(p); megaKnot.invec = tm.MultiplyPoint3x4(invec); megaKnot.outvec = tm.MultiplyPoint3x4(outvec); knots.Add(megaKnot); } public bool Contains(Vector3 p) { if (!closed) { return false; } int index = knots.Count - 1; bool flag = false; for (int i = 0; i < knots.Count; i++) { if (((knots[i].p.z < p.z && knots[index].p.z >= p.z) || (knots[index].p.z < p.z && knots[i].p.z >= p.z)) && knots[i].p.x + (p.z - knots[i].p.z) / (knots[index].p.z - knots[i].p.z) * (knots[index].p.x - knots[i].p.x) < p.x) { flag = !flag; } index = i; } return flag; } public float Area() { float num = 0f; if (closed) { for (int i = 0; i < knots.Count; i++) { int index = (i + 1) % knots.Count; num += (knots[i].p.z + knots[index].p.z) * (knots[index].p.x - knots[i].p.x); } } return num * 0.5f; } public float CalcLength(int steps) { if (steps < 1) { steps = 1; } subdivs = steps; return CalcLength(); } public float CalcLength() { length = 0f; int num = knots.Count - 1; if (closed) { num++; } for (int i = 0; i < num; i++) { int index = (i + 1) % knots.Count; Vector3 vector = knots[i].p; float num2 = 1f / (float)subdivs; float num3 = num2; knots[i].seglength = 0f; if (knots[i].lengths == null || knots[i].lengths.Length != subdivs + 1) { knots[i].lengths = new float[subdivs + 1]; knots[i].points = new Vector3[subdivs + 1]; } knots[i].lengths[0] = length; knots[i].points[0] = knots[i].p; float num4 = 0f; for (int j = 1; j < subdivs; j++) { Vector3 vector2 = knots[i].Interpolate(num3, knots[index]); knots[i].points[j] = vector2; num4 = Vector3.Magnitude(vector2 - vector); knots[i].seglength += num4; vector = vector2; num3 += num2; length += num4; knots[i].lengths[j] = length; } num4 = Vector3.Magnitude(knots[index].p - vector); knots[i].seglength += num4; length += num4; knots[i].lengths[subdivs] = length; knots[i].points[subdivs] = knots[index].p; knots[i].length = length; length = knots[i].length; } return length; } public float GetTwist(float alpha) { int num = 0; if (closed) { alpha = Mathf.Repeat(alpha, 1f); float num2 = alpha * length; if (num2 > knots[knots.Count - 1].length) { alpha = 1f - (length - num2) / knots[knots.Count - 1].seglength; return TwistVal(knots[knots.Count - 1].twist, knots[0].twist, alpha); } for (num = 0; num < knots.Count && !(num2 <= knots[num].length); num++) { } alpha = 1f - (knots[num].length - num2) / knots[num].seglength; if (num < knots.Count - 1) { return TwistVal(knots[num].twist, knots[num + 1].twist, alpha); } return TwistVal(knots[num].twist, knots[0].twist, alpha); } alpha = Mathf.Clamp(alpha, 0f, 0.9999f); float num3 = alpha * length; for (num = 0; num < knots.Count && !(num3 <= knots[num].length); num++) { } alpha = 1f - (knots[num].length - num3) / knots[num].seglength; if (num < knots.Count - 1) { return TwistVal(knots[num].twist, knots[num + 1].twist, alpha); } return knots[num].twist; } public Vector3 Interpolate(float alpha, bool type, ref int k) { int num = 0; if (constantSpeed) { return InterpolateCS(alpha, type, ref k); } if (closed) { if (type) { float num2 = alpha * length; if (num2 > knots[knots.Count - 1].length) { k = knots.Count - 1; alpha = 1f - (length - num2) / knots[knots.Count - 1].seglength; return knots[knots.Count - 1].Interpolate(alpha, knots[0]); } for (num = 0; num < knots.Count && !(num2 <= knots[num].length); num++) { } alpha = 1f - (knots[num].length - num2) / knots[num].seglength; } else { float num3 = alpha * (float)knots.Count; num = (int)num3; if (num == knots.Count) { num--; alpha = 1f; } else { alpha = num3 - (float)num; } } if (num < knots.Count - 1) { k = num; return knots[num].Interpolate(alpha, knots[num + 1]); } k = num; return knots[num].Interpolate(alpha, knots[0]); } if (type) { float num4 = alpha * length; for (num = 0; num < knots.Count && !(num4 <= knots[num].length); num++) { } alpha = 1f - (knots[num].length - num4) / knots[num].seglength; } else { float num5 = alpha * (float)knots.Count; num = (int)num5; if (num == knots.Count) { num--; alpha = 1f; } else { alpha = num5 - (float)num; } } if (num < knots.Count - 1) { k = num; return knots[num].Interpolate(alpha, knots[num + 1]); } k = num; return knots[num].p; } public Vector3 InterpolateCS(float alpha, bool type, ref int k) { int num = 0; if (closed) { float num2 = alpha * length; if (num2 > knots[knots.Count - 1].length) { k = knots.Count - 1; alpha = 1f - (length - num2) / knots[knots.Count - 1].seglength; return knots[knots.Count - 1].InterpolateCS(alpha, knots[0]); } for (num = 0; num < knots.Count && !(num2 <= knots[num].length); num++) { } alpha = 1f - (knots[num].length - num2) / knots[num].seglength; if (num < knots.Count - 1) { k = num; return knots[num].InterpolateCS(alpha, knots[num + 1]); } k = num; return knots[num].InterpolateCS(alpha, knots[0]); } if (type) { float num3 = alpha * length; for (num = 0; num < knots.Count && !(num3 <= knots[num].length); num++) { } alpha = 1f - (knots[num].length - num3) / knots[num].seglength; } else { float num4 = alpha * (float)knots.Count; num = (int)num4; if (num == knots.Count) { num--; alpha = 1f; } else { alpha = num4 - (float)num; } } if (num < knots.Count - 1) { k = num; return knots[num].InterpolateCS(alpha, knots[num + 1]); } k = num; return knots[num].p; } private float easeInOutSine(float start, float end, float value) { end -= start; return (0f - end) / 2f * (Mathf.Cos((float)Math.PI * value / 1f) - 1f) + start; } private float TwistVal(float v1, float v2, float alpha) { if (twistmode == MegaShapeEase.Linear) { return Mathf.Lerp(v1, v2, alpha); } return easeInOutSine(v1, v2, alpha); } public Vector3 Interpolate(float alpha, bool type, ref int k, ref float twist) { int num = 0; if (knots == null || knots.Count == 0) { return Vector3.zero; } if (constantSpeed) { return InterpolateCS(alpha, type, ref k, ref twist); } if (closed) { if (type) { float num2 = alpha * length; if (num2 > knots[knots.Count - 1].length) { k = knots.Count - 1; alpha = 1f - (length - num2) / knots[knots.Count - 1].seglength; twist = TwistVal(knots[knots.Count - 1].twist, knots[0].twist, alpha); return knots[knots.Count - 1].Interpolate(alpha, knots[0]); } for (num = 0; num < knots.Count && !(num2 <= knots[num].length); num++) { } alpha = 1f - (knots[num].length - num2) / knots[num].seglength; } else { float num3 = alpha * (float)knots.Count; num = (int)num3; if (num == knots.Count) { num--; alpha = 1f; } else { alpha = num3 - (float)num; } } if (num < knots.Count - 1) { k = num; twist = TwistVal(knots[num].twist, knots[num + 1].twist, alpha); return knots[num].Interpolate(alpha, knots[num + 1]); } k = num; twist = TwistVal(knots[num].twist, knots[0].twist, alpha); return knots[num].Interpolate(alpha, knots[0]); } if (type) { float num4 = alpha * length; for (num = 0; num < knots.Count && !(num4 <= knots[num].length); num++) { } alpha = 1f - (knots[num].length - num4) / knots[num].seglength; } else { float num5 = alpha * (float)knots.Count; num = (int)num5; if (num == knots.Count) { num--; alpha = 1f; } else { alpha = num5 - (float)num; } } if (num < knots.Count - 1) { k = num; twist = TwistVal(knots[num].twist, knots[num + 1].twist, alpha); return knots[num].Interpolate(alpha, knots[num + 1]); } k = num; twist = knots[num].twist; return knots[num].p; } public Vector3 InterpolateCS(float alpha, bool type, ref int k, ref float twist) { int num = 0; if (closed) { float num2 = alpha * length; if (num2 > knots[knots.Count - 1].length) { k = knots.Count - 1; alpha = 1f - (length - num2) / knots[knots.Count - 1].seglength; twist = TwistVal(knots[knots.Count - 1].twist, knots[0].twist, alpha); return knots[knots.Count - 1].InterpolateCS(alpha, knots[0]); } for (num = 0; num < knots.Count && !(num2 <= knots[num].length); num++) { } alpha = ((num != knots.Count && knots[num].seglength != 0f) ? (1f - (knots[num].length - num2) / knots[num].seglength) : 0f); if (num < knots.Count - 1) { k = num; twist = TwistVal(knots[num].twist, knots[num + 1].twist, alpha); return knots[num].InterpolateCS(alpha, knots[num + 1]); } num = (k = knots.Count - 1); twist = TwistVal(knots[num].twist, knots[0].twist, alpha); return knots[num].InterpolateCS(alpha, knots[0]); } if (type) { float num3 = alpha * length; for (num = 0; num < knots.Count && !(num3 <= knots[num].length); num++) { } alpha = ((num != knots.Count && knots[num].seglength != 0f) ? (1f - (knots[num].length - num3) / knots[num].seglength) : 0f); } else { float num4 = alpha * (float)knots.Count; num = (int)num4; if (num == knots.Count) { num--; alpha = 1f; } else { alpha = num4 - (float)num; } } if (num < knots.Count - 1) { k = num; twist = TwistVal(knots[num].twist, knots[num + 1].twist, alpha); return knots[num].InterpolateCS(alpha, knots[num + 1]); } num = (k = knots.Count - 1); twist = knots[num].twist; return knots[num].p; } public Vector3 InterpCurve3D(float alpha, bool type, ref int k) { k = 0; if (knots == null || knots.Count == 0) { return Vector3.zero; } if (alpha < 0f) { if (!closed) { Vector3 vector = Interpolate(0f, type, ref k); Vector3 vector2 = Interpolate(0.01f, type, ref k); Vector3 vector3 = vector2 - vector; vector3.Normalize(); return vector + length * alpha * vector3; } alpha = Mathf.Repeat(alpha, 1f); } else if (alpha > 1f) { if (!closed) { Vector3 vector4 = Interpolate(1f, type, ref k); Vector3 vector5 = Interpolate(0.99f, type, ref k); Vector3 vector6 = vector5 - vector4; vector6.Normalize(); return vector4 + length * (1f - alpha) * vector6; } alpha %= 1f; } return Interpolate(alpha, type, ref k); } public Vector3 InterpBezier3D(int knot, float a) { if (knot < knots.Count) { int num = knot + 1; if (num == knots.Count && closed) { num = 0; } return knots[knot].Interpolate(a, knots[num]); } return Vector3.zero; } public void Centre(float scale) { Vector3 zero = Vector3.zero; for (int i = 0; i < knots.Count; i++) { zero += knots[i].p; } zero /= (float)knots.Count; for (int j = 0; j < knots.Count; j++) { knots[j].p -= zero; knots[j].invec -= zero; knots[j].outvec -= zero; knots[j].p *= scale; knots[j].invec *= scale; knots[j].outvec *= scale; } } public void Reverse() { List list = new List(); for (int num = knots.Count - 1; num >= 0; num--) { MegaKnot megaKnot = new MegaKnot(); megaKnot.p = knots[num].p; megaKnot.invec = knots[num].outvec; megaKnot.outvec = knots[num].invec; list.Add(megaKnot); } knots = list; CalcLength(); } public void SetHeight(float y) { for (int i = 0; i < knots.Count; i++) { knots[i].p.y = y; knots[i].outvec.y = y; knots[i].invec.y = y; } } public void SetTwist(float twist) { for (int i = 0; i < knots.Count; i++) { knots[i].twist = twist; } } }