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

376 lines
12 KiB
C#

using cfg.CampCfg;
using Framework;
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<Cell> setCellDrag;
/// <summary>
/// 当前拖动的建筑单位
/// </summary>
private BuildingCampUnit buildingCampUnit;
/// <summary>
/// 是否拖动状态
/// </summary>
private bool isDrag;
/// <summary>
/// 编辑模式下未保存的营地单位集合
/// </summary>
public HashSet<CampUnitBase> SetEditUnit { get; private set; }
/// <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 dicCellState)
{
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();
IsDrag = false;
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>
public void SaveCampUnit(CampUnitBase campUnitBase)
{
if (campUnitBase is not BuildingCampUnit buildingUnit)
return;
if (!SetEditUnit.Remove(campUnitBase))
return;
setUnit.Remove(campUnitBase);
EventManager.Instance.Send(EventManager.EventName.Camp_EditRemoveUnit);
// TODO 向服务器发送保存数据
PlaceCampItem(buildingUnit);
}
/// <summary>
/// 移除未保存的营地单位
/// </summary>
public void RemoveCampUnit(CampUnitBase campUnitBase)
{
if (campUnitBase is not BuildingCampUnit buildingUnit)
return;
if (!SetEditUnit.Remove(campUnitBase))
return;
setUnit.Remove(campUnitBase);
EventManager.Instance.Send(EventManager.EventName.Camp_EditRemoveUnit);
#region 设置编辑模式营地地板状态
if (!dicCellByIndex.TryGetValue(buildingUnit.CellIndex, out Cell centerCell))
return;
foreach (Vector2 offset in buildingUnit.Cfg.ListPosOffset)
{
Vector2Int gridPos = GetCellPosByOffset(new Vector2Int(centerCell.row, centerCell.column), offset); // 计算格子位置
if (!dicCellByRowCol.TryGetValue(gridPos, out Cell cell))
continue;
dicEditCellState[cell.index] = E_CampCellState.Empty;
dicCellState[cell.index] = E_CampCellState.Empty;
SetCellColorByCellState(cell, E_CampCellState.Empty);
}
#endregion
campUnitBase.Dispose();
}
/// <summary>
/// 编辑模式下点击
/// </summary>
/// <param name="screenPos"></param>
public void OnEditClick(Vector2 screenPos)
{
int cellIndex = GroundHitHelper.CalcHitCellIndex(screenPos, GridSystem);
if (!TryGetPlaceUnit(cellIndex, out CampUnitBase campUnit))
return;
if (campUnit is not BuildingCampUnit buildingCampUnit)
return;
// TODO 已放置保存建筑转到未保存状态
#region 还原营地地板为空状态
if (!dicCellByIndex.TryGetValue(buildingCampUnit.CellIndex, out Cell centerCell))
return;
foreach (Vector2 offset in buildingCampUnit.Cfg.ListPosOffset)
{
Vector2Int gridPos = GetCellPosByOffset(new Vector2Int(centerCell.row, centerCell.column), offset); // 计算格子位置
if (!dicCellByRowCol.TryGetValue(gridPos, out Cell cell))
continue;
dicCellState[cell.index] = E_CampCellState.Empty;
dicUnit.Remove(cell.index);
}
#endregion
SetEditUnit.Add(campUnit);
EventManager.Instance.Send(EventManager.EventName.Camp_EditPlaceUnit);
}
#region 私有方法
/// <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 = GetCellPosByOffset(new Vector2Int(centerCell.row, centerCell.column), offset);
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 = GetCellPosByOffset(new Vector2Int(centerCell.row, centerCell.column), offset); // 计算格子位置
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 = GetCellPosByOffset(new Vector2Int(centerCell.row, centerCell.column), offset); // 计算格子位置
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);
EventManager.Instance.Send(EventManager.EventName.Camp_EditPlaceUnit);
}
#endregion
}
}