263 lines
5.8 KiB
C#
263 lines
5.8 KiB
C#
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;
|
|
}
|
|
}
|