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 System.Linq; using TGS; using UnityEditor; using UnityEngine; using UnityEngine.InputSystem.EnhancedTouch; using ObjectFieldAlignment = Sirenix.OdinInspector.ObjectFieldAlignment; namespace MapEditor { public class MapGridWindow : OdinEditorWindow { #region Inner Class [Serializable] public class RegionArea { [HorizontalGroup("1")] [ReadOnly] public int id; [HorizontalGroup("1")] [ReadOnly] [LabelText("数量")] public int regionCount; public List positions => _region.positions; private MapData.Region _region; public RegionArea(MapData.Region region) { _region = region; } [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); canEditorRegion = 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); } } #endregion #region Fields And Properties private static MapGridWindow thisWindow; //1.#FFBF0072 2.#FF960072 private static readonly Color regionColor = MapUtils.GetRGBAColor("FF960072"); private static readonly Color cellBorderColor = new Color(229f, 229f, 229f, 237f); private static readonly float cellBorderWidth = 1f; private static List _terrainTypeConfig; private static bool canEditorRegion = false; private bool EditorNewRegion = false; private string _mapDataJsonStr = ""; private GameObject selectedGameObject; private Vector3 previousPosition; private Vector3 previousRotation; private MapData _currentMapData = null; private RegionArea _currEditRegionArea; private MapManager _currMapManager; private Map _map; private Dictionary _buffPrefabDic; private GameObject buffRoot; #endregion #region Editor [Button("保存")] private void RebuildPrefab() { _currMapManager.SaveMapData(); } [Button("清除网格数据")] private void ClearGridData() { if (EditorUtility.DisplayDialog("清理网格数据", "您是否确认清理地图网格数据", "确认", "取消")) { _currentMapData.ClearGridData(); _map.TerrainGridSystem.TerritoryDestroyAll(); ClearRegionColor(); UpdateRegion(); _currMapManager.SaveMapData(); } } [BoxGroup("地块信息")] [LabelText("刷地块"), Indent] [OnValueChanged("OnCanBrushTerrainTypeChanged")] [LabelWidth(100)] [SerializeField] [ShowIf("@!CanEditorAreaType")] private bool CanBrushTerrainType; private void OnCanBrushTerrainTypeChanged() { if (CanBrushTerrainType && _map != null) { CanEditorAreaType = false; // CanBrushBuffCellIndex = false; } } [HorizontalGroup("地块信息/Territory")] [ValueDropdown("GetTerrainTypeProperties")] [Indent] [LabelText("选择地块")] [ShowIf("CanBrushTerrainType")] public int TerrainTypeIndex = 0; [ShowIf("CanBrushTerrainType")] [HorizontalGroup("地块信息/Territory")] [Button(SdfIconType.GearFill, "编辑地块")] public void EditTerrainTypeConfig() { var window = GetWindow(); window.Show(); } /*[BoxGroup("指示信息")] [LabelText("刷指示信息"), Indent] [OnValueChanged("OnCanBrushBuffCellIndexChanged")] [LabelWidth(100)] [SerializeField] [ShowIf("@!CanEditorAreaType")] private bool CanBrushBuffCellIndex; private void OnCanBrushBuffCellIndexChanged() { if (CanBrushBuffCellIndex && _map != null) { CanEditorAreaType = false; CanBrushTerrainType = false; } } [BoxGroup("指示信息/GameObj")] [PreviewField(150, ObjectFieldAlignment.Center)] [LabelText("指示预览图"), ShowIf("CanBrushBuffCellIndex")] [AssetList(Path = BuffPrefabPath)] public GameObject buffObject;*/ [BoxGroup("地区信息")] [HorizontalGroup("地区信息/Region")] [LabelText("编辑地区"), Indent] [OnValueChanged("OnCanEditorAreaTypeChanged")] [LabelWidth(100)] [SerializeField] private bool CanEditorAreaType; private void OnCanEditorAreaTypeChanged() { var map = _map; if (CanEditorAreaType) { CanBrushTerrainType = false; // CanBrushBuffCellIndex = false; } else { ClearRegionColor(); SceneView.RepaintAll(); canEditorRegion = false; } } [LabelText("地区列表")] [VerticalGroup("地区信息/RegionInfo")] [ShowIf("CanEditorAreaType")] [VerticalGroup("地区信息/RegionInfo"), Indent] [ListDrawerSettings(CustomAddFunction = "CustomAddRegion", CustomRemoveIndexFunction = "CustomRemoveRegion", DraggableItems = false)] public List 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(); } #endregion #region MainLife public static void OpenWindow(MapManager mapSceneEditor) { MapEditorSettings.Init(); thisWindow = GetWindow(); thisWindow.name = "MapGridWindow"; thisWindow.position = GUIHelper.GetEditorWindowRect().AlignCenter(800, 600); thisWindow._currMapManager = mapSceneEditor; thisWindow._currentMapData = null; 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.TerrainTypeProperties; _map.TerrainGridSystem.highlightEffect = HighlightEffect.Default; tgs.OnMouseClickOnGrid += OnMouseClickCell; UpdateRegion(); } protected override void OnEnable() { EnhancedTouchSupport.Enable(); TerrainTypeConfig.Load(); _buffPrefabDic = new Dictionary(); base.OnEnable(); } protected override void OnDisable() { DestroyBuffObj(); _buffPrefabDic = null; EnhancedTouchSupport.Disable(); base.OnDisable(); } protected override void OnGUI() { base.OnGUI(); if (_currMapManager == null || _currMapManager.MapData != _currentMapData) { Debug.Log("地图数据变更,请重新点击编辑网格!"); Close(); } } protected override void OnDestroy() { base.OnDestroy(); DestroyBuffObj(); if (_currMapManager != null) _currMapManager.SaveMapData(); ClearRegionColor(); _map.TerrainGridSystem.OnMouseClickOnGrid -= OnMouseClickCell; UnityEditor.Compilation.CompilationPipeline.compilationStarted -= OnCompilationStart; } #endregion #region Other 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 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 && !CanEditorAreaType) { return; } if (CanEditorAreaType && _currEditRegionArea == null) return; if (isOpTrue && TerrainTypeIndex >= 0 && CanBrushTerrainType) { SetCellBlockType(cellIndex, TerrainTypeIndex); } else if (!isOpTrue && CanBrushTerrainType) { if (_currentMapData.BlocksData[cellIndex].TerrainTypeIndex == TerrainTypeIndex) { ClearCellBlockType(cellIndex); } } if (isOpTrue && canEditorRegion) { _currEditRegionArea.AddPosition(cellIndex); } else if (!isOpTrue && canEditorRegion) { _currEditRegionArea.RemovePosition(cellIndex); } } private void SetCellBlockType(int cellIndex, int TerrainTypeIndex) { var map = _map; // Key: TerrainTypeIndex Value: tgs.territories.index if (!map.TerrainTypeIndexDic.ContainsKey(TerrainTypeIndex)) map.TerrainTypeIndexDic.Add(TerrainTypeIndex, map.TerrainTypeIndexDic.Count); if (!_terrainTypeConfig[TerrainTypeIndex].selectable) map.TerrainGridSystem.CellSetBorderVisible(cellIndex, false); map.SetTerrainType(cellIndex, TerrainTypeIndex); map.TerrainGridSystem.CellToggleRegionSurface(cellIndex, true, _terrainTypeConfig[TerrainTypeIndex].Color); var buffPath = _terrainTypeConfig[TerrainTypeIndex].buffObjectPath; if (!string.IsNullOrEmpty(buffPath)) { AddBuffCell(cellIndex, buffPath); } Debug.Log( $"Set Territory, cellIndex ({cellIndex}), terrain type ({TerrainTypeIndex}), name ({_terrainTypeConfig[TerrainTypeIndex].Color})"); } private void ClearCellBlockType(int cellIndex) { var map = _map; map.TerrainGridSystem.CellSetBorderVisible(cellIndex, true); map.TerrainGridSystem.CellHideRegionSurface(cellIndex); _map.SetBlockColor(cellIndex, false, _terrainTypeConfig[TerrainTypeIndex].Color); map?.SetTerrainType(cellIndex, -1); var buffPath = _terrainTypeConfig[TerrainTypeIndex].buffObjectPath; if (!string.IsNullOrEmpty(buffPath)) { RemoveBuffCell(cellIndex); } Debug.Log($"Cell Clear Territory, cellIndex({cellIndex})"); } private bool banSaveMapList = false; private void SetCellBorderType() { var map = _map; if (map != null) { map.TerrainGridSystem.cellBorderColor = cellBorderColor / 255f; map.TerrainGridSystem.cellBorderThickness = cellBorderWidth; } } private static IEnumerable GetTerrainTypeProperties() { _terrainTypeConfig = TerrainTypeConfig.TerrainTypeProperties; var list = new ValueDropdownList(); if (_terrainTypeConfig != null) { for (int i = 0; i < _terrainTypeConfig.Count; i++) { list.Add(_terrainTypeConfig[i].name, i); } } return list; } private void ClearRegionColor() { if (_map == null) return; for (int i = 0; i < _map.MapData.regions.Count; i++) { _map.SetRegionColor(i, false, regionColor); } } 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); 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(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); /*var buffParticle = buff.transform.Find("EndNotice").gameObject; var particleSystem = buffParticle.GetComponentInChildren(); if (particleSystem != null) { particleSystem.Play(); SceneView.RepaintAll(); }*/ return buff; } #endregion } }