1938 lines
63 KiB
C#
1938 lines
63 KiB
C#
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;
|
||
|
||
namespace MapEditor
|
||
{
|
||
public class MapGridWindow : OdinEditorWindow
|
||
{
|
||
#region Fields And Properties
|
||
|
||
private static MapGridWindow _thisWindow;
|
||
|
||
private static Dictionary<int, TerrainTypeProperty> _terrainTypeConfig;
|
||
|
||
private static Dictionary<int, LegionTerrainTypeProperty> _legionTerrainTypeConfig;
|
||
|
||
private MapData _currentMapData;
|
||
|
||
private MapManager _currMapManager;
|
||
|
||
private Map _map;
|
||
|
||
private bool _isLegionMap;
|
||
|
||
#endregion
|
||
|
||
#region 显示地图索引功能
|
||
|
||
[BoxGroup("显示地格索引")]
|
||
[LabelText("显示类型"), Indent]
|
||
[OnValueChanged("ShowCellIndex")]
|
||
[LabelWidth(100)]
|
||
[SerializeField]
|
||
private CellDebugInfo cellDebugInfo = CellDebugInfo.Nothing;
|
||
|
||
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")]
|
||
public int terrainTypeIndex = 0;
|
||
|
||
private IEnumerable GetTerrainTypeProperties()
|
||
{
|
||
ValueDropdownList<int> list = new();
|
||
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()
|
||
{
|
||
if (!_isLegionMap)
|
||
{
|
||
var window = GetWindow<TerrainTypeConfigWindow>();
|
||
window.Show();
|
||
}
|
||
else
|
||
{
|
||
var window = GetWindow<LegionTerrainTypeConfigWindow>();
|
||
window.Show();
|
||
}
|
||
}
|
||
|
||
private void SetCellBlockType(int cellIndex, int terrainTypeIndex)
|
||
{
|
||
if (!_isLegionMap)
|
||
{
|
||
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);
|
||
|
||
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;
|
||
}
|
||
|
||
var map = _map;
|
||
// Key: terrainTypeIndex Value: tgs.territories.index
|
||
if (!map.LegionTerrainTypeIndexDic.ContainsKey(terrainTypeIndex))
|
||
map.LegionTerrainTypeIndexDic.Add(terrainTypeIndex, map.LegionTerrainTypeIndexDic.Count);
|
||
|
||
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);
|
||
}
|
||
|
||
Debug.Log(
|
||
$"设置军团地格: ({cellIndex}), 地格类型: ({terrainTypeIndex}), 名字: ({terrainTypeProperty.name})");
|
||
}
|
||
}
|
||
|
||
private void ClearCellBlockType(int cellIndex)
|
||
{
|
||
if (!_isLegionMap)
|
||
{
|
||
if (!_terrainTypeConfig.TryGetValue(terrainTypeIndex, out TerrainTypeProperty terrainTypeProperty))
|
||
{
|
||
DebugUtil.LogError($"没有取到地格属性,id:{terrainTypeIndex}");
|
||
return;
|
||
}
|
||
|
||
var map = _map;
|
||
map.TerrainGridSystem.CellSetBorderVisible(cellIndex, true);
|
||
map.TerrainGridSystem.CellHideRegionSurface(cellIndex);
|
||
|
||
_map.SetBlockColor(cellIndex, false, terrainTypeProperty.Color);
|
||
map.SetTerrainType(cellIndex, -1);
|
||
var buffPath = terrainTypeProperty.buffObjectPath;
|
||
if (!string.IsNullOrEmpty(buffPath))
|
||
{
|
||
RemoveBuffCell(cellIndex);
|
||
}
|
||
|
||
Debug.Log($"清除地格cellIndex: ({cellIndex})");
|
||
}
|
||
else
|
||
{
|
||
if (!_legionTerrainTypeConfig.TryGetValue(terrainTypeIndex, out var terrainTypeProperty))
|
||
{
|
||
DebugUtil.LogError($"没有取到军团地格属性,id:{terrainTypeIndex}");
|
||
return;
|
||
}
|
||
|
||
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);
|
||
}
|
||
|
||
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);
|
||
/*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;
|
||
|
||
[Serializable]
|
||
public class RegionArea
|
||
{
|
||
[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 RegionArea(MapData.Region region)
|
||
{
|
||
_region = region;
|
||
note = _region.note;
|
||
}
|
||
|
||
[Button("编辑"), HorizontalGroup("1")]
|
||
private void EditorRegion()
|
||
{
|
||
var map = _thisWindow._map;
|
||
_thisWindow._currEditRegionArea = this;
|
||
var regionslist = map.MapData.regions;
|
||
for (int i = 0; i < regionslist.Count; i++)
|
||
{
|
||
map.SetRegionColor(i, false, regionColor);
|
||
}
|
||
|
||
map.SetRegionColor(_region, true, regionColor);
|
||
canEditorSingleRegion = true;
|
||
}
|
||
|
||
|
||
public void AddPosition(int cellIndex)
|
||
{
|
||
if (positions.Contains(cellIndex))
|
||
return;
|
||
positions.Add(cellIndex);
|
||
regionCount++;
|
||
_thisWindow._map.TerrainGridSystem.CellToggleRegionSurface(cellIndex, true, regionColor);
|
||
}
|
||
|
||
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("OnCanEditorAreaTypeChanged")]
|
||
[LabelWidth(100)]
|
||
[SerializeField]
|
||
private bool canEditorArea;
|
||
|
||
private void OnCanEditorAreaTypeChanged()
|
||
{
|
||
if (canEditorArea)
|
||
{
|
||
canBrushTerrainType = false;
|
||
}
|
||
else
|
||
{
|
||
ClearRegionColor();
|
||
SceneView.RepaintAll();
|
||
canEditorSingleRegion = false;
|
||
_currEditRegionArea = null;
|
||
}
|
||
}
|
||
|
||
[LabelText("地区列表")]
|
||
[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 雷区
|
||
|
||
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;
|
||
|
||
[Serializable]
|
||
public class BlockRegionArea
|
||
{
|
||
private const string BuffPrefabPath = "Art_Out/Other/BuffPoint";
|
||
|
||
[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;
|
||
}
|
||
|
||
[Button("编辑"), HorizontalGroup("1")]
|
||
private void EditorRegion()
|
||
{
|
||
var map = _thisWindow._map;
|
||
_thisWindow._currEditBlockRegion = this;
|
||
var regionsList = map.MapData.blockRegions;
|
||
foreach (var blockRegion in regionsList)
|
||
{
|
||
map.SetBlocksColor(blockRegion.positions, false, BlockRegionColor);
|
||
}
|
||
|
||
map.SetBlocksColor(_region.positions, true, BlockRegionColor);
|
||
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()
|
||
{
|
||
obj = _thisWindow.CreateBlockObj(_region.path, pos);
|
||
}
|
||
|
||
[Button("更换指示"), HorizontalGroup("3")]
|
||
[HideIf("NeedAdd")]
|
||
private void ChangeObj()
|
||
{
|
||
if (obj) DestroyImmediate(obj);
|
||
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;
|
||
note = _region.note;
|
||
if (!string.IsNullOrEmpty(region.path))
|
||
{
|
||
obj = _thisWindow.CreateBlockObj(_region.path, _region.centerPos);
|
||
buffObject = AssetDatabase.LoadAssetAtPath<GameObject>(_region.path);
|
||
}
|
||
}
|
||
|
||
public void AddPosition(int cellIndex)
|
||
{
|
||
if (Positions.Contains(cellIndex))
|
||
return;
|
||
Positions.Add(cellIndex);
|
||
DebugUtil.Log($"{id}阻挡区添加地格{cellIndex}");
|
||
regionCount++;
|
||
_thisWindow._map.TerrainGridSystem.CellToggleRegionSurface(cellIndex, true, BlockRegionColor);
|
||
}
|
||
|
||
public void RemovePosition(int cellIndex)
|
||
{
|
||
if (!Positions.Contains(cellIndex))
|
||
return;
|
||
Positions.Remove(cellIndex);
|
||
|
||
DebugUtil.Log($"{id}阻挡区移除地格{cellIndex}");
|
||
regionCount--;
|
||
_thisWindow._map.TerrainGridSystem.CellHideRegionSurface(cellIndex);
|
||
}
|
||
}
|
||
|
||
[BoxGroup("阻挡区信息")]
|
||
[HorizontalGroup("阻挡区信息/Region")]
|
||
[ShowIf("@!_isLegionMap")]
|
||
[LabelText("编辑阻挡区"), Indent]
|
||
[OnValueChanged("OnCanEditorBlockAreaChanged")]
|
||
[LabelWidth(100)]
|
||
[SerializeField]
|
||
private bool canEditorBlockArea;
|
||
|
||
private void OnCanEditorBlockAreaChanged()
|
||
{
|
||
if (canEditorBlockArea)
|
||
{
|
||
canEditorArea = false;
|
||
canEditorMinesArea = false;
|
||
canBrushTerrainType = false;
|
||
canEditorDefenseArea = false;
|
||
canEditorSingleRegion = false;
|
||
canEditorSingleDefenseRegion = false;
|
||
ClearDefenseRegionColor();
|
||
ClearRegionColor();
|
||
ClearMinesRegionColor();
|
||
}
|
||
else
|
||
{
|
||
ClearBlockRegionColor();
|
||
SceneView.RepaintAll();
|
||
_currEditBlockRegion = null;
|
||
canEditorSingleBlockRegion = false;
|
||
}
|
||
}
|
||
|
||
[LabelText("阻挡区列表")]
|
||
[ShowIf("@!_isLegionMap&&canEditorBlockArea")]
|
||
[VerticalGroup("阻挡区信息/RegionInfo"), Indent]
|
||
[ListDrawerSettings(CustomAddFunction = "CustomAddBlockRegion",
|
||
CustomRemoveIndexFunction = "CustomRemoveBlockRegionIndex",
|
||
DraggableItems = false)]
|
||
public List<BlockRegionArea> blockRegionList = new();
|
||
|
||
private void CustomAddBlockRegion()
|
||
{
|
||
var region = new MapData.BlockRegion();
|
||
_currentMapData.blockRegions.Add(region);
|
||
UpdateBlockRegion();
|
||
}
|
||
|
||
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();
|
||
}
|
||
|
||
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,
|
||
};
|
||
|
||
blockRegionList.Add(blockRegion);
|
||
index++;
|
||
}
|
||
}
|
||
}
|
||
|
||
private void ClearBlockRegionColor()
|
||
{
|
||
if (_map == null)
|
||
return;
|
||
foreach (var blockRegion in _map.MapData.blockRegions)
|
||
{
|
||
_map.SetBlocksColor(blockRegion.positions, false, BlockRegionColor);
|
||
}
|
||
}
|
||
|
||
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
|
||
|
||
#region 刷怪触发区
|
||
|
||
private static readonly Color DefenseRegionColor = Color.magenta;
|
||
|
||
private DefenseRegionArea _currEditDefenseRegion;
|
||
|
||
private static bool canEditorSingleDefenseRegion = false;
|
||
|
||
[Serializable]
|
||
public class DefenseRegionArea
|
||
{
|
||
[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 DefenseRegionArea(MapData.Region region)
|
||
{
|
||
_region = region;
|
||
note = _region.note;
|
||
}
|
||
|
||
[Button("编辑"), HorizontalGroup("1")]
|
||
private void EditorRegion()
|
||
{
|
||
var map = _thisWindow._map;
|
||
_thisWindow._currEditDefenseRegion = this;
|
||
var regionsList = map.MapData.defenseRegions;
|
||
foreach (var defenseRegion in regionsList)
|
||
{
|
||
map.SetBlocksColor(defenseRegion.positions, false, DefenseRegionColor);
|
||
}
|
||
|
||
map.SetBlocksColor(_region.positions, true, DefenseRegionColor);
|
||
canEditorSingleDefenseRegion = true;
|
||
}
|
||
|
||
public void AddPosition(int cellIndex)
|
||
{
|
||
if (Positions.Contains(cellIndex))
|
||
return;
|
||
Positions.Add(cellIndex);
|
||
DebugUtil.Log($"{id}防守区添加地格{cellIndex}");
|
||
regionCount++;
|
||
_thisWindow._map.TerrainGridSystem.CellToggleRegionSurface(cellIndex, true, DefenseRegionColor);
|
||
}
|
||
|
||
public void RemovePosition(int cellIndex)
|
||
{
|
||
if (!Positions.Contains(cellIndex))
|
||
return;
|
||
Positions.Remove(cellIndex);
|
||
|
||
DebugUtil.Log($"{id}防守区移除地格{cellIndex}");
|
||
regionCount--;
|
||
_thisWindow._map.TerrainGridSystem.CellHideRegionSurface(cellIndex);
|
||
}
|
||
}
|
||
|
||
[BoxGroup("刷怪触发区")]
|
||
[HorizontalGroup("刷怪触发区/Region")]
|
||
[ShowIf("@!_isLegionMap")]
|
||
[LabelText("编辑触发区"), Indent]
|
||
[OnValueChanged("OnCanEditorDefenseAreaChanged")]
|
||
[LabelWidth(100)]
|
||
[SerializeField]
|
||
private bool canEditorDefenseArea;
|
||
|
||
private void OnCanEditorDefenseAreaChanged()
|
||
{
|
||
if (canEditorDefenseArea)
|
||
{
|
||
canEditorBlockArea = false;
|
||
canEditorArea = false;
|
||
canEditorMinesArea = false;
|
||
canBrushTerrainType = false;
|
||
canEditorSingleRegion = false;
|
||
canEditorSingleBlockRegion = false;
|
||
ClearBlockRegionColor();
|
||
ClearRegionColor();
|
||
ClearMinesRegionColor();
|
||
}
|
||
else
|
||
{
|
||
ClearDefenseRegionColor();
|
||
SceneView.RepaintAll();
|
||
_currEditDefenseRegion = null;
|
||
canEditorSingleDefenseRegion = false;
|
||
}
|
||
}
|
||
|
||
[LabelText("刷怪触发区列表")]
|
||
[ShowIf("@!_isLegionMap&&canEditorDefenseArea")]
|
||
[VerticalGroup("刷怪触发区/RegionInfo"), Indent]
|
||
[ListDrawerSettings(CustomAddFunction = "CustomAddDefenseRegion",
|
||
CustomRemoveIndexFunction = "CustomRemoveDefenseRegion",
|
||
DraggableItems = false)]
|
||
public List<DefenseRegionArea> defenseRegionList = new();
|
||
|
||
private void CustomAddDefenseRegion()
|
||
{
|
||
var region = new MapData.Region();
|
||
_currentMapData.defenseRegions.Add(region);
|
||
UpdateDefenseRegion();
|
||
}
|
||
|
||
private void CustomRemoveDefenseRegion(int index)
|
||
{
|
||
ClearDefenseRegionColor();
|
||
_currentMapData.defenseRegions.RemoveAt(index);
|
||
UpdateDefenseRegion();
|
||
}
|
||
|
||
private void UpdateDefenseRegion()
|
||
{
|
||
defenseRegionList.Clear();
|
||
if (_currentMapData != null)
|
||
{
|
||
var index = 0;
|
||
foreach (var region in _currentMapData.defenseRegions)
|
||
{
|
||
var defenseRegion = new DefenseRegionArea(region)
|
||
{
|
||
id = index,
|
||
regionCount = region.positions.Count,
|
||
};
|
||
|
||
defenseRegionList.Add(defenseRegion);
|
||
index++;
|
||
}
|
||
}
|
||
}
|
||
|
||
private void ClearDefenseRegionColor()
|
||
{
|
||
if (_map == null)
|
||
return;
|
||
foreach (var defenseRegion in _map.MapData.defenseRegions)
|
||
{
|
||
_map.SetBlocksColor(defenseRegion.positions, false, DefenseRegionColor);
|
||
}
|
||
}
|
||
|
||
#endregion*/
|
||
|
||
#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()
|
||
{
|
||
SaveBlockSphereInfo();
|
||
_currMapManager.SaveMapData();
|
||
}
|
||
|
||
[Button("清除网格数据")]
|
||
private void ClearGridData()
|
||
{
|
||
if (EditorUtility.DisplayDialog("清理网格数据", "您是否确认清理地图网格数据", "确认", "取消"))
|
||
{
|
||
_currentMapData.ClearGridData();
|
||
_map.TerrainGridSystem.TerritoryDestroyAll();
|
||
ClearRegionColor();
|
||
UpdateRegion();
|
||
DestroyBlockSphere();
|
||
_currMapManager.SaveMapData();
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region MainLife
|
||
|
||
public static void OpenWindow(MapManager mapSceneEditor, bool isLegionMap = false)
|
||
{
|
||
MapEditorSettings.Init();
|
||
_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();
|
||
UnityEditor.Compilation.CompilationPipeline.compilationStarted += OnCompilationStart;
|
||
}
|
||
|
||
private static void OnCompilationStart(object obj)
|
||
{
|
||
_thisWindow?.Close();
|
||
_thisWindow = null;
|
||
}
|
||
|
||
private void LoadBuffPrefab()
|
||
{
|
||
DestroyBuffObj();
|
||
_buffPrefabDic.Clear();
|
||
var buffObjCells = _map.MapData.showBuffPoints;
|
||
foreach (var cell in buffObjCells)
|
||
{
|
||
var buffObj = CreateBuffObj(cell.cellIndex, cell.path);
|
||
_buffPrefabDic.TryAdd(cell.cellIndex, buffObj);
|
||
}
|
||
}
|
||
|
||
private void DestroyBuffObj()
|
||
{
|
||
if (_buffPrefabDic == null) return;
|
||
_buffPrefabDic.Clear();
|
||
DestroyImmediate(buffRoot);
|
||
buffRoot = null;
|
||
}
|
||
|
||
private void LoadMap(TerrainGridSystem tgs, MapData data, Map map)
|
||
{
|
||
_currentMapData = data;
|
||
_map = map;
|
||
_terrainTypeConfig = TerrainTypeConfig.DicTerrainTypePropertie;
|
||
_legionTerrainTypeConfig = LegionTerrainTypeConfig.DicTerrainTypePropertie;
|
||
_map.TerrainGridSystem.highlightEffect = HighlightEffect.Default;
|
||
tgs.OnMouseClickOnGrid += OnMouseClickCell;
|
||
UpdateRegion();
|
||
// 加载阻挡球
|
||
LoadBlockSphereInfo();
|
||
}
|
||
|
||
private void Awake()
|
||
{
|
||
SceneView.duringSceneGui += OnSceneGUI;
|
||
}
|
||
|
||
protected override void OnEnable()
|
||
{
|
||
EnhancedTouchSupport.Enable();
|
||
TerrainTypeConfig.Load();
|
||
LegionTerrainTypeConfig.Load();
|
||
_buffPrefabDic = new Dictionary<int, GameObject>();
|
||
base.OnEnable();
|
||
}
|
||
|
||
protected override void OnDisable()
|
||
{
|
||
DestroyBuffObj();
|
||
_buffPrefabDic = null;
|
||
EnhancedTouchSupport.Disable();
|
||
DestroyBlockSphere();
|
||
ShowHiddenObjects();
|
||
base.OnDisable();
|
||
}
|
||
|
||
protected override void OnGUI()
|
||
{
|
||
base.OnGUI();
|
||
if (_currMapManager == null || _currMapManager.MapData != _currentMapData)
|
||
{
|
||
Debug.Log("地图数据变更,请重新点击编辑网格!");
|
||
Close();
|
||
}
|
||
}
|
||
|
||
protected override void OnDestroy()
|
||
{
|
||
base.OnDestroy();
|
||
ShowHiddenObjects();
|
||
DestroyBuffObj();
|
||
if (_currMapManager != null)
|
||
_currMapManager.SaveMapData();
|
||
ClearRegionColor();
|
||
DestroyBlockSphere();
|
||
_map.TerrainGridSystem.OnMouseClickOnGrid -= OnMouseClickCell;
|
||
UnityEditor.Compilation.CompilationPipeline.compilationStarted -= OnCompilationStart;
|
||
SceneView.duringSceneGui -= OnSceneGUI;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 点击事件
|
||
|
||
private void OnMouseClickCell(TerrainGridSystem tgs, int cellIndex, int buttonIndex)
|
||
{
|
||
int leftButton = 0;
|
||
|
||
OnCellOperation(tgs, cellIndex, buttonIndex == leftButton);
|
||
}
|
||
|
||
private void OnCellOperation(TerrainGridSystem tgs, int cellIndex, bool isOpTrue)
|
||
{
|
||
if (!canBrushTerrainType && !canEditorArea) return;
|
||
|
||
if (canEditorArea && _currEditRegionArea == null) return;
|
||
|
||
// 地块
|
||
if (canBrushTerrainType)
|
||
OnClickBlockType(cellIndex, isOpTrue);
|
||
|
||
// 普通地区
|
||
if (isOpTrue && canEditorSingleRegion && _currEditRegionArea != null)
|
||
{
|
||
_currEditRegionArea.AddPosition(cellIndex);
|
||
}
|
||
else if (!isOpTrue && canEditorSingleRegion && _currEditRegionArea != null)
|
||
{
|
||
_currEditRegionArea.RemovePosition(cellIndex);
|
||
}
|
||
}
|
||
|
||
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);
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Draw
|
||
|
||
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
|
||
}
|
||
} |