using System; using System.Diagnostics; using System.IO; using Framework; using Gameplay; using LC.Newtonsoft.Json; using UnityEngine; using Sirenix.OdinInspector; using TGS; using UnityEngine.Serialization; using Debug = DebugUtil; using JsonSerializer = Newtonsoft.Json.JsonSerializer; using Object = UnityEngine.Object; #if UNITY_EDITOR using UnityEditor; using UnityEditor.SceneManagement; #endif [ExecuteAlways] public class MapSceneEditor : MonoBehaviour { //#if UNITY_EDITOR public GameObject treeRoot; private const string MAP_DATA_NAME = "MapData"; private const float UPP = 100; private TerrainGridSystem _tgs; public TerrainGridSystem TGS => _tgs; public bool HasSetGround => _groundMaterial != null && _groundMaterial.mainTexture != null; public bool HasMap => _mapDataJson != null; public MapData MapData { get => _mapData; set { if (_mapData != value) { _mapData = value; if (value == null) { Map = null; } else { Map = MapUtils.LoadMap(_tgs, _mapData); MapUtils.BindCameraController(_camera, Map); var cameraController = _camera.gameObject.GetComponent(); cameraController.InitializeCameraPosition(initialCameraPosition); } } } } public Map Map { get; private set; } public int Width => _tgs.columnCount; public int Height => _tgs.rowCount; [HideInInspector] [SerializeField] private Camera _camera; [TableColumnWidth(57, Resizable = false)] [PreviewField(Alignment = ObjectFieldAlignment.Center)] [AssetList(Path = (Constants.MAP_TEXTURE_PATH_WITHOUT_ASSET))] [OnValueChanged("OnMapMaterialChanged")] [LabelText("地面图")] [SerializeField] private Material _groundMaterial; private void OnMapMaterialChanged() { if (HasSetGround) { _tgs.GetComponent().sharedMaterial = _groundMaterial; ResetMapScale(); } } [LabelText("地图尺寸")] [LabelWidth(100)] //[ReadOnly] [SerializeField] [OnValueChanged("OnMapScaleChanged")] [ShowIf("HasSetGround")] private Vector2 _mapScale; private void OnMapScaleChanged() { //防止网格上的显示在修改缩放后出现问题 _tgs.regularHexagons = false; var currScale = _tgs.transform.localScale; var xRatio = _mapScale.x / currScale.x; var yRatio = _mapScale.y / currScale.y; var ration = Mathf.Approximately(xRatio, 1) ? yRatio : xRatio; _mapScale = currScale * ration; _tgs.transform.localScale = new Vector3(_mapScale.x, _mapScale.y, 1); _tgs.regularHexagons = true; } [Button("重置地图大小")] [ShowIf("HasSetGround")] private void ResetMapScale() { if (HasSetGround) { //防止网格上的显示在修改缩放后出现问题 _tgs.regularHexagons = false; _mapScale = (new Vector2(_groundMaterial.mainTexture.width, _groundMaterial.mainTexture.height) / UPP); _tgs.transform.localScale = new Vector3(_mapScale.x, _mapScale.y, 1); _tgs.regularHexagons = true; } } [LabelText("网格宽高")] [OnValueChanged("OnGridWidthHeightChanged")] [HideIf("HasMap")] [SerializeField] private Vector2Int _gridWidthHeight; private void OnGridWidthHeightChanged() { _tgs.columnCount = _gridWidthHeight.x; _tgs.rowCount = _gridWidthHeight.y; } [HideIf("HasMap")] [Button("铺满网格")] private void FillMapWithGrid() { var width = GetHexCount(_mapScale.x, _tgs.regularHexagonsWidth, false); var height = GetHexCount(_mapScale.y, _tgs.regularHexagonsWidth, true); _tgs.rowCount = height; _tgs.columnCount = width; _gridWidthHeight = new Vector2Int(width, height); } [LabelText("摄像机初始视角")] [LabelWidth(150)] [OnValueChanged("OnInitialCameraPositionChanged")] public Vector2Int initialCameraPosition; private void OnInitialCameraPositionChanged() { if (_camera != null && HasMap) { initialCameraPosition.x = Math.Clamp(initialCameraPosition.x, 0, Height - 1); initialCameraPosition.y = Math.Clamp(initialCameraPosition.y, 0, Width - 1); var cameraController = _camera.gameObject.GetComponent(); if (_mapData != null) _mapData.initialCameraPosition = initialCameraPosition; cameraController.InitializeCameraPosition(initialCameraPosition); } } public TextAsset MapDataJson { get => _mapDataJson; private set { var data = JsonToMapData(value); if (CheckMapData(data)) { _mapDataJson = value; MapData = data; } else { _mapDataJson = null; MapData = null; } } } [LabelText("地图数据")] [ShowIf("HasSetGround")] [OnValueChanged("OnMapDataJsonChanged")] [SerializeField] private TextAsset _mapDataJson; [Space] [HideLabel] [ShowIf("HasMap")] [SerializeField] private MapData _mapData; private void OnMapDataJsonChanged(TextAsset k_mapDataJson) { MapDataJson = k_mapDataJson; } [Button("创建地图数据")] [ShowIf("HasSetGround")] private void CreateMapData() { #if UNITY_EDITOR var scene = gameObject.scene; // var scenePath = scene.path; var mapDataDir = Path.GetDirectoryName(Constants.MAP_CONFIG_FORMAT_PATH); var count = AssetDatabase.FindAssets("t:TextAsset", new[] { mapDataDir }).Length; var dataName = $"{scene.name}_{count + 1}"; var dataPath = $"{mapDataDir}/{dataName}.json"; using (var fileStream = File.Create(dataPath)) { } AssetDatabase.Refresh(); var textAsset = AssetDatabase.LoadAssetAtPath(dataPath); EditorGUIUtility.PingObject(textAsset); if (MapDataJson == null) MapDataJson = textAsset; #endif } private int GetHexCount(float totalLength, float hexWidth, bool isDiagonal) { if (isDiagonal) return Mathf.FloorToInt((4 * totalLength) / (3 * hexWidth) - 1 / 3f); else { var sqrt3 = Mathf.Sqrt(3); var countInFloat = (totalLength - (sqrt3 / 4 * hexWidth)) / (Mathf.Sqrt(3) / 2 * hexWidth); return Mathf.FloorToInt(countInFloat); } } private bool CheckMapData(MapData k_mapData) { if (k_mapData == null) return false; if (k_mapData.width != Width || k_mapData.height != Height) { Debug.LogError("当前地图数据宽高和当前地板宽高不匹配!"); return false; } return true; } private MapData JsonToMapData(TextAsset jsonText) { if (jsonText != null) { var jsonStr = jsonText.text; if (string.IsNullOrEmpty(jsonStr)) { var mapData = new MapData { width = Width, height = Height }; mapData.ResetBlocks(); return mapData; } else { return JsonConvert.DeserializeObject(jsonStr); } } return null; } #region MainLife private void OnEnable() { var objs = Object.FindObjectsOfType(); if (objs == null || objs.Length == 0) { Debug.LogError("Terrain Grid System Is Null!"); return; } _tgs = null; foreach (var tgs in objs) { if (tgs.gameObject.scene == gameObject.scene) _tgs = tgs; } if (_tgs == null) { Debug.LogError("Terrain Grid System Is Null!"); return; } _gridWidthHeight = new Vector2Int(_tgs.columnCount, _tgs.rowCount); MapData = JsonToMapData(_mapDataJson); _tgs.showCells = true; _tgs.colorizeTerritories = true; _tgs.TerritoryDestroyAll(); } private void Awake() { if (Application.isPlaying) { if (_camera != null) _camera.gameObject.SetActive(false); if (treeRoot != null) { //StaticBatchingUtility.Combine(treeRoot); } } } [Button("保存")] public void SaveMapData() { #if UNITY_EDITOR if (_mapDataJson != null && !Application.isPlaying) { var path = AssetDatabase.GetAssetPath(_mapDataJson); JsonHelper.SaveJson(path, _mapData); Debug.Log($"保存地图数据成功!"); EditorSceneManager.SaveOpenScenes(); AssetDatabase.Refresh(); } #endif } [Button("打印树数量")] private void LogTreeCount() { var objs = Object.FindObjectsOfType(); var count = 0; var vertexCount = 0; var triangles = 0; var treeCountInScreen = 0; var mainCam = Camera.main; foreach (var treeRenderer in objs) { if (treeRenderer.gameObject.name.ToLower().Contains("tree")) { count++; var viewPortPoint = mainCam.WorldToViewportPoint(treeRenderer.transform.position); if (viewPortPoint.x >= 0 && viewPortPoint.x <= 1 && viewPortPoint.y >= 0 && viewPortPoint.y <= 1) { treeCountInScreen++; var mesh = treeRenderer.gameObject.GetComponent().sharedMesh; vertexCount += mesh.vertexCount; triangles += mesh.triangles.Length/3; } } } Debug.Log($"tree count:{count} treeInScreen:{treeCountInScreen} vertexCount:{vertexCount} triangles:{triangles}"); } private void OnDestroy() { SaveMapData(); } #endregion //#endif }