#if UNITY_EDITOR using UnityEditor; using UnityEngine; using BaseGames.World.Map; namespace BaseGames.Editor.Map { /// /// MapRoomDataSO 自定义编辑器(架构 15_MapShopModule §5)。 /// 在 Scene View 中直接拖拽调整房间格子位置/大小;提供一键居中 SceneView 快捷按钮。 /// 拖动自动吸附到整格精度;左下/右上角可独立拖动(含反转保护);支持 Undo。 /// [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); } /// 将世界坐标吸附到最近格点。 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