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 const string BuffPrefabPath = "Art/Other/hud"; 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 Dictionary _buffPathDic; #endregion #region Editor [Button("保存")] private void RebuildPrefab() { _currMapManager.SaveBuffObjCellIndex(_buffPathDic); _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; _map.TerrainGridSystem.colorizeTerritories = true; } } [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 = AssetDatabase.LoadAssetAtPath(cell.path); if (buffObj == null) { DebugUtil.LogError("读不到指示图标: {0}", cell.path); } _buffPrefabDic.Add(cell.cellIndex, CreateBuffObj(cell.cellIndex, buffObj)); _buffPathDic.Add(cell.cellIndex, cell.path); } } private void DestroyBuffObj() { if (_buffPrefabDic == null) return; foreach (var buff in _buffPrefabDic) { if (buff.Value != null) DestroyImmediate(buff.Value); } _buffPrefabDic.Clear(); _buffPathDic.Clear(); } private void LoadMap(TerrainGridSystem tgs, MapData data, Map map) { _currentMapData = data; _map = map; //MapEditorUtils.LoadMap(tgs, data); _terrainTypeConfig = TerrainTypeConfig.TerrainTypeProperties; _map.TerrainGridSystem.highlightEffect = HighlightEffect.Default; // for (int i = 0; i < _map.MapData.BlocksData.Count; i++) // { // if (_map.MapData.BlocksData[i].TerrainTypeIndex != -1) // { // if (_terrainTypeConfig[_map.MapData.BlocksData[i].TerrainTypeIndex].emptyBlock) // { // _map.TerrainGridSystem.CellSetBorderVisible(i, false); // } // } // } //MapEditorUtils.ResetCamera(); // if (Camera.main != null) // { // var cameraController = Camera.main.gameObject.GetComponent(); // //cameraController.SwitchCameraView(false); // } tgs.OnMouseClickOnGrid += OnMouseClickCell; //tgs.OnMouseMoveOnGrid += OnMouseMoveOnCell; UpdateRegion(); } protected override void OnEnable() { EnhancedTouchSupport.Enable(); TerrainTypeConfig.Load(); _buffPrefabDic = new Dictionary(); _buffPathDic = new Dictionary(); base.OnEnable(); } protected override void OnDisable() { DestroyBuffObj(); _buffPrefabDic = null; _buffPathDic = 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(); //SetCellBorderType(); _map.TerrainGridSystem.OnMouseClickOnGrid -= OnMouseClickCell; //_map.TerrainGridSystem.OnMouseMoveOnGrid -= OnMouseMoveOnCell; //_map.TerrainGridSystem.TerritoryDestroyAll(); 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 OnMouseMoveOnCell(TerrainGridSystem tgs, int cellIndex, bool isControl, bool isShift) { OnCellOperation(tgs, cellIndex, isControl); } private void OnCellOperation(TerrainGridSystem tgs, int cellIndex, bool isOpTrue) { if (!CanBrushTerrainType && !CanEditorAreaType && !CanBrushBuffCellIndex) { return; } if (CanEditorAreaType && _currEditRegionArea == null) return; var map = _map; if (isOpTrue && TerrainTypeIndex >= 0 && CanBrushTerrainType) { SetCellTerritory(tgs, cellIndex, TerrainTypeIndex); } else if (!isOpTrue && CanBrushTerrainType) { if (_currentMapData.BlocksData[cellIndex].TerrainTypeIndex == TerrainTypeIndex) { ClearCellTerritory(tgs, cellIndex); } } if (isOpTrue && canEditorRegion) { _currEditRegionArea.AddPosition(cellIndex); } else if (!isOpTrue && canEditorRegion) { _currEditRegionArea.RemovePosition(cellIndex); } if (isOpTrue && CanBrushBuffCellIndex) { AddBuffCell(cellIndex); } else if (!isOpTrue && CanBrushBuffCellIndex) { RemoveBuffCell(cellIndex); } } private void SetCellTerritory(TerrainGridSystem tgs, int cellIndex, int TerrainTypeIndex) { var map = _map; // Key: TerrainTypeIndex Value: tgs.territories.index if (!map.TerrainTypeIndexDic.ContainsKey(TerrainTypeIndex)) { Territory territory = tgs.TerritoryCreate(cellIndex); map.TerrainTypeIndexDic.Add(TerrainTypeIndex, map.TerrainTypeIndexDic.Count); territory.fillColor = _terrainTypeConfig[TerrainTypeIndex].Color; } if (!_terrainTypeConfig[TerrainTypeIndex].selectable) { map.TerrainGridSystem.CellSetBorderVisible(cellIndex, false); } map?.SetTerrainType(cellIndex, TerrainTypeIndex); tgs.CellSetTerritory(cellIndex, map.TerrainTypeIndexDic[TerrainTypeIndex]); Debug.Log( $"Set Territory, cellIndex ({cellIndex}), terrain type ({TerrainTypeIndex}), name ({_terrainTypeConfig[TerrainTypeIndex].Color})"); } private void ClearCellTerritory(TerrainGridSystem tgs, int cellIndex) { var map = _map; map.TerrainGridSystem.CellSetBorderVisible(cellIndex, true); var tIndex = tgs.CellGetTerritoryIndex(cellIndex); if (tIndex != -1) { tgs.CellSetTerritory(cellIndex, -1); map?.SetTerrainType(cellIndex, -1); 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) { // 阵地buff指示 if (!_buffPrefabDic.ContainsKey(cellIndex) && buffObject != null) { var buff = CreateBuffObj(cellIndex, buffObject); _buffPrefabDic.Add(cellIndex, buff); var path = "Assets/" + BuffPrefabPath + "/" + buffObject.name+".prefab"; _buffPathDic.Add(cellIndex, path); 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); _buffPathDic.Remove(cellIndex); DebugUtil.Log("格子{0}移除指示图标", cellIndex); } } private GameObject CreateBuffObj(int cellIndex, GameObject buffObj) { var posV3 = _map.TGSCellIndex2WorldPosition(cellIndex); var buff = Instantiate(buffObj, posV3, buffObj.transform.rotation); buff.SetActive(true); /*var buffParticle = buff.transform.Find("EndNotice").gameObject; var particleSystem = buffParticle.GetComponentInChildren(); if (particleSystem != null) { particleSystem.Play(); SceneView.RepaintAll(); }*/ return buff; } #endregion } }