多轮审查和修复
This commit is contained in:
140
Assets/Scripts/Editor/Map/MapRoomDataEditor.cs
Normal file
140
Assets/Scripts/Editor/Map/MapRoomDataEditor.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
#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
|
||||
Reference in New Issue
Block a user