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

363 lines
7.7 KiB
C#

using System.Collections.Generic;
using UnityEngine;
[AddComponentMenu("Modifiers/Rubber")]
public class MegaRubber : MegaModifier
{
public MegaRubberType Presets;
public MegaWeightChannel channel;
public MegaWeightChannel stiffchannel = MegaWeightChannel.None;
public Vector3 Intensity = Vector3.one;
public float gravity;
public float mass = 1f;
public Vector3 stiffness = new Vector3(0.2f, 0.2f, 0.2f);
public Vector3 damping = new Vector3(0.7f, 0.7f, 0.7f);
public float threshold;
public float size = 0.001f;
public bool showweights = true;
private float oomass;
private float grav;
private bool defined;
public VertexRubber[] vr;
private int[] notmoved;
public Transform target;
private bool weightsChanged;
private MegaModifiers mods;
public override string ModName()
{
return "Rubber";
}
public override string GetHelpURL()
{
return "?page_id=1254";
}
[ContextMenu("Reset Physics")]
public void ResetPhysics()
{
MegaModifiers component = GetComponent<MegaModifiers>();
if ((bool)component)
{
Init(component);
}
}
private int[] FindVerts(Vector3[] vts, Vector3 p)
{
List<int> list = new List<int>();
for (int i = 0; i < vts.Length; i++)
{
if (p.x == vts[i].x && p.y == vts[i].y && p.z == vts[i].z)
{
list.Add(i);
}
}
return list.ToArray();
}
private bool HavePoint(Vector3[] vts, List<int> points, Vector3 p)
{
for (int i = 0; i < points.Count; i++)
{
if (p.x == vts[points[i]].x && p.y == vts[points[i]].y && p.z == vts[points[i]].z)
{
return true;
}
}
return false;
}
private void Init(MegaModifiers mod)
{
if (mod.verts == null)
{
return;
}
List<int> list = new List<int>();
List<int> list2 = new List<int>();
int index = (int)channel;
for (int i = 0; i < mod.verts.Length; i++)
{
if (channel == MegaWeightChannel.None || mod.cols == null || mod.cols.Length == 0)
{
continue;
}
if (mod.cols[i][index] > threshold)
{
if (!HavePoint(mod.verts, list2, mod.verts[i]))
{
list2.Add(i);
}
}
else
{
list.Add(i);
}
}
notmoved = list.ToArray();
if (list2.Count > 0)
{
vr = new VertexRubber[list2.Count];
for (int j = 0; j < list2.Count; j++)
{
int num = list2[j];
float s = 1f;
if (stiffchannel != MegaWeightChannel.None && mod.cols != null && mod.cols.Length > 0)
{
s = mod.cols[num][(int)stiffchannel];
}
float w = (mod.cols[num][index] - threshold) / (1f - threshold);
vr[j] = new VertexRubber(base.transform.TransformPoint(mod.verts[num]), w, s);
vr[j].indices = FindVerts(mod.verts, mod.verts[num]);
}
}
else
{
vr = null;
}
defined = true;
}
public override bool ModLateUpdate(MegaModContext mc)
{
if (weightsChanged)
{
ResetPhysics();
weightsChanged = false;
}
return Prepare(mc);
}
public override bool Prepare(MegaModContext mc)
{
if ((bool)target)
{
tm = target.worldToLocalMatrix * base.transform.localToWorldMatrix;
invtm = tm.inverse;
}
else
{
tm = base.transform.localToWorldMatrix;
invtm = base.transform.worldToLocalMatrix;
}
oomass = 1f / mass;
grav = gravity * 0.1f;
if (!defined)
{
Init(mc.mod);
}
if (vr != null)
{
return true;
}
return false;
}
public override void Modify(MegaModifiers mc)
{
UpdateVerts(0, vr.Length);
for (int i = 0; i < notmoved.Length; i++)
{
sverts[notmoved[i]] = verts[notmoved[i]];
}
}
public void SetTarget(Transform target)
{
if ((bool)target)
{
tm = target.worldToLocalMatrix * base.transform.localToWorldMatrix;
invtm = tm.inverse;
}
else
{
tm = base.transform.localToWorldMatrix;
invtm = base.transform.worldToLocalMatrix;
}
InitVerts(0, vr.Length);
}
private void InitVerts(int start, int end)
{
for (int i = start; i < end; i++)
{
int num = vr[i].indices[0];
Vector3 point = verts[num];
Vector3 pos = tm.MultiplyPoint(point);
VertexRubber vertexRubber = vr[i];
vertexRubber.vel = Vector3.zero;
vertexRubber.pos = pos;
}
}
private void UpdateVerts(int start, int end)
{
Vector3 zero = Vector3.zero;
for (int i = start; i < end; i++)
{
int num = vr[i].indices[0];
Vector3 point = verts[num];
Vector3 vector = tm.MultiplyPoint(point);
VertexRubber vertexRubber = vr[i];
vertexRubber.force.x = (vector.x - vertexRubber.pos.x) * stiffness.x * vertexRubber.stiff;
vertexRubber.acc.x = vertexRubber.force.x * oomass;
vertexRubber.vel.x = damping.x * (vertexRubber.vel.x + vertexRubber.acc.x);
vertexRubber.pos.x += vertexRubber.vel.x;
vertexRubber.force.y = (vector.y - vertexRubber.pos.y) * stiffness.y * vertexRubber.stiff;
vertexRubber.force.y -= grav;
vertexRubber.acc.y = vertexRubber.force.y * oomass;
vertexRubber.vel.y = damping.y * (vertexRubber.vel.y + vertexRubber.acc.y);
vertexRubber.pos.y += vertexRubber.vel.y;
vertexRubber.force.z = (vector.z - vertexRubber.pos.z) * stiffness.z * vertexRubber.stiff;
vertexRubber.acc.z = vertexRubber.force.z * oomass;
vertexRubber.vel.z = damping.z * (vertexRubber.vel.z + vertexRubber.acc.z);
vertexRubber.pos.z += vertexRubber.vel.z;
vector = invtm.MultiplyPoint(vr[i].pos);
zero.x = point.x + (vector.x - point.x) * vertexRubber.weight * Intensity.x;
zero.y = point.y + (vector.y - point.y) * vertexRubber.weight * Intensity.y;
zero.z = point.z + (vector.z - point.z) * vertexRubber.weight * Intensity.z;
vertexRubber.cpos = zero;
for (int j = 0; j < vr[i].indices.Length; j++)
{
int num2 = vr[i].indices[j];
sverts[num2] = zero;
}
}
}
public void ChangeMaterial()
{
switch (Presets)
{
case MegaRubberType.HardRubber:
gravity = 0f;
mass = 8f;
stiffness = new Vector3(0.5f, 0.5f, 0.5f);
damping = new Vector3(0.9f, 0.9f, 0.9f);
Intensity = new Vector3(0.5f, 0.5f, 0.5f);
break;
case MegaRubberType.Jelly:
gravity = 0f;
mass = 1f;
stiffness = new Vector3(0.95f, 0.95f, 0.95f);
damping = new Vector3(0.95f, 0.95f, 0.95f);
Intensity = Vector3.one;
break;
case MegaRubberType.SoftRubber:
gravity = 0f;
mass = 2f;
stiffness = new Vector3(0.5f, 0.5f, 0.5f);
damping = new Vector3(0.85f, 0.85f, 0.85f);
Intensity = Vector3.one;
break;
case MegaRubberType.SoftLatex:
gravity = 1f;
mass = 0.9f;
stiffness = new Vector3(0.3f, 0.3f, 0.3f);
damping = new Vector3(0.25f, 0.25f, 0.25f);
Intensity = Vector3.one;
break;
}
}
public void ChangeChannel()
{
MegaModifiers component = GetComponent<MegaModifiers>();
if ((bool)component)
{
Init(component);
}
}
public override void DoWork(MegaModifiers mc, int index, int start, int end, int cores)
{
ModifyCompressedMT(mc, index, cores);
}
public void ModifyCompressedMT(MegaModifiers mc, int tindex, int cores)
{
int num = notmoved.Length / cores;
int num2 = tindex * num;
int num3 = num2 + num;
if (tindex == cores - 1)
{
num3 = notmoved.Length;
}
if (notmoved != null)
{
for (int i = num2; i < num3; i++)
{
int num4 = notmoved[i];
sverts[num4] = verts[num4];
}
}
num = vr.Length / cores;
num2 = tindex * num;
num3 = num2 + num;
if (tindex == cores - 1)
{
num3 = vr.Length;
}
UpdateVerts(num2, num3);
}
private MegaModifiers GetMod()
{
if (mods == null)
{
mods = GetComponent<MegaModifiers>();
}
return mods;
}
public void UpdateCols(int first, Color[] newcols)
{
GetMod();
if ((bool)mods)
{
mods.UpdateCols(first, newcols);
}
weightsChanged = true;
}
public void UpdateCol(int i, Color col)
{
GetMod();
if ((bool)mods)
{
mods.UpdateCol(i, col);
}
weightsChanged = true;
}
public void UpdateCols(Color[] newcols)
{
GetMod();
if ((bool)mods)
{
mods.UpdateCols(newcols);
}
weightsChanged = true;
}
}