Files
2026-02-21 16:45:37 +08:00

319 lines
7.8 KiB
C#

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);
}
}
}