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 { /// /// 射线检测点列表 /// private RaycastHit[] hits; /// /// 编辑模式下地板状态 /// private Dictionary dicEditCellState; /// /// 修改过的地板颜色集合 /// private HashSet setCellDrag; /// /// 当前拖动的建筑单位 /// private BuildingCampUnit buildingCampUnit; /// /// 是否拖动状态 /// private bool isDrag; /// /// 编辑模式下未保存的营地单位集合 /// public HashSet SetEditUnit { get; private set; } /// /// 编辑状态 /// public bool IsEdit { get; private set; } /// /// 是否拖动状态 /// public bool IsDrag { get; private set; } private void InitEdit() { hits = new RaycastHit[1]; dicEditCellState = new Dictionary(); SetEditUnit = new HashSet(); setCellDrag = new HashSet(); IsEdit = false; } /// /// 进入编辑模式 /// 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(); } /// /// 退出编辑模式 /// 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; } /// /// 进入拖动状态 /// 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(); } /// /// 保存单位 /// 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); } /// /// 移除未保存的营地单位 /// 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(); } /// /// 编辑模式下点击 /// /// 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 私有方法 /// /// 清除拖动的格子 /// private void ClearDragCell() { foreach (Cell cell in setCellDrag) { if (dicEditCellState.TryGetValue(cell.index, out E_CampCellState cellState)) SetCellColorByCellState(cell, cellState); } setCellDrag.Clear(); } /// /// 设置拖动建筑影响的格子 /// 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)); } } } /// /// 设置拖动状态的颜色 /// /// 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); } /// /// 编辑检查能否放置 /// /// 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; } /// /// 编辑下放置营地物件 /// /// /// 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 } }