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(); if ((bool)component) { Init(component); } } private int[] FindVerts(Vector3[] vts, Vector3 p) { List list = new List(); 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 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 list = new List(); List list2 = new List(); 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(); 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(); } 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; } }