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

326 lines
11 KiB
C#
Raw Normal View History

2023-08-22 19:08:45 +08:00
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;
2026-04-27 11:55:39 +08:00
using Cell = TGS.Cell;
2023-08-22 19:08:45 +08:00
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<GameObject, List<int>> mapObjectOccupyCells = new Dictionary<GameObject, List<int>>();
2023-11-16 18:27:03 +08:00
// public static Map CreateNewMap(int id, string name, int column, int row, string backgroundPath, MapData.EnvironmentType environmentType)
// {
// OpenMapScene();
//
// var asset = AssetDatabase.LoadAssetAtPath<GameObject>(MapEditorConstant.MapTemplatePrefab);
// var root = GameObject.Instantiate(asset);
// var tgs = root.GetComponentInChildren<TerrainGridSystem>();
//
// 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<Texture2D>(backgroundPath));
// map.ShowInfo((int)Map.InfoMask.ShowAll);
// ResetCamera();
// return map;
// }
2023-08-22 19:08:45 +08:00
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);
}
}
2023-11-15 18:19:17 +08:00
// 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");
// }
// }
// }
2023-08-22 19:08:45 +08:00
2023-12-18 19:42:46 +08:00
// 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;
// }
2023-08-22 19:08:45 +08:00
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>();
// camera.tag = "MainCamera";
// }
//
// var mainCamera = Camera.main;
// var cameraController = mainCamera.gameObject.GetComponent<CameraController>();
// if (!cameraController)
// {
// cameraController = mainCamera.gameObject.AddComponent<CameraController>();
// }
//
// 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);
// }
// }
// }
2023-08-22 19:08:45 +08:00
/// <summary>
/// 物件自动吸附格子
/// </summary>
/// <param name="mapObject"></param>
public static void ObjectAutoAdsorptionCell(GameObject mapObject)
{
var map = EditorMap.Instance.Current;
MeshFilter meshFilter = mapObject.GetComponentInChildren<MeshFilter>();
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);
2023-10-19 15:00:19 +08:00
if (cell != null)
{
var nearestPoint = FindNearestPoint(cell.index, centerWorldPos);
2023-08-22 19:08:45 +08:00
2023-10-19 15:00:19 +08:00
mapObject.transform.position = nearestPoint;
2023-08-22 19:08:45 +08:00
2023-10-19 15:00:19 +08:00
Vector3 centerWorldPos2 = mapObject.transform.TransformPoint(new Vector3(bounds.center.x, 0f, bounds.center.z));
2023-08-22 19:08:45 +08:00
2023-10-19 15:00:19 +08:00
Vector3 moveVector = mapObject.transform.position - centerWorldPos2;
2023-08-22 19:08:45 +08:00
2023-10-19 15:00:19 +08:00
mapObject.transform.position += moveVector;
2023-08-22 19:08:45 +08:00
2023-10-19 15:00:19 +08:00
CalculateFloorArea(mapObject ,bounds);
}
2023-08-22 19:08:45 +08:00
}
}
/// <summary>
/// 刷地图建筑物占地地块默认刷为0号地块
/// </summary>
public static void CalculateFloorArea(GameObject mapObject, Bounds bounds)
{
2025-06-25 14:29:40 +08:00
Dictionary<int, TerrainTypeProperty> terrainTypeConfig = TerrainTypeConfig.DicTerrainTypePropertie;
2023-08-22 19:08:45 +08:00
var map = EditorMap.Instance.Current;
2023-10-19 15:00:19 +08:00
if (mapObjectOccupyCells.TryGetValue(mapObject, out var cells))
2023-08-22 19:08:45 +08:00
{
2023-10-19 15:00:19 +08:00
foreach (var cell in cells)
2023-08-22 19:08:45 +08:00
{
map.TerrainGridSystem.CellSetColor(cell, Color.clear);
}
2023-10-19 15:00:19 +08:00
cells.Clear();
2023-08-22 19:08:45 +08:00
}
else
{
2023-10-19 15:00:19 +08:00
cells = new List<int>();
mapObjectOccupyCells.Add(mapObject, cells);
2023-08-22 19:08:45 +08:00
}
2023-10-19 15:00:19 +08:00
var lowerLeft = mapObject.transform.TransformPoint(new Vector3(bounds.min.x, 0f, bounds.min.y));
2023-08-22 19:08:45 +08:00
2023-10-19 15:00:19 +08:00
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));
2023-08-22 19:08:45 +08:00
2023-10-19 15:00:19 +08:00
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));
2023-08-22 19:08:45 +08:00
2023-10-19 15:00:19 +08:00
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));
2023-08-22 19:08:45 +08:00
2023-10-19 15:00:19 +08:00
if (map.TerrainGridSystem.CellGetAtPosition(minPos, true) != null &&
map.TerrainGridSystem.CellGetAtPosition(maxPos, true) != null)
2023-08-22 19:08:45 +08:00
{
2023-10-19 15:00:19 +08:00
var minCellPos = map.TGSCellIndex2BlockPosition(map.TerrainGridSystem.CellGetAtPosition(minPos, true).index);
2023-08-22 19:08:45 +08:00
2023-10-19 15:00:19 +08:00
var maxCellPos = map.TGSCellIndex2BlockPosition(map.TerrainGridSystem.CellGetAtPosition(maxPos, true).index);
2023-08-22 19:08:45 +08:00
2023-10-19 15:00:19 +08:00
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)
2023-08-22 19:08:45 +08:00
{
2023-10-19 15:00:19 +08:00
for(int j = minY; j <= maxY; ++j)
{
2023-08-22 19:08:45 +08:00
2023-10-19 15:00:19 +08:00
var cellIndex = map.BlockPosition2TGSCellIndex(new(i, j));
2023-08-22 19:08:45 +08:00
2023-10-19 15:00:19 +08:00
cells.Add(cellIndex);
2023-08-22 19:08:45 +08:00
2023-10-19 15:00:19 +08:00
map.TerrainGridSystem.CellSetColor(cellIndex, terrainTypeConfig[0].Color);
}
2023-08-22 19:08:45 +08:00
}
}
2023-10-19 15:00:19 +08:00
2023-08-22 19:08:45 +08:00
}
2023-10-19 15:00:19 +08:00
2023-08-22 19:08:45 +08:00
/// <summary>
/// 计算3m以下的包围盒大小
/// </summary>
/// <param name="mesh"></param>
/// <returns></returns>
public static Bounds CalculateBounds(Mesh mesh)
{
float limitHeight = 3f;
if (mesh != null)
{
Vector3[] vertices = mesh.vertices;
List<Vector3> 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();
}
}
/// <summary>
/// 寻找六边形中距离最近的点
/// </summary>
/// <param name="cellIndex"></param>
/// <param name="centerPos"></param>
/// <returns></returns>
public static Vector3 FindNearestPoint(int cellIndex, Vector3 centerPos)
{
var map = EditorMap.Instance.Current;
Dictionary<Vector3,float> vertices = new Dictionary<Vector3,float>();
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;
}
}