Files
Main/Assets/Plugins/Code/UniScene/PathGrid/Define/DynamicBlock.cs
2025-01-25 04:38:09 +08:00

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;
}
}
}