NLDClient-yudde/ProjectNLD/Assets/Editor/MapEditor/MapGridWindow.cs

1938 lines
63 KiB
C#
Raw Normal View History

2023-11-16 18:27:03 +08:00
using Gameplay;
using Sirenix.OdinInspector;
using Sirenix.OdinInspector.Editor;
using Sirenix.Utilities;
using Sirenix.Utilities.Editor;
using System;
using System.Collections;
using System.Collections.Generic;
using TGS;
using UnityEditor;
using UnityEngine;
using UnityEngine.InputSystem.EnhancedTouch;
using ObjectFieldAlignment = Sirenix.OdinInspector.ObjectFieldAlignment;
2023-11-16 18:27:03 +08:00
namespace MapEditor
{
public class MapGridWindow : OdinEditorWindow
{
#region Fields And Properties
2025-08-25 17:34:39 +08:00
private static MapGridWindow _thisWindow;
2025-06-25 14:45:41 +08:00
private static Dictionary<int, TerrainTypeProperty> _terrainTypeConfig;
2025-08-25 17:34:39 +08:00
private static Dictionary<int, LegionTerrainTypeProperty> _legionTerrainTypeConfig;
private MapData _currentMapData;
private MapManager _currMapManager;
private Map _map;
2025-08-25 17:34:39 +08:00
private bool _isLegionMap;
#endregion
#region 显示地图索引功能
[BoxGroup("显示地格索引")]
[LabelText("显示类型"), Indent]
[OnValueChanged("ShowCellIndex")]
[LabelWidth(100)]
[SerializeField]
private CellDebugInfo cellDebugInfo = CellDebugInfo.Nothing;
2025-08-27 19:39:34 +08:00
2025-08-25 17:34:39 +08:00
private void ShowCellIndex()
{
if (_map == null || _map.TerrainGridSystem == null) return;
_map.TerrainGridSystem.displayCellDebugInfo = cellDebugInfo;
var obj = FindObjectOfType<TerrainGridSystem>().gameObject;
Selection.activeGameObject = obj;
}
#endregion
#region 刷地块信息
[BoxGroup("地块信息")]
[LabelText("刷地块"), Indent]
[OnValueChanged("OnCanBrushTerrainTypeChanged")]
[LabelWidth(100)]
[SerializeField]
[ShowIf("@!canEditorArea")]
private bool canBrushTerrainType;
private void OnCanBrushTerrainTypeChanged()
{
if (canBrushTerrainType && _map != null)
{
canEditorArea = false;
ClearRegionColor();
}
}
[HorizontalGroup("地块信息/Territory")]
[ValueDropdown("GetTerrainTypeProperties")]
[Indent]
[LabelText("选择地块")]
[ShowIf("canBrushTerrainType")]
2025-08-25 17:34:39 +08:00
public int terrainTypeIndex = 0;
2025-08-25 17:34:39 +08:00
private IEnumerable GetTerrainTypeProperties()
{
2025-06-27 17:46:23 +08:00
ValueDropdownList<int> list = new();
2025-08-25 17:34:39 +08:00
if (!_isLegionMap)
foreach (var terrainTypeProperty in TerrainTypeConfig.DicTerrainTypePropertie.Values)
{
list.Add(terrainTypeProperty.name, terrainTypeProperty.id);
}
else
foreach (var legionTerrainTypeProperty in LegionTerrainTypeConfig.DicTerrainTypePropertie.Values)
{
list.Add(legionTerrainTypeProperty.name, legionTerrainTypeProperty.id);
}
return list;
}
[ShowIf("canBrushTerrainType")]
[HorizontalGroup("地块信息/Territory")]
[Button(SdfIconType.GearFill, "编辑地块")]
public void EditTerrainTypeConfig()
{
2025-08-25 17:34:39 +08:00
if (!_isLegionMap)
{
var window = GetWindow<TerrainTypeConfigWindow>();
window.Show();
}
else
{
var window = GetWindow<LegionTerrainTypeConfigWindow>();
window.Show();
}
}
2025-08-25 17:34:39 +08:00
private void SetCellBlockType(int cellIndex, int terrainTypeIndex)
{
2025-08-25 17:34:39 +08:00
if (!_isLegionMap)
2025-06-25 14:45:41 +08:00
{
2025-08-25 17:34:39 +08:00
if (!_terrainTypeConfig.TryGetValue(terrainTypeIndex, out TerrainTypeProperty terrainTypeProperty))
{
DebugUtil.LogError($"没有取到地格属性id:{terrainTypeIndex}");
return;
}
var map = _map;
// Key: terrainTypeIndex Value: tgs.territories.index
if (!map.TerrainTypeIndexDic.ContainsKey(terrainTypeIndex))
map.TerrainTypeIndexDic.Add(terrainTypeIndex, map.TerrainTypeIndexDic.Count);
2025-06-25 14:45:41 +08:00
2025-08-25 17:34:39 +08:00
map.TerrainGridSystem.CellSetBorderVisible(cellIndex, false);
map.SetTerrainType(cellIndex, terrainTypeIndex);
map.TerrainGridSystem.CellToggleRegionSurface(cellIndex, true, terrainTypeProperty.Color);
var buffPath = terrainTypeProperty.buffObjectPath;
if (!string.IsNullOrEmpty(buffPath))
AddBuffCell(cellIndex, buffPath);
Debug.Log(
$"设置地格: ({cellIndex}), 地格类型: ({terrainTypeIndex}), 名字: ({terrainTypeProperty.name})");
}
else
{
if (!_legionTerrainTypeConfig.TryGetValue(terrainTypeIndex, out var terrainTypeProperty))
{
DebugUtil.LogError($"没有取到军团地格属性id:{terrainTypeIndex}");
return;
}
2025-08-25 17:34:39 +08:00
var map = _map;
// Key: terrainTypeIndex Value: tgs.territories.index
if (!map.LegionTerrainTypeIndexDic.ContainsKey(terrainTypeIndex))
map.LegionTerrainTypeIndexDic.Add(terrainTypeIndex, map.LegionTerrainTypeIndexDic.Count);
2025-08-25 17:34:39 +08:00
map.TerrainGridSystem.CellSetBorderVisible(cellIndex, false);
map.SetTerrainType(cellIndex, terrainTypeIndex, true);
map.TerrainGridSystem.CellToggleRegionSurface(cellIndex, true, terrainTypeProperty.Color);
var buffPath = terrainTypeProperty.buffObjectPath;
if (!string.IsNullOrEmpty(buffPath))
{
AddBuffCell(cellIndex, buffPath);
}
2025-08-25 17:34:39 +08:00
Debug.Log(
$"设置军团地格: ({cellIndex}), 地格类型: ({terrainTypeIndex}), 名字: ({terrainTypeProperty.name})");
}
}
private void ClearCellBlockType(int cellIndex)
{
2025-08-25 17:34:39 +08:00
if (!_isLegionMap)
2025-06-25 14:45:41 +08:00
{
2025-08-25 17:34:39 +08:00
if (!_terrainTypeConfig.TryGetValue(terrainTypeIndex, out TerrainTypeProperty terrainTypeProperty))
{
DebugUtil.LogError($"没有取到地格属性,id:{terrainTypeIndex}");
return;
}
2025-06-25 14:45:41 +08:00
2025-08-25 17:34:39 +08:00
var map = _map;
map.TerrainGridSystem.CellSetBorderVisible(cellIndex, true);
map.TerrainGridSystem.CellHideRegionSurface(cellIndex);
2025-06-25 14:45:41 +08:00
2025-08-25 17:34:39 +08:00
_map.SetBlockColor(cellIndex, false, terrainTypeProperty.Color);
map.SetTerrainType(cellIndex, -1);
var buffPath = terrainTypeProperty.buffObjectPath;
if (!string.IsNullOrEmpty(buffPath))
{
RemoveBuffCell(cellIndex);
}
2025-06-25 14:45:41 +08:00
2025-08-25 17:34:39 +08:00
Debug.Log($"清除地格cellIndex: ({cellIndex})");
}
2025-08-25 17:34:39 +08:00
else
{
if (!_legionTerrainTypeConfig.TryGetValue(terrainTypeIndex, out var terrainTypeProperty))
{
DebugUtil.LogError($"没有取到军团地格属性,id:{terrainTypeIndex}");
return;
}
2025-08-25 17:34:39 +08:00
var map = _map;
map.TerrainGridSystem.CellSetBorderVisible(cellIndex, true);
map.TerrainGridSystem.CellHideRegionSurface(cellIndex);
_map.SetBlockColor(cellIndex, false, terrainTypeProperty.Color);
map.SetTerrainType(cellIndex, -1, true);
var buffPath = terrainTypeProperty.buffObjectPath;
if (!string.IsNullOrEmpty(buffPath))
{
RemoveBuffCell(cellIndex);
}
2025-08-25 17:34:39 +08:00
Debug.Log($"清除军团地格cellIndex: ({cellIndex})");
}
}
#region 地块指示物
private Dictionary<int, GameObject> _buffPrefabDic;
private GameObject buffRoot;
private void AddBuffCell(int cellIndex, string path)
{
// 阵地buff指示
if (!_buffPrefabDic.ContainsKey(cellIndex))
{
var buff = CreateBuffObj(cellIndex, path);
if (buff == null) return;
_buffPrefabDic.Add(cellIndex, buff);
2025-08-25 17:34:39 +08:00
/*var showBuffData = new MapData.ShowBuffData
_currentMapData.showBuffPoints.Add();*/
DebugUtil.Log("格子{0}添加指示图标,路径为{1}", cellIndex, path);
}
}
private void RemoveBuffCell(int cellIndex)
{
if (_buffPrefabDic.TryGetValue(cellIndex, out var buff))
{
if (buff != null)
{
DestroyImmediate(buff);
}
_buffPrefabDic.Remove(cellIndex);
DebugUtil.Log("格子{0}移除指示图标", cellIndex);
}
}
private GameObject CreateBuffObj(int cellIndex, string path)
{
var buffObj = AssetDatabase.LoadAssetAtPath<GameObject>(path);
if (buffObj == null)
{
DebugUtil.LogError($"{path} 路径下无Buff指示预制体 ");
return null;
}
if (buffRoot == null)
buffRoot = new GameObject("buffRoot");
var posV3 = _map.TGSCellIndex2WorldPosition(cellIndex);
var buff = Instantiate(buffObj, posV3, buffObj.transform.rotation, buffRoot.transform);
buff.SetActive(true);
return buff;
}
#endregion
#endregion
#region 地区信息
private static readonly Color regionColor = MapUtils.GetRGBAColor("FF960072");
private static bool canEditorSingleRegion = false;
private RegionArea _currEditRegionArea;
2023-11-19 14:01:26 +08:00
[Serializable]
2023-11-17 18:16:53 +08:00
public class RegionArea
{
2024-10-09 13:38:54 +08:00
[HorizontalGroup("1")] [ReadOnly] public int id;
2023-11-19 14:01:26 +08:00
2024-10-09 13:38:54 +08:00
[HorizontalGroup("1")] [ReadOnly] [LabelText("数量")]
2023-11-17 18:16:53 +08:00
public int regionCount;
2023-11-19 14:01:26 +08:00
2025-06-12 12:41:07 +08:00
[LabelText("备注"), HorizontalGroup("1")] [OnValueChanged("OnNoteValueChanged")]
public string note;
private void OnNoteValueChanged()
{
_region.note = note;
}
2023-11-19 14:01:26 +08:00
public List<int> positions => _region.positions;
private MapData.Region _region;
public RegionArea(MapData.Region region)
{
_region = region;
2025-06-12 12:41:07 +08:00
note = _region.note;
2023-11-19 14:01:26 +08:00
}
[Button("编辑"), HorizontalGroup("1")]
2023-11-17 18:16:53 +08:00
private void EditorRegion()
{
2025-08-25 17:34:39 +08:00
var map = _thisWindow._map;
_thisWindow._currEditRegionArea = this;
2023-11-19 14:01:26 +08:00
var regionslist = map.MapData.regions;
2023-11-17 18:16:53 +08:00
for (int i = 0; i < regionslist.Count; i++)
{
map.SetRegionColor(i, false, regionColor);
}
2023-11-19 14:01:26 +08:00
map.SetRegionColor(_region, true, regionColor);
2025-05-28 14:50:34 +08:00
canEditorSingleRegion = true;
2023-11-17 18:16:53 +08:00
}
2023-11-19 14:01:26 +08:00
2025-06-12 12:41:07 +08:00
2023-11-19 14:01:26 +08:00
public void AddPosition(int cellIndex)
{
if (positions.Contains(cellIndex))
return;
positions.Add(cellIndex);
regionCount++;
2025-08-25 17:34:39 +08:00
_thisWindow._map.TerrainGridSystem.CellToggleRegionSurface(cellIndex, true, regionColor);
2023-11-19 14:01:26 +08:00
}
public void RemovePosition(int cellIndex)
{
if (!positions.Contains(cellIndex))
return;
positions.Remove(cellIndex);
regionCount--;
2025-08-25 17:34:39 +08:00
_thisWindow._map.TerrainGridSystem.CellHideRegionSurface(cellIndex);
2023-11-19 14:01:26 +08:00
}
2023-11-17 18:16:53 +08:00
}
2023-11-16 18:27:03 +08:00
[BoxGroup("地区信息")]
[HorizontalGroup("地区信息/Region")]
[LabelText("编辑地区"), Indent]
2025-08-25 17:34:39 +08:00
[ShowIf("@!_isLegionMap")]
[OnValueChanged("OnCanEditorAreaTypeChanged")]
[LabelWidth(100)]
[SerializeField]
private bool canEditorArea;
private void OnCanEditorAreaTypeChanged()
{
if (canEditorArea)
{
canBrushTerrainType = false;
}
else
{
ClearRegionColor();
SceneView.RepaintAll();
canEditorSingleRegion = false;
2025-06-04 15:24:42 +08:00
_currEditRegionArea = null;
}
}
[LabelText("地区列表")]
2025-08-25 17:34:39 +08:00
[ShowIf("@!_isLegionMap&&canEditorArea")]
[VerticalGroup("地区信息/RegionInfo"), Indent]
[ListDrawerSettings(CustomAddFunction = "CustomAddRegion", CustomRemoveIndexFunction = "CustomRemoveRegion",
DraggableItems = false)]
public List<RegionArea> RegionList = new();
private void CustomAddRegion()
{
var region = new MapData.Region();
_currentMapData.regions.Add(region);
UpdateRegion();
}
private void CustomRemoveRegion(int index)
{
ClearRegionColor();
_currentMapData.regions.RemoveAt(index);
UpdateRegion();
}
private void UpdateRegion()
{
RegionList.Clear();
if (_currentMapData != null)
{
int index = 0;
foreach (var region in _currentMapData.regions)
{
RegionArea ra = new RegionArea(region);
ra.id = index;
ra.regionCount = ra.positions.Count;
RegionList.Add(ra);
index++;
}
}
}
private void ClearRegionColor()
{
if (_map == null)
return;
for (int i = 0; i < _map.MapData.regions.Count; i++)
{
_map.SetRegionColor(i, false, regionColor);
}
}
#endregion
/*#region 雷区
2025-11-17 19:30:14 +08:00
private static readonly Color MinesColor = MapUtils.GetRGBAColor("2D004CFF");
private static bool canEditorSingleMinesRegion;
private MinesRegionArea _currEditMinesRegionArea;
[Serializable]
public class MinesRegionArea
{
[HorizontalGroup("1")] [ReadOnly] public int id;
[HorizontalGroup("1")] [ReadOnly] [LabelText("数量")]
public int regionCount;
[LabelText("备注"), HorizontalGroup("1")] [OnValueChanged("OnNoteValueChanged")]
public string note;
private void OnNoteValueChanged()
{
_region.note = note;
}
public List<int> positions => _region.positions;
private MapData.Region _region;
public MinesRegionArea(MapData.Region region)
{
_region = region;
note = _region.note;
}
[Button("编辑"), HorizontalGroup("1")]
private void EditorRegion()
{
var map = _thisWindow._map;
_thisWindow._currEditMinesRegionArea = this;
var regionList = map.MapData.minesRegions;
foreach (var region in regionList)
{
map.SetBlocksColor(region.positions, false, MinesColor);
}
map.SetBlocksColor(_region.positions, true, MinesColor);
canEditorSingleMinesRegion = true;
}
public void AddPosition(int cellIndex)
{
if (positions.Contains(cellIndex))
return;
positions.Add(cellIndex);
regionCount++;
_thisWindow._map.TerrainGridSystem.CellToggleRegionSurface(cellIndex, true, MinesColor);
}
public void RemovePosition(int cellIndex)
{
if (!positions.Contains(cellIndex))
return;
positions.Remove(cellIndex);
regionCount--;
_thisWindow._map.TerrainGridSystem.CellHideRegionSurface(cellIndex);
}
}
[BoxGroup("雷区信息")]
[HorizontalGroup("雷区信息/Region")]
[LabelText("编辑雷区"), Indent]
[ShowIf("@!_isLegionMap")]
[OnValueChanged("OnCanEditorMinesAreaTypeChanged")]
[LabelWidth(100)]
[SerializeField]
private bool canEditorMinesArea;
private void OnCanEditorMinesAreaTypeChanged()
{
if (canEditorMinesArea)
{
canEditorArea = false;
canBrushTerrainType = false;
canEditorBlockArea = false;
canEditorDefenseArea = false;
canEditorSingleBlockRegion = false;
canEditorSingleDefenseRegion = false;
ClearDefenseRegionColor();
ClearBlockRegionColor();
ClearRegionColor();
}
else
{
ClearMinesRegionColor();
SceneView.RepaintAll();
canEditorSingleMinesRegion = false;
_currEditMinesRegionArea = null;
}
}
[LabelText("雷区列表")]
[ShowIf("@!_isLegionMap&&canEditorMinesArea")]
[VerticalGroup("雷区信息/RegionInfo"), Indent]
[ListDrawerSettings(CustomAddFunction = "CustomAddMinesRegion",
CustomRemoveIndexFunction = "CustomRemoveMinesRegion",
DraggableItems = false)]
public List<MinesRegionArea> minesRegionList = new();
private void CustomAddMinesRegion()
{
var region = new MapData.Region();
_currentMapData.minesRegions.Add(region);
UpdateMinesRegion();
}
private void CustomRemoveMinesRegion(int index)
{
ClearMinesRegionColor();
_currentMapData.minesRegions.RemoveAt(index);
UpdateMinesRegion();
}
private void UpdateMinesRegion()
{
minesRegionList.Clear();
if (_currentMapData != null)
{
var index = 0;
foreach (var region in _currentMapData.minesRegions)
{
MinesRegionArea ra = new MinesRegionArea(region)
{
id = index
};
ra.regionCount = ra.positions.Count;
minesRegionList.Add(ra);
index++;
}
}
}
private void ClearMinesRegionColor()
{
if (_map == null)
return;
foreach (var region in _map.MapData.minesRegions)
{
_map.SetBlocksColor(region.positions, false, MinesColor);
}
}
#endregion
#region 阻挡区信息
private static readonly Color BlockRegionColor = Color.blue;
private BlockRegionArea _currEditBlockRegion;
private static bool canEditorSingleBlockRegion = false;
private Dictionary<int, GameObject> _blockPrefabDic;
private GameObject blockRoot;
2025-05-28 14:50:34 +08:00
[Serializable]
public class BlockRegionArea
{
private const string BuffPrefabPath = "Art_Out/Other/BuffPoint";
2025-05-28 14:50:34 +08:00
[HorizontalGroup("1")] [ReadOnly] public int id;
[HorizontalGroup("1")] [ReadOnly] [LabelText("数量")]
public int regionCount;
2025-08-25 17:34:39 +08:00
2025-06-12 12:41:07 +08:00
[LabelText("备注"), HorizontalGroup("1")] [OnValueChanged("OnNoteValueChanged")]
public string note;
private void OnNoteValueChanged()
{
_region.note = note;
}
2025-05-28 14:50:34 +08:00
[Button("编辑"), HorizontalGroup("1")]
private void EditorRegion()
{
2025-08-25 17:34:39 +08:00
var map = _thisWindow._map;
_thisWindow._currEditBlockRegion = this;
2025-05-28 14:50:34 +08:00
var regionsList = map.MapData.blockRegions;
foreach (var blockRegion in regionsList)
2025-05-28 14:50:34 +08:00
{
map.SetBlocksColor(blockRegion.positions, false, BlockRegionColor);
2025-05-28 14:50:34 +08:00
}
map.SetBlocksColor(_region.positions, true, BlockRegionColor);
2025-05-28 14:50:34 +08:00
canEditorSingleBlockRegion = true;
}
[HorizontalGroup("3")]
[PreviewField(50, ObjectFieldAlignment.Center)]
[LabelText("指示预览图"), OnValueChanged("OnObjectValueChanged")]
[AssetList(Path = BuffPrefabPath)]
public GameObject buffObject;
private void OnObjectValueChanged()
{
if (buffObject != null)
{
_region.path = "Assets/" + BuffPrefabPath + "/" + buffObject.name + ".prefab";
}
}
[HorizontalGroup("2")] [LabelText("指示位置"), OnValueChanged("OnPosValueChanged")]
public Vector3 pos = Vector3.zero;
private void OnPosValueChanged()
{
_region.centerPos = pos;
if (obj != null)
{
obj.transform.position = pos;
}
}
[Button("添加至场景"), HorizontalGroup("3")]
[ShowIf("NeedAdd")]
private void AddToScene()
{
2025-08-25 17:34:39 +08:00
obj = _thisWindow.CreateBlockObj(_region.path, pos);
}
[Button("更换指示"), HorizontalGroup("3")]
[HideIf("NeedAdd")]
private void ChangeObj()
{
if (obj) DestroyImmediate(obj);
2025-08-25 17:34:39 +08:00
obj = _thisWindow.CreateBlockObj(_region.path, pos);
}
private bool NeedAdd => obj == null;
[HideInInspector] public GameObject obj;
public List<int> Positions => _region.positions;
[HideInInspector] public MapData.BlockRegion _region;
public BlockRegionArea(MapData.BlockRegion region)
{
_region = region;
pos = _region.centerPos;
2025-06-12 12:41:07 +08:00
note = _region.note;
if (!string.IsNullOrEmpty(region.path))
{
2025-08-25 17:34:39 +08:00
obj = _thisWindow.CreateBlockObj(_region.path, _region.centerPos);
buffObject = AssetDatabase.LoadAssetAtPath<GameObject>(_region.path);
}
}
2025-05-28 14:50:34 +08:00
public void AddPosition(int cellIndex)
{
if (Positions.Contains(cellIndex))
return;
Positions.Add(cellIndex);
DebugUtil.Log($"{id}阻挡区添加地格{cellIndex}");
regionCount++;
2025-08-25 17:34:39 +08:00
_thisWindow._map.TerrainGridSystem.CellToggleRegionSurface(cellIndex, true, BlockRegionColor);
2025-05-28 14:50:34 +08:00
}
public void RemovePosition(int cellIndex)
{
if (!Positions.Contains(cellIndex))
return;
Positions.Remove(cellIndex);
2025-05-28 14:50:34 +08:00
DebugUtil.Log($"{id}阻挡区移除地格{cellIndex}");
regionCount--;
2025-08-25 17:34:39 +08:00
_thisWindow._map.TerrainGridSystem.CellHideRegionSurface(cellIndex);
2025-05-28 14:50:34 +08:00
}
}
[BoxGroup("阻挡区信息")]
[HorizontalGroup("阻挡区信息/Region")]
2025-08-25 17:34:39 +08:00
[ShowIf("@!_isLegionMap")]
[LabelText("编辑阻挡区"), Indent]
[OnValueChanged("OnCanEditorBlockAreaChanged")]
[LabelWidth(100)]
[SerializeField]
private bool canEditorBlockArea;
2023-11-16 18:27:03 +08:00
private void OnCanEditorBlockAreaChanged()
{
if (canEditorBlockArea)
{
canEditorArea = false;
2025-11-17 19:30:14 +08:00
canEditorMinesArea = false;
canBrushTerrainType = false;
canEditorDefenseArea = false;
2025-06-04 15:24:42 +08:00
canEditorSingleRegion = false;
canEditorSingleDefenseRegion = false;
ClearDefenseRegionColor();
ClearRegionColor();
2025-11-17 19:30:14 +08:00
ClearMinesRegionColor();
}
else
{
ClearBlockRegionColor();
SceneView.RepaintAll();
2025-06-04 15:24:42 +08:00
_currEditBlockRegion = null;
canEditorSingleBlockRegion = false;
}
}
2023-11-16 18:27:03 +08:00
[LabelText("阻挡区列表")]
2025-08-25 17:34:39 +08:00
[ShowIf("@!_isLegionMap&&canEditorBlockArea")]
[VerticalGroup("阻挡区信息/RegionInfo"), Indent]
[ListDrawerSettings(CustomAddFunction = "CustomAddBlockRegion",
CustomRemoveIndexFunction = "CustomRemoveBlockRegionIndex",
DraggableItems = false)]
public List<BlockRegionArea> blockRegionList = new();
2023-11-16 18:27:03 +08:00
private void CustomAddBlockRegion()
{
var region = new MapData.BlockRegion();
_currentMapData.blockRegions.Add(region);
UpdateBlockRegion();
}
2023-11-16 18:27:03 +08:00
private void CustomRemoveBlockRegionIndex(int index)
{
if (index < blockRegionList.Count)
{
if (blockRegionList[index].obj != null)
{
DebugUtil.LogError($"删除{blockRegionList[index].id}的指示");
DestroyImmediate(blockRegionList[index].obj);
}
}
ClearBlockRegionColor();
_currentMapData.blockRegions.RemoveAt(index);
UpdateBlockRegion();
}
2023-11-19 14:01:26 +08:00
private void UpdateBlockRegion()
{
blockRegionList.Clear();
if (_currentMapData != null)
{
var index = 0;
foreach (var region in _currentMapData.blockRegions)
{
var blockRegion = new BlockRegionArea(region)
{
id = index,
regionCount = region.positions.Count,
};
2023-11-16 18:27:03 +08:00
blockRegionList.Add(blockRegion);
index++;
}
}
}
2023-11-19 14:01:26 +08:00
private void ClearBlockRegionColor()
{
if (_map == null)
return;
foreach (var blockRegion in _map.MapData.blockRegions)
{
_map.SetBlocksColor(blockRegion.positions, false, BlockRegionColor);
}
}
2023-11-16 18:27:03 +08:00
private GameObject CreateBlockObj(string path, Vector3 pos)
{
var blockObj = AssetDatabase.LoadAssetAtPath<GameObject>(path);
if (blockObj == null)
{
DebugUtil.LogError($"{path} 路径下无Block指示预制体 ");
return null;
}
if (blockRoot == null)
blockRoot = new GameObject("BlockRoot");
var obj = Instantiate(blockObj, pos, blockObj.transform.rotation, blockRoot.transform);
obj.SetActive(true);
return obj;
}
private void DestroyAllBlockObj()
{
if (blockRoot)
DestroyImmediate(blockRoot);
foreach (var blockRegion in blockRegionList)
{
if (blockRegion.obj)
DestroyImmediate(blockRegion.obj);
}
}
#endregion
2023-11-19 14:01:26 +08:00
2025-12-10 13:23:32 +08:00
#region 刷怪触发区
2025-05-28 14:50:34 +08:00
2025-06-04 15:24:42 +08:00
private static readonly Color DefenseRegionColor = Color.magenta;
2023-11-19 22:57:17 +08:00
private DefenseRegionArea _currEditDefenseRegion;
2023-11-19 14:01:26 +08:00
private static bool canEditorSingleDefenseRegion = false;
2024-10-09 13:38:54 +08:00
[Serializable]
public class DefenseRegionArea
{
[HorizontalGroup("1")] [ReadOnly] public int id;
2025-04-02 16:04:07 +08:00
[HorizontalGroup("1")] [ReadOnly] [LabelText("数量")]
public int regionCount;
2025-08-25 17:34:39 +08:00
2025-06-12 12:41:07 +08:00
[LabelText("备注"), HorizontalGroup("1")] [OnValueChanged("OnNoteValueChanged")]
public string note;
private void OnNoteValueChanged()
{
_region.note = note;
}
2023-11-16 18:27:03 +08:00
public List<int> Positions => _region.positions;
2023-11-16 18:27:03 +08:00
private MapData.Region _region;
2023-11-16 18:27:03 +08:00
public DefenseRegionArea(MapData.Region region)
2023-11-21 15:04:56 +08:00
{
_region = region;
2025-06-12 12:41:07 +08:00
note = _region.note;
2024-10-09 13:38:54 +08:00
}
[Button("编辑"), HorizontalGroup("1")]
private void EditorRegion()
{
2025-08-25 17:34:39 +08:00
var map = _thisWindow._map;
_thisWindow._currEditDefenseRegion = this;
var regionsList = map.MapData.defenseRegions;
foreach (var defenseRegion in regionsList)
{
map.SetBlocksColor(defenseRegion.positions, false, DefenseRegionColor);
}
2025-05-28 14:50:34 +08:00
map.SetBlocksColor(_region.positions, true, DefenseRegionColor);
canEditorSingleDefenseRegion = true;
}
2023-11-16 18:27:03 +08:00
public void AddPosition(int cellIndex)
2023-11-16 18:27:03 +08:00
{
if (Positions.Contains(cellIndex))
return;
Positions.Add(cellIndex);
DebugUtil.Log($"{id}防守区添加地格{cellIndex}");
regionCount++;
2025-08-25 17:34:39 +08:00
_thisWindow._map.TerrainGridSystem.CellToggleRegionSurface(cellIndex, true, DefenseRegionColor);
2023-11-16 18:27:03 +08:00
}
public void RemovePosition(int cellIndex)
{
if (!Positions.Contains(cellIndex))
return;
Positions.Remove(cellIndex);
2024-10-09 14:18:50 +08:00
DebugUtil.Log($"{id}防守区移除地格{cellIndex}");
regionCount--;
2025-08-25 17:34:39 +08:00
_thisWindow._map.TerrainGridSystem.CellHideRegionSurface(cellIndex);
}
}
2024-10-09 15:07:23 +08:00
2025-12-10 13:23:32 +08:00
[BoxGroup("刷怪触发区")]
[HorizontalGroup("刷怪触发区/Region")]
2025-08-25 17:34:39 +08:00
[ShowIf("@!_isLegionMap")]
2025-12-10 13:23:32 +08:00
[LabelText("编辑触发区"), Indent]
[OnValueChanged("OnCanEditorDefenseAreaChanged")]
2023-11-16 18:27:03 +08:00
[LabelWidth(100)]
[SerializeField]
private bool canEditorDefenseArea;
2023-11-16 18:27:03 +08:00
private void OnCanEditorDefenseAreaChanged()
2023-11-16 18:27:03 +08:00
{
if (canEditorDefenseArea)
2023-11-16 18:27:03 +08:00
{
2025-05-28 14:50:34 +08:00
canEditorBlockArea = false;
canEditorArea = false;
2025-11-17 19:30:14 +08:00
canEditorMinesArea = false;
canBrushTerrainType = false;
2025-06-04 15:24:42 +08:00
canEditorSingleRegion = false;
canEditorSingleBlockRegion = false;
ClearBlockRegionColor();
ClearRegionColor();
2025-11-17 19:30:14 +08:00
ClearMinesRegionColor();
2023-11-16 18:27:03 +08:00
}
else
{
ClearDefenseRegionColor();
2023-11-19 23:41:18 +08:00
SceneView.RepaintAll();
2025-06-04 15:24:42 +08:00
_currEditDefenseRegion = null;
canEditorSingleDefenseRegion = false;
2023-11-16 18:27:03 +08:00
}
}
2025-12-10 13:23:32 +08:00
[LabelText("刷怪触发区列表")]
2025-08-25 17:34:39 +08:00
[ShowIf("@!_isLegionMap&&canEditorDefenseArea")]
2025-12-10 13:23:32 +08:00
[VerticalGroup("刷怪触发区/RegionInfo"), Indent]
[ListDrawerSettings(CustomAddFunction = "CustomAddDefenseRegion",
CustomRemoveIndexFunction = "CustomRemoveDefenseRegion",
2023-11-19 22:57:17 +08:00
DraggableItems = false)]
public List<DefenseRegionArea> defenseRegionList = new();
2023-11-19 14:01:26 +08:00
private void CustomAddDefenseRegion()
2023-11-19 14:01:26 +08:00
{
var region = new MapData.Region();
_currentMapData.defenseRegions.Add(region);
UpdateDefenseRegion();
2023-11-19 14:01:26 +08:00
}
private void CustomRemoveDefenseRegion(int index)
2023-11-19 14:01:26 +08:00
{
ClearDefenseRegionColor();
_currentMapData.defenseRegions.RemoveAt(index);
UpdateDefenseRegion();
2023-11-19 14:01:26 +08:00
}
2023-11-16 18:27:03 +08:00
private void UpdateDefenseRegion()
2025-05-28 14:50:34 +08:00
{
defenseRegionList.Clear();
if (_currentMapData != null)
2025-05-28 14:50:34 +08:00
{
var index = 0;
foreach (var region in _currentMapData.defenseRegions)
{
var defenseRegion = new DefenseRegionArea(region)
{
id = index,
regionCount = region.positions.Count,
};
defenseRegionList.Add(defenseRegion);
index++;
}
2025-05-28 14:50:34 +08:00
}
}
private void ClearDefenseRegionColor()
{
if (_map == null)
return;
foreach (var defenseRegion in _map.MapData.defenseRegions)
2025-05-28 14:50:34 +08:00
{
_map.SetBlocksColor(defenseRegion.positions, false, DefenseRegionColor);
2025-05-28 14:50:34 +08:00
}
}
#endregion*/
2025-05-28 14:50:34 +08:00
2025-09-03 14:43:56 +08:00
#region 阻挡球编辑
/// <summary>
/// 球体根节点
/// </summary>
private GameObject blockSphereRoot;
/// <summary>
/// 已修改阻挡球字典
/// </summary>
private readonly Dictionary<int, MapData.BlockSphereInfo> blockSphereInfo = new();
/// <summary>
/// 被隐藏的物体列表,用于后续恢复显示
/// </summary>
private readonly List<GameObject> hideObjs = new List<GameObject>();
/// <summary>
/// 所有禁止攻击的格子
/// </summary>
private readonly List<int> banAttackCells = new();
/// <summary>
/// 标准六边形内接圆直径
/// </summary>
private static readonly float Calibre = 3f;
/// <summary>
/// 编辑时颜色
/// </summary>
private static readonly Color EditingSphereColor = Color.red;
/// <summary>
/// 已编辑过的数据颜色
/// </summary>
private static readonly Color ChangedSphereColor = Color.green;
[Serializable]
public class BlockSpereEditorInfo
{
[HideInInspector] public MapData.BlockSphereInfo blockSphereInfo;
#region 可视字段
[HorizontalGroup("1", 0.1f)] [LabelText("地格")] [LabelWidth(30)] [ReadOnly]
public int cellIndex;
[HorizontalGroup("1", 0.12f)]
[LabelText("缩放")]
[LabelWidth(30)]
[EnableIf("canEditor")]
[ShowIf("@isChanged||canEditor")]
[OnValueChanged("OnScaleValueChanged")]
public float scale = 1f;
[HorizontalGroup("1", 0.25f)]
[LabelText("偏移")]
[LabelWidth(30)]
[EnableIf("canEditor")]
[ShowIf("@isChanged||canEditor")]
[OnValueChanged("OnOffestValueChanged")]
public Vector2 offest;
[HorizontalGroup("1", 0.25f)]
[LabelText("备注")]
[LabelWidth(30)]
[EnableIf("canEditor")]
// [ShowIf("@isChanged||canEditor")]
[OnValueChanged("OnNoteValueChanged")]
public string note;
#endregion
#region 字段
/// <summary>
/// 可编辑
/// </summary>
[HideInInspector] public bool canEditor;
/// <summary>
/// 数据已经变化
/// </summary>
[HideInInspector] public bool isChanged;
/// <summary>
/// 阻挡球物体
/// </summary>
[HideInInspector] public GameObject sphere;
/// <summary>
/// 原始共享材质
/// </summary>
[HideInInspector] public Material originalSharedMaterial;
/// <summary>
/// 编辑时的临时材质
/// </summary>
[HideInInspector] public Material editingMaterial;
/// <summary>
/// 地格中心位置
/// </summary>
[HideInInspector] public Vector3 originalPos;
#endregion
#region 构造函数
public BlockSpereEditorInfo(int cellIndex, GameObject sphere)
{
var map = _thisWindow._map;
this.cellIndex = cellIndex;
blockSphereInfo = new MapData.BlockSphereInfo()
{
cellIndex = cellIndex,
};
originalPos = map.TGSCellIndex2WorldPosition(cellIndex);
if (sphere != null)
{
this.sphere = sphere;
SetSphereColor(Color.white);
}
isChanged = false;
}
public BlockSpereEditorInfo(MapData.BlockSphereInfo blockInfo, GameObject sphere)
{
var map = _thisWindow._map;
blockSphereInfo = new MapData.BlockSphereInfo
{
cellIndex = blockInfo.cellIndex,
scale = blockInfo.scale,
note = blockInfo.note,
offestPos = blockInfo.offestPos,
};
cellIndex = blockInfo.cellIndex;
originalPos = map.TGSCellIndex2WorldPosition(blockInfo.cellIndex);
offest = new Vector2(blockInfo.offestPos.x - originalPos.x, blockInfo.offestPos.z - originalPos.z);
scale = blockInfo.scale / Calibre;
if (sphere != null)
{
this.sphere = sphere;
}
UpdateChangedData();
}
#endregion
#region 按钮
[Button("恢复默认")]
[HorizontalGroup("1")]
[ShowIf("isChanged")]
public void Revert()
{
if (!isChanged) return;
isChanged = false;
if (sphere != null)
{
scale = 1f;
offest = new Vector2(0f, 0f);
blockSphereInfo.offestPos = originalPos;
blockSphereInfo.scale = Calibre;
sphere.transform.localScale = Vector3.one * Calibre;
sphere.transform.position = originalPos;
// 如果正在监听这个球体,更新监听的位置和缩放
if (_thisWindow.currentEditingSphere == this)
{
_thisWindow.lastPosition = originalPos;
_thisWindow.lastScale = Vector3.one * Calibre;
}
if (!canEditor)
{
SetSphereColor(Color.white);
}
}
}
[Button("编辑")]
[HorizontalGroup("1")]
[HideIf("canEditor")]
private void EditorBlockAttack()
{
canEditor = true;
if (sphere != null)
{
var renderer = sphere.GetComponent<Renderer>();
// 保存原始材质(可能已经是绿色的编辑过材质)
originalSharedMaterial = renderer.sharedMaterial;
// 创建编辑用的红色材质
editingMaterial = new Material(originalSharedMaterial);
editingMaterial.color = EditingSphereColor;
renderer.sharedMaterial = editingMaterial;
if (_thisWindow.currentEditingSphere != null)
{
_thisWindow.currentEditingSphere.ExitEditorBlockAttack();
}
Selection.activeGameObject = sphere;
_thisWindow.StartMonitoringSphere(this);
}
}
[Button("保存")]
[HorizontalGroup("1")]
[ShowIf("canEditor")]
public void ExitEditorBlockAttack()
{
canEditor = false;
if (sphere != null)
{
var renderer = sphere.GetComponent<Renderer>();
// 清理临时材质并恢复原始材质
if (editingMaterial != null)
{
DestroyImmediate(editingMaterial);
editingMaterial = null;
}
// 恢复原始材质
if (originalSharedMaterial != null)
{
renderer.sharedMaterial = originalSharedMaterial;
}
blockSphereInfo.scale = Calibre * scale;
blockSphereInfo.offestPos = sphere.transform.position;
DebugUtil.Log(
$"保存 {blockSphereInfo.cellIndex} 上的阻挡攻击球体真实直径为: {blockSphereInfo.scale}, 具体位置为: {blockSphereInfo.offestPos}, " +
$"原始的位置是:{originalPos}, 原始直径是:{Calibre}");
UpdateChangedData();
}
// 停止监听Transform变化
_thisWindow.StopMonitoringSphere();
}
#endregion
#region 值变化
private void OnScaleValueChanged()
{
var realScale = Calibre * scale;
if (sphere != null)
{
sphere.transform.localScale = Vector3.one * realScale;
}
UpdateChangedData();
}
private void OnOffestValueChanged()
{
var realOffestX = offest.x + originalPos.x;
var realOffestZ = offest.y + originalPos.z;
var newPos = new Vector3(realOffestX, 0f, realOffestZ);
if (sphere != null)
{
sphere.transform.position = newPos;
}
UpdateChangedData();
}
private void OnNoteValueChanged()
{
blockSphereInfo.note = note;
}
public void UpdateChangedData()
{
isChanged = offest != Vector2.zero ||
!Mathf.Approximately(1f, scale);
// 如果状态发生变化且不在编辑状态,更新球体颜色
if (!canEditor && sphere != null)
{
SetSphereColor(isChanged ? ChangedSphereColor : Color.white);
}
}
/// <summary>
/// 设置球体颜色
/// </summary>
private void SetSphereColor(Color color)
{
if (sphere == null) return;
var renderer = sphere.GetComponent<Renderer>();
if (renderer != null)
{
if (!canEditor)
{
if (renderer.sharedMaterial != null)
{
var material = new Material(renderer.sharedMaterial);
material.color = color;
renderer.sharedMaterial = material;
}
}
}
}
#endregion
}
[BoxGroup("攻击阻挡球")]
[HorizontalGroup("攻击阻挡球/Block")]
[LabelText("编辑攻击阻挡球"), Indent]
[ShowIf("@!_isLegionMap")]
[OnValueChanged("OnCanEditorBlockSphereChanged")]
[LabelWidth(100)]
[SerializeField]
private bool canEditorBlockSphere;
private void OnCanEditorBlockSphereChanged()
{
if (canEditorBlockSphere)
{
showBuildings = false;
HideObjectsExcept();
blockSphereEditorList.Clear();
UpdateBlockSphereInfo();
foreach (var cellIndex in banAttackCells)
{
if (blockSphereInfo.TryGetValue(cellIndex, out var sphereInfo))
{
var sphere = CreateSphere(cellIndex, sphereInfo.offestPos, Vector3.one * sphereInfo.scale);
var blockEditorInfo = new BlockSpereEditorInfo(sphereInfo, sphere);
blockSphereEditorList.Add(blockEditorInfo);
}
else
{
var pos = _map.TGSCellIndex2WorldPosition(cellIndex);
var sphere = CreateSphere(cellIndex, pos, Vector3.one * Calibre);
var blockEditorInfo = new BlockSpereEditorInfo(cellIndex, sphere);
blockSphereEditorList.Add(blockEditorInfo);
}
}
editingBlockSphereList.Clear();
foreach (var editorInfo in blockSphereEditorList)
{
if (editorInfo.isChanged)
{
editingBlockSphereList.Add(editorInfo);
}
}
}
else
{
// 清理所有临时材质
foreach (var editorInfo in blockSphereEditorList)
{
if (editorInfo.editingMaterial != null)
{
if (editorInfo.sphere != null)
{
var renderer = editorInfo.sphere.GetComponent<Renderer>();
if (renderer != null)
{
renderer.sharedMaterial = editorInfo.originalSharedMaterial;
}
}
DestroyImmediate(editorInfo.editingMaterial);
}
}
showBuildings = true;
ShowHiddenObjects();
DestroyBlockSphere();
}
}
/// <summary>
/// 更新阻挡球信息
/// </summary>
private void UpdateBlockSphereInfo()
{
blockSphereInfo.Clear();
GetAllBanAttackCell();
foreach (var blockInfo in _currentMapData.BlockSphereInfos)
{
blockSphereInfo[blockInfo.cellIndex] = blockInfo;
}
}
/// <summary>
/// 获取所有禁止攻击地格
/// </summary>
private void GetAllBanAttackCell()
{
banAttackCells.Clear();
var allCells = _currentMapData.BlocksData;
for (var i = 0; i < allCells.Count; i++)
{
var blockData = allCells[i];
if (!blockData.IsDefaultTerrainType())
{
var blockInfo = blockData.GetTerrainTypeProperty();
if (blockInfo.banAttack)
{
banAttackCells.Add(i);
}
}
}
}
[LabelText("展示建筑")]
[HorizontalGroup("攻击阻挡球/BlockBuildings"), Indent]
[ShowIf("@!_isLegionMap&&canEditorBlockSphere")]
[OnValueChanged("OnShowBuildingsChanged")]
public bool showBuildings;
private void OnShowBuildingsChanged()
{
if (showBuildings)
{
ShowHiddenObjects();
}
else
{
HideObjectsExcept();
}
}
[LabelText("添加地格")] [HorizontalGroup("攻击阻挡球/新数据"), Indent] [ShowIf("canEditorBlockSphere")]
public int addCellIndex;
[Button("添加编辑")]
[HorizontalGroup("攻击阻挡球/新数据/Add"), Indent]
[ShowIf("@!_isLegionMap&&canEditorBlockSphere")]
public void AddBlockSphere()
{
if (!banAttackCells.Contains(addCellIndex))
{
EditorUtility.DisplayDialog("错误", $"地格 {addCellIndex} 不是攻击阻挡地格!", "确定");
return;
}
foreach (var blockSpereEditor in editingBlockSphereList)
{
if (blockSpereEditor.cellIndex == addCellIndex)
{
return;
}
}
foreach (var blockSpereEditor in blockSphereEditorList)
{
if (blockSpereEditor.cellIndex == addCellIndex)
{
editingBlockSphereList.Add(blockSpereEditor);
break;
}
}
}
[LabelText("阻挡球列表")]
[HorizontalGroup("攻击阻挡球/EditList"), Indent]
[ShowIf("@!_isLegionMap&&canEditorBlockSphere")]
[ListDrawerSettings(HideAddButton = true, CustomRemoveIndexFunction = "CustomRemoveBlockSphereIndex")]
public List<BlockSpereEditorInfo> editingBlockSphereList = new();
[HideInInspector] public List<BlockSpereEditorInfo> blockSphereEditorList = new();
private void CustomRemoveBlockSphereIndex(int index)
{
if (index < editingBlockSphereList.Count)
{
editingBlockSphereList[index].Revert();
DebugUtil.Log($"删除并还原{editingBlockSphereList[index].cellIndex}的阻挡球编辑数据");
editingBlockSphereList.RemoveAt(index);
}
}
/// <summary>
/// 创建球体
/// </summary>
private GameObject CreateSphere(int cellIndex, Vector3 pos, Vector3 scale)
{
var sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
sphere.transform.position = pos;
sphere.transform.localScale = scale;
if (blockSphereRoot == null)
blockSphereRoot = new GameObject("blockSphereRoot");
sphere.transform.SetParent(blockSphereRoot.transform);
sphere.name = "sphere" + cellIndex;
return sphere;
}
private void DestroyBlockSphere()
{
DestroyImmediate(blockSphereRoot);
}
/// <summary>
/// 保存数据
/// </summary>
private void SaveBlockSphereInfo()
{
_currentMapData.BlockSphereInfos.Clear();
foreach (var blockSpereEditor in editingBlockSphereList)
{
_currentMapData.BlockSphereInfos.Add(blockSpereEditor.blockSphereInfo);
}
}
/// <summary>
/// 加载数据
/// </summary>
private void LoadBlockSphereInfo()
{
blockSphereInfo.Clear();
foreach (var blockInfo in _currentMapData.BlockSphereInfos)
{
blockSphereInfo[blockInfo.cellIndex] = blockInfo;
}
}
#region Sphere物体编辑器监听
/// <summary>
/// 当前正在编辑的球体信息
/// </summary>
[HideInInspector] public BlockSpereEditorInfo currentEditingSphere;
/// <summary>
/// 上次记录的位置
/// </summary>
[HideInInspector] public Vector3 lastPosition;
/// <summary>
/// 上次记录的缩放
/// </summary>
[HideInInspector] public Vector3 lastScale;
/// <summary>
/// 开始监听球体Transform变化
/// </summary>
private void StartMonitoringSphere(BlockSpereEditorInfo editorInfo)
{
currentEditingSphere = editorInfo;
if (editorInfo.sphere != null)
{
lastPosition = editorInfo.sphere.transform.position;
lastScale = editorInfo.sphere.transform.localScale;
// 注册编辑器更新回调
EditorApplication.update += OnEditorUpdate;
}
}
/// <summary>
/// 停止监听球体Transform变化
/// </summary>
private void StopMonitoringSphere()
{
currentEditingSphere = null;
EditorApplication.update -= OnEditorUpdate;
}
/// <summary>
/// 编辑器更新回调
/// </summary>
private void OnEditorUpdate()
{
if (currentEditingSphere?.sphere == null || !currentEditingSphere.canEditor)
{
StopMonitoringSphere();
return;
}
var sphere = currentEditingSphere.sphere;
var transform = sphere.transform;
// 检查位置变化
if (Vector3.Distance(transform.position, lastPosition) > 0.001f)
{
// 锁定Y轴
var newPos = transform.position;
newPos.y = 0f;
transform.position = newPos;
// 更新偏移值
var offsetX = newPos.x - currentEditingSphere.originalPos.x;
var offsetZ = newPos.z - currentEditingSphere.originalPos.z;
currentEditingSphere.offest = new Vector2(offsetX, offsetZ);
lastPosition = newPos;
// 标记为已修改
currentEditingSphere.UpdateChangedData();
}
// 检查缩放变化
if (Vector3.Distance(transform.localScale, lastScale) > 0.001f)
{
var newScale = transform.localScale.x;
transform.localScale = Vector3.one * newScale;
currentEditingSphere.scale = newScale / Calibre;
lastScale = transform.localScale;
currentEditingSphere.UpdateChangedData();
}
}
#endregion
#region 物体隐藏/显示管理
/// <summary>
/// 需要隐藏的物体节点名字
/// </summary>
private readonly List<string> hideObjsRoot = new()
{
"Art", "BackGround", "Buildings", "enemyObjRoot", "midObjRoot", "selfObjRoot"
};
/// <summary>
/// 不需要隐藏的物体节点名字
/// </summary>
private readonly List<string> noHideObjsRoot = new()
{
"Ground", "Ground2", "Lights", "Fog", "Global Volume", "Effects"
};
/// <summary>
/// 隐藏指定节点下的物体(排除白名单中的物体)
/// </summary>
public void HideObjectsExcept()
{
if (hideObjsRoot == null || hideObjsRoot.Count == 0)
{
return;
}
// 清空之前的隐藏物体列表
hideObjs.Clear();
foreach (string nodeName in hideObjsRoot)
{
GameObject node = GameObject.Find(nodeName);
if (node == null)
{
continue;
}
HideChildrenRecursively(node.transform, noHideObjsRoot);
}
}
/// <summary>
/// 递归隐藏子物体
/// </summary>
/// <param name="parent">父级Transform</param>
/// <param name="excludeNames">排除的物体名列表</param>
private void HideChildrenRecursively(Transform parent, List<string> excludeNames)
{
for (int i = 0; i < parent.childCount; i++)
{
Transform child = parent.GetChild(i);
GameObject childObj = child.gameObject;
// 检查是否在排除列表中(完全匹配)
bool shouldExclude = false;
if (excludeNames != null)
{
foreach (string excludeName in excludeNames)
{
if (childObj.name.Equals(excludeName, System.StringComparison.OrdinalIgnoreCase))
{
shouldExclude = true;
break;
}
}
}
if (shouldExclude)
{
continue;
}
else
{
// 不在排除列表中,隐藏此物体
if (childObj.activeSelf)
{
childObj.SetActive(false);
hideObjs.Add(childObj);
}
// 继续递归处理子物体
HideChildrenRecursively(child, excludeNames);
}
}
}
/// <summary>
/// 显示之前隐藏的所有物体
/// </summary>
private void ShowHiddenObjects()
{
if (hideObjs == null || hideObjs.Count == 0)
{
return;
}
for (int i = hideObjs.Count - 1; i >= 0; i--)
{
GameObject obj = hideObjs[i];
// 检查物体是否仍然存在(可能已被删除)
if (obj != null)
{
obj.SetActive(true);
}
hideObjs.RemoveAt(i);
}
}
#endregion
#endregion
#region 功能
[Button("保存")]
private void RebuildPrefab()
2025-05-28 14:50:34 +08:00
{
2025-09-03 14:43:56 +08:00
SaveBlockSphereInfo();
_currMapManager.SaveMapData();
2025-05-28 14:50:34 +08:00
}
[Button("清除网格数据")]
private void ClearGridData()
2025-05-28 14:50:34 +08:00
{
if (EditorUtility.DisplayDialog("清理网格数据", "您是否确认清理地图网格数据", "确认", "取消"))
{
_currentMapData.ClearGridData();
_map.TerrainGridSystem.TerritoryDestroyAll();
ClearRegionColor();
UpdateRegion();
2025-09-03 14:43:56 +08:00
DestroyBlockSphere();
_currMapManager.SaveMapData();
}
2025-05-28 14:50:34 +08:00
}
#endregion
2023-11-16 18:27:03 +08:00
#region MainLife
2025-08-25 17:34:39 +08:00
public static void OpenWindow(MapManager mapSceneEditor, bool isLegionMap = false)
2023-11-17 18:16:53 +08:00
{
MapEditorSettings.Init();
2025-08-25 17:34:39 +08:00
_thisWindow = GetWindow<MapGridWindow>();
_thisWindow.name = "MapGridWindow";
_thisWindow.position = GUIHelper.GetEditorWindowRect().AlignCenter(800, 600);
_thisWindow._currMapManager = mapSceneEditor;
_thisWindow._currentMapData = null;
_thisWindow._isLegionMap = isLegionMap;
_thisWindow.ShowTab();
_thisWindow.LoadMap(mapSceneEditor.TGS, mapSceneEditor.MapData, mapSceneEditor.Map);
_thisWindow.LoadBuffPrefab();
2023-11-19 22:57:17 +08:00
UnityEditor.Compilation.CompilationPipeline.compilationStarted += OnCompilationStart;
2023-11-17 18:16:53 +08:00
}
2023-11-16 18:27:03 +08:00
2023-11-19 22:57:17 +08:00
private static void OnCompilationStart(object obj)
{
2025-08-25 17:34:39 +08:00
_thisWindow?.Close();
_thisWindow = null;
2023-11-19 22:57:17 +08:00
}
2024-10-09 13:38:54 +08:00
private void LoadBuffPrefab()
{
DestroyBuffObj();
_buffPrefabDic.Clear();
2024-10-09 14:18:50 +08:00
var buffObjCells = _map.MapData.showBuffPoints;
foreach (var cell in buffObjCells)
2024-10-09 13:38:54 +08:00
{
var buffObj = CreateBuffObj(cell.cellIndex, cell.path);
2025-04-02 15:48:55 +08:00
_buffPrefabDic.TryAdd(cell.cellIndex, buffObj);
2024-10-09 13:38:54 +08:00
}
}
private void DestroyBuffObj()
{
if (_buffPrefabDic == null) return;
_buffPrefabDic.Clear();
2025-04-02 16:04:07 +08:00
DestroyImmediate(buffRoot);
buffRoot = null;
2024-10-09 13:38:54 +08:00
}
2025-09-03 14:43:56 +08:00
2023-11-19 22:57:17 +08:00
private void LoadMap(TerrainGridSystem tgs, MapData data, Map map)
2023-11-17 18:16:53 +08:00
{
_currentMapData = data;
2023-11-19 22:57:17 +08:00
_map = map;
2025-06-25 14:45:41 +08:00
_terrainTypeConfig = TerrainTypeConfig.DicTerrainTypePropertie;
2025-08-25 17:34:39 +08:00
_legionTerrainTypeConfig = LegionTerrainTypeConfig.DicTerrainTypePropertie;
2023-11-17 18:16:53 +08:00
_map.TerrainGridSystem.highlightEffect = HighlightEffect.Default;
2023-11-21 19:52:50 +08:00
tgs.OnMouseClickOnGrid += OnMouseClickCell;
2023-11-19 14:01:26 +08:00
UpdateRegion();
2025-09-03 14:43:56 +08:00
// 加载阻挡球
LoadBlockSphereInfo();
}
private void Awake()
{
SceneView.duringSceneGui += OnSceneGUI;
2023-11-17 18:16:53 +08:00
}
2025-11-17 19:30:14 +08:00
2023-11-17 18:16:53 +08:00
protected override void OnEnable()
{
EnhancedTouchSupport.Enable();
TerrainTypeConfig.Load();
2025-08-25 17:34:39 +08:00
LegionTerrainTypeConfig.Load();
2024-10-09 13:38:54 +08:00
_buffPrefabDic = new Dictionary<int, GameObject>();
2023-11-17 18:16:53 +08:00
base.OnEnable();
}
protected override void OnDisable()
{
2024-10-09 13:38:54 +08:00
DestroyBuffObj();
_buffPrefabDic = null;
2023-11-17 18:16:53 +08:00
EnhancedTouchSupport.Disable();
2025-09-03 14:43:56 +08:00
DestroyBlockSphere();
ShowHiddenObjects();
2023-11-17 18:16:53 +08:00
base.OnDisable();
}
2023-11-20 12:25:41 +08:00
protected override void OnGUI()
{
base.OnGUI();
2023-12-20 12:47:57 +08:00
if (_currMapManager == null || _currMapManager.MapData != _currentMapData)
2023-11-20 12:25:41 +08:00
{
Debug.Log("地图数据变更,请重新点击编辑网格!");
Close();
}
}
2023-11-19 14:01:26 +08:00
protected override void OnDestroy()
{
base.OnDestroy();
2025-09-03 14:43:56 +08:00
ShowHiddenObjects();
2024-10-09 13:38:54 +08:00
DestroyBuffObj();
if (_currMapManager != null)
2023-12-20 12:47:57 +08:00
_currMapManager.SaveMapData();
2023-11-20 12:25:41 +08:00
ClearRegionColor();
2025-09-03 14:43:56 +08:00
DestroyBlockSphere();
2023-11-21 19:52:50 +08:00
_map.TerrainGridSystem.OnMouseClickOnGrid -= OnMouseClickCell;
2023-11-19 22:57:17 +08:00
UnityEditor.Compilation.CompilationPipeline.compilationStarted -= OnCompilationStart;
2025-09-03 14:43:56 +08:00
SceneView.duringSceneGui -= OnSceneGUI;
2023-11-19 14:01:26 +08:00
}
2023-11-16 18:27:03 +08:00
#endregion
#region 点击事件
2025-05-28 14:50:34 +08:00
2023-11-21 19:52:50 +08:00
private void OnMouseClickCell(TerrainGridSystem tgs, int cellIndex, int buttonIndex)
{
int leftButton = 0;
2024-10-09 13:38:54 +08:00
OnCellOperation(tgs, cellIndex, buttonIndex == leftButton);
2023-11-21 19:52:50 +08:00
}
2025-05-28 14:50:34 +08:00
2023-11-21 19:52:50 +08:00
private void OnCellOperation(TerrainGridSystem tgs, int cellIndex, bool isOpTrue)
2023-11-16 18:27:03 +08:00
{
if (!canBrushTerrainType && !canEditorArea) return;
2023-11-19 22:57:17 +08:00
if (canEditorArea && _currEditRegionArea == null) return;
2025-05-28 14:50:34 +08:00
// 地块
2025-08-25 17:34:39 +08:00
if (canBrushTerrainType)
OnClickBlockType(cellIndex, isOpTrue);
2023-11-16 18:27:03 +08:00
2025-05-28 14:50:34 +08:00
// 普通地区
2025-06-04 15:24:42 +08:00
if (isOpTrue && canEditorSingleRegion && _currEditRegionArea != null)
2023-11-16 18:27:03 +08:00
{
2023-11-19 14:01:26 +08:00
_currEditRegionArea.AddPosition(cellIndex);
2023-11-16 18:27:03 +08:00
}
2025-06-04 15:24:42 +08:00
else if (!isOpTrue && canEditorSingleRegion && _currEditRegionArea != null)
2023-11-16 18:27:03 +08:00
{
2023-11-19 14:01:26 +08:00
_currEditRegionArea.RemovePosition(cellIndex);
2023-11-16 18:27:03 +08:00
}
2024-10-09 13:38:54 +08:00
}
2025-08-25 17:34:39 +08:00
private void OnClickBlockType(int cellIndex, bool isOpTrue)
{
if (isOpTrue && terrainTypeIndex >= 0)
{
SetCellBlockType(cellIndex, terrainTypeIndex);
}
else if (!isOpTrue)
{
if (!_isLegionMap && _currentMapData.BlocksData[cellIndex].TerrainTypeIndex == terrainTypeIndex)
{
ClearCellBlockType(cellIndex);
}
else if (_isLegionMap && _currentMapData.BlocksData[cellIndex].LegionTypeIndex == terrainTypeIndex)
{
ClearCellBlockType(cellIndex);
}
}
}
2023-11-16 18:27:03 +08:00
#endregion
2025-09-03 14:43:56 +08:00
#region Draw
2025-11-17 19:30:14 +08:00
2025-09-03 14:43:56 +08:00
private void OnSceneGUI(SceneView sceneView)
{
DrawSphereID();
}
private GUIStyle labelStyleSphere;
private void DrawSphereID()
{
if (!canEditorBlockSphere)
return;
labelStyleSphere ??= new GUIStyle
{
fontSize = 30,
fontStyle = FontStyle.Bold,
normal =
{
textColor = Color.black
}
};
foreach (var blockSpereEditor in blockSphereEditorList)
{
if (blockSpereEditor.sphere != null)
{
var pos = new Vector3(blockSpereEditor.sphere.transform.position.x, Calibre,
blockSpereEditor.sphere.transform.position.z);
Handles.Label(pos, blockSpereEditor.cellIndex.ToString(),
labelStyleSphere);
}
}
}
#endregion
2023-11-16 18:27:03 +08:00
}
}