using System; using System.Collections.Generic; using UnityEngine; [AddComponentMenu("Modifiers/Paint")] public class MegaPaint : MegaModifier { public float radius = 1f; public float amount = 10f; public float decay = 1f; public bool usedecay; public MegaFallOff fallOff; public float gaussc = 0.25f; public bool useAvgNorm; public Vector3 normal = Vector3.up; public MegaPaintMode mode; private bool hadahit; private Vector3 relativePoint = Vector3.zero; private List affected = new List(); private List distances = new List(); private Matrix4x4 mat = default(Matrix4x4); private Vector3[] offsets; private Vector3[] normals; private Collider mycollider; public override string ModName() { return "Paint"; } public override string GetHelpURL() { return "?page_id=1292"; } private static float LinearFalloff(float distance, float inRadius) { return Mathf.Clamp01(1f - distance / inRadius); } private static float PointFalloff(float dist, float inRadius) { return (0f - dist * dist) / (inRadius * inRadius) + 1f; } public static float GaussFalloff(float v, float c) { float f = (float)Math.E; float num = 1f; float num2 = 0.5f; float num3 = (v - num2) * (v - num2); float num4 = 2f * c * c; return num * Mathf.Pow(f, 0f - num3 / num4); } private float Gaussian(float dist, float width) { return Mathf.Exp((0f - dist) * dist / width); } private void DeformMesh(Vector3 position, float power, float inRadius) { if (hadahit) { float num = inRadius * inRadius; Vector3 zero = Vector3.zero; for (int i = 0; i < verts.Length; i++) { Vector3 vector = verts[i]; float sqrMagnitude = (vector - position).sqrMagnitude; if (!(sqrMagnitude > num)) { affected.Add(i); float num2 = Mathf.Sqrt(sqrMagnitude); distances.Add(num2); if (useAvgNorm) { float num3 = LinearFalloff(num2, inRadius); zero += num3 * normals[i]; } } } zero = ((!useAvgNorm) ? normal : zero.normalized); for (int j = 0; j < affected.Count; j++) { float num4 = 0f; switch (fallOff) { case MegaFallOff.Gauss: num4 = GaussFalloff(distances[j], inRadius); break; case MegaFallOff.Point: num4 = PointFalloff(distances[j], inRadius); break; default: num4 = LinearFalloff(distances[j], inRadius); break; } switch (mode) { case MegaPaintMode.Add: offsets[affected[j]] += zero * num4 * power; break; case MegaPaintMode.Subtract: offsets[affected[j]] -= zero * num4 * power; break; case MegaPaintMode.Set: offsets[affected[j]] = zero * amount; break; case MegaPaintMode.Multiply: offsets[affected[j]] = Vector3.Scale(offsets[affected[j]], zero * (1f + num4 * power)); break; } } } 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 override void Modify(MegaModifiers mc) { DeformMesh(relativePoint, amount * Time.deltaTime, radius); } public override Vector3 Map(int i, Vector3 p) { return p; } public override bool ModLateUpdate(MegaModContext mc) { return Prepare(mc); } public override bool Prepare(MegaModContext mc) { if (mycollider == null) { mycollider = GetComponent(); } affected.Clear(); distances.Clear(); if (offsets == null || offsets.Length != mc.mod.verts.Length) { offsets = new Vector3[mc.mod.verts.Length]; } normals = mc.mod.mesh.normals; mat = Matrix4x4.identity; SetAxis(mat); hadahit = false; if (Input.GetMouseButton(0)) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hitInfo; if (Physics.Raycast(ray, out hitInfo) && hitInfo.collider == mycollider) { hadahit = true; relativePoint = hitInfo.collider.transform.InverseTransformPoint(hitInfo.point); } } return true; } public override void PrepareMT(MegaModifiers mc, int cores) { } public override void DoWork(MegaModifiers mc, int index, int start, int end, int cores) { if (index == 0) { Modify(mc); } } }