using System.Collections.Generic;
using UnityEngine;
namespace AibisDream
{
///
/// 网格可视化组件
/// 负责在Unity场景中可视化显示网格和单元格状态
///
public class GridVisualizer : MonoBehaviour
{
[Header("网格配置")]
[SerializeField] private BlockPuzzleGrid gridComponent;
[SerializeField] private int gridWidth = 10;
[SerializeField] private int gridHeight = 10;
[SerializeField] private float cellSize = 1f;
private IBlockPuzzleGrid _grid;
[Header("可视化设置")]
[SerializeField] private bool showGridLines = true;
[SerializeField] private bool showCellSprites = true;
[SerializeField] private Color emptyCellColor = new Color(0.9f, 0.9f, 0.9f, 0.3f);
[SerializeField] private Color occupiedCellColor = new Color(0.2f, 0.6f, 1f, 1f);
[SerializeField] private Color gridLineColor = new Color(0.5f, 0.5f, 0.5f, 0.5f);
[SerializeField] private float gridLineWidth = 0.02f;
[Header("预制体(可选)")]
[SerializeField] private Sprite cellSprite;
[SerializeField] private Material cellMaterial;
// 单元格可视化对象池
private Dictionary<(int x, int y), GameObject> _cellObjects = new Dictionary<(int x, int y), GameObject>();
private GameObject _gridLinesParent;
private GameObject _cellsParent;
private BlockPuzzleGrid _internalGrid;
private void Awake()
{
// 创建父对象用于组织层级
_gridLinesParent = new GameObject("GridLines");
_gridLinesParent.transform.SetParent(transform);
_gridLinesParent.transform.localPosition = Vector3.zero;
_cellsParent = new GameObject("Cells");
_cellsParent.transform.SetParent(transform);
_cellsParent.transform.localPosition = Vector3.zero;
}
private void Start()
{
InitializeGrid();
}
///
/// 初始化网格
///
public void InitializeGrid()
{
// 优先使用外部网格组件
if (gridComponent != null)
{
// 如果组件还没有初始化,先初始化它
if (!gridComponent.IsInitialized())
{
gridComponent.Initialize();
}
_grid = gridComponent;
}
else
{
// 如果没有外部网格,创建内部网格组件
if (_internalGrid == null)
{
_internalGrid = gameObject.GetComponent();
if (_internalGrid == null)
{
_internalGrid = gameObject.AddComponent();
}
}
_internalGrid.Initialize(gridWidth, gridHeight, cellSize, transform.position);
_grid = _internalGrid;
}
CreateVisualization();
}
///
/// 设置网格引用
///
public void SetGrid(IBlockPuzzleGrid grid)
{
_grid = grid;
ClearVisualization();
CreateVisualization();
}
///
/// 创建可视化
///
private void CreateVisualization()
{
if (_grid == null) return;
if (showGridLines)
{
DrawGridLines();
}
if (showCellSprites)
{
CreateCellSprites();
}
}
///
/// 绘制网格线
///
private void DrawGridLines()
{
// 清除旧的网格线
foreach (Transform child in _gridLinesParent.transform)
{
if (Application.isPlaying)
{
Destroy(child.gameObject);
}
else
{
DestroyImmediate(child.gameObject);
}
}
// 创建网格线(使用LineRenderer或简单的Quad)
for (int x = 0; x <= _grid.Width; x++)
{
CreateLine(
_grid.GridToWorld(x, 0),
_grid.GridToWorld(x, _grid.Height),
gridLineWidth,
gridLineColor
);
}
for (int y = 0; y <= _grid.Height; y++)
{
CreateLine(
_grid.GridToWorld(0, y),
_grid.GridToWorld(_grid.Width, y),
gridLineWidth,
gridLineColor
);
}
}
///
/// 创建一条线
///
private void CreateLine(Vector3 start, Vector3 end, float width, Color color)
{
GameObject lineObj = new GameObject("GridLine");
lineObj.transform.SetParent(_gridLinesParent.transform);
lineObj.transform.localPosition = Vector3.zero;
LineRenderer lineRenderer = lineObj.AddComponent();
lineRenderer.useWorldSpace = true;
lineRenderer.positionCount = 2;
lineRenderer.SetPosition(0, start);
lineRenderer.SetPosition(1, end);
lineRenderer.startWidth = width;
lineRenderer.endWidth = width;
lineRenderer.material = new Material(Shader.Find("Sprites/Default"));
lineRenderer.startColor = color;
lineRenderer.endColor = color;
lineRenderer.sortingOrder = 0;
}
///
/// 创建单元格精灵
///
private void CreateCellSprites()
{
// 清除旧的单元格
ClearCellSprites();
// 为每个单元格创建可视化对象
for (int x = 0; x < _grid.Width; x++)
{
for (int y = 0; y < _grid.Height; y++)
{
CreateCellSprite(x, y);
}
}
}
///
/// 创建单个单元格精灵
///
private void CreateCellSprite(int x, int y)
{
GameObject cellObj = new GameObject($"Cell_{x}_{y}");
cellObj.transform.SetParent(_cellsParent.transform);
cellObj.transform.position = _grid.GridToWorld(x, y);
SpriteRenderer spriteRenderer = cellObj.AddComponent();
// 如果没有指定Sprite,创建一个简单的白色Sprite
if (cellSprite == null)
{
cellSprite = CreateDefaultSprite();
}
spriteRenderer.sprite = cellSprite;
spriteRenderer.color = emptyCellColor;
spriteRenderer.sortingOrder = 1;
// 设置大小
float spriteSize = _grid.CellSize * 0.9f; // 稍微小一点,留出网格线空间
cellObj.transform.localScale = new Vector3(spriteSize, spriteSize, 1f);
// 如果有材质,应用材质
if (cellMaterial != null)
{
spriteRenderer.material = cellMaterial;
}
_cellObjects[(x, y)] = cellObj;
}
///
/// 创建默认的白色Sprite
///
private Sprite CreateDefaultSprite()
{
Texture2D texture = new Texture2D(1, 1);
texture.SetPixel(0, 0, Color.white);
texture.Apply();
return Sprite.Create(texture, new Rect(0, 0, 1, 1), new Vector2(0.5f, 0.5f), 1f);
}
///
/// 更新单元格可视化状态
///
public void UpdateCellVisual(int x, int y)
{
if (!_cellObjects.TryGetValue((x, y), out GameObject cellObj))
{
return;
}
SpriteRenderer spriteRenderer = cellObj.GetComponent();
if (spriteRenderer == null) return;
GridCellState state = _grid.GetCellState(x, y);
spriteRenderer.color = state == GridCellState.Occupied ? occupiedCellColor : emptyCellColor;
}
///
/// 更新所有单元格可视化
///
public void UpdateAllCellsVisual()
{
if (_grid == null) return;
for (int x = 0; x < _grid.Width; x++)
{
for (int y = 0; y < _grid.Height; y++)
{
UpdateCellVisual(x, y);
}
}
}
///
/// 清除单元格精灵
///
private void ClearCellSprites()
{
foreach (var kvp in _cellObjects)
{
if (Application.isPlaying)
{
Destroy(kvp.Value);
}
else
{
DestroyImmediate(kvp.Value);
}
}
_cellObjects.Clear();
}
///
/// 清除所有可视化
///
private void ClearVisualization()
{
ClearCellSprites();
foreach (Transform child in _gridLinesParent.transform)
{
if (Application.isPlaying)
{
Destroy(child.gameObject);
}
else
{
DestroyImmediate(child.gameObject);
}
}
}
private void OnDestroy()
{
ClearVisualization();
}
// 在编辑器中预览网格
private void OnDrawGizmos()
{
if (_grid == null) return;
// 绘制网格边界
Gizmos.color = gridLineColor;
Vector3 bottomLeft = _grid.GridToWorld(0, 0);
Vector3 bottomRight = _grid.GridToWorld(_grid.Width, 0);
Vector3 topLeft = _grid.GridToWorld(0, _grid.Height);
Vector3 topRight = _grid.GridToWorld(_grid.Width, _grid.Height);
Gizmos.DrawLine(bottomLeft, bottomRight);
Gizmos.DrawLine(bottomRight, topRight);
Gizmos.DrawLine(topRight, topLeft);
Gizmos.DrawLine(topLeft, bottomLeft);
}
}
}