363 lines
7.7 KiB
C#
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;
|
|
}
|
|
}
|