|
|
|
|
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, Min(8)] private int segments = 16;
|
|
|
|
|
[SerializeField] private float smooth = 3f;
|
|
|
|
|
[SerializeField] private Vector2 distanceMinMax = new Vector2(1, 2);
|
|
|
|
|
[SerializeField] private bool isDrop = false;
|
|
|
|
|
[SerializeField] private bool isClear = false;
|
|
|
|
|
|
|
|
|
|
private List<List<Vector2>> paints = new List<List<Vector2>>();
|
|
|
|
|
private List<List<Vector2>> smoothedPaints = new List<List<Vector2>>();
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
var minDist = size / segments * distanceMinMax.x;
|
|
|
|
|
var maxDist = size / segments * distanceMinMax.y;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < paints.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
var points = paints[i];
|
|
|
|
|
var pre = points.Select(p => ApplyPaintDrop(p, center, r)).ToArray();
|
|
|
|
|
var incs = pre.Select((p, k) =>
|
|
|
|
|
{
|
|
|
|
|
var dist = (p - pre[(k + 1) % pre.Length]).magnitude;
|
|
|
|
|
return dist < minDist ? 0 : Mathf.CeilToInt(dist / minDist);
|
|
|
|
|
}).ToArray();
|
|
|
|
|
|
|
|
|
|
var newPoints = new List<Vector2>();
|
|
|
|
|
for (int j = 0; j < points.Count; j++)
|
|
|
|
|
{
|
|
|
|
|
var inc = incs[j];
|
|
|
|
|
if (inc == 0)
|
|
|
|
|
{
|
|
|
|
|
newPoints.Add(points[j]);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var p1 = points[j];
|
|
|
|
|
var p2 = points[(j + 1) % points.Count];
|
|
|
|
|
for (int k = 0; k < inc; k++)
|
|
|
|
|
{
|
|
|
|
|
var p = Vector2.Lerp(p1, p2, (float)k / inc);
|
|
|
|
|
newPoints.Add(p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
points.Clear();
|
|
|
|
|
points.AddRange(newPoints);
|
|
|
|
|
smoothedPaints[i].Clear();
|
|
|
|
|
smoothedPaints[i].AddRange(newPoints);
|
|
|
|
|
|
|
|
|
|
for (int j = 0; j < points.Count; j++)
|
|
|
|
|
{
|
|
|
|
|
points[j] = ApplyPaintDrop(points[j], 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;
|
|
|
|
|
var minDist = size / segments * distanceMinMax.x;
|
|
|
|
|
var maxDist = size / segments * distanceMinMax.y;
|
|
|
|
|
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());
|
|
|
|
|
for (int i = 0; i < points.Count; ++i)
|
|
|
|
|
{
|
|
|
|
|
var p1 = points[i];
|
|
|
|
|
var p2 = points[(i + 1) % points.Count];
|
|
|
|
|
var dist = (p1 - p2).magnitude;
|
|
|
|
|
var t = Mathf.Clamp01((dist - minDist) / (maxDist - minDist));
|
|
|
|
|
var c = Color.Lerp(Color.cyan, Color.magenta, t);
|
|
|
|
|
using var lc = new Handles.DrawingScope(c);
|
|
|
|
|
Handles.DrawLine(p1, p2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|