using Framework; using Gameplay; using NPOI.SS.Formula.Functions; using System.Collections.Generic; using System.IO; using System.Linq; using Cysharp.Threading.Tasks; using TGS; using UnityEditor; using UnityEditor.SceneManagement; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UIElements; using static UnityEditor.Searcher.SearcherWindow.Alignment; public class EditorMap { private static EditorMap _instance; public static EditorMap Instance { get { if (_instance == null) { _instance = new EditorMap(); } return _instance; } } public delegate void OnMapChanged(); public OnMapChanged onMapChanged; public Map Current { get => _map; set { _map = value; onMapChanged?.Invoke(); } } private Map _map; } public class MapEditorUtils { public const float UPP = 100; public static Dictionary> mapObjectOccupyCells = new Dictionary>(); // public static Map CreateNewMap(int id, string name, int column, int row, string backgroundPath, MapData.EnvironmentType environmentType) // { // OpenMapScene(); // // var asset = AssetDatabase.LoadAssetAtPath(MapEditorConstant.MapTemplatePrefab); // var root = GameObject.Instantiate(asset); // var tgs = root.GetComponentInChildren(); // // tgs.columnCount = column; // tgs.rowCount = row; // // MapData mapData = new MapData(id, name, column, row, environmentType); // var map = Map.Create(root, mapData); // map.SetGroundTexture(AssetDatabase.LoadAssetAtPath(backgroundPath)); // map.ShowInfo((int)Map.InfoMask.ShowAll); // ResetCamera(); // return map; // } public static void OpenMapScene() { //GameSceneManager.Instance.ChangeScene(GameSceneManager.EnumScene.GameLevel); var scene = SceneManager.GetActiveScene(); if (scene.path == MapEditorConstant.MapEditorScene) { return; } else { EditorSceneManager.OpenScene(MapEditorConstant.MapEditorScene); } } // public static void SaveEditorMap() // { // var map = EditorMap.Instance.Current; // if (map != null) // { // var prefabFilePath = string.Format(Constants.MAP_ASSET_FORMAT_PATH, map.GetMapFileName()); // // // PrefabUtility.SaveAsPrefabAssetAndConnect(map.GameObject, // // prefabFilePath, InteractionMode.UserAction); // // var configFilePath = string.Format(Constants.MAP_CONFIG_FORMAT_PATH, map.GetMapFileName()); // // if (File.Exists(configFilePath)) // // { // // VersionControlSystem.Checkout(configFilePath); // // } // Framework.JsonHelper.SaveJson(configFilePath, map.MapData); // // if (File.Exists(prefabFilePath) && File.Exists(configFilePath)) // { // CustomPopUpWindow.PopUp($"Save Successfully:\n {prefabFilePath} \n {configFilePath} \n"); // } // } // } // public static Map LoadMap(TerrainGridSystem terrainGridSystem,MapData mapData) // { // //OpenMapScene(); // //ResetCamera(); // //MapUtils.UnLoadMap(EditorMap.Instance.Current); // var map = MapUtils.LoadMap(terrainGridSystem,mapData); // if (map != null) // { // map.ShowInfo((int)Map.InfoMask.ShowAll); // return map; // } // return null; // } public static void UnLoadMap(EditorMap editorMap) { MapUtils.UnLoadMap(editorMap.Current); editorMap.Current = null; } // public static void ResetCamera() // { // if (Camera.main == null) // { // var camera = new GameObject("Main Camera").AddComponent(); // camera.tag = "MainCamera"; // } // // var mainCamera = Camera.main; // var cameraController = mainCamera.gameObject.GetComponent(); // if (!cameraController) // { // cameraController = mainCamera.gameObject.AddComponent(); // } // // cameraController.Map = EditorMap.Instance.Current != null ? EditorMap.Instance.Current : null; // mainCamera.orthographic = true; // mainCamera.orthographicSize = cameraController.CameraMaxSize; // mainCamera.gameObject.transform.forward = Vector3.down; // mainCamera.gameObject.transform.up = Vector3.forward; // if (Application.isPlaying) // { // if (mainCamera != null) // { // GameObject.DontDestroyOnLoad(mainCamera.gameObject); // } // } // } /// /// 物件自动吸附格子 /// /// public static void ObjectAutoAdsorptionCell(GameObject mapObject) { var map = EditorMap.Instance.Current; MeshFilter meshFilter = mapObject.GetComponentInChildren(); if (meshFilter != null) { var bounds = CalculateBounds(meshFilter.sharedMesh); // Debug.Log($"包围盒大小:{bounds.size},包围盒中心位置:{bounds.center},最大:{bounds.max},最小:{bounds.min}"); Vector3 centerWorldPos = mapObject.transform.TransformPoint(new Vector3(bounds.center.x, 0f, bounds.center.z)); Cell cell = map.TerrainGridSystem.CellGetAtPosition(centerWorldPos, true); if (cell != null) { var nearestPoint = FindNearestPoint(cell.index, centerWorldPos); mapObject.transform.position = nearestPoint; Vector3 centerWorldPos2 = mapObject.transform.TransformPoint(new Vector3(bounds.center.x, 0f, bounds.center.z)); Vector3 moveVector = mapObject.transform.position - centerWorldPos2; mapObject.transform.position += moveVector; CalculateFloorArea(mapObject ,bounds); } } } /// /// 刷地图建筑物占地地块,默认刷为0号地块 /// public static void CalculateFloorArea(GameObject mapObject, Bounds bounds) { Dictionary terrainTypeConfig = TerrainTypeConfig.DicTerrainTypePropertie; var map = EditorMap.Instance.Current; if (mapObjectOccupyCells.TryGetValue(mapObject, out var cells)) { foreach (var cell in cells) { map.TerrainGridSystem.CellSetColor(cell, Color.clear); } cells.Clear(); } else { cells = new List(); mapObjectOccupyCells.Add(mapObject, cells); } var lowerLeft = mapObject.transform.TransformPoint(new Vector3(bounds.min.x, 0f, bounds.min.y)); var topRight = mapObject.transform.TransformPoint(new Vector3(bounds.max.x, 0f, bounds.max.y)); var lowerRight = mapObject.transform.TransformPoint(new Vector3(bounds.max.x, 0f, bounds.min.y)); var topLeft = mapObject.transform.TransformPoint(new Vector3(bounds.min.x, 0f, bounds.max.y)); var minPos = new Vector3(Mathf.Min(lowerLeft.x, topRight.x, lowerRight.x, topLeft.x), 0f, Mathf.Min(lowerLeft.z, topRight.z, lowerRight.z, topLeft.z)); var maxPos = new Vector3(Mathf.Max(lowerLeft.x, topRight.x, lowerRight.x, topLeft.x), 0f, Mathf.Max(lowerLeft.z, topRight.z, lowerRight.z, topLeft.z)); if (map.TerrainGridSystem.CellGetAtPosition(minPos, true) != null && map.TerrainGridSystem.CellGetAtPosition(maxPos, true) != null) { var minCellPos = map.TGSCellIndex2BlockPosition(map.TerrainGridSystem.CellGetAtPosition(minPos, true).index); var maxCellPos = map.TGSCellIndex2BlockPosition(map.TerrainGridSystem.CellGetAtPosition(maxPos, true).index); var minX = Mathf.Min(minCellPos.x, maxCellPos.x); var maxX = Mathf.Max(minCellPos.x, maxCellPos.x); var minY = Mathf.Min(minCellPos.y, maxCellPos.y); var maxY = Mathf.Max(minCellPos.y, maxCellPos.y); //Debug.Log($"最大y:{maxY},最小y:{minY},最大x:{maxX},最小x:{minX}"); for (int i = minX; i <= maxX; ++i) { for(int j = minY; j <= maxY; ++j) { var cellIndex = map.BlockPosition2TGSCellIndex(new(i, j)); cells.Add(cellIndex); map.TerrainGridSystem.CellSetColor(cellIndex, terrainTypeConfig[0].Color); } } } } /// /// 计算3m以下的包围盒大小 /// /// /// public static Bounds CalculateBounds(Mesh mesh) { float limitHeight = 3f; if (mesh != null) { Vector3[] vertices = mesh.vertices; List limitVertices = vertices.Where(vertex => vertex.z <= limitHeight).ToList(); Bounds bounds = new Bounds(new Vector3(limitVertices[0].x, limitVertices[0].y, 0f), Vector3.zero); foreach (Vector3 vertex in limitVertices) { bounds.Encapsulate(new Vector3(vertex.x, vertex.y, 0f)); } return bounds; } else { return new Bounds(); } } /// /// 寻找六边形中距离最近的点 /// /// /// /// public static Vector3 FindNearestPoint(int cellIndex, Vector3 centerPos) { var map = EditorMap.Instance.Current; Dictionary vertices = new Dictionary(); for (int index = 0;index < map.TerrainGridSystem.CellGetVertexCount(cellIndex); index++) { var vertex = map.TerrainGridSystem.CellGetVertexPosition(cellIndex, index); float distance = Vector3.Distance(vertex, centerPos); vertices.Add(vertex, distance); } vertices.Add(map.TGSCellIndex2WorldPosition(cellIndex), Vector3.Distance(map.TGSCellIndex2WorldPosition(cellIndex), centerPos)); var neareatPoint = vertices.FirstOrDefault(x => x.Value == vertices.Values.Min()).Key; return neareatPoint; } }