using System.Collections.Generic; using System.Linq; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif namespace UltraCombos { [ExecuteAlways] public class DroppingPaint : MonoBehaviour { [SerializeField] private float size = 1; [SerializeField] private int segments = 16; [SerializeField] private float smooth = 3f; [SerializeField] private bool isDrop = false; [SerializeField] private bool isClear = false; private List> paints = new List>(); private List> smoothedPaints = new List>(); private void Update() { if (isDrop) { isDrop = false; Drop(); } if (isClear) { isClear = false; Clear(); } var t = Time.deltaTime * smooth; for (int i = 0; i < paints.Count; i++) { var points = paints[i]; for (int j = 0; j < points.Count; j++) { smoothedPaints[i][j] = Vector2.Lerp(smoothedPaints[i][j], points[j], t); } } } public void Drop() { var r = Random.Range(size * 0.1f, size * 0.2f); var px = Random.Range(-size * 0.4f, +size * 0.4f); var py = Random.Range(-size * 0.4f, +size * 0.4f); var angle = Mathf.PI * 2 / segments; var circle = Enumerable.Range(0, segments).Select(i => { var x = px + r * Mathf.Cos(angle * i); var y = py + r * Mathf.Sin(angle * i); return new Vector2(x, y); }).ToList(); var center = new Vector2(px, py); foreach (var points in paints) { for (int i = 0; i < points.Count; i++) { points[i] = ApplyPaintDrop(points[i], center, r); } } paints.Add(circle); smoothedPaints.Add(circle.Select(c => center).ToList()); } public void Clear() { paints.Clear(); smoothedPaints.Clear(); } private void OnDrawGizmos() { #if UNITY_EDITOR using var mtx = new Handles.DrawingScope(transform.localToWorldMatrix); Handles.DrawWireCube(Vector3.zero, Vector2.one * size); if (smoothedPaints.Count == 0) return; var dh = 1f / smoothedPaints.Count; var h = 0f; foreach (var points in smoothedPaints) { using var col = new Handles.DrawingScope(Color.HSVToRGB(h, 0.7f, 0.8f)); foreach (var point in points) { Handles.DrawWireDisc(new Vector3(point.x, point.y, 0), Vector3.forward, 0.02f); } //Handles.DrawPolyLine(points.Select(p => new Vector3(p.x, p.y, 0)).ToArray()); Handles.DrawAAConvexPolygon(points.Select(p => new Vector3(p.x, p.y, 0)).ToArray()); h += dh; } #endif } private Vector2 ApplyPaintDrop(Vector2 p, Vector2 c, float r) { var d = Vector2.Distance(p, c); if (d > r) { return c + (p - c) * Mathf.Sqrt(1 + (r * r) / (d * d)); } var edge = c + (p - c) * (r / d + 0.002f); return ApplyPaintDrop(edge, c, r); } private List ResamplePoints(List points, float minSpacing, float maxSpacing) { List newPoints = new List(); int count = points.Count; for (int i = 0; i < count; i++) { Vector2 p1 = points[i]; Vector2 p2 = points[(i + 1) % count]; float dist = Vector2.Distance(p1, p2); newPoints.Add(p1); if (dist > maxSpacing) { int numNewPoints = Mathf.FloorToInt(dist / minSpacing); for (int j = 1; j <= numNewPoints; j++) { float t = j / (float)(numNewPoints + 1); newPoints.Add(Vector2.Lerp(p1, p2, t)); } } } return newPoints; } } }