329 lines
11 KiB
C#
329 lines
11 KiB
C#
using Thousandto.Core.Base;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
|
|
using System.Text;
|
|
using UnityEngine;
|
|
using PathEditor.Proxy.Plugin;
|
|
|
|
namespace Thousandto.Plugins.PathGrid
|
|
{
|
|
public enum DyBlockType
|
|
{
|
|
None = 0,
|
|
Circle,
|
|
AABB,
|
|
OBB,
|
|
}
|
|
|
|
public abstract class DynamicBlock
|
|
{
|
|
internal struct BlockInfo
|
|
{
|
|
public int cellIndex;
|
|
public bool block;
|
|
public BlockInfo(int _cellIndex, bool _block)
|
|
{
|
|
cellIndex = _cellIndex;
|
|
block = _block;
|
|
}
|
|
}
|
|
public abstract List<int> GetConverCells(PathGirdData grid);
|
|
protected DyBlockType m_type = DyBlockType.None;
|
|
}
|
|
|
|
public class Circle : DynamicBlock
|
|
{
|
|
Vector2 m_center;
|
|
float m_radius;
|
|
public Circle(Vector2 center, float radius)
|
|
{
|
|
m_center = center;
|
|
m_radius = radius;
|
|
m_type = DyBlockType.Circle;
|
|
}
|
|
public override List<int> GetConverCells(PathGirdData grid)
|
|
{
|
|
var ret = new List<int>();
|
|
var _center = m_center - MathLib.ToVector2_XOZ(ref grid.Position);
|
|
var _startY = _center.y - m_radius;
|
|
var _endY = _center.y + m_radius;
|
|
var _startX = _center.x - m_radius;
|
|
var _endX = _center.x + m_radius;
|
|
var radSq = m_radius * m_radius;
|
|
var cellSize = grid.CellSize;
|
|
var halfCellSize = Vector2.one * cellSize * 0.5f;
|
|
var startY = (int)(_startY * grid.RecipCellSize) - 1;
|
|
var endY = (int)(_endY * grid.RecipCellSize) + 1;
|
|
var startX = (int)(_startX * grid.RecipCellSize) - 1;
|
|
var endX = (int)(_endX * grid.RecipCellSize) + 1;
|
|
var curPos = Vector2.zero;
|
|
for (var j = startY; j <= endY; ++j)
|
|
{
|
|
curPos.y = halfCellSize.y + j * cellSize;
|
|
for (var i = startX; i <= endX; ++i)
|
|
{
|
|
curPos.x = halfCellSize.x + i * cellSize;
|
|
var id = grid.GetCellID(i, j);
|
|
if (id != -1)
|
|
{
|
|
// valid check
|
|
if (MathLib.GetDistanceSq(ref curPos, ref _center) <= radSq)
|
|
{
|
|
ret.Add(id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
public class AABB : DynamicBlock
|
|
{
|
|
Vector2 m_center;
|
|
Vector2 m_halfSize;
|
|
public AABB(Vector2 center, Vector2 size)
|
|
{
|
|
m_center = center;
|
|
m_halfSize = size * 0.5f;
|
|
m_type = DyBlockType.AABB;
|
|
}
|
|
public override List<int> GetConverCells(PathGirdData grid)
|
|
{
|
|
var ret = new List<int>();
|
|
var _center = m_center - MathLib.ToVector2_XOZ(ref grid.Position);
|
|
var _startY = _center.y - m_halfSize.y;
|
|
var _endY = _center.y + m_halfSize.y;
|
|
var _startX = _center.x - m_halfSize.x;
|
|
var _endX = _center.x + m_halfSize.x;
|
|
var cellSize = grid.CellSize;
|
|
var halfCellSize = Vector2.one * cellSize * 0.5f;
|
|
var startY = (int)(_startY * grid.RecipCellSize) - 1;
|
|
var endY = (int)(_endY * grid.RecipCellSize) + 1;
|
|
var startX = (int)(_startX * grid.RecipCellSize) - 1;
|
|
var endX = (int)(_endX * grid.RecipCellSize) + 1;
|
|
var curPos = Vector2.zero;
|
|
var diff = Vector2.zero;
|
|
for (var j = startY; j <= endY; ++j)
|
|
{
|
|
curPos.y = halfCellSize.y + j * cellSize;
|
|
for (var i = startX; i <= endX; ++i)
|
|
{
|
|
curPos.x = halfCellSize.x + i * cellSize;
|
|
var id = grid.GetCellID(i, j);
|
|
if (id != -1)
|
|
{
|
|
diff = curPos - _center;
|
|
if (MathLib.FastAbs(diff.x) <= m_halfSize.x &&
|
|
MathLib.FastAbs(diff.y) <= m_halfSize.y)
|
|
{
|
|
ret.Add(id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
public class OBB : DynamicBlock
|
|
{
|
|
Vector2 m_center;
|
|
Vector2 m_direction;
|
|
Vector2 m_halfSize;
|
|
public OBB(Vector2 center, Vector2 size, Vector2 dir)
|
|
{
|
|
m_center = center;
|
|
m_halfSize = size * 0.5f;
|
|
m_type = DyBlockType.OBB;
|
|
m_direction = dir;
|
|
}
|
|
public override List<int> GetConverCells(PathGirdData grid)
|
|
{
|
|
var ret = new List<int>();
|
|
var _center = m_center - MathLib.ToVector2_XOZ(ref grid.Position);
|
|
var normal = new Vector2(m_direction.y, -m_direction.x);
|
|
var h = m_direction * m_halfSize.x;
|
|
var v = normal * m_halfSize.y;
|
|
var a = _center + h + v;
|
|
var b = _center + h - v;
|
|
var c = _center - h + v;
|
|
var d = _center - h - v;
|
|
var maxx = Math.Max(Math.Max(a.x, b.x), Math.Max(c.x, d.x));
|
|
var maxy = Math.Max(Math.Max(a.y, b.y), Math.Max(c.y, d.y));
|
|
var minx = Math.Min(Math.Min(a.x, b.x), Math.Min(c.x, d.x));
|
|
var miny = Math.Min(Math.Min(a.y, b.y), Math.Min(c.y, d.y));
|
|
var cellSize = grid.CellSize;
|
|
var halfCellSize = Vector2.one * cellSize * 0.5f;
|
|
var startY = (int)(miny * grid.RecipCellSize) - 1;
|
|
var endY = (int)(maxy * grid.RecipCellSize) + 1;
|
|
var startX = (int)(minx * grid.RecipCellSize) - 1;
|
|
var endX = (int)(maxx * grid.RecipCellSize) + 1;
|
|
var curPos = Vector2.zero;
|
|
var diff = Vector2.zero;
|
|
var transPos = Vector2.zero;
|
|
for (var j = startY; j <= endY; ++j)
|
|
{
|
|
curPos.y = halfCellSize.y + j * cellSize;
|
|
for (var i = startX; i <= endX; ++i)
|
|
{
|
|
curPos.x = halfCellSize.x + i * cellSize;
|
|
var id = grid.GetCellID(i, j);
|
|
if (id != -1)
|
|
{
|
|
diff = curPos - _center;
|
|
transPos.x = MathLib.VectorDot(ref diff, ref m_direction);
|
|
transPos.y = MathLib.VectorDot(ref diff, ref normal);
|
|
if (MathLib.FastAbs(transPos.x) <= m_halfSize.x &&
|
|
MathLib.FastAbs(transPos.y) <= m_halfSize.y)
|
|
{
|
|
ret.Add(id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
public class PathBlocker
|
|
{
|
|
enum State
|
|
{
|
|
Inactive,
|
|
Enabled,
|
|
Disabled,
|
|
}
|
|
public struct CellInfo
|
|
{
|
|
public int column;
|
|
public int row;
|
|
public PathGridType ori_type; // save the original block info for reverting
|
|
public CellInfo(int c, int r, PathGridType type)
|
|
{
|
|
column = c;
|
|
row = r;
|
|
ori_type = type;
|
|
}
|
|
}
|
|
|
|
int m_instId = 0;
|
|
PathGirdData m_grid = null;
|
|
DynamicBlock m_blockShape = null;
|
|
State m_state = State.Inactive;
|
|
List<CellInfo> m_fillInfo = null;
|
|
|
|
public static PathBlocker CreateAABB(PathGirdData grid, ref Vector2 center, ref Vector2 size, int instId = 0)
|
|
{
|
|
return new PathBlocker(grid, new AABB(center, size), instId);
|
|
}
|
|
|
|
public static PathBlocker CreateCircle(PathGirdData grid, ref Vector2 center, float radius, int instId = 0)
|
|
{
|
|
return new PathBlocker(grid, new Circle(center, radius), instId);
|
|
}
|
|
|
|
public static PathBlocker CreateOBB(PathGirdData grid, ref Vector2 center, ref Vector2 size, ref Vector2 dir, int instId = 0)
|
|
{
|
|
var _dir = dir;
|
|
_dir.Normalize();
|
|
return new PathBlocker(grid, new OBB(center, size, _dir), instId);
|
|
}
|
|
|
|
static int InstIDGen = 0;
|
|
|
|
static int GenId()
|
|
{
|
|
return ++InstIDGen;
|
|
}
|
|
|
|
PathBlocker(PathGirdData grid, DynamicBlock shape, int instId = 0)
|
|
{
|
|
if (m_instId >= 0)
|
|
{
|
|
m_instId = GenId();
|
|
}
|
|
m_grid = grid;
|
|
m_blockShape = shape;
|
|
var ids = m_blockShape.GetConverCells(grid);
|
|
m_fillInfo = new List<CellInfo>(ids.Count);
|
|
if (instId > 0)
|
|
{
|
|
for (int i = 0; i < ids.Count; ++i)
|
|
{
|
|
int c, r;
|
|
if (grid.GetCellCoord(ids[i], out c, out r))
|
|
{
|
|
m_fillInfo.Add(new CellInfo(c, r, grid.GetCellType(c, r)));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < ids.Count; ++i)
|
|
{
|
|
int c, r;
|
|
if (grid.GetCellCoord(ids[i], out c, out r))
|
|
{
|
|
m_fillInfo.Add(new CellInfo(c, r, PathGridType.None));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public int instId
|
|
{
|
|
get
|
|
{
|
|
return m_instId;
|
|
}
|
|
}
|
|
|
|
public List<CellInfo> GetFillCells()
|
|
{
|
|
var ids = m_blockShape.GetConverCells(m_grid);
|
|
var fillInfo = new List<CellInfo>(ids.Count);
|
|
for (int i = 0; i < ids.Count; ++i)
|
|
{
|
|
int c, r;
|
|
if (m_grid.GetCellCoord(ids[i], out c, out r))
|
|
{
|
|
fillInfo.Add(new CellInfo(c, r, PathGridType.None));
|
|
}
|
|
}
|
|
return fillInfo;
|
|
}
|
|
|
|
public bool Enable()
|
|
{
|
|
if (m_state != State.Enabled)
|
|
{
|
|
m_state = State.Enabled;
|
|
for (int i = 0; i < m_fillInfo.Count; ++i)
|
|
{
|
|
var info = m_fillInfo[i];
|
|
m_grid.SetBlock(info.column, info.row, PathGridType.UserBlock);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool Disable()
|
|
{
|
|
if (m_state == State.Enabled)
|
|
{
|
|
m_state = State.Disabled;
|
|
for (int i = 0; i < m_fillInfo.Count; ++i)
|
|
{
|
|
var info = m_fillInfo[i];
|
|
m_grid.SetBlock(info.column, info.row, info.ori_type);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
}
|