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

644 lines
24 KiB
C#
Raw Normal View History

2023-12-15 18:32:21 +08:00
using System.IO;
using cfg.FightCfg;
2023-12-15 18:32:21 +08:00
using Gameplay;
using MapEditor;
using Sirenix.OdinInspector.Editor;
using TGS;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
2024-08-08 18:57:34 +08:00
using UnityEngine.Rendering.Universal;
2025-08-25 17:34:39 +08:00
using UnityEngine.SceneManagement;
2024-08-08 18:57:34 +08:00
using Constants = Framework.Constants;
2023-12-15 18:32:21 +08:00
using Object = UnityEngine.Object;
[CustomEditor(typeof(MapManager))]
public class MapManagerInspector : OdinEditor
{
2023-12-21 15:05:08 +08:00
private enum ECameraCheckCorner
{
None,
LeftDown,
RightDown,
LeftUp,
RightUp,
}
private readonly string[] checkCornerType = new[]
{
"无",
"左下角",
"右下角",
"左上角",
"右上角",
};
2023-12-15 18:32:21 +08:00
private readonly string[] environmentType = new[]
{
"平原",
"山地",
"草原",
"林地",
"雪地",
"泥地",
"戈壁",
"沙漠",
"高原",
"竞技场",
2025-12-10 16:44:38 +08:00
"火车关",
2023-12-15 18:32:21 +08:00
};
private MapManager Target => target as MapManager;
private TerrainGridSystem TGS => Target.TGS;
private MapData MapData => Target.MapData;
private Map Map => Target.Map;
2024-08-08 18:57:34 +08:00
2023-12-15 18:32:21 +08:00
private bool _isEditingGrid;
2023-12-21 15:05:08 +08:00
private bool _isEditingCameraOriginPos;
private bool _isCheckingCamera;
2024-08-12 13:01:56 +08:00
private bool _isEditingCameraInfo;
2023-12-15 18:32:21 +08:00
2023-12-21 15:05:08 +08:00
private ECameraCheckCorner _checkType;
2023-12-15 18:32:21 +08:00
2025-08-25 17:34:39 +08:00
private const string LegionMapConfigPrefix = "LegionMapData_";
2024-07-02 18:13:12 +08:00
private const string MapConfigPrefix = "MapData_";
2024-08-08 18:57:34 +08:00
private const string UICanvasCheck = "Assets/Editor/MapEditor/LevelUICheck.prefab";
private GameObject _uiLevelCheck;
2024-07-02 18:13:12 +08:00
2023-12-21 15:05:08 +08:00
//scene gui
2023-12-15 18:32:21 +08:00
private bool _isHitGround;
private Vector3 _mouseHitPosition;
private Event _currEvent;
private GameObject _ground;
private RaycastHit[] _hits = new RaycastHit[1];
protected override void OnEnable()
{
base.OnEnable();
var allTgs = Object.FindObjectsOfType<TerrainGridSystem>();
foreach (var tgs in allTgs)
{
if (tgs != TGS)
{
2023-12-18 20:31:58 +08:00
foreach (Transform child in tgs.transform)
{
child.gameObject.SetActive(false);
}
2023-12-15 18:32:21 +08:00
}
}
2023-12-18 19:42:46 +08:00
DeActiveScene();
ApplyInitialCameraPosition();
2023-12-18 19:42:46 +08:00
}
private void DeActiveScene()
{
var sceneManagers = FindObjectsOfType<NLDSceneManager>();
foreach (var sceneManager in sceneManagers)
{
2023-12-20 12:47:57 +08:00
SceneVisibilityManager.instance.DisablePicking(sceneManager.Art.gameObject, true);
2023-12-18 19:42:46 +08:00
}
2023-12-15 18:32:21 +08:00
}
protected override void OnDisable()
{
2024-08-08 18:57:34 +08:00
if (_uiLevelCheck)
DestroyImmediate(_uiLevelCheck);
2024-08-12 13:01:56 +08:00
if (GameObject.Find("LevelUICheck(Clone)"))
2024-08-08 18:57:34 +08:00
DestroyImmediate(GameObject.Find("LevelUICheck(Clone)"));
2023-12-15 18:32:21 +08:00
base.OnDisable();
Target.SaveMapData();
}
/// <summary>
/// 加载地图后应用存储的相机初始位置与FOV
/// </summary>
private void ApplyInitialCameraPosition()
{
if (Application.isPlaying)
return;
if (Target == null || Target.CameraController == null || Map == null || TGS == null)
return;
var camera = Target.CameraController;
camera.CameraBounds = TGS.bounds;
var initPos = Map.BlockPosition2WorldPosition(MapData.initialCameraPosition);
camera.InitializeCameraPosition(
initPos,
MapData.cameraMarginInfo,
camera.rightMargin,
camera.leftMargin,
camera.topMargin,
camera.bottomMargin);
}
2023-12-15 18:32:21 +08:00
public override void OnInspectorGUI()
{
2023-12-21 15:05:08 +08:00
if (Application.isPlaying)
2023-12-20 12:47:57 +08:00
return;
2023-12-15 18:32:21 +08:00
base.OnInspectorGUI();
DrawCreateMapData();
DrawMapData();
2023-12-20 12:47:57 +08:00
EditorSceneManager.MarkSceneDirty(Target.gameObject.scene);
2023-12-15 18:32:21 +08:00
}
private void DrawCreateMapData()
{
2023-12-21 19:08:04 +08:00
if (GUILayout.Button("创建地图配置"))
2023-12-15 18:32:21 +08:00
{
2023-12-21 19:08:04 +08:00
var mapDataDir = Path.GetDirectoryName(Constants.MAP_CONFIG_FORMAT_PATH);
2025-08-25 17:34:39 +08:00
var mapDataName = Target.isLegionMap
? $"{mapDataDir}/{LegionMapConfigPrefix + Target.gameObject.scene.name}.json"
: $"{mapDataDir}/{MapConfigPrefix + Target.gameObject.scene.name}.json";
var dataPath = EditorUtil.GetAssetUniquePath(mapDataName, out var textName);
2023-12-21 19:08:04 +08:00
using (var fileStream = File.Create(dataPath))
2023-12-15 18:32:21 +08:00
{
}
2023-12-21 19:08:04 +08:00
AssetDatabase.Refresh();
var textAsset = AssetDatabase.LoadAssetAtPath<TextAsset>(dataPath);
EditorGUIUtility.PingObject(textAsset);
2023-12-26 17:05:08 +08:00
Target.MapDataJson = textAsset;
2023-12-15 18:32:21 +08:00
}
}
private void DrawMapData()
{
var mapAsset = Target.MapDataJson;
EditorGUI.BeginChangeCheck();
mapAsset = EditorGUILayout.ObjectField("地图配置", mapAsset, typeof(TextAsset), false) as TextAsset;
if (EditorGUI.EndChangeCheck())
{
Target.MapDataJson = mapAsset;
ApplyInitialCameraPosition();
}
2023-12-15 18:32:21 +08:00
if (Target.MapDataJson != null)
{
EditorGUI.BeginChangeCheck();
2023-12-18 19:42:46 +08:00
var column = EditorGUILayout.DelayedIntField("网格宽度", TGS.columnCount);
var raw = EditorGUILayout.DelayedIntField("网格高度", TGS.rowCount);
2023-12-15 18:32:21 +08:00
if (EditorGUI.EndChangeCheck())
{
2023-12-18 19:42:46 +08:00
var width = column;
var height = raw;
MapData.Width = width;
MapData.Height = height;
2023-12-15 18:32:21 +08:00
TGS.columnCount = width;
TGS.rowCount = height;
2023-12-18 19:42:46 +08:00
Target.SaveMapData();
Target.Refresh();
2023-12-20 12:47:57 +08:00
}
EditorGUI.BeginChangeCheck();
var gridOffset = EditorGUILayout.Vector2Field("网格偏移",
new Vector2(TGS.transform.position.x, TGS.transform.position.z));
if (EditorGUI.EndChangeCheck())
{
var transform = TGS.transform;
transform.position = new Vector3(gridOffset.x, 0, gridOffset.y);
MapData.position = transform.position;
2023-12-15 18:32:21 +08:00
}
MapData.environmentType =
(ELevelTerrainType)EditorGUILayout.Popup("环境类型", (int)MapData.environmentType, environmentType);
2023-12-18 19:42:46 +08:00
2023-12-21 15:30:37 +08:00
DrawCheckCamera();
DrawCameraOriginPosition();
2023-12-21 15:05:08 +08:00
2023-12-21 15:30:37 +08:00
if (GUILayout.Button("打开网格编辑器"))
2023-12-21 15:05:08 +08:00
{
2025-08-25 17:34:39 +08:00
MapGridWindow.OpenWindow(Target, Target.isLegionMap);
2023-12-21 15:05:08 +08:00
}
// DrawCameraInfo();
2023-12-21 15:30:37 +08:00
if (GUILayout.Button("保存"))
2023-12-21 15:05:08 +08:00
{
2023-12-21 15:30:37 +08:00
Target.SaveMapData();
2023-12-21 15:05:08 +08:00
}
2023-12-21 15:30:37 +08:00
}
}
2023-12-21 15:05:08 +08:00
/*private void DrawCameraInfo()
2024-08-12 13:01:56 +08:00
{
_isEditingCameraInfo = EditorGUILayout.Toggle("编辑相机间距", _isEditingCameraInfo);
if (_isEditingCameraInfo)
{
MapData.cameraMarginInfo.leftMarginInFight =
EditorGUILayout.FloatField("战斗中相机左间距", MapData.cameraMarginInfo.leftMarginInFight);
MapData.cameraMarginInfo.rightMarginInFight =
EditorGUILayout.FloatField("战斗中相机右间距", MapData.cameraMarginInfo.rightMarginInFight);
MapData.cameraMarginInfo.topMarginInFight =
EditorGUILayout.FloatField("战斗中相机上间距", MapData.cameraMarginInfo.topMarginInFight);
MapData.cameraMarginInfo.bottomMarginInFight =
EditorGUILayout.FloatField("战斗中相机下间距", MapData.cameraMarginInfo.bottomMarginInFight);
MapData.cameraMarginInfo.leftMarginInPre =
EditorGUILayout.FloatField("准备前相机左间距", MapData.cameraMarginInfo.leftMarginInPre);
MapData.cameraMarginInfo.rightMarginInPre =
EditorGUILayout.FloatField("准备前相机右间距", MapData.cameraMarginInfo.rightMarginInPre);
MapData.cameraMarginInfo.topMarginInInPre =
EditorGUILayout.FloatField("准备前相机上间距", MapData.cameraMarginInfo.topMarginInInPre);
MapData.cameraMarginInfo.bottomMarginInPre =
EditorGUILayout.FloatField("准备前相机下间距", MapData.cameraMarginInfo.bottomMarginInPre);
}
}*/
2024-08-12 13:01:56 +08:00
2023-12-21 15:30:37 +08:00
private void DrawCheckCamera()
{
if (!_isCheckingCamera && GUILayout.Button("检查相机可否超出地图"))
{
_isCheckingCamera = true;
2025-04-29 15:30:55 +08:00
Target.CameraController.GetComponent<Camera>().orthographicSize = Target.CameraController.CameraMaxSize;
2024-08-08 18:57:34 +08:00
if (_uiLevelCheck == null)
{
var ui = AssetDatabase.LoadAssetAtPath<GameObject>(UICanvasCheck);
_uiLevelCheck = Instantiate(ui);
var uiCamera = _uiLevelCheck.transform.Find("UICamera").GetComponent<Camera>();
var baseCameraData = Camera.main?.GetComponent<UniversalAdditionalCameraData>();
baseCameraData?.cameraStack.Add(uiCamera);
}
2024-08-12 13:01:56 +08:00
}
2023-12-21 15:30:37 +08:00
if (_isCheckingCamera && GUILayout.Button("退出相机检查"))
{
2024-08-08 18:57:34 +08:00
if (_uiLevelCheck)
DestroyImmediate(_uiLevelCheck);
2023-12-21 15:30:37 +08:00
_isCheckingCamera = false;
2025-04-29 15:30:55 +08:00
Target.CameraController.GetComponent<Camera>().orthographicSize = Target.CameraController.CameraMinSize;
2023-12-21 15:30:37 +08:00
}
if (_isCheckingCamera)
{
EditorGUI.BeginChangeCheck();
_checkType = (ECameraCheckCorner)EditorGUILayout.Popup("检查角落", (int)_checkType, checkCornerType);
if (EditorGUI.EndChangeCheck())
2023-12-21 15:05:08 +08:00
{
2023-12-21 15:30:37 +08:00
switch (_checkType)
2023-12-21 15:05:08 +08:00
{
2023-12-21 15:30:37 +08:00
case ECameraCheckCorner.None:
break;
case ECameraCheckCorner.LeftDown:
var leftDownPoint = new Vector2Int(0, 0);
2024-08-08 18:57:34 +08:00
Target.CameraController.InitializeCameraPosition(
Map.BlockPosition2WorldPosition(leftDownPoint));
2023-12-21 15:30:37 +08:00
break;
case ECameraCheckCorner.RightDown:
var rightDownPoint = new Vector2Int(0, TGS.columnCount - 1);
2024-08-08 18:57:34 +08:00
Target.CameraController.InitializeCameraPosition(
Map.BlockPosition2WorldPosition(rightDownPoint));
2023-12-21 15:30:37 +08:00
break;
case ECameraCheckCorner.LeftUp:
var leftUpPoint = new Vector2Int(TGS.rowCount - 1, 0);
Target.CameraController.InitializeCameraPosition(Map.BlockPosition2WorldPosition(leftUpPoint));
2023-12-21 15:30:37 +08:00
break;
case ECameraCheckCorner.RightUp:
var rightUpPoint = new Vector2Int(TGS.rowCount - 1, TGS.columnCount - 1);
Target.CameraController.InitializeCameraPosition(Map.BlockPosition2WorldPosition(rightUpPoint));
2023-12-21 15:30:37 +08:00
break;
default:
break;
2023-12-21 15:05:08 +08:00
}
}
2023-12-21 15:30:37 +08:00
}
}
2023-12-21 15:05:08 +08:00
2023-12-21 15:30:37 +08:00
private void DrawCameraOriginPosition()
{
if (!_isEditingCameraOriginPos)
{
2025-04-08 16:01:38 +08:00
if (GUILayout.Button("编辑相机初始位置和大小"))
2023-12-15 18:32:21 +08:00
{
2023-12-21 15:30:37 +08:00
_isEditingCameraOriginPos = true;
// 编辑模式下提前设置相机包围盒,避免 CameraBounds 为空导致红框不显示/不更新
if (Target?.CameraController != null && Target?.TGS != null)
{
Target.CameraController.CameraBounds = Target.TGS.bounds;
}
2023-12-15 18:32:21 +08:00
}
2023-12-21 15:30:37 +08:00
}
else
{
2025-04-08 16:01:38 +08:00
// 添加相机FOV和正交大小设置
EditorGUI.BeginChangeCheck();
2025-08-25 17:34:39 +08:00
MapData.cameraMarginInfo.initialFOV = EditorGUILayout.Slider("初始FOV", MapData.cameraMarginInfo.initialFOV,
Target.CameraController.CameraMinFOV, Target.CameraController.CameraMaxFOV);
2025-04-08 16:01:38 +08:00
// MapData.cameraMarginInfo.initialOrthographicSize = EditorGUILayout.Slider("初始正交大小", MapData.cameraMarginInfo.initialOrthographicSize, Target.CameraController.CameraMinSize, Target.CameraController.CameraMaxSize);
2025-08-25 17:34:39 +08:00
2025-04-08 16:01:38 +08:00
if (EditorGUI.EndChangeCheck())
{
// 实时预览FOV设置效果
var camera = Target.CameraController.MainCamera;
if (camera != null)
{
if (camera.orthographic)
{
camera.orthographicSize = MapData.cameraMarginInfo.initialOrthographicSize;
}
else
{
2025-04-08 18:51:32 +08:00
Target.CameraController.SetCameraFOVSize(MapData.cameraMarginInfo.initialFOV);
2025-08-25 17:34:39 +08:00
camera.fieldOfView = Mathf.Clamp(MapData.cameraMarginInfo.initialFOV,
Target.CameraController.CameraMinFOV,
2025-04-29 15:30:55 +08:00
Target.CameraController.CameraMaxFOV);
2025-08-25 17:34:39 +08:00
2025-04-08 16:01:38 +08:00
// 强制刷新场景视图
SceneView.RepaintAll();
}
}
}
2025-08-25 17:34:39 +08:00
2023-12-21 15:30:37 +08:00
EditorGUILayout.LabelField("请在场景中点击网格来选取相机初始位置并在Game窗口中查看");
if (GUILayout.Button("退出编辑相机初始位置"))
2023-12-15 18:32:21 +08:00
{
2023-12-21 15:30:37 +08:00
_isEditingCameraOriginPos = false;
2023-12-15 18:32:21 +08:00
}
}
}
2023-12-21 15:05:08 +08:00
private void OnSceneGUI()
{
if (!_isEditingCameraOriginPos)
return;
ResetSceneGUIState(Event.current);
DrawMouse();
HandleInput();
}
2025-08-25 17:34:39 +08:00
private void ResetSceneGUIState(Event e)
2023-12-21 15:05:08 +08:00
{
_isHitGround = false;
_mouseHitPosition = Vector3.zero;
_currEvent = e;
_ground = null;
}
2025-08-25 17:34:39 +08:00
private void DrawMouse()
2023-12-21 15:05:08 +08:00
{
var mousePosSS = _currEvent.mousePosition;
var ray = HandleUtility.GUIPointToWorldRay(mousePosSS);
var count = Physics.RaycastNonAlloc(ray, _hits, 1000, 1 << LayerMask.NameToLayer("Ground"));
if (count > 0)
{
var hit = _hits[0];
_mouseHitPosition = hit.point;
Handles.color = Color.yellow;
Handles.DrawSolidDisc(_mouseHitPosition, Vector3.up, 1);
_isHitGround = true;
_ground = hit.collider.gameObject;
}
}
2025-08-25 17:34:39 +08:00
private void HandleInput()
2023-12-21 15:05:08 +08:00
{
if (!_isHitGround)
return;
var controlID = GUIUtility.GetControlID(FocusType.Passive);
var eventType = _currEvent.GetTypeForControl(controlID);
switch (eventType)
{
case EventType.MouseDown:
if (_currEvent.button == 0)
{
GUIUtility.hotControl = controlID;
if (_isEditingCameraOriginPos)
{
var cell = TGS.CellGetAtPosition(_mouseHitPosition, true);
if (cell == null)
{
Debug.LogError("点击点附件没有网格!设置相机初始位置失败!");
return;
}
MapData.initialCameraPosition = MapData.BlockIndex2Position(cell.index);
// 确保相机包围盒使用当前地图的网格范围
if (Target?.CameraController != null)
{
Target.CameraController.CameraBounds = TGS.bounds;
}
2024-08-08 18:57:34 +08:00
Target.CameraController.InitializeCameraPosition(
Map.BlockPosition2WorldPosition(MapData.initialCameraPosition));
2023-12-21 15:05:08 +08:00
}
}
break;
case EventType.MouseUp:
if (GUIUtility.hotControl == controlID && _currEvent.button == 0)
{
GUIUtility.hotControl = 0;
_currEvent.Use();
}
break;
}
}
2025-04-03 15:47:16 +08:00
2025-08-25 17:34:39 +08:00
#region 网格参考图导出功能
2025-04-03 15:47:16 +08:00
private void CaptureGridImage()
{
var tgs = TGS;
if (tgs == null)
{
Debug.LogError("无法找到TerrainGridSystem组件");
return;
}
// 获取网格尺寸信息
int columnCount = tgs.columnCount;
int rowCount = tgs.rowCount;
if (columnCount <= 0 || rowCount <= 0)
{
Debug.LogError("网格尺寸无效");
return;
}
try
{
EditorUtility.DisplayProgressBar("导出网格参考图", "初始化...", 0.1f);
2025-08-25 17:34:39 +08:00
2025-04-03 15:47:16 +08:00
// 询问用户选择网格颜色
2025-08-25 17:34:39 +08:00
bool useHighContrast = EditorUtility.DisplayDialog("选择网格颜色",
"请选择导出的网格线颜色:",
2025-04-03 15:47:16 +08:00
"默认颜色", "高对比度(白底黑线)");
2025-08-25 17:34:39 +08:00
2025-04-03 15:47:16 +08:00
// 获取网格的实际世界空间边界
Bounds gridBounds = tgs.bounds;
2025-08-25 17:34:39 +08:00
2025-04-03 15:47:16 +08:00
// 计算网格的实际世界空间大小单位Unity单位
float worldWidth = gridBounds.size.x;
float worldHeight = gridBounds.size.z; // 注意z轴是Unity中的垂直方向
2025-08-25 17:34:39 +08:00
2025-04-03 15:47:16 +08:00
// 计算图片像素尺寸 = 世界空间大小 * 100
int textureWidth = Mathf.CeilToInt(worldWidth * 100);
int textureHeight = Mathf.CeilToInt(worldHeight * 100);
2025-08-25 17:34:39 +08:00
2025-04-03 15:47:16 +08:00
// 显示计算结果并确认
if (!EditorUtility.DisplayDialog("确认导出",
$"网格真实尺寸: {worldWidth:F2}x{worldHeight:F2} 单位\n" +
$"导出图片分辨率: {textureWidth}x{textureHeight} 像素\n\n" +
"继续导出?",
"导出", "取消"))
{
EditorUtility.ClearProgressBar();
return;
}
EditorUtility.DisplayProgressBar("导出网格参考图", "准备相机...", 0.2f);
// 创建临时相机
GameObject tempCameraObj = new GameObject("TempGridCamera");
Camera tempCamera = tempCameraObj.AddComponent<Camera>();
tempCamera.clearFlags = CameraClearFlags.SolidColor;
tempCamera.backgroundColor = useHighContrast ? Color.white : new Color(1, 1, 1, 0); // 高对比度时使用白底
tempCamera.orthographic = true;
// 将相机放置在网格正上方
tempCamera.transform.position = new Vector3(
gridBounds.center.x,
gridBounds.max.y + 10, // 确保相机在网格上方足够高
gridBounds.center.z
);
tempCamera.transform.rotation = Quaternion.Euler(90, 0, 0); // 俯视
// 设置相机的视图大小,使其刚好包含整个网格
tempCamera.orthographicSize = worldHeight * 0.5f; // 正交相机尺寸是高度的一半
tempCamera.aspect = worldWidth / worldHeight;
EditorUtility.DisplayProgressBar("导出网格参考图", "创建渲染纹理...", 0.3f);
2025-08-25 17:34:39 +08:00
2025-04-03 15:47:16 +08:00
// 创建RenderTexture
2025-08-25 17:34:39 +08:00
RenderTexture renderTexture =
new RenderTexture(textureWidth, textureHeight, 24, RenderTextureFormat.ARGB32);
2025-04-03 15:47:16 +08:00
renderTexture.antiAliasing = 1;
renderTexture.filterMode = FilterMode.Point; // 避免模糊
renderTexture.Create();
// 保存原始状态
bool originalShowCells = tgs.showCells;
bool originalShowTerritories = tgs.showTerritories;
Color originalCellBorderColor = tgs.cellBorderColor;
float originalCellBorderThickness = tgs.cellBorderThickness;
2025-08-25 17:34:39 +08:00
2025-04-03 15:47:16 +08:00
try
{
EditorUtility.DisplayProgressBar("导出网格参考图", "设置网格渲染参数...", 0.4f);
2025-08-25 17:34:39 +08:00
2025-04-03 15:47:16 +08:00
// 临时设置网格渲染参数
tgs.showCells = true;
tgs.showTerritories = false;
2025-08-25 17:34:39 +08:00
2025-04-03 15:47:16 +08:00
// 设置网格线颜色和宽度
if (useHighContrast)
{
tgs.cellBorderColor = Color.black;
tgs.cellBorderThickness = Mathf.Max(2.0f, tgs.cellBorderThickness); // 确保线条足够粗
}
2025-08-25 17:34:39 +08:00
2025-04-03 15:47:16 +08:00
EditorUtility.DisplayProgressBar("导出网格参考图", "渲染网格...", 0.6f);
2025-08-25 17:34:39 +08:00
2025-04-03 15:47:16 +08:00
// 设置并渲染
RenderTexture originalRenderTexture = RenderTexture.active;
tempCamera.targetTexture = renderTexture;
RenderTexture.active = renderTexture;
2025-08-25 17:34:39 +08:00
2025-04-03 15:47:16 +08:00
// 设置相机渲染遮罩,只渲染网格层
tempCamera.cullingMask = 1 << tgs.gameObject.layer;
2025-08-25 17:34:39 +08:00
2025-04-03 15:47:16 +08:00
// 渲染场景到RenderTexture
tempCamera.Render();
2025-08-25 17:34:39 +08:00
2025-04-03 15:47:16 +08:00
EditorUtility.DisplayProgressBar("导出网格参考图", "创建图片...", 0.7f);
2025-08-25 17:34:39 +08:00
2025-04-03 15:47:16 +08:00
// 创建纹理并读取像素
Texture2D texture2D = new Texture2D(textureWidth, textureHeight, TextureFormat.RGBA32, false);
texture2D.ReadPixels(new Rect(0, 0, textureWidth, textureHeight), 0, 0);
texture2D.Apply();
2025-08-25 17:34:39 +08:00
2025-04-03 15:47:16 +08:00
EditorUtility.DisplayProgressBar("导出网格参考图", "保存图片...", 0.8f);
2025-08-25 17:34:39 +08:00
2025-04-03 15:47:16 +08:00
// 保存为PNG
byte[] bytes = texture2D.EncodeToPNG();
string fileName = $"GridMap_{textureWidth}x{textureHeight}_{System.DateTime.Now:yyyyMMdd_HHmmss}.png";
string path = EditorUtility.SaveFilePanel("保存网格图片", Application.dataPath, fileName, "png");
2025-08-25 17:34:39 +08:00
2025-04-03 15:47:16 +08:00
if (!string.IsNullOrEmpty(path))
{
try
{
System.IO.File.WriteAllBytes(path, bytes);
EditorUtility.DisplayProgressBar("导出网格参考图", "刷新资源...", 0.9f);
AssetDatabase.Refresh();
2025-08-25 17:34:39 +08:00
2025-04-03 15:47:16 +08:00
// 如果路径在Assets文件夹内获取相对路径并高亮显示导出的贴图
if (path.StartsWith(Application.dataPath))
{
2025-08-25 17:34:39 +08:00
var assetPath = "Assets" + path.Substring(Application.dataPath.Length);
2025-04-03 15:47:16 +08:00
Texture2D exportedTexture = AssetDatabase.LoadAssetAtPath<Texture2D>(assetPath);
if (exportedTexture != null)
{
EditorGUIUtility.PingObject(exportedTexture);
Selection.activeObject = exportedTexture;
}
}
2025-08-25 17:34:39 +08:00
2025-04-03 15:47:16 +08:00
// 显示成功信息和使用说明
2025-08-25 17:34:39 +08:00
EditorUtility.DisplayDialog("导出成功",
2025-04-03 15:47:16 +08:00
$"网格图片已导出\n" +
$"网格实际尺寸: {worldWidth:F2}x{worldHeight:F2} 单位\n" +
$"导出图片分辨率: {textureWidth}x{textureHeight} 像素\n" +
$"缩放比例: 100像素/单位\n" +
$"路径: {path}\n\n" +
"使用说明:\n" +
"1. 在美术软件中直接使用此图片作为参考层\n" +
"2. 绘制的美术资源与网格完全对齐即可\n" +
2025-08-25 17:34:39 +08:00
"3. 导入到Unity后无需调整Scale将自动匹配网格",
2025-04-03 15:47:16 +08:00
"确定");
}
catch (System.Exception e)
{
EditorUtility.DisplayDialog("导出失败", $"保存图片时发生错误: {e.Message}", "确定");
}
}
2025-08-25 17:34:39 +08:00
2025-04-03 15:47:16 +08:00
// 清理资源
RenderTexture.active = originalRenderTexture;
tempCamera.targetTexture = null;
Object.DestroyImmediate(texture2D);
Object.DestroyImmediate(renderTexture);
}
finally
{
// 恢复原始状态
tgs.showCells = originalShowCells;
tgs.showTerritories = originalShowTerritories;
tgs.cellBorderColor = originalCellBorderColor;
tgs.cellBorderThickness = originalCellBorderThickness;
2025-08-25 17:34:39 +08:00
2025-04-03 15:47:16 +08:00
// 清理相机
Object.DestroyImmediate(tempCameraObj);
}
}
catch (System.Exception e)
{
Debug.LogException(e);
EditorUtility.DisplayDialog("导出失败", $"导出过程中发生错误: {e.Message}", "确定");
}
finally
{
// 无论如何都清除进度条
EditorUtility.ClearProgressBar();
}
}
2025-08-25 17:34:39 +08:00
#endregion
2023-12-15 18:32:21 +08:00
}