using System; using UnityEngine; [AddComponentMenu("Modifiers/Attractor Shape")] public class MegaAttractorShape : MegaModifier { public MegaShape shape; public int curve; public MegaAttractType attractType; public float distance; public float rotate; public float force; public float slide; public AnimationCurve crv = new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(1f, 1f)); public int itercount = 4; private int k; private Vector3 tangent; private float alpha; private Vector3 delta; private Vector3 nvp; private Vector3 dir = Vector3.zero; private Matrix4x4 rottm = Matrix4x4.identity; private float slidealpha; private Matrix4x4 swtm; private Matrix4x4 swltm; private Matrix4x4 lwtm; private Matrix4x4 wltm; public float limit = 1f; private float limit2; private Vector3 shapepos; public bool flat = true; public bool splinechanged = true; private float positiveInfinity; private float num2; public Vector3[] points; private Vector3 tp = Vector3.zero; private Vector3 qc = Vector3.zero; public override string ModName() { return "Attractor Shape"; } public override string GetHelpURL() { return "?page_id=338"; } public Vector3 FindNearestPointWorld(Vector3 p, int iterations, ref float alpha) { return swtm.MultiplyPoint3x4(FindNearestPoint(swltm.MultiplyPoint3x4(p), iterations, ref alpha)); } private void Start() { PrepareShape(); } private void PrepareShape() { if (points == null || points.Length == 0) { points = new Vector3[101]; } int num = 0; int num2 = 0; for (float num3 = 0f; num3 <= 1f; num3 += 0.01f) { points[num2++] = shape.splines[curve].Interpolate(num3, true, ref num); } } private void Find(Vector3 p) { positiveInfinity = float.PositiveInfinity; num2 = 0f; for (int i = 0; i < 101; i++) { float num = (float)i / 100f; float sqrMagnitude = (points[i] - p).sqrMagnitude; if (positiveInfinity > sqrMagnitude) { positiveInfinity = sqrMagnitude; num2 = num; } } } public Vector3 FindNearestPoint(Vector3 p, int iterations, ref float alpha) { int num = 0; Find(p); MegaSpline megaSpline = shape.splines[curve]; for (int i = 0; i < itercount; i++) { float num2 = 0.01f * Mathf.Pow(10f, 0f - (float)i); float num3 = num2 * 0.1f; for (float num4 = Mathf.Clamp01(this.num2 - num2); num4 <= Mathf.Clamp01(this.num2 + num2); num4 += num3) { float sqrMagnitude = (megaSpline.Interpolate(num4, true, ref num) - p).sqrMagnitude; if (positiveInfinity > sqrMagnitude) { positiveInfinity = sqrMagnitude; this.num2 = num4; } } } alpha = this.num2; return shape.InterpCurve3D(curve, this.num2, true); } public override Vector3 Map(int i, Vector3 p) { p = tm.MultiplyPoint3x4(p); Vector3 vector = lwtm.MultiplyPoint3x4(p); qc.x = vector.x - shapepos.x; qc.y = vector.y - shapepos.y; qc.z = vector.z - shapepos.z; if (qc.sqrMagnitude < limit2) { Vector3 point = FindNearestPointWorld(vector, itercount, ref alpha); if (attractType == MegaAttractType.Repulse) { delta.x = vector.x - point.x; delta.y = vector.y - point.y; delta.z = vector.z - point.z; } else { delta.x = point.x - vector.x; delta.y = point.y - vector.y; delta.z = point.z - vector.z; } float magnitude = delta.magnitude; if (magnitude < distance) { float num = distance - magnitude; float time = num / distance; float num2 = crv.Evaluate(time); if (attractType == MegaAttractType.Attract || attractType == MegaAttractType.Repulse) { Vector3 vector2 = delta.normalized * num * num2 * force; if (attractType == MegaAttractType.Attract) { if (vector2.magnitude <= magnitude) { nvp = wltm.MultiplyPoint3x4(vector + vector2); } else { nvp = wltm.MultiplyPoint3x4(point); } } else { nvp = wltm.MultiplyPoint3x4(vector + vector2); } } else { float num3 = ((!(slide >= 0f)) ? (alpha + alpha * slidealpha * num2) : (alpha + (1f - alpha) * slidealpha * num2)); if (num3 < 0f) { num3 = 0f; } else if (num3 >= 1f) { num3 = 0.99999f; } Vector3 vector3 = swtm.MultiplyPoint3x4(shape.splines[curve].InterpCurve3D(num3, true, ref k)); float num4 = num3 + 0.01f; if (num3 + 0.01f >= 1f) { num4 = num3 - 0.01f; } Vector3 vector4 = swtm.MultiplyPoint3x4(shape.splines[curve].InterpCurve3D(num4, true, ref k)); if (alpha + 0.01f < 1f) { dir = (vector3 - vector4).normalized; } else { dir = (vector4 - vector3).normalized; } Vector3 normalized = Vector3.Cross(delta, dir).normalized; rottm.SetColumn(0, normalized); rottm.SetColumn(1, Vector3.Cross(-normalized, dir)); rottm.SetColumn(2, dir); rottm.SetColumn(3, vector3); float f = (-90f + rotate * num * num2) * ((float)Math.PI / 180f); tp.x = magnitude * Mathf.Cos(f); tp.y = magnitude * Mathf.Sin(f); tp.z = ((!flat) ? p.z : 0f); nvp = rottm.MultiplyPoint3x4(tp); nvp = wltm.MultiplyPoint3x4(nvp); } } else { nvp = p; } p = nvp; } return invtm.MultiplyPoint3x4(p); } public override bool ModLateUpdate(MegaModContext mc) { return Prepare(mc); } public override bool Prepare(MegaModContext mc) { if ((bool)shape) { if (splinechanged || points == null || points.Length == 0) { PrepareShape(); splinechanged = false; } limit2 = limit * limit; shapepos = shape.transform.position; slidealpha = slide * 0.01f; swtm = shape.transform.localToWorldMatrix; swltm = shape.transform.worldToLocalMatrix; lwtm = base.transform.localToWorldMatrix; wltm = base.transform.worldToLocalMatrix; return true; } return false; } }