Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / map / DungeonRoomTemplate.cs
@小李xl 小李xl on 17 Jul 2023 36 KB 保存房间大小位置数据
/*
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using Generator;
using Godot;

[Tool]
public partial class DungeonRoomTemplate : TileMap
{    
    /// <summary>
    /// 是否启用编辑模式
    /// </summary>
    [Export]
    public bool EnableEdit = false;

    /// <summary>
    /// 房间权重, 值越大, 生成地牢是越容易出现该房间
    /// </summary>
    [Export(PropertyHint.Range, "1, 500")]
    public int Weight
    {
        get => _weight;
        set
        {
            _weight = value;
            _changeWeight = true;
            _changeWeightTimer = 0;
        }
    }
    private int _weight = DefaultWeight;
    private bool _changeWeight = false;
    private float _changeWeightTimer = 0;

#if TOOLS
    //是否悬停在线上
    private bool _hover = false;

    //悬停点
    private Vector2 _hoverPoint1;
    private Vector2 _hoverPoint2;
    private DoorDirection _hoverDirection;
    private bool _canPut = false;

    //选中点
    private bool _hasActivePoint = false;
    //选中左/右点
    private byte _activePointType = 0;
    private DoorAreaInfo _activeArea = null;

    //拖拽
    private bool _isDrag = false;
    private float _startDragValue;
    private Vector2 _startDragPositionValue;
    private bool _dragHasCollision = false;

    private bool _mouseDown = false;

    //房间配置
    private DungeonRoomInfo _dungeonRoomInfo;
    private Rect2 _prevRect;

    //是否能是否按下
    private bool _clickSave = false;

    private DungeonTileMap _dungeonTileMap;
    private TileDrawHandler _tileDrawHandler;

    //计算导航的计时器
    private float _calcTileNavTimer = 0;

    private partial class TileDrawHandler : Node2D
    {
        public DungeonRoomTemplate RoomTemplate;

        public override void _Draw()
        {
            if (!Engine.IsEditorHint() || RoomTemplate == null)
            {
                return;
            }
            if (RoomTemplate.TileSet != null)
            {
                //绘制地图轮廓
                var mapRange = CalcTileRange(RoomTemplate);
                mapRange.Position -= new Vector2(2, 2);
                mapRange.Size += new Vector2(4, 4);
                DrawRect(mapRange, RoomTemplate._hover ? Colors.Green : new Color(0.03137255F, 0.59607846F, 0.03137255F), false, 2);

                //绘制悬停
                if (RoomTemplate._hover && !RoomTemplate._isDrag)
                {
                    if (!RoomTemplate._hasActivePoint) //这里判断是否悬停在拖动点上
                    {
                        var color = RoomTemplate._canPut ? new Color(0, 1, 0, 0.2f) : new Color(1, 0, 0, 0.2f);
                        switch (RoomTemplate._hoverDirection)
                        {
                            case DoorDirection.E:
                                DrawRect(
                                    new Rect2(new Vector2(RoomTemplate._hoverPoint1.X + 2, RoomTemplate._hoverPoint1.Y), 30,
                                        RoomTemplate._hoverPoint2.Y - RoomTemplate._hoverPoint1.Y), color);
                                DrawCircle(new Vector2(RoomTemplate._hoverPoint1.X + 2, RoomTemplate._hoverPoint1.Y), 5, color);
                                DrawCircle(new Vector2(RoomTemplate._hoverPoint2.X + 2, RoomTemplate._hoverPoint2.Y), 5, color);
                                break;
                            case DoorDirection.W:
                                DrawRect(
                                    new Rect2(new Vector2(RoomTemplate._hoverPoint1.X - 2 - 30, RoomTemplate._hoverPoint1.Y), 30,
                                        RoomTemplate._hoverPoint2.Y - RoomTemplate._hoverPoint1.Y), color);
                                DrawCircle(new Vector2(RoomTemplate._hoverPoint1.X - 2, RoomTemplate._hoverPoint1.Y), 5, color);
                                DrawCircle(new Vector2(RoomTemplate._hoverPoint2.X - 2, RoomTemplate._hoverPoint2.Y), 5, color);
                                break;
                            case DoorDirection.S:
                                DrawRect(
                                    new Rect2(new Vector2(RoomTemplate._hoverPoint1.X, RoomTemplate._hoverPoint1.Y + 2),
                                        RoomTemplate._hoverPoint2.X - RoomTemplate._hoverPoint1.X, 30), color);
                                DrawCircle(new Vector2(RoomTemplate._hoverPoint1.X, RoomTemplate._hoverPoint1.Y + 2), 5, color);
                                DrawCircle(new Vector2(RoomTemplate._hoverPoint2.X, RoomTemplate._hoverPoint2.Y + 2), 5, color);
                                break;
                            case DoorDirection.N:
                                DrawRect(
                                    new Rect2(new Vector2(RoomTemplate._hoverPoint1.X, RoomTemplate._hoverPoint1.Y - 30 - 2),
                                        RoomTemplate._hoverPoint2.X - RoomTemplate._hoverPoint1.X, 30), color);
                                DrawCircle(new Vector2(RoomTemplate._hoverPoint1.X, RoomTemplate._hoverPoint1.Y - 2), 5, color);
                                DrawCircle(new Vector2(RoomTemplate._hoverPoint2.X, RoomTemplate._hoverPoint2.Y - 2), 5, color);
                                break;
                        }
                    }
                }

                //绘制区域
                if (RoomTemplate._dungeonRoomInfo != null && RoomTemplate._dungeonRoomInfo.DoorAreaInfos != null)
                {
                    var color2 = new Color(0, 1, 0, 0.8f);
                    //绘制已经存在的
                    foreach (var doorAreaInfo in RoomTemplate._dungeonRoomInfo.DoorAreaInfos)
                    {
                        var flag = RoomTemplate._hasActivePoint && RoomTemplate._activeArea == doorAreaInfo;
                        var color3 = (flag && RoomTemplate._activePointType == 0)
                            ? (RoomTemplate._isDrag
                                ? (RoomTemplate._dragHasCollision
                                    ? new Color(1, 0, 0, 0.8f)
                                    : new Color(0.2F, 0.4117647F, 0.8392157F, 0.8f))
                                : new Color(1, 1, 1, 0.8f))
                            : color2;
                        var color4 = (flag && RoomTemplate._activePointType == 1)
                            ? (RoomTemplate._isDrag
                                ? (RoomTemplate._dragHasCollision
                                    ? new Color(1, 0, 0, 0.8f)
                                    : new Color(0.2F, 0.4117647F, 0.8392157F, 0.8f))
                                : new Color(1, 1, 1, 0.8f))
                            : color2;
                        switch (doorAreaInfo.Direction)
                        {
                            case DoorDirection.E:
                                DrawRect(
                                    new Rect2(
                                        new Vector2(mapRange.Position.X + mapRange.Size.X,
                                            mapRange.Position.Y + doorAreaInfo.Start + 2), 30,
                                        doorAreaInfo.End - doorAreaInfo.Start), color2);
                                DrawCircle(
                                    new Vector2(mapRange.Position.X + mapRange.Size.X,
                                        mapRange.Position.Y + doorAreaInfo.Start + 2), 5, color3);
                                DrawCircle(
                                    new Vector2(mapRange.Position.X + mapRange.Size.X,
                                        mapRange.Position.Y + doorAreaInfo.End + 2),
                                    5, color4);
                                break;
                            case DoorDirection.W:
                                DrawRect(
                                    new Rect2(
                                        new Vector2(mapRange.Position.X - 30, mapRange.Position.Y + doorAreaInfo.Start + 2),
                                        30, doorAreaInfo.End - doorAreaInfo.Start), color2);
                                DrawCircle(new Vector2(mapRange.Position.X, mapRange.Position.Y + doorAreaInfo.Start + 2),
                                    5,
                                    color3);
                                DrawCircle(new Vector2(mapRange.Position.X, mapRange.Position.Y + doorAreaInfo.End + 2), 5,
                                    color4);
                                break;
                            case DoorDirection.S:
                                DrawRect(
                                    new Rect2(
                                        new Vector2(mapRange.Position.X + doorAreaInfo.Start + 2,
                                            mapRange.Position.Y + mapRange.Size.Y), doorAreaInfo.End - doorAreaInfo.Start,
                                        30),
                                    color2);
                                DrawCircle(
                                    new Vector2(mapRange.Position.X + doorAreaInfo.Start + 2,
                                        mapRange.Position.Y + mapRange.Size.Y), 5, color3);
                                DrawCircle(
                                    new Vector2(mapRange.Position.X + doorAreaInfo.End + 2,
                                        mapRange.Position.Y + mapRange.Size.Y),
                                    5, color4);
                                break;
                            case DoorDirection.N:
                                DrawRect(
                                    new Rect2(
                                        new Vector2(mapRange.Position.X + doorAreaInfo.Start + 2, mapRange.Position.Y - 30),
                                        doorAreaInfo.End - doorAreaInfo.Start, 30), color2);
                                DrawCircle(new Vector2(mapRange.Position.X + doorAreaInfo.Start + 2, mapRange.Position.Y),
                                    5,
                                    color3);
                                DrawCircle(new Vector2(mapRange.Position.X + doorAreaInfo.End + 2, mapRange.Position.Y), 5,
                                    color4);
                                break;
                        }
                    }
                }
                
                //绘制导航, 现在有点问题, 绘制的内容会被自身的 tile 所挡住
                if (RoomTemplate._dungeonTileMap != null)
                {
                    var result = RoomTemplate._dungeonTileMap.GetGenerateNavigationResult();
                    if (result != null)
                    {
                        if (result.Success)
                        {
                            var polygonData = RoomTemplate._dungeonTileMap.GetPolygonData();
                            Utils.DrawNavigationPolygon(this, polygonData, 2);
                        }
                        else
                        {
                            var color = new Color(1, 0, 0, 0.5f);
                            var tileCellSize = GameConfig.TileCellSize;
                            var point = (result.Exception.Point + new Vector2(0.5f, 0.5f)) * tileCellSize;
                            DrawCircle(point, 4, color);
                            DrawLine(point + new Vector2(-tileCellSize / 2f, -tileCellSize / 2f), point + new Vector2(tileCellSize / 2f, tileCellSize / 2f), color, 2);
                            DrawLine(point + new Vector2(-tileCellSize / 2f, tileCellSize / 2f), point + new Vector2(tileCellSize / 2f, -tileCellSize / 2f), color, 2);
                        }
                    }
                }
            }
        }

    }
    
    public override void _Ready()
    {
        if (!Engine.IsEditorHint())
        {
            return;
        }
        EnableEdit = false;
    }

    public override void _Process(double delta)
    {
        if (!Engine.IsEditorHint())
        {
            return;
        }

        if (TileSet == null)
        {
            return;
        }

        if (_dungeonTileMap == null)
        {
            _dungeonTileMap = new DungeonTileMap(this);
            _dungeonTileMap.SetFloorAtlasCoords(new List<Vector2I>() { new Vector2I(0, 8) });
            OnTileChanged();
            var callable = new Callable(this, nameof(OnTileChanged));
            if (!IsConnected("changed", callable))
            {
                Connect("changed", callable);
            }
        }

        if (_tileDrawHandler == null)
        {
            _tileDrawHandler = GetNodeOrNull<TileDrawHandler>("TileDrawHandler");
            if (_tileDrawHandler == null)
            {
                _tileDrawHandler = new TileDrawHandler();
                _tileDrawHandler.RoomTemplate = this;
                _tileDrawHandler.Name = "TileDrawHandler";
                _tileDrawHandler.ZIndex = 100;
                AddChild(_tileDrawHandler);
            }
            else
            {
                _tileDrawHandler.RoomTemplate = this;
            }
        }
        
        //导航计算
        if (_calcTileNavTimer > 0)
        {
            _calcTileNavTimer -= (float)delta;
            //重新计算导航
            if (_calcTileNavTimer <= 0)
            {
                _dungeonTileMap.GenerateNavigationPolygon(0);
            }
        }

        //加载配置
        var initConfigs = false;
        if (_dungeonRoomInfo == null)
        {
            initConfigs = true;

            var path = SceneFilePath;
            if (!string.IsNullOrEmpty(path))
            {
                var start = GameConfig.RoomTileDir.Length + 6;
                var name = path.Substring(start, path.Length - start - 5);
                ReadConfig(CalcTileRange(this), name);
            }
            
        }

        //按键检测
        var isClick = false;
        if (Input.IsMouseButtonPressed(MouseButton.Left))
        {
            if (!_mouseDown)
            {
                _mouseDown = true;
                isClick = true;
            }
        }
        else if (_mouseDown)
        {
            _mouseDown = false;
            isClick = false;
        }

        if (Input.IsMouseButtonPressed(MouseButton.Middle)) //中键移除门
        {
            if (EnableEdit && _activeArea != null)
            {
                RemoveDoorArea(_activeArea);
                _hasActivePoint = false;
                _activeArea = null;
            }
        }
        else if (TileSet != null) //编辑操作
        {
            var mapRect = CalcTileRange(this);
            var mousePosition = GetLocalMousePosition();

            if (mapRect != _prevRect)
            {
                if (!initConfigs)
                {
                    OnMapRectChange();
                }
            }

            _prevRect = mapRect;
            
            if (EnableEdit)
            {
                var tileSize = TileSet.TileSize;
                if (_isDrag) //拖拽中
                {
                    if (_activeArea != null)
                    {
                        //拖拽节点操作
                        if (_activeArea.Direction == DoorDirection.N || _activeArea.Direction == DoorDirection.S)
                        {
                            if (_activePointType == 0)
                            {
                                var mouseOffset = Approach(mousePosition.X, tileSize.X);
                                _activeArea.StartPosition = new Vector2(mouseOffset, _activeArea.StartPosition.Y);
                                _activeArea.Start = mouseOffset - mapRect.Position.X;
                                _dragHasCollision = _activeArea.StartPosition.X <= mapRect.Position.X ||
                                                    _activeArea.StartPosition.X + 3 * tileSize.X >=
                                                    _activeArea.EndPosition.X ||
                                                    CheckDoorCollision(_activeArea.Direction, _activeArea);
                            }
                            else
                            {
                                var mouseOffset = Approach(mousePosition.X, tileSize.X);
                                _activeArea.EndPosition = new Vector2(mouseOffset, _activeArea.EndPosition.Y);
                                _activeArea.End = mouseOffset - mapRect.Position.X;
                                _dragHasCollision = _activeArea.EndPosition.X >= mapRect.Position.X + mapRect.Size.X ||
                                                    _activeArea.EndPosition.X - 3 * tileSize.X <=
                                                    _activeArea.StartPosition.X ||
                                                    CheckDoorCollision(_activeArea.Direction, _activeArea);
                            }
                        }
                        else
                        {
                            if (_activePointType == 0)
                            {
                                var mouseOffset = Approach(mousePosition.Y, tileSize.Y);
                                _activeArea.StartPosition = new Vector2(_activeArea.StartPosition.X, mouseOffset);
                                _activeArea.Start = mouseOffset - mapRect.Position.Y;
                                _dragHasCollision = _activeArea.StartPosition.Y <= mapRect.Position.Y ||
                                                    _activeArea.StartPosition.Y + 3 * tileSize.Y >=
                                                    _activeArea.EndPosition.Y ||
                                                    CheckDoorCollision(_activeArea.Direction, _activeArea);
                            }
                            else
                            {
                                var mouseOffset = Approach(mousePosition.Y, tileSize.Y);
                                _activeArea.EndPosition = new Vector2(_activeArea.EndPosition.X, mouseOffset);
                                _activeArea.End = mouseOffset - mapRect.Position.Y;
                                _dragHasCollision = _activeArea.EndPosition.Y >= mapRect.Position.Y + mapRect.Size.Y ||
                                                    _activeArea.EndPosition.Y - 3 * tileSize.Y <=
                                                    _activeArea.StartPosition.Y ||
                                                    CheckDoorCollision(_activeArea.Direction, _activeArea);
                            }
                        }
                    }
                }
                else
                {
                    if (Mathf.Abs(mousePosition.Y - mapRect.Position.Y) <= 8 && mousePosition.X >= mapRect.Position.X &&
                        mousePosition.X <= mapRect.Position.X + mapRect.Size.X) //上
                    {
                        _hover = true;
                        _hoverDirection = DoorDirection.N;
                        var mouseOffset = Approach(mousePosition.X, tileSize.X);
                        _hoverPoint1 = new Vector2(mouseOffset - tileSize.X * 2, mapRect.Position.Y);
                        _hoverPoint2 = new Vector2(_hoverPoint1.X + tileSize.X * 4, _hoverPoint1.Y);

                        //判断是否能放下新的门
                        if (_hoverPoint1.X <= mapRect.Position.X ||
                            _hoverPoint2.X >= mapRect.Position.X + mapRect.Size.X ||
                            CheckDoorCollision())
                        {
                            _canPut = false;
                            FindHoverPoint(mouseOffset);
                        }
                        else
                        {
                            _canPut = true;
                            _hasActivePoint = false;
                            _activeArea = null;
                        }
                    }
                    else if (Mathf.Abs(mousePosition.X - mapRect.Position.X) <= 8 &&
                             mousePosition.Y >= mapRect.Position.Y &&
                             mousePosition.Y <= mapRect.Position.Y + mapRect.Size.Y) //左
                    {
                        _hover = true;
                        _hoverDirection = DoorDirection.W;
                        var mouseOffset = Approach(mousePosition.Y, tileSize.Y);
                        _hoverPoint1 = new Vector2(mapRect.Position.X, mouseOffset - tileSize.Y * 2);
                        _hoverPoint2 = new Vector2(_hoverPoint1.X, _hoverPoint1.Y + tileSize.X * 4);

                        //判断是否能放下新的门
                        if (_hoverPoint1.Y <= mapRect.Position.Y ||
                            _hoverPoint2.Y >= mapRect.Position.Y + mapRect.Size.Y ||
                            CheckDoorCollision())
                        {
                            _canPut = false;
                            FindHoverPoint(mouseOffset);
                        }
                        else
                        {
                            _canPut = true;
                            _hasActivePoint = false;
                            _activeArea = null;
                        }
                    }
                    else if (Mathf.Abs(mousePosition.Y - (mapRect.Position.Y + mapRect.Size.Y)) <= 8 &&
                             mousePosition.X >= mapRect.Position.X &&
                             mousePosition.X <= mapRect.Position.X + mapRect.Size.X) //下
                    {
                        _hover = true;
                        _hoverDirection = DoorDirection.S;
                        var mouseOffset = Approach(mousePosition.X, tileSize.X);
                        _hoverPoint1 = new Vector2(mouseOffset - tileSize.X * 2,
                            mapRect.Position.Y + mapRect.Size.Y);
                        _hoverPoint2 = new Vector2(_hoverPoint1.X + tileSize.X * 4, _hoverPoint1.Y);

                        //判断是否能放下新的门
                        if (_hoverPoint1.X <= mapRect.Position.X ||
                            _hoverPoint2.X >= mapRect.Position.X + mapRect.Size.X ||
                            CheckDoorCollision())
                        {
                            _canPut = false;
                            FindHoverPoint(mouseOffset);
                        }
                        else
                        {
                            _canPut = true;
                            _hasActivePoint = false;
                            _activeArea = null;
                        }
                    }
                    else if (Mathf.Abs(mousePosition.X - (mapRect.Position.X + mapRect.Size.X)) <= 8 &&
                             mousePosition.Y >= mapRect.Position.Y &&
                             mousePosition.Y <= mapRect.Position.Y + mapRect.Size.Y) //右
                    {
                        _hover = true;
                        _hoverDirection = DoorDirection.E;
                        var mouseOffset = Approach(mousePosition.Y, tileSize.Y);
                        _hoverPoint1 = new Vector2(mapRect.Position.X + mapRect.Size.X,
                            mouseOffset - tileSize.Y * 2);
                        _hoverPoint2 = new Vector2(_hoverPoint1.X, _hoverPoint1.Y + tileSize.X * 4);

                        //判断是否能放下新的门
                        if (_hoverPoint1.Y <= mapRect.Position.Y ||
                            _hoverPoint2.Y >= mapRect.Position.Y + mapRect.Size.Y ||
                            CheckDoorCollision())
                        {
                            _canPut = false;
                            FindHoverPoint(mouseOffset);
                        }
                        else
                        {
                            _canPut = true;
                            _hasActivePoint = false;
                            _activeArea = null;
                        }
                    }
                    else
                    {
                        ClearState();
                    }
                }

                if (isClick && _canPut) //判断是否可以创建新的点
                {
                    CreateDoorArea(mapRect);
                }
                else if (_mouseDown && !_isDrag) //拖拽节点
                {
                    _isDrag = true;
                    _dragHasCollision = false;
                    if (_activeArea != null)
                    {
                        if (_activePointType == 0)
                        {
                            _startDragValue = _activeArea.Start;
                            _startDragPositionValue = _activeArea.StartPosition;
                        }
                        else
                        {
                            _startDragValue = _activeArea.End;
                            _startDragPositionValue = _activeArea.EndPosition;
                        }
                    }
                }
                else if (!_mouseDown && _isDrag) //松开拖拽的点
                {
                    _isDrag = false;
                    if (_activeArea != null) //提交拖拽结果
                    {
                        if (_dragHasCollision)
                        {
                            if (_activePointType == 0)
                            {
                                _activeArea.Start = _startDragValue;
                                _activeArea.StartPosition = _startDragPositionValue;
                            }
                            else
                            {
                                _activeArea.End = _startDragValue;
                                _activeArea.EndPosition = _startDragPositionValue;
                            }
                        }

                        //OnDoorAreaChange();
                    }

                    _dragHasCollision = false;
                }
            }
            else
            {
                ClearState();
            }

            _tileDrawHandler.QueueRedraw();
        }
        else
        {
            ClearState();
        }

        //按下 ctrl + s 保存
        if (Input.IsKeyPressed(Key.Ctrl) && Input.IsKeyPressed(Key.S))
        {
            if (!_clickSave)
            {
                TriggerSave();
            }
            _clickSave = true;
            
            // if (_canSave)
            // {
            //     _canSave = false;
            //     TriggerSave();
            // }
        }
        else
        {
            _clickSave = false;
        }
        
        //权重发生改变
        if (_changeWeight)
        {
            _changeWeightTimer += (float)delta;
            if (_changeWeightTimer > 1)
            {
                _changeWeightTimer = 0;
                _changeWeight = false;
                //权重改变, 保存数据
                TriggerSave();
            }
        }
    }
    
    private void ClearState()
    {
        _hover = false;
        _canPut = false;
        _hasActivePoint = false;
        _activeArea = null;
    }

    private void OnTileChanged()
    {
        _calcTileNavTimer = 1f;
    }
    
    //创建门
    private void CreateDoorArea(Rect2 mapRect)
    {
        var doorAreaInfo = new DoorAreaInfo();
        doorAreaInfo.Direction = _hoverDirection;
        doorAreaInfo.StartPosition = _hoverPoint1;
        doorAreaInfo.EndPosition = _hoverPoint2;
        switch (_hoverDirection)
        {
            case DoorDirection.E:
            case DoorDirection.W:
                doorAreaInfo.Start = _hoverPoint1.Y - mapRect.Position.Y;
                doorAreaInfo.End = _hoverPoint2.Y - mapRect.Position.Y;
                break;
            case DoorDirection.N:
            case DoorDirection.S:
                doorAreaInfo.Start = _hoverPoint1.X - mapRect.Position.X;
                doorAreaInfo.End = _hoverPoint2.X - mapRect.Position.X;
                break;
        }

        _dungeonRoomInfo.DoorAreaInfos.Add(doorAreaInfo);
        //OnDoorAreaChange();
    }

    //移除门
    private void RemoveDoorArea(DoorAreaInfo doorAreaInfo)
    {
        _dungeonRoomInfo.DoorAreaInfos.Remove(doorAreaInfo);
        //OnDoorAreaChange();
    }

    //检查门是否有碰撞
    private bool CheckDoorCollision()
    {
        foreach (var doorAreaInfo in _dungeonRoomInfo.DoorAreaInfos)
        {
            if (doorAreaInfo.Direction == _hoverDirection)
            {
                switch (_hoverDirection)
                {
                    case DoorDirection.E:
                    case DoorDirection.W:
                        if (CheckValueCollision(doorAreaInfo.StartPosition.Y, doorAreaInfo.EndPosition.Y,  _hoverPoint1.Y, _hoverPoint2.Y))
                        {
                            return true;
                        }
                        break;
                    case DoorDirection.S:
                    case DoorDirection.N:
                        if (CheckValueCollision(doorAreaInfo.StartPosition.X, doorAreaInfo.EndPosition.X,  _hoverPoint1.X, _hoverPoint2.X))
                        {
                            return true;
                        }
                        break;
                }
            }
        }

        return false;
    }

    //检查门是否有碰撞
    private bool CheckDoorCollision(DoorDirection direction, DoorAreaInfo info)
    {
        foreach (var doorAreaInfo in _dungeonRoomInfo.DoorAreaInfos)
        {
            if (doorAreaInfo.Direction == direction && info != doorAreaInfo &&
                CheckValueCollision(doorAreaInfo.Start, doorAreaInfo.End, info.Start, info.End))
            {
                return true;
            }
        }

        return false;
    }
    
    private bool CheckValueCollision(float o1, float o2, float h1, float h2)
    {
        var size = TileSet.TileSize.X;
        return !(h2 < o1 - 3 * size || o2 + 3 * size < h1);
    }

    private void FindHoverPoint(float mouseOffset)
    {
        if (_isDrag)
        {
            return;
        }
        
        //检测是否有碰撞的点
        var flag = false;
        foreach (var doorAreaInfo in _dungeonRoomInfo.DoorAreaInfos)
        {
            if (doorAreaInfo.Direction == _hoverDirection)
            {
                if (_hoverDirection == DoorDirection.N || _hoverDirection == DoorDirection.S)
                {
                    if (Math.Abs(doorAreaInfo.StartPosition.X - mouseOffset) < 0.0001f)
                    {
                        _hasActivePoint = true;
                        _activePointType = 0;
                        _activeArea = doorAreaInfo;
                        flag = true;
                        break;
                    }
                    else if (Math.Abs(doorAreaInfo.EndPosition.X - mouseOffset) < 0.0001f)
                    {
                        _hasActivePoint = true;
                        _activePointType = 1;
                        _activeArea = doorAreaInfo;
                        flag = true;
                        break;
                    }
                }
                else
                {
                    if (Math.Abs(doorAreaInfo.StartPosition.Y - mouseOffset) < 0.0001f)
                    {
                        _hasActivePoint = true;
                        _activePointType = 0;
                        _activeArea = doorAreaInfo;
                        flag = true;
                        break;
                    }
                    else if (Math.Abs(doorAreaInfo.EndPosition.Y - mouseOffset) < 0.0001f)
                    {
                        _hasActivePoint = true;
                        _activePointType = 1;
                        _activeArea = doorAreaInfo;
                        flag = true;
                        break;
                    }
                }
            }
        }

        if (!flag)
        {
            _hasActivePoint = false;
            _activeArea = null;
        }
    }

    private float Approach(float value, float period)
    {
        var temp = value % period;
        if (Mathf.Abs(temp) >= period / 2)
        {
            return ((int)(value / period) + (value >= 0 ? 1 : -1)) * period;
        }

        return (int)(value / period) * period;
    }

    //地图大小改变
    private void OnMapRectChange()
    {
        _dungeonRoomInfo.DoorAreaInfos.Clear();
        _canPut = false;
        _hasActivePoint = false;
        _activeArea = null;
        //OnDoorAreaChange();
    }

    // //区域数据修改
    // private void OnDoorAreaChange()
    // {
    //     _canSave = true;
    // }

    //触发保存操作
    private void TriggerSave()
    {
        //如果没有找到对应的场景文件,则不保存
        var path = _dungeonRoomInfo.GroupName + "/" + DungeonManager.DungeonRoomTypeToString(_dungeonRoomInfo.RoomType) + "/" + _dungeonRoomInfo.FileName;
        if (!File.Exists(GameConfig.RoomTileDir + path + ".tscn"))
        {
            return;
        }
        //计算导航网格
        _dungeonTileMap.GenerateNavigationPolygon(0);
        var rect = GetUsedRect();
        DungeonRoomInfo.SaveConfig(_dungeonRoomInfo.DoorAreaInfos, rect.Position, rect.Size,
            _dungeonRoomInfo.GroupName, _dungeonRoomInfo.RoomType, Name, Weight);
    }
    
    /// <summary>
    /// 计算tile所占区域
    /// </summary>
    /// <returns></returns>
    public static Rect2 CalcTileRange(TileMap tileMap)
    {
        var usedRect = tileMap.GetUsedRect();
        var pos = usedRect.Position * tileMap.TileSet.TileSize;
        var size = usedRect.Size * tileMap.TileSet.TileSize;
        return new Rect2(tileMap.ToLocal(pos), size);
    }

    /// <summary>
    /// 读取房间配置
    /// </summary>
    private void ReadConfig(Rect2 mapRect, string name)
    {
        var path = GameConfig.RoomTileDataDir + name + ".json";

        if (File.Exists(path))
        {
            var text = File.ReadAllText(path);
            try
            {
                _dungeonRoomInfo = DeserializeDungeonRoomInfo(text);
                
                //填充 StartPosition 和 EndPosition 数据
                foreach (var doorAreaInfo in _dungeonRoomInfo.DoorAreaInfos)
                {
                    doorAreaInfo.CalcPosition(mapRect.Position, mapRect.Size);
                }

                Weight = _dungeonRoomInfo.Weight;
            }
            catch (Exception e)
            {
                GD.PrintErr($"加载房间数据'{path}'发生异常: " + e);
            }
        }
    }

    /// <summary>
    /// 反序列化 DungeonRoomInfo
    /// </summary>
    public static DungeonRoomInfo DeserializeDungeonRoomInfo(string text)
    {
        // 下面这句代码在 Godot4.0_rc2的编辑器模式下, 重载脚本会导致编辑器一直报错!, 所以暂时先用下面的方法
        //var roomInfo = JsonSerializer.Deserialize<DungeonRoomInfo>(text);

        var obj = Json.ParseString(text).AsGodotDictionary();
        var roomInfo = new DungeonRoomInfo();
        if (obj.ContainsKey("Position"))
        {
            var position = obj["Position"].AsGodotDictionary();
            roomInfo.Position = new SerializeVector2(position["X"].AsInt32(), position["Y"].AsInt32());
        }

        if (obj.ContainsKey("Size"))
        {
            var size = obj["Size"].AsGodotDictionary();
            roomInfo.Size = new SerializeVector2(size["X"].AsInt32(), size["Y"].AsInt32());
        }

        if (obj.ContainsKey("RoomType"))
        {
            var roomType = obj["RoomType"].AsInt32();
            roomInfo.RoomType = (DungeonRoomType)roomType;
        }
        
        if (obj.ContainsKey("GroupName"))
        {
            roomInfo.GroupName = obj["GroupName"].AsString();
        }
        
        if (obj.ContainsKey("FileName"))
        {
            roomInfo.FileName = obj["FileName"].AsString();
        }
        
        if (obj.ContainsKey("Weight"))
        {
            roomInfo.Weight = obj["Weight"].AsInt32();
        }

        if (obj.ContainsKey("DoorAreaInfos"))
        {
            var doorAreaInfos = obj["DoorAreaInfos"].AsGodotArray<Variant>();
            roomInfo.DoorAreaInfos = new List<DoorAreaInfo>();
            foreach (var item in doorAreaInfos)
            {
                var temp = item.AsGodotDictionary();
                var doorInfo = new DoorAreaInfo();
                doorInfo.Direction = (DoorDirection)temp["Direction"].AsInt32();
                doorInfo.Start = temp["Start"].AsInt32();
                doorInfo.End = temp["End"].AsInt32();
                roomInfo.DoorAreaInfos.Add(doorInfo);
            }
        }

        return roomInfo;
    }
#endif

    /// <summary>
    /// 获取所有标记数据
    /// </summary>
    public ActivityMark[] GetMarks()
    {
        var list = new List<ActivityMark>();
        foreach (var child in GetChildren())
        {
            EachAndGetMarks(child, list);
        }

        return list.ToArray();
    }

    private void EachAndGetMarks(Node node, List<ActivityMark> list)
    {
        if (node is ActivityMark mark)
        {
            list.Add(mark);
        }
        foreach (var child in node.GetChildren())
        {
            EachAndGetMarks(child, list);
        }
    }
}
*/