using UnityEngine; [AddComponentMenu("Modifiers/Deformable")] public class MegaDeformable : MegaModifier { public float Hardness = 0.5f; public bool DeformMeshCollider = true; public float UpdateFrequency; public float MaxVertexMov; public Color32 DeformedVertexColor = Color.gray; public Texture2D HardnessMap; public bool usedecay; public float decay = 0.999f; public Color[] baseColors; public float sizeFactor; public float[] map; public Vector3[] offsets; public float impactFactor = 0.1f; public float ColForce = 0.5f; public MegaModifyObject modobj; private ContactPoint[] colpoints; public override string ModName() { return "Deformable"; } public override void ModStart(MegaModifiers mc) { Vector3 size = mc.mesh.bounds.size; sizeFactor = Mathf.Min(size.x, size.y, size.z); if (mc.mesh.colors != null) { baseColors = mc.mesh.colors; } LoadMap(mc); } public override bool ModLateUpdate(MegaModContext mc) { return Prepare(mc); } public override bool Prepare(MegaModContext mc) { if (offsets == null || offsets.Length != mc.mod.verts.Length) { offsets = new Vector3[mc.mod.verts.Length]; } return true; } public override MegaModChannel ChannelsReq() { return (MegaModChannel)65; } public override MegaModChannel ChannelsChanged() { return (MegaModChannel)65; } private void LoadMesh() { } public void LoadMap() { MegaModifiers component = GetComponent(); if ((bool)component) { LoadMap(component); } } private void LoadMap(MegaModifiers mc) { if ((bool)HardnessMap) { Vector2[] uv = mc.mesh.uv; map = new float[uv.Length]; for (int i = 0; i < uv.Length; i++) { Vector2 vector = uv[i]; map[i] = HardnessMap.GetPixelBilinear(vector.x, vector.y).a; } } else { map = null; } } public override void Modify(MegaModifiers mc) { float colForce = ColForce; sizeFactor = mc.bbox.size.magnitude; float num = colForce * (sizeFactor * (impactFactor / Mathf.Max(impactFactor, Hardness))); if (colpoints != null) { for (int i = 0; i < colpoints.Length; i++) { ContactPoint contactPoint = colpoints[i]; for (int j = 0; j < verts.Length; j++) { Vector3 vector = verts[j] + offsets[j]; Vector3 vector2 = base.transform.InverseTransformPoint(contactPoint.point); float sqrMagnitude = (vector - vector2).sqrMagnitude; if (!(sqrMagnitude <= num)) { continue; } Vector3 vector3 = base.transform.InverseTransformDirection(contactPoint.normal * (1f - sqrMagnitude / num) * num); if (map != null) { vector3 *= 1f - map[j]; } offsets[j] += vector3; if (MaxVertexMov > 0f) { float maxVertexMov = MaxVertexMov; vector3 = offsets[j]; sqrMagnitude = vector3.magnitude; if (sqrMagnitude > maxVertexMov) { offsets[j] = vector3 * (maxVertexMov / sqrMagnitude); } if (baseColors.Length > 0) { sqrMagnitude /= MaxVertexMov; mc.cols[j] = Color.Lerp(baseColors[j], DeformedVertexColor, sqrMagnitude); } } else if (mc.cols.Length > 0) { mc.cols[j] = Color.Lerp(baseColors[j], DeformedVertexColor, offsets[j].magnitude / (num * 10f)); } } } } colpoints = null; if (!usedecay) { for (int k = 0; k < verts.Length; k++) { sverts[k].x = verts[k].x + offsets[k].x; sverts[k].y = verts[k].y + offsets[k].y; sverts[k].z = verts[k].z + offsets[k].z; } return; } for (int l = 0; l < verts.Length; l++) { offsets[l].x *= decay; offsets[l].y *= decay; offsets[l].z *= decay; sverts[l].x = verts[l].x + offsets[l].x; sverts[l].y = verts[l].y + offsets[l].y; sverts[l].z = verts[l].z + offsets[l].z; } } public void Repair(float repair, MegaModifiers mc) { Repair(repair, Vector3.zero, 0f, mc); } public void Repair(float repair, Vector3 point, float radius, MegaModifiers mc) { if (!mc.mesh) { return; } point = base.transform.InverseTransformPoint(point); for (int i = 0; i < mc.verts.Length; i++) { if (!(radius > 0f) || !((point - mc.sverts[i]).magnitude >= radius)) { Vector3 vector = offsets[i]; offsets[i] = vector * (1f - repair); if (baseColors.Length > 0) { mc.cols[i] = Color.Lerp(mc.cols[i], baseColors[i], repair); } } } } private void OnCollisionEnter(Collision collision) { if (modobj == null) { modobj = GetComponent(); } if ((bool)modobj) { modobj.Enabled = true; } colpoints = collision.contacts; } private void OnCollisionStay(Collision collision) { colpoints = collision.contacts; } private void OnCollisionExit(Collision collision) { if ((bool)modobj && !usedecay) { modobj.Enabled = false; } } }