2017-04-12 01:23:07 +09:00

216 lines
4.5 KiB
C#

using UnityEngine;
using System.Collections.Generic;
[ExecuteInEditMode]
[AddComponentMenu("Destructible 2D/D2D Edge Colliders")]
public class D2D_EdgeColliders : D2D_Collider
{
[System.Serializable]
public class Cell
{
public List<EdgeCollider2D> EdgeCollider2Ds = new List<EdgeCollider2D>();
public void Destroy()
{
foreach (var edgeCollider2D in EdgeCollider2Ds)
{
D2D_Helper.Destroy(edgeCollider2D);
}
EdgeCollider2Ds.Clear();
}
public void ReplaceColliders(List<EdgeCollider2D> newEdgeCollider2Ds)
{
Destroy();
EdgeCollider2Ds.AddRange(newEdgeCollider2Ds);
}
public void UpdateColliderSettings(bool isTrigger, PhysicsMaterial2D material)
{
foreach (var edgeCollider2D in EdgeCollider2Ds)
{
if (edgeCollider2D != null)
{
edgeCollider2D.isTrigger = isTrigger;
edgeCollider2D.sharedMaterial = material;
}
}
}
}
[D2D_PopupAttribute(8, 16, 32, 64, 128, 256)]
public int CellSize = 64;
[D2D_RangeAttribute(0.0f, 0.3f)]
public float Tolerance = 0.01f;
[SerializeField]
private List<Cell> cells = new List<Cell>();
[SerializeField]
private int cellsX;
[SerializeField]
private int cellsY;
[SerializeField]
private int cellsXY;
[SerializeField]
private int width;
[SerializeField]
private int height;
public void RebuildAllColliders(Texture2D alphaTex)
{
if (alphaTex != null)
{
RebuildColliders(alphaTex, 0, alphaTex.width, 0, alphaTex.height);
}
else
{
DestroyAllCells();
}
}
public void RebuildColliders(Texture2D alphaTex, int xMin, int xMax, int yMin, int yMax)
{
UpdateColliders(alphaTex);
if (cells.Count > 0)
{
//var stopwatch = System.Diagnostics.Stopwatch.StartNew();
xMin = Mathf.Clamp(xMin - 1, 0, alphaTex.width - 1);
yMin = Mathf.Clamp(yMin - 1, 0, alphaTex.height - 1);
var cellXMin = xMin / CellSize;
var cellYMin = yMin / CellSize;
var cellXMax = (xMax + CellSize - 1) / CellSize;
var cellYMax = (yMax + CellSize - 1) / CellSize;
for (var cellY = cellYMin; cellY <= cellYMax; cellY++)
{
for (var cellX = cellXMin; cellX <= cellXMax; cellX++)
{
if (cellX >= 0 && cellX < cellsX && cellY >= 0 && cellY < cellsY)
{
xMin = CellSize * cellX;
yMin = CellSize * cellY;
xMax = Mathf.Min(CellSize + xMin, alphaTex.width);
yMax = Mathf.Min(CellSize + yMin, alphaTex.height);
var cell = cells[cellX + cellY * cellsX];
var newEdgeCollider2Ds = D2D_EdgeCalculator.Generate(gameObject, alphaTex, xMin, xMax, yMin, yMax, Tolerance);
cell.ReplaceColliders(newEdgeCollider2Ds);
cell.UpdateColliderSettings(IsTrigger, Material);
}
}
}
//stopwatch.Stop(); Debug.Log("RebuildColliders took " + stopwatch.ElapsedMilliseconds + " ms");
}
}
public override void UpdateColliderSettings()
{
foreach (var cell in cells)
{
if (cell != null)
{
cell.UpdateColliderSettings(IsTrigger, Material);
}
}
}
private void UpdateColliders(Texture2D alphaTex)
{
if (alphaTex != null && alphaTex.width > 0 && alphaTex.height > 0 && CellSize > 0 && Tolerance >= 0.0f)
{
cellsX = (alphaTex.width + CellSize - 1) / CellSize;
cellsY = (alphaTex.height + CellSize - 1) / CellSize;
cellsXY = cellsX * cellsY;
if (cells.Count > 0)
{
if (cells.Count != cellsXY)
{
DestroyAllCells();
}
if (alphaTex.width != width || alphaTex.height != height)
{
DestroyAllCells();
}
}
// Rebuild all cells?
if (cells.Count == 0 && cellsXY > 0)
{
width = alphaTex.width;
height = alphaTex.height;
for (var i = 0; i < cellsXY; i++)
{
cells.Add(new Cell());
}
}
}
else
{
DestroyAllCells();
}
}
protected virtual void OnDestroy()
{
D2D_Helper.DestroyManaged(DestroyAllCells);
}
protected override void RebuildAll()
{
var destructible = D2D_Helper.GetComponentUpwards<D2D_Destructible>(transform);
if (destructible != null)
{
RebuildAllColliders(destructible.AlphaTex);
}
}
private void DestroyAllCells()
{
if (cells.Count > 0)
{
foreach (var cell in cells)
{
cell.Destroy();
}
cells.Clear();
}
}
#if UNITY_EDITOR
protected override void SetHideFlags(HideFlags hideFlags)
{
foreach (var cell in cells)
{
foreach (var edgeCollider2D in cell.EdgeCollider2Ds)
{
if (edgeCollider2D != null)
{
edgeCollider2D.hideFlags = hideFlags;
}
}
}
}
#else
protected override void SetHideFlags(HideFlags hideFlags)
{
}
#endif
}