Files
zeling_v2/Assets/Scripts/Editor/Map/MapRoomDataEditor.cs
2026-05-12 15:34:08 +08:00

141 lines
5.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using BaseGames.World.Map;
namespace BaseGames.Editor.Map
{
/// <summary>
/// MapRoomDataSO 自定义编辑器(架构 15_MapShopModule §5
/// 在 Scene View 中直接拖拽调整房间格子位置/大小;提供一键居中 SceneView 快捷按钮。
/// 拖动自动吸附到整格精度;左下/右上角可独立拖动(含反转保护);支持 Undo。
/// </summary>
[CustomEditor(typeof(MapRoomDataSO))]
public class MapRoomDataEditor : UnityEditor.Editor
{
private const float CELL_SIZE = 1f; // 每格在 Scene 中的世界单位尺寸
private static readonly Color FillColor = new Color(0.2f, 0.6f, 1f, 0.15f);
private static readonly Color OutlineColor = new Color(0.2f, 0.6f, 1f, 0.9f);
private static readonly Color HandleColor = new Color(1f, 0.85f, 0.2f, 1f);
private static readonly GUIStyle LabelStyle = new GUIStyle
{
alignment = TextAnchor.MiddleCenter,
fontStyle = FontStyle.Bold,
normal = { textColor = Color.white },
};
private MapRoomDataSO _target;
private void OnEnable() => _target = (MapRoomDataSO)target;
// ── Inspector ─────────────────────────────────────────────────────────
public override void OnInspectorGUI()
{
DrawDefaultInspector();
EditorGUILayout.Space(8);
EditorGUILayout.HelpBox(
"在 Scene View 中可直接拖拽房间角点调整 GridPosition / GridSize。\n" +
"拖动自动吸附到 1 格精度,支持 Undo。",
MessageType.Info);
if (GUILayout.Button("居中 Scene View 到此房间", GUILayout.Height(28)))
CenterSceneViewOnRoom(_target);
}
// ── Scene GUI ─────────────────────────────────────────────────────────
private void OnSceneGUI()
{
if (_target == null) return;
Vector3 origin = new Vector3(
_target.GridPosition.x * CELL_SIZE,
_target.GridPosition.y * CELL_SIZE, 0f);
Vector3 size = new Vector3(
_target.GridSize.x * CELL_SIZE,
_target.GridSize.y * CELL_SIZE, 0f);
// 绘制半透明矩形Vector3[] 重载正确)
Handles.DrawSolidRectangleWithOutline(GetRectCorners(origin, size), FillColor, OutlineColor);
// 房间 ID 标签(居中、加粗、白色)
Handles.Label(origin + size * 0.5f,
string.IsNullOrEmpty(_target.RoomId) ? "(No RoomId)" : _target.RoomId,
LabelStyle);
// ── 双角控制点(左下 = BL右上 = TR────────────────────────────
EditorGUI.BeginChangeCheck();
Vector3 newBL = DragHandle(origin, "BL");
Vector3 newTR = DragHandle(origin + size, "TR");
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(_target, "Resize MapRoom");
// 防反转:确保 BL ≤ TR
float minX = Mathf.Min(newBL.x, newTR.x);
float minY = Mathf.Min(newBL.y, newTR.y);
float maxX = Mathf.Max(newBL.x, newTR.x);
float maxY = Mathf.Max(newBL.y, newTR.y);
_target.GridPosition = ToGrid(new Vector2(minX, minY));
var newSize = ToGrid(new Vector2(maxX, maxY)) - _target.GridPosition;
_target.GridSize = new Vector2Int(Mathf.Max(1, newSize.x), Mathf.Max(1, newSize.y));
EditorUtility.SetDirty(_target);
}
}
// ── 帮助方法 ──────────────────────────────────────────────────────────
private static Vector3 DragHandle(Vector3 pos, string label)
{
float sz = HandleUtility.GetHandleSize(pos) * 0.12f;
Color prev = Handles.color;
Handles.color = HandleColor;
var result = Handles.FreeMoveHandle(pos, sz, Vector3.zero, Handles.DotHandleCap);
Handles.color = prev;
return SnapToGrid(result);
}
/// <summary>将世界坐标吸附到最近格点。</summary>
private static Vector3 SnapToGrid(Vector3 world)
=> new(Mathf.Round(world.x / CELL_SIZE) * CELL_SIZE,
Mathf.Round(world.y / CELL_SIZE) * CELL_SIZE,
0f);
private static Vector2Int ToGrid(Vector2 world)
=> new(Mathf.RoundToInt(world.x / CELL_SIZE),
Mathf.RoundToInt(world.y / CELL_SIZE));
private static void CenterSceneViewOnRoom(MapRoomDataSO room)
{
if (room == null) return;
var sv = SceneView.lastActiveSceneView;
if (sv == null) return;
Vector3 center = new Vector3(
(room.GridPosition.x + room.GridSize.x * 0.5f) * CELL_SIZE,
(room.GridPosition.y + room.GridSize.y * 0.5f) * CELL_SIZE, 0f);
sv.Frame(new Bounds(center, new Vector3(
room.GridSize.x * CELL_SIZE * 2f,
room.GridSize.y * CELL_SIZE * 2f, 1f)), false);
}
private static Vector3[] GetRectCorners(Vector3 origin, Vector3 size)
=> new[]
{
origin,
origin + new Vector3(size.x, 0f, 0f),
origin + size,
origin + new Vector3(0f, size.y, 0f),
};
}
}
#endif