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

193 lines
4.0 KiB
C#

using UnityEngine;
[AddComponentMenu("Modifiers/Conform")]
public class MegaConformMod : MegaModifier
{
public GameObject target;
public float[] offsets;
public Collider conformCollider;
public Bounds bounds;
public float[] last;
public Vector3[] last1;
public Vector3[] conformedVerts;
public float conformAmount = 1f;
public float raystartoff;
public float offset;
public float raydist = 100f;
public MegaAxis axis = MegaAxis.Y;
private Matrix4x4 loctoworld;
private Matrix4x4 ctm;
private Matrix4x4 cinvtm;
private Ray ray = default(Ray);
private RaycastHit hit;
public bool useLocalDown;
public bool flipDown = true;
public MegaAxis downAxis = MegaAxis.Y;
public override string ModName()
{
return "Conform";
}
public override string GetHelpURL()
{
return "?page_id=4547";
}
public void SetTarget(GameObject targ)
{
target = targ;
if ((bool)target)
{
conformCollider = target.GetComponent<Collider>();
}
}
public override Vector3 Map(int i, Vector3 p)
{
return p;
}
public override void Modify(MegaModifiers mc)
{
if ((bool)conformCollider)
{
if (useLocalDown)
{
Vector3 vector = Vector3.down;
switch (downAxis)
{
case MegaAxis.X:
vector = base.transform.right;
break;
case MegaAxis.Y:
vector = base.transform.up;
break;
case MegaAxis.Z:
vector = base.transform.forward;
break;
}
if (flipDown)
{
vector = -vector;
}
ray.direction = vector;
Vector3 vector2 = -vector * raystartoff;
Vector3 direction = ray.direction;
Vector3 vector3 = -base.transform.InverseTransformDirection(direction);
for (int i = 0; i < verts.Length; i++)
{
Vector3 origin = ctm.MultiplyPoint(verts[i]) - vector2;
ray.origin = origin;
sverts[i] = verts[i];
if (conformCollider.Raycast(ray, out hit, raydist))
{
Vector3 vector4 = cinvtm.MultiplyPoint(hit.point);
sverts[i] = Vector3.Lerp(verts[i], vector4 + vector3 * (offsets[i] + offset), conformAmount);
last1[i] = sverts[i];
}
else
{
sverts[i] = last1[i];
}
}
return;
}
int index = (int)axis;
for (int j = 0; j < verts.Length; j++)
{
Vector3 origin2 = ctm.MultiplyPoint(verts[j]);
origin2.y += raystartoff;
ray.origin = origin2;
ray.direction = Vector3.down;
sverts[j] = verts[j];
if (conformCollider.Raycast(ray, out hit, raydist))
{
Vector3 vector5 = cinvtm.MultiplyPoint(hit.point);
sverts[j][index] = Mathf.Lerp(verts[j][index], vector5[index] + offsets[j] + offset, conformAmount);
last[j] = sverts[j][index];
}
else
{
sverts[j][index] = last[j];
}
}
}
else
{
verts.CopyTo(sverts, 0);
}
}
public override bool ModLateUpdate(MegaModContext mc)
{
return Prepare(mc);
}
public override bool Prepare(MegaModContext mc)
{
if ((bool)target)
{
if (conformCollider != target.GetComponent<Collider>())
{
conformCollider = target.GetComponent<Collider>();
}
if (conformCollider == null)
{
return false;
}
if (conformedVerts == null || conformedVerts.Length != mc.mod.verts.Length)
{
conformedVerts = new Vector3[mc.mod.verts.Length];
offsets = new float[mc.mod.verts.Length];
last = new float[mc.mod.verts.Length];
for (int i = 0; i < mc.mod.verts.Length; i++)
{
offsets[i] = mc.mod.verts[i][(int)axis] - mc.bbox.min[(int)axis];
}
}
if (useLocalDown && (last1 == null || last1.Length != last.Length))
{
last1 = new Vector3[last.Length];
}
loctoworld = base.transform.localToWorldMatrix;
ctm = loctoworld;
cinvtm = base.transform.worldToLocalMatrix;
return true;
}
conformCollider = null;
return true;
}
public void ChangeAxis()
{
MegaModifyObject component = GetComponent<MegaModifyObject>();
if ((bool)component)
{
for (int i = 0; i < component.verts.Length; i++)
{
offsets[i] = component.verts[i][(int)axis] - component.bbox.min[(int)axis];
}
}
}
}