NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Gameplay/Camp/Camp.Edit.cs

278 lines
8.2 KiB
C#

using cfg.CampCfg;
using Gameplay.Building.Impl;
using PhxhSDK;
using System.Collections.Generic;
using TGS;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Rendering;
namespace Gameplay.Camp
{
public sealed partial class Camp
{
/// <summary>
/// 射线检测点列表
/// </summary>
private RaycastHit[] hits;
/// <summary>
/// 编辑模式下地板状态
/// </summary>
private Dictionary<int, E_CampCellState> dicEditCellState;
/// <summary>
/// 编辑模式下未保存的营地单位集合
/// </summary>
private HashSet<CampUnitBase> setEditUnit;
/// <summary>
/// 修改过的地板颜色集合
/// </summary>
private HashSet<Cell> setCellDrag;
/// <summary>
/// 当前拖动的建筑单位
/// </summary>
private BuildingCampUnit buildingCampUnit;
/// <summary>
/// 编辑状态
/// </summary>
public bool IsEdit { get; private set; }
/// <summary>
/// 是否拖动状态
/// </summary>
public bool IsDrag { get; private set; }
private void InitEdit()
{
hits = new RaycastHit[1];
dicEditCellState = new Dictionary<int, E_CampCellState>();
setEditUnit = new HashSet<CampUnitBase>();
setCellDrag = new HashSet<Cell>();
IsEdit = false;
}
/// <summary>
/// 进入编辑模式
/// </summary>
public void SetInfoByEdit()
{
setCellDrag.Clear();
foreach (var kv in dicCellStateByIndex)
{
dicEditCellState[kv.Key] = kv.Value;
}
#region 设置格子颜色
foreach (Cell cell in GridSystem.cells)
{
if (!TryGetCellStateByIndex(cell.index, out E_CampCellState cellState))
continue;
SetCellColorByCellState(cell, cellState);
}
#endregion
IsShowAllGrid = true;
IsEdit = true;
}
public void UpdateEdit()
{
if (!IsDrag)
return;
ClearDragCell(); // 还原拖动的格子
SetDragCell();
}
/// <summary>
/// 退出编辑模式
/// </summary>
public void ExitEdit()
{
if (!IsEdit)
return;
IsShowAllGrid = false;
dicEditCellState.Clear();
foreach (CampUnitBase unit in setEditUnit)
{
unit.Dispose();
}
setEditUnit.Clear();
if (null != buildingCampUnit)
{
buildingCampUnit.Dispose();
buildingCampUnit = null;
}
setCellDrag.Clear();
IsEdit = false;
}
/// <summary>
/// 进入拖动状态
/// </summary>
public async void EnterDrag(DataCampObject dataCampObject)
{
if (IsDrag)
return;
GameObject goCampObject = await LoadCampObject(dataCampObject.Path);
buildingCampUnit = new(goCampObject, dataCampObject);
IsDrag = true;
}
public void ExitDrag()
{
if (!IsDrag)
return;
IsDrag = false;
if (!EditCheckPlace(buildingCampUnit.CellIndex, buildingCampUnit.Cfg.ListPosOffset))
{
UITipsManager.ShowTips("该位置不能放置");
buildingCampUnit.Dispose();
}
else
EditPlaceCampItem();
buildingCampUnit = null;
ClearDragCell();
}
/// <summary>
/// 清除拖动的格子
/// </summary>
private void ClearDragCell()
{
foreach (Cell cell in setCellDrag)
{
if (dicEditCellState.TryGetValue(cell.index, out E_CampCellState cellState))
SetCellColorByCellState(cell, cellState);
}
setCellDrag.Clear();
}
/// <summary>
/// 设置拖动建筑影响的格子
/// </summary>
private void SetDragCell()
{
Vector2 mousePos = Mouse.current.position.ReadValue();
// 发射射线
Ray ray = CameraManager.Instance.MainCamera.ScreenPointToRay(mousePos);
int hitNum = Physics.RaycastNonAlloc(ray.origin, ray.direction, hits);
if (hitNum <= 0)
return;
RaycastHit firstHit = hits[0];
Cell centerCell = GridSystem.CellGetAtPosition(firstHit.point, true); // 中心点
if (null == centerCell)
{
buildingCampUnit.CellIndex = -1;
buildingCampUnit.SetPos(new Vector3(firstHit.point.x, 0f, firstHit.point.z));
return;
}
foreach (Vector2 offset in buildingCampUnit.Cfg.ListPosOffset)
{
Vector2Int newPosInt = new(centerCell.row + (int)offset.x, centerCell.column + (int)offset.y);
if (!TryGetCellByRowCol(newPosInt, out Cell cell))
continue;
setCellDrag.Add(cell);
SetDragStateColor(cell);
if (Vector2Int.zero == offset)
{
buildingCampUnit.CellIndex = cell.index;
Vector3 pos = GridSystem.CellGetPosition(cell);
buildingCampUnit.SetPos(new Vector3(pos.x, 0f, pos.z));
}
}
}
/// <summary>
/// 设置拖动状态的颜色
/// </summary>
/// <param name="cell"></param>
private void SetDragStateColor(Cell cell)
{
if (!dicEditCellState.TryGetValue(cell.index, out E_CampCellState cellState))
return;
E_CampCellState tempState = cellState switch
{
E_CampCellState.Empty => E_CampCellState.Valid,
E_CampCellState.Occupancy => E_CampCellState.Invalid,
_ => throw new System.NotImplementedException(),
};
SetCellColorByCellState(cell, tempState);
}
/// <summary>
/// 编辑检查能否放置
/// </summary>
/// <returns></returns>
private bool EditCheckPlace(int cellIndex, params Vector2[] offsets)
{
if (!TryGetCellByIndex(cellIndex, out Cell centerCell))
return false;
foreach (Vector2 offset in offsets)
{
Vector2Int cellPos = new(centerCell.row + (int)offset.x, centerCell.column + (int)offset.y); // 计算格子位置
if (!dicCellByRowCol.TryGetValue(cellPos, out Cell cell))
return false;
if (!dicEditCellState.TryGetValue(cell.index, out E_CampCellState cellState))
return false;
if (E_CampCellState.Empty != cellState)
return false;
}
return true;
}
/// <summary>
/// 编辑下放置营地物件
/// </summary>
/// <param name="goCampObject"></param>
/// <param name="gridIndex"></param>
private void EditPlaceCampItem()
{
#region 设置营地地板状态
if (!dicCellByIndex.TryGetValue(buildingCampUnit.CellIndex, out Cell centerCell))
return;
foreach (Vector2 offset in buildingCampUnit.Cfg.ListPosOffset)
{
Vector2Int gridPos = new(centerCell.row + (int)offset.x, centerCell.column + (int)offset.y); // 计算格子位置
if (!dicCellByRowCol.TryGetValue(gridPos, out Cell cell))
continue;
if (dicEditCellState.ContainsKey(cell.index))
dicEditCellState[cell.index] = E_CampCellState.Occupancy;
}
#endregion
Vector3 pos = GridSystem.CellGetPosition(centerCell.index);
buildingCampUnit.SetPos(new Vector3(pos.x, 0f, pos.z)); // 设置建筑物位置
setEditUnit.Add(buildingCampUnit);
}
}
}