using System; using UnityEngine; [AddComponentMenu("Modifiers/Dynamic Ripple")] public class MegaDynamicRipple : MegaModifier { public MegaAxis axis = MegaAxis.Y; public int cols = 8; public int rows = 8; [HideInInspector] public float[] buffer1; [HideInInspector] public float[] buffer2; [HideInInspector] public int[] vertexIndices; public float damping = 0.999f; public float WaveHeight = 2f; public float Force = 1f; public float DropsPerSec = 1f; public float speed = 0.5f; public float[] input; public float inputdamp = 0.99f; public float InputForce = 0.1f; public bool Obstructions; public float[] blockers; private float time; public float scale = 1f; private bool swapMe = true; public bool bilinearSample; public Texture2D obTexture; private Collider mycollider; private float[] currentBuffer; public int vertcomponent = 1; public int wakesize = 1; public float wakefalloff = 1f; public float wakeforce = 1f; private float lastcol = -1f; private float lastrow = -1f; private bool lastdown; private int xc; private int yc; public override string ModName() { return "Dynamic Ripple"; } public override string GetHelpURL() { return "?page_id=2395"; } [ContextMenu("Reset Sim")] public void ResetGrid() { Setup(); } public void SetObstructions(Texture2D obtex) { obTexture = obtex; if (blockers == null || blockers.Length != buffer1.Length) { blockers = new float[buffer1.Length]; } if ((bool)obTexture) { for (int i = 0; i < rows; i++) { int num = i * cols; float v = (float)i / (float)rows; for (int j = 0; j < cols; j++) { float u = (float)j / (float)cols; if (bilinearSample) { blockers[num + j] = obTexture.GetPixelBilinear(u, v).grayscale; } else { blockers[num + j] = obTexture.GetPixel(j, i).grayscale; } } } } else { for (int k = 0; k < blockers.Length; k++) { blockers[k] = 1f; } } } public override void Modify(MegaModifiers mc) { for (int i = 0; i < verts.Length; i++) { Vector3 vector = verts[i]; int num = vertexIndices[i]; vector[vertcomponent] += currentBuffer[num] * scale; sverts[i] = vector; } } public override Vector3 Map(int i, Vector3 p) { p = tm.MultiplyPoint3x4(p); if (i >= 0) { int num = vertexIndices[i]; p[vertcomponent] += currentBuffer[num] * scale; } return invtm.MultiplyPoint3x4(p); } public override bool ModLateUpdate(MegaModContext mc) { if (buffer1 == null || rows * cols != buffer1.Length) { Setup(); swapMe = false; currentBuffer = buffer2; return false; } if (swapMe) { processRipples(buffer1, buffer2); currentBuffer = buffer2; } else { processRipples(buffer2, buffer1); currentBuffer = buffer2; } swapMe = !swapMe; return Prepare(mc); } public override bool Prepare(MegaModContext mc) { if (mycollider == null) { mycollider = GetComponent(); } return true; } private void Setup() { int num = rows * cols; buffer1 = new float[num]; buffer2 = new float[num]; input = new float[num]; swapMe = false; currentBuffer = buffer2; vertexIndices = new int[verts.Length]; SetObstructions(obTexture); for (int i = 0; i < num; i++) { buffer1[i] = 0f; buffer2[i] = 0f; } int index = 0; int index2 = 1; Vector3 vector = bbox.Size(); if (vector.x == 0f) { axis = MegaAxis.X; } if (vector.y == 0f) { axis = MegaAxis.Y; } if (vector.z == 0f) { axis = MegaAxis.Z; } switch (axis) { case MegaAxis.X: vertcomponent = 0; index = 1; index2 = 2; break; case MegaAxis.Y: vertcomponent = 1; index = 0; index2 = 2; break; case MegaAxis.Z: vertcomponent = 2; index = 0; index2 = 1; break; } for (int j = 0; j < verts.Length; j++) { float num2 = (verts[j][index] - bbox.min[index]) / vector[index]; float num3 = (verts[j][index2] - bbox.min[index2]) / vector[index2]; if (num2 >= 1f) { num2 = 0.999f; } if (num3 >= 1f) { num3 = 0.999f; } int num4 = (int)(num2 * (float)cols); int num5 = (int)(num3 * (float)rows); float num6 = num5 * cols + num4; vertexIndices[j] = (int)num6; } } private void splashAtPoint(int x, int y, float force) { int num = y * cols + x; buffer1[num] = force; buffer1[num - 1] = force * 0.5f; buffer1[num + 1] = force * 0.5f; buffer1[num + cols] = force * 0.5f; buffer1[num + cols + 1] = force * 0.45f; buffer1[num + cols - 1] = force * 0.45f; buffer1[num - cols] = force * 0.5f; buffer1[num - cols + 1] = force * 0.45f; buffer1[num - cols - 1] = force * 0.45f; } private void splashAtPoint1(int x, int y, float force) { int num = y * cols + x; buffer1[num] = force; buffer1[num - 1] = force * 0.5f; buffer1[num + 1] = force * 0.5f; buffer1[num + cols] = force * 0.5f; buffer1[num + cols + 1] = force * 0.45f; buffer1[num + cols - 1] = force * 0.45f; buffer1[num - cols] = force * 0.5f; buffer1[num - cols + 1] = force * 0.45f; buffer1[num - cols - 1] = force * 0.45f; buffer2[num] = force; buffer2[num - 1] = force * 0.5f; buffer2[num + 1] = force * 0.5f; buffer2[num + cols] = force * 0.5f; buffer2[num + cols + 1] = force * 0.45f; buffer2[num + cols - 1] = force * 0.45f; buffer2[num - cols] = force * 0.5f; buffer2[num - cols + 1] = force * 0.45f; buffer2[num - cols - 1] = force * 0.45f; } private int ipart(float x) { return (int)x; } private int round(float x) { return ipart(x + 0.5f); } private float fpart(float x) { return x - (float)(int)x; } private float rfpart(float x) { return 1f - fpart(x); } private void swap(ref float v1, ref float v2) { float num = v1; v1 = v2; v2 = num; } private void plot(int x, int y, float force) { input[x + y * cols] = force; } private void drawLine(float x1, float y1, float x2, float y2, float force) { float v = x2 - x1; float v2 = y2 - y1; if (Mathf.Abs(v) < Mathf.Abs(v2)) { swap(ref x1, ref y1); swap(ref x2, ref y2); swap(ref v, ref v2); } if (x2 < x1) { swap(ref x1, ref x2); swap(ref y1, ref y2); } float num = v2 / v; float num2 = round(x1); float num3 = y1 + num * (num2 - x1); float num4 = rfpart(x1 + 0.5f); int num5 = (int)num2; int num6 = ipart(num3); plot(num5, num6, rfpart(num3) * num4 * force); plot(num5, num6 + 1, fpart(num3) * num4 * force); float num7 = num3 + num; num2 = round(x2); num3 = y2 + num * (num2 - x2); num4 = fpart(x2 + 0.5f); int num8 = (int)num2; int num9 = ipart(num3); plot(num8, num9, rfpart(num3) * num4 * force); plot(num8, num9 + 1, fpart(num3) * num4 * force); for (int i = num5 + 1; i < num8 - 1; i++) { plot(i, ipart(num7), rfpart(num7) * force); plot(i, ipart(num7) + 1, fpart(num7) * force); num7 += num; } } private void wakeAtPointWu(float x, float y, float force) { } public void wakeAtPointAdd1(float x, float y, float force) { int num = Mathf.RoundToInt(x) - 1; int num2 = Mathf.RoundToInt(y) - 1; float[] array = new float[4]; int num3 = 0; int num4 = 0; float num5 = 0f; for (int i = num2; i < num2 + 2; i++) { for (int j = num; j < num + 2; j++) { float num6 = (float)j + 0.5f - x; float num7 = (float)i + 0.5f - y; float num8 = Mathf.Sqrt(num6 * num6 + num7 * num7); if (num8 < 1f) { num5 += num8; array[num3] = num8; num4++; } else { array[num3] = 1f; } num3++; } } num3 = 0; for (int k = num2; k < num2 + 2; k++) { for (int l = num; l < num + 2; l++) { if (k >= 0 && k < rows && l >= 0 && l < cols && array[num3] < 1f) { input[l + k * cols] = force * (array[num3] / num5); } num3++; } } } private void wakeAtPointAdd(int x, int y, float force) { int num = y * cols + x; input[num] = force; } private void wakeAtPoint(int x, int y, float force) { int num = y * cols + x; input[num] = force; input[num - 1] = force * 0.5f; input[num + 1] = force * 0.5f; input[num + cols] = force * 0.5f; input[num + cols + 1] = force * 0.45f; input[num + cols - 1] = force * 0.45f; input[num - cols] = force * 0.5f; input[num - cols + 1] = force * 0.45f; input[num - cols - 1] = force * 0.45f; } private void processRipples(float[] source, float[] dest) { for (int i = 1; i < rows - 1; i++) { int num = i * cols; for (int j = 1; j < cols - 1; j++) { input[num + j] *= inputdamp; } } if (Obstructions) { for (int k = 1; k < rows - 1; k++) { int num2 = k * cols; for (int l = 1; l < cols - 1; l++) { int num3 = num2 + l; dest[num3] = input[num3] + ((source[num3 - 1] + source[num3 + 1] + source[num3 - cols] + source[num3 + cols]) * speed - dest[num3]); dest[num3] = dest[num3] * damping * blockers[num3]; } } return; } for (int m = 1; m < rows - 1; m++) { int num4 = m * cols; for (int n = 1; n < cols - 1; n++) { int num5 = num4 + n; dest[num5] = input[num5] + ((source[num5 - 1] + source[num5 + 1] + source[num5 - cols] + source[num5 + cols]) * speed - dest[num5]); dest[num5] *= damping; } } } private void Update() { if (buffer1 == null || rows * cols != buffer1.Length) { return; } time += Time.deltaTime; int num = (int)(time * DropsPerSec); if (num > 0) { time = 0f; if (rows > 8 && cols > 8) { for (int i = 0; i < num; i++) { int x = UnityEngine.Random.Range(8, cols - 8); int y = UnityEngine.Random.Range(8, rows - 8); splashAtPoint(x, y, Force * UnityEngine.Random.Range(0.1f, 1f)); } } } checkInput(); } public float GetWaterHeight(Vector3 lpos) { if (currentBuffer == null) { return 0f; } float num = (lpos.x - bbox.min.x) / (bbox.max.x - bbox.min.x); float num2 = (lpos.y - bbox.min.y) / (bbox.max.y - bbox.min.y); int num3 = (int)(num * (float)cols); int num4 = (int)(num2 * (float)rows); if (num3 < 0 || num3 >= cols) { return 0f; } if (num4 < 0 || num4 >= rows) { return 0f; } return currentBuffer[num4 * cols + num3]; } private void checkInput() { if (Input.GetMouseButton(0)) { RaycastHit[] array = Physics.RaycastAll(Camera.main.ScreenPointToRay(Input.mousePosition)); for (int i = 0; i < array.Length; i++) { if (!(array[i].collider.gameObject == base.gameObject)) { continue; } if (array[i].collider is BoxCollider) { Vector3 vector = base.gameObject.transform.worldToLocalMatrix.MultiplyPoint(array[i].point); BoxCollider boxCollider = (BoxCollider)array[i].collider; vector -= boxCollider.center; if (boxCollider.size.x != 0f) { vector.x /= boxCollider.size.x; } if (boxCollider.size.y != 0f) { vector.y /= boxCollider.size.y; } if (boxCollider.size.z != 0f) { vector.z /= boxCollider.size.z; } vector.x += 0.5f; vector.y += 0.5f; vector.z += 0.5f; float num = 0f; float num2 = 0f; switch (axis) { case MegaAxis.X: vertcomponent = 0; num = vector.y * (float)(cols - 1); num2 = vector.z * (float)(rows - 1); break; case MegaAxis.Y: num = vector.x * (float)(cols - 1); num2 = vector.z * (float)(rows - 1); break; case MegaAxis.Z: num = vector.x * (float)(cols - 1); num2 = vector.y * (float)(rows - 1); break; } if (lastdown) { Line(lastcol, lastrow, num, num2); } else { wakeAtPointAdd1((int)num, (int)num2, 0f - InputForce); } lastdown = true; lastrow = num2; lastcol = num; } else { float num3 = (1f - array[i].textureCoord.x) * (float)(cols - 1); float num4 = array[i].textureCoord.y * (float)(rows - 1); if (lastdown) { Line(lastcol, lastrow, num3, num4); } else { wakeAtPointAdd1((int)num3, (int)num4, 0f - InputForce); } lastdown = true; lastrow = num4; lastcol = num3; } break; } } else { lastdown = false; } } private void checkInput1() { if (Input.GetMouseButton(0)) { RaycastHit hitInfo; if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hitInfo) && !(hitInfo.collider.gameObject != base.gameObject)) { float num = (1f - hitInfo.textureCoord.x) * (float)(cols - 1); float num2 = hitInfo.textureCoord.y * (float)(rows - 1); if (lastdown) { Line(lastcol, lastrow, num, num2); } else { wakeAtPointAdd1((int)num, (int)num2, 0f - InputForce); } lastdown = true; lastrow = num2; lastcol = num; } } else { lastdown = false; } } private void Line(float x0, float y0, float x1, float y1) { if (Mathf.Abs(y1 - y0) > Mathf.Abs(x1 - x0)) { int num = (int)Mathf.Abs(y0 - y1); float num2 = 1f; if (y1 < y0) { num2 = -1f; } float num3 = x1 - x0; if (num > 0) { num3 /= (float)num; } for (int i = 0; i <= num; i++) { wakeAtPointAdd1(x0, y0, 0f - InputForce); x0 += num3; y0 += num2; } } else { int num4 = (int)Mathf.Abs(x0 - x1); float num5 = 1f; if (x1 < x0) { num5 = -1f; } float num6 = y1 - y0; if (num4 > 0) { num6 /= (float)num4; } for (int j = 0; j <= num4; j++) { wakeAtPointAdd1(x0, y0, 0f - InputForce); x0 += num5; y0 += num6; } } } public void Line(float x0, float y0, float x1, float y1, float force) { if (Mathf.Abs(y1 - y0) > Mathf.Abs(x1 - x0)) { int num = (int)Mathf.Abs(y0 - y1); float num2 = 1f; if (y1 < y0) { num2 = -1f; } float num3 = x1 - x0; if (num > 0) { num3 /= (float)num; } for (int i = 0; i <= num; i++) { wakeAtPointAdd1(x0, y0, force); x0 += num3; y0 += num2; } } else { int num4 = (int)Mathf.Abs(x0 - x1); float num5 = 1f; if (x1 < x0) { num5 = -1f; } float num6 = y1 - y0; if (num4 > 0) { num6 /= (float)num4; } for (int j = 0; j <= num4; j++) { wakeAtPointAdd1(x0, y0, force); x0 += num5; y0 += num6; } } } public void ForceAt(float x, float y, float force) { Vector3 zero = Vector3.zero; zero.x = x; zero.z = y; zero = base.transform.worldToLocalMatrix.MultiplyPoint(zero); x = (zero.x - bbox.min[xc]) / (bbox.max[xc] - bbox.min[xc]); y = (zero.y - bbox.min[yc]) / (bbox.max[yc] - bbox.min[yc]); int num = (int)(x * (float)cols); int num2 = (int)(y * (float)rows); if (num >= 0 && num < cols && num2 >= 0 && num2 < rows) { input[num2 * cols + num] = force; } } public void ForceAt(Vector3 p, float force) { p = base.transform.worldToLocalMatrix.MultiplyPoint(p); BoxCollider boxCollider = (BoxCollider)mycollider; if (boxCollider.size.x != 0f) { p.x /= boxCollider.size.x; } if (boxCollider.size.y != 0f) { p.y /= boxCollider.size.y; } if (boxCollider.size.z != 0f) { p.z /= boxCollider.size.z; } p.x += 0.5f; p.y += 0.5f; p.z += 0.5f; float num = 0f; float num2 = 0f; switch (axis) { case MegaAxis.X: vertcomponent = 0; num = p.y * (float)(cols - 1); num2 = p.z * (float)(rows - 1); break; case MegaAxis.Y: num = p.x * (float)(cols - 1); num2 = p.z * (float)(rows - 1); break; case MegaAxis.Z: num = p.x * (float)(cols - 1); num2 = p.y * (float)(rows - 1); break; } int num3 = (int)num; int num4 = (int)num2; if (num3 >= 0 && num3 < cols && num4 >= 0 && num4 < rows) { input[num4 * cols + num3] = force; } } private void BuildMesh() { Vector3 zero = Vector3.zero; Vector3 vector = Vector3.zero; xc = 0; yc = 0; switch (axis) { case MegaAxis.X: xc = 1; yc = 2; break; case MegaAxis.Y: xc = 0; yc = 2; break; case MegaAxis.Z: xc = 0; yc = 1; break; } for (int i = 0; i < rows; i++) { zero.z = bbox.min[yc] + (bbox.max[yc] - bbox.min[yc]) * ((float)i / (float)rows); for (int j = 0; j < cols; j++) { zero.x = bbox.min[xc] + (bbox.max[xc] - bbox.min[xc]) * ((float)j / (float)cols); zero.y = currentBuffer[i * cols + j]; if (j > 0) { Gizmos.DrawLine(vector, zero); } vector = zero; } } for (int k = 0; k < cols; k++) { zero.x = bbox.min[xc] + (bbox.max[xc] - bbox.min[xc]) * ((float)k / (float)cols); for (int l = 0; l < rows; l++) { zero.z = bbox.min[yc] + (bbox.max[yc] - bbox.min[yc]) * ((float)l / (float)rows); zero.y = currentBuffer[l * cols + k]; if (l > 0) { Gizmos.DrawLine(vector, zero); } vector = zero; } } } public override void DrawGizmo(MegaModContext context) { Gizmos.color = Color.yellow; Matrix4x4 identity = Matrix4x4.identity; Vector3 pos = gizmoPos; pos.x = 0f - pos.x; pos.y = 0f - pos.y; pos.z = 0f - pos.z; Vector3 s = gizmoScale; s.x = 1f - (s.x - 1f); s.y = 1f - (s.y - 1f); identity.SetTRS(pos, Quaternion.Euler(gizmoRot), s); Matrix4x4 mat = Matrix4x4.identity; switch (axis) { case MegaAxis.X: MegaMatrix.RotateZ(ref mat, (float)Math.PI / 2f); break; case MegaAxis.Z: MegaMatrix.RotateX(ref mat, (float)Math.PI / 2f); break; } Gizmos.matrix = base.transform.localToWorldMatrix * identity * mat; BuildMesh(); } }