using System; using UnityEngine; [AddComponentMenu("Modifiers/Path Deform")] public class MegaPathDeform : MegaModifier { public float percent; public float stretch = 1f; public float twist; public float rotate; public MegaAxis axis; public bool flip; public MegaShape path; public bool animate; public float speed = 1f; public bool drawpath; public float tangent = 1f; [HideInInspector] public Matrix4x4 mat = default(Matrix4x4); public bool UseTwistCurve; public AnimationCurve twistCurve = new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(1f, 1f)); public bool UseStretchCurve; public AnimationCurve stretchCurve = new AnimationCurve(new Keyframe(0f, 1f), new Keyframe(1f, 1f)); public Vector3 Up = Vector3.up; public int curve; public bool usedist; public float distance; public MegaLoopMode loopmode = MegaLoopMode.None; private Vector3 start; private Quaternion tw = Quaternion.identity; private float usepercent; private float usetan; private float ovlen; public override string ModName() { return "PathDeform"; } public override string GetHelpURL() { return "?page_id=273"; } public override Vector3 Map(int i, Vector3 p) { p = tm.MultiplyPoint3x4(p); float num = 0f; float num3; if (UseStretchCurve) { float num2 = stretchCurve.Evaluate(Mathf.Repeat(p.z * ovlen + usepercent, 1f)) * stretch; num3 = p.z * ovlen * num2 + usepercent; } else { num3 = p.z * ovlen * stretch + usepercent; } Vector3 vector = path.InterpCurve3D(curve, num3, path.normalizedInterp, ref num) - start; Vector3 vector2 = path.InterpCurve3D(curve, num3 + usetan, path.normalizedInterp) - start; num3 = ((!path.splines[curve].closed) ? Mathf.Clamp01(num3) : Mathf.Repeat(num3, 1f)); if (UseTwistCurve) { float num4 = twistCurve.Evaluate(num3) * twist; tw = Quaternion.AngleAxis(num4 + num, Vector3.forward); } else { tw = Quaternion.AngleAxis(num + twist * num3, Vector3.forward); } Vector3 forward = vector2 - vector; Quaternion q = Quaternion.LookRotation(forward, Up) * tw; Matrix4x4 identity = Matrix4x4.identity; MegaMatrix.SetTR(ref identity, vector, q); identity = mat * identity; p.z = 0f; return identity.MultiplyPoint3x4(p); } public override void ModStart(MegaModifiers mc) { } public override bool ModLateUpdate(MegaModContext mc) { if (animate) { percent += speed * Time.deltaTime; if (usedist) { distance = percent * 0.01f * path.splines[curve].length; } } return Prepare(mc); } public override bool Prepare(MegaModContext mc) { if (path != null) { if (curve >= path.splines.Count) { curve = 0; } if (usedist) { percent = distance / path.splines[curve].length * 100f; } usepercent = percent / 100f; switch (loopmode) { case MegaLoopMode.Clamp: usepercent = Mathf.Clamp01(usepercent); break; case MegaLoopMode.Loop: usepercent = Mathf.Repeat(usepercent, 1f); break; case MegaLoopMode.PingPong: usepercent = Mathf.PingPong(usepercent, 1f); break; } ovlen = 1f / path.splines[curve].length; usetan = tangent * 0.01f; mat = Matrix4x4.identity; MegaAxis megaAxis = axis; if (megaAxis == MegaAxis.Z) { MegaMatrix.RotateX(ref mat, -(float)Math.PI / 2f); } MegaMatrix.RotateZ(ref mat, (float)Math.PI / 180f * rotate); SetAxis(mat); start = path.splines[curve].knots[0].p; Vector3 vector = path.InterpCurve3D(0, 0.01f, path.normalizedInterp); Vector3 vector2 = Vector3.zero; switch (axis) { case MegaAxis.X: vector2 = Vector3.left; break; case MegaAxis.Y: vector2 = Vector3.back; break; case MegaAxis.Z: vector2 = Vector3.up; break; } Quaternion identity = Quaternion.identity; if (flip) { vector2 = -vector2; } identity = Quaternion.FromToRotation(vector - start, vector2); mat.SetTRS(Vector3.zero, identity, Vector3.one); return true; } return false; } public void OnDrawGizmos() { if (drawpath) { Display(this); } } private void Display(MegaPathDeform pd) { if (!(pd.path != null)) { return; } pd.mat = Matrix4x4.identity; Vector3 p = pd.path.splines[curve].knots[0].p; Vector3 vector = pd.path.InterpCurve3D(curve, 0.01f, pd.path.normalizedInterp); Vector3 vector2 = Vector3.zero; switch (axis) { case MegaAxis.X: vector2 = Vector3.left; break; case MegaAxis.Y: vector2 = Vector3.back; break; case MegaAxis.Z: vector2 = Vector3.up; break; } Quaternion identity = Quaternion.identity; if (flip) { vector2 = -vector2; } identity = Quaternion.FromToRotation(vector - p, vector2); pd.mat.SetTRS(Vector3.zero, identity, Vector3.one); Matrix4x4 matrix4x = pd.transform.localToWorldMatrix * pd.mat; for (int i = 0; i < pd.path.splines.Count; i++) { float num = pd.path.stepdist * 0.1f; if (num < 0.01f) { num = 0.01f; } float num2 = pd.path.splines[i].length / (pd.path.splines[i].length / num); int num3 = 0; int k = -1; int k2 = -1; Vector3 point = pd.path.splines[i].Interpolate(0f, pd.path.normalizedInterp, ref k2) - p; for (float num4 = num2; num4 < pd.path.splines[i].length; num4 += num2) { float alpha = num4 / pd.path.splines[i].length; Vector3 vector3 = pd.path.splines[i].Interpolate(alpha, pd.path.normalizedInterp, ref k) - p; if ((num3 & 1) == 1) { Gizmos.color = pd.path.col1; } else { Gizmos.color = pd.path.col2; } if (k != k2) { for (k2++; k2 <= k; k2++) { Gizmos.DrawLine(matrix4x.MultiplyPoint(point), matrix4x.MultiplyPoint(pd.path.splines[i].knots[k2].p - p)); point = pd.path.splines[i].knots[k2].p - p; } } k2 = k; Gizmos.DrawLine(matrix4x.MultiplyPoint(point), matrix4x.MultiplyPoint(vector3)); num3++; point = vector3; } if ((num3 & 1) == 1) { Gizmos.color = pd.path.col1; } else { Gizmos.color = pd.path.col2; } if (pd.path.splines[i].closed) { Vector3 point2 = pd.path.splines[i].Interpolate(0f, pd.path.normalizedInterp, ref k) - p; Gizmos.DrawLine(matrix4x.MultiplyPoint(point), matrix4x.MultiplyPoint(point2)); } } Vector3 point3 = pd.path.InterpCurve3D(curve, percent / 100f, pd.path.normalizedInterp) - p; vector = pd.path.InterpCurve3D(curve, percent / 100f + tangent * 0.01f, pd.path.normalizedInterp) - p; Gizmos.color = Color.blue; Vector3 size = new Vector3(pd.path.KnotSize * 0.01f, pd.path.KnotSize * 0.01f, pd.path.KnotSize * 0.01f); Gizmos.DrawCube(matrix4x.MultiplyPoint(point3), size); Gizmos.DrawCube(matrix4x.MultiplyPoint(vector), size); } public override void DrawGizmo(MegaModContext context) { if (Prepare(context)) { Vector3 min = context.bbox.min; Vector3 max = context.bbox.max; if (context.mod.sourceObj != null) { Gizmos.matrix = context.mod.sourceObj.transform.localToWorldMatrix; } else { Gizmos.matrix = base.transform.localToWorldMatrix; } corners[0] = new Vector3(min.x, min.y, min.z); corners[1] = new Vector3(min.x, max.y, min.z); corners[2] = new Vector3(max.x, max.y, min.z); corners[3] = new Vector3(max.x, min.y, min.z); corners[4] = new Vector3(min.x, min.y, max.z); corners[5] = new Vector3(min.x, max.y, max.z); corners[6] = new Vector3(max.x, max.y, max.z); corners[7] = new Vector3(max.x, min.y, max.z); DrawEdge(corners[0], corners[1]); DrawEdge(corners[1], corners[2]); DrawEdge(corners[2], corners[3]); DrawEdge(corners[3], corners[0]); DrawEdge(corners[4], corners[5]); DrawEdge(corners[5], corners[6]); DrawEdge(corners[6], corners[7]); DrawEdge(corners[7], corners[4]); DrawEdge(corners[0], corners[4]); DrawEdge(corners[1], corners[5]); DrawEdge(corners[2], corners[6]); DrawEdge(corners[3], corners[7]); ExtraGizmo(context); } } }