diff --git a/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMap.cs b/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMap.cs
new file mode 100644
index 0000000..6175254
--- /dev/null
+++ b/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMap.cs
@@ -0,0 +1,1013 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Text.Json;
+using Godot;
+using Godot.Collections;
+using UI.MapEditorTools;
+
+namespace UI.MapEditor;
+
+public partial class EditorTileMap : TileMap
+{
+
+ public enum MouseButtonType
+ {
+ ///
+ /// 无状态
+ ///
+ None,
+ ///
+ /// 拖拽模式
+ ///
+ Drag,
+ ///
+ /// 笔
+ ///
+ Pen,
+ ///
+ /// 绘制区域模式
+ ///
+ Area,
+ ///
+ /// 编辑工具模式
+ ///
+ Edit,
+ }
+
+ ///
+ /// 自动图块地板层
+ ///
+ public const int AutoFloorLayer = 0;
+ ///
+ /// 自定义图块地板层
+ ///
+ public const int CustomFloorLayer = 1;
+ ///
+ /// 自动图块中间层
+ ///
+ public const int AutoMiddleLayer = 2;
+ ///
+ /// 自定义图块中间层
+ ///
+ public const int CustomMiddleLayer = 3;
+ ///
+ /// 自动图块顶层
+ ///
+ public const int AutoTopLayer = 4;
+ ///
+ /// 自定义图块顶层
+ ///
+ public const int CustomTopLayer = 5;
+ ///
+ /// 标记数据层
+ ///
+ public const int MarkLayer = 10;
+
+ ///
+ /// 所属地图编辑器UI
+ ///
+ public MapEditorPanel MapEditorPanel { get; set; }
+
+ ///
+ /// 编辑器工具UI
+ ///
+ public MapEditorToolsPanel MapEditorToolsPanel { get; set; }
+
+ ///
+ /// 左键功能
+ ///
+ public MouseButtonType MouseType { get; private set; } = MouseButtonType.Pen;
+
+ //鼠标坐标
+ private Vector2 _mousePosition;
+ //鼠标所在的cell坐标
+ private Vector2I _mouseCellPosition;
+ //上一帧鼠标所在的cell坐标
+ private Vector2I _prevMouseCellPosition = new Vector2I(-99999, -99999);
+ //单次绘制是否改变过tile数据
+ private bool _changeFlag = false;
+ //左键开始按下时鼠标所在的坐标
+ private Vector2I _mouseStartCellPosition;
+ //鼠标中建是否按下
+ private bool _isMiddlePressed = false;
+ private Vector2 _moveOffset;
+ //左键是否按下
+ private bool _isLeftPressed = false;
+ //右键是否按下
+ private bool _isRightPressed = false;
+ //绘制填充区域
+ private bool _drawFullRect = false;
+ //负责存储自动图块数据
+ private Grid _autoCellLayerGrid = new Grid();
+ //用于生成导航网格
+ private DungeonTileMap _dungeonTileMap;
+ //停止绘制多久后开始执行生成操作
+ private float _generateInterval = 3f;
+ //生成自动图块和导航网格的计时器
+ private float _generateTimer = -1;
+ //检测地形结果
+ private bool _checkTerrainFlag = true;
+ //错误地形位置
+ private Vector2I _checkTerrainErrorPosition = Vector2I.Zero;
+ //是否执行生成地形成功
+ private bool _isGenerateTerrain = false;
+ private bool _initLayer = false;
+
+ //--------- 配置数据 -------------
+ private int _sourceId = 0;
+ private int _terrainSet = 0;
+ private int _terrain = 0;
+ private AutoTileConfig _autoTileConfig = new AutoTileConfig();
+
+ ///
+ /// 正在编辑的房间数据
+ ///
+ public DungeonRoomSplit RoomSplit { get; private set; }
+
+ ///
+ /// 波数网格选中的索引
+ ///
+ public int SelectWaveIndex
+ {
+ get => _selectWaveIndex;
+ set
+ {
+ if (_selectWaveIndex != value)
+ {
+ _selectWaveIndex = value;
+ EventManager.EmitEvent(EventEnum.OnSelectWave, value);
+ }
+ }
+ }
+
+ private int _selectWaveIndex = -1;
+
+ ///
+ /// 选中的预设
+ ///
+ public int SelectPreinstallIndex
+ {
+ get => _selectPreinstallIndex;
+ set
+ {
+ if (_selectPreinstallIndex != value)
+ {
+ _selectPreinstallIndex = value;
+ EventManager.EmitEvent(EventEnum.OnSelectPreinstall, value);
+ }
+ }
+ }
+
+ private int _selectPreinstallIndex = -1;
+
+ ///
+ /// 当前选中的预设
+ ///
+ public RoomPreinstall SelectPreinstall
+ {
+ get
+ {
+ if (SelectPreinstallIndex == -1 || SelectPreinstallIndex >= RoomSplit.Preinstall.Count)
+ {
+ return null;
+ }
+
+ return RoomSplit.Preinstall[SelectPreinstallIndex];
+ }
+ }
+
+ ///
+ /// 选中的标记
+ ///
+ public MarkTool SelectMark => MapEditorToolsPanel.ActiveMark;
+
+ //变动过的数据
+
+ //地图位置, 单位: 格
+ private Vector2I _roomPosition;
+ //地图大小, 单位: 格
+ private Vector2I _roomSize;
+ private List _doorConfigs = new List();
+ //-------------------------------
+
+ public override void _Ready()
+ {
+ InitLayer();
+ }
+
+ public override void _Process(double delta)
+ {
+ var newDelta = (float)delta;
+ _drawFullRect = false;
+ var position = GetLocalMousePosition();
+ _mouseCellPosition = LocalToMap(position);
+ _mousePosition = new Vector2(
+ _mouseCellPosition.X * GameConfig.TileCellSize,
+ _mouseCellPosition.Y * GameConfig.TileCellSize
+ );
+
+ if (!MapEditorToolsPanel.S_HBoxContainer.Instance.IsPositionOver(GetGlobalMousePosition())) //不在Ui节点上
+ {
+ //左键绘制
+ if (_isLeftPressed)
+ {
+ if (MouseType == MouseButtonType.Pen) //绘制单格
+ {
+ if (_prevMouseCellPosition != _mouseCellPosition || !_changeFlag) //鼠标位置变过
+ {
+ _changeFlag = true;
+ _prevMouseCellPosition = _mouseCellPosition;
+ //绘制自动图块
+ SetSingleAutoCell(_mouseCellPosition);
+ }
+ }
+ else if (MouseType == MouseButtonType.Area) //绘制区域
+ {
+ _drawFullRect = true;
+ }
+ else if (MouseType == MouseButtonType.Drag) //拖拽
+ {
+ SetMapPosition(GetGlobalMousePosition() + _moveOffset);
+ }
+ }
+ else if (_isRightPressed) //右键擦除
+ {
+ if (MouseType == MouseButtonType.Pen) //绘制单格
+ {
+ if (_prevMouseCellPosition != _mouseCellPosition || !_changeFlag) //鼠标位置变过
+ {
+ _changeFlag = true;
+ _prevMouseCellPosition = _mouseCellPosition;
+ EraseSingleAutoCell(_mouseCellPosition);
+ }
+ }
+ else if (MouseType == MouseButtonType.Area) //绘制区域
+ {
+ _drawFullRect = true;
+ }
+ else if (MouseType == MouseButtonType.Drag) //拖拽
+ {
+ SetMapPosition(GetGlobalMousePosition() + _moveOffset);
+ }
+ }
+ else if (_isMiddlePressed) //中键移动
+ {
+ SetMapPosition(GetGlobalMousePosition() + _moveOffset);
+ }
+ }
+
+ //绘制停止指定时间后, 生成导航网格
+ if (_generateTimer > 0)
+ {
+ _generateTimer -= newDelta;
+ if (_generateTimer <= 0)
+ {
+ //计算区域
+ CalcTileRect(false);
+ GD.Print("开始检测是否可以生成地形...");
+ if (CheckTerrain())
+ {
+ GD.Print("开始绘制导航网格...");
+ if (GenerateNavigation())
+ {
+ GD.Print("开始绘制自动贴图...");
+ GenerateTerrain();
+ _isGenerateTerrain = true;
+ }
+ }
+ else
+ {
+ SetErrorCell(_checkTerrainErrorPosition);
+ }
+ }
+ }
+ }
+
+ ///
+ /// 绘制辅助线
+ ///
+ public void DrawGuides(CanvasItem canvasItem)
+ {
+ //轴线
+ canvasItem.DrawLine(new Vector2(0, 2000), new Vector2(0, -2000), Colors.Green);
+ canvasItem.DrawLine(new Vector2(2000, 0), new Vector2( -2000, 0), Colors.Red);
+
+ //绘制房间区域
+ if (_roomSize.X != 0 && _roomSize.Y != 0)
+ {
+ var size = TileSet.TileSize;
+ canvasItem.DrawRect(new Rect2(_roomPosition * size, _roomSize * size),
+ Colors.Aqua, false, 5f / Scale.X);
+ }
+
+ if (_checkTerrainFlag) //已经通过地形检测
+ {
+ //绘制导航网格
+ var result = _dungeonTileMap.GetGenerateNavigationResult();
+ if (result != null && result.Success)
+ {
+ var polygonData = _dungeonTileMap.GetPolygonData();
+ Utils.DrawNavigationPolygon(canvasItem, polygonData, 3f / Scale.X);
+ }
+ }
+
+ if (MouseType == MouseButtonType.Pen || MouseType == MouseButtonType.Area)
+ {
+ if (_drawFullRect) //绘制填充矩形
+ {
+ var size = TileSet.TileSize;
+ var cellPos = _mouseStartCellPosition;
+ var temp = size;
+ if (_mouseStartCellPosition.X > _mouseCellPosition.X)
+ {
+ cellPos.X += 1;
+ temp.X -= size.X;
+ }
+ if (_mouseStartCellPosition.Y > _mouseCellPosition.Y)
+ {
+ cellPos.Y += 1;
+ temp.Y -= size.Y;
+ }
+
+ var pos = cellPos * size;
+ canvasItem.DrawRect(new Rect2(pos, _mousePosition - pos + temp), Colors.White, false, 2f / Scale.X);
+ }
+ else //绘制单格
+ {
+ canvasItem.DrawRect(new Rect2(_mousePosition, TileSet.TileSize), Colors.White, false, 2f / Scale.X);
+ }
+ }
+ }
+
+ public override void _Input(InputEvent @event)
+ {
+ if (@event is InputEventMouseButton mouseButton)
+ {
+ if (mouseButton.ButtonIndex == MouseButton.Left) //左键
+ {
+ if (mouseButton.Pressed) //按下
+ {
+ _moveOffset = Position - GetGlobalMousePosition();
+ _mouseStartCellPosition = LocalToMap(GetLocalMousePosition());
+ }
+ else
+ {
+ _changeFlag = false;
+ if (_drawFullRect) //松开, 提交绘制的矩形区域
+ {
+ SetRectAutoCell(_mouseStartCellPosition, _mouseCellPosition);
+ _drawFullRect = false;
+ }
+ }
+
+ _isLeftPressed = mouseButton.Pressed;
+ }
+ else if (mouseButton.ButtonIndex == MouseButton.Right) //右键
+ {
+ if (mouseButton.Pressed) //按下
+ {
+ _moveOffset = Position - GetGlobalMousePosition();
+ _mouseStartCellPosition = LocalToMap(GetLocalMousePosition());
+ }
+ else
+ {
+ _changeFlag = false;
+ if (_drawFullRect) //松开, 提交擦除的矩形区域
+ {
+ EraseRectAutoCell(_mouseStartCellPosition, _mouseCellPosition);
+ _drawFullRect = false;
+ }
+ }
+
+ _isRightPressed = mouseButton.Pressed;
+ }
+ else if (mouseButton.ButtonIndex == MouseButton.WheelDown)
+ {
+ //缩小
+ Shrink();
+ }
+ else if (mouseButton.ButtonIndex == MouseButton.WheelUp)
+ {
+ //放大
+ Magnify();
+ }
+ else if (mouseButton.ButtonIndex == MouseButton.Middle)
+ {
+ _isMiddlePressed = mouseButton.Pressed;
+ if (_isMiddlePressed)
+ {
+ _moveOffset = Position - GetGlobalMousePosition();
+ }
+ }
+ }
+ else if (@event is InputEventKey eventKey)
+ {
+ if (eventKey.Pressed && eventKey.Keycode == Key.M)
+ {
+ GD.Print("保存地牢房间数据...");
+ TriggerSave();
+ }
+ }
+ }
+
+ //将指定层数据存入list中
+ private void PushLayerDataToList(int layer, int sourceId, List list)
+ {
+ var layerArray = GetUsedCellsById(layer, sourceId);
+ foreach (var pos in layerArray)
+ {
+ var atlasCoords = GetCellAtlasCoords(layer, pos);
+ list.Add(pos.X);
+ list.Add(pos.Y);
+ list.Add(_sourceId);
+ list.Add(atlasCoords.X);
+ list.Add(atlasCoords.Y);
+ }
+ }
+
+ private void SetLayerDataFromList(int layer, List list)
+ {
+ for (var i = 0; i < list.Count; i += 5)
+ {
+ var pos = new Vector2I(list[i], list[i + 1]);
+ var sourceId = list[i + 2];
+ var atlasCoords = new Vector2I(list[i + 3], list[i + 4]);
+ SetCell(layer, pos, sourceId, atlasCoords);
+ if (layer == AutoFloorLayer)
+ {
+ _autoCellLayerGrid.Set(pos, true);
+ }
+ }
+ }
+
+ //保存地牢
+ private void TriggerSave()
+ {
+ SaveRoomInfoConfig();
+ SaveTileInfoConfig();
+ SavePreinstallConfig();
+ }
+
+ ///
+ /// 加载地牢, 返回是否加载成功
+ ///
+ public bool Load(DungeonRoomSplit roomSplit)
+ {
+ //重新加载数据
+ roomSplit.ReloadRoomInfo();
+ roomSplit.ReloadTileInfo();
+ roomSplit.ReloadPreinstall();
+
+ RoomSplit = roomSplit;
+ var roomInfo = roomSplit.RoomInfo;
+ var tileInfo = roomSplit.TileInfo;
+
+ _roomPosition = roomInfo.Position.AsVector2I();
+ SetMapSize(roomInfo.Size.AsVector2I(), true);
+ _doorConfigs.Clear();
+ foreach (var doorAreaInfo in roomInfo.DoorAreaInfos)
+ {
+ _doorConfigs.Add(doorAreaInfo.Clone());
+ }
+
+ //初始化层级数据
+ InitLayer();
+
+ //地块数据
+ SetLayerDataFromList(AutoFloorLayer, tileInfo.Floor);
+ SetLayerDataFromList(AutoMiddleLayer, tileInfo.Middle);
+ SetLayerDataFromList(AutoTopLayer, tileInfo.Top);
+
+ //导航网格数据
+ _dungeonTileMap.SetPolygonData(tileInfo.NavigationList);
+
+ //聚焦
+ //MapEditorPanel.CallDelay(0.1f, OnClickCenterTool);
+ //CallDeferred(nameof(OnClickCenterTool), null);
+
+ //加载门编辑区域
+ foreach (var doorAreaInfo in _doorConfigs)
+ {
+ MapEditorToolsPanel.CreateDoorTool(doorAreaInfo);
+ }
+
+ //聚焦
+ OnClickCenterTool(null);
+ return true;
+ }
+
+ private void InitLayer()
+ {
+ if (_initLayer)
+ {
+ return;
+ }
+
+ _initLayer = true;
+ //初始化层级数据
+ AddLayer(CustomFloorLayer);
+ SetLayerZIndex(CustomFloorLayer, CustomFloorLayer);
+ AddLayer(AutoMiddleLayer);
+ SetLayerZIndex(AutoMiddleLayer, AutoMiddleLayer);
+ AddLayer(CustomMiddleLayer);
+ SetLayerZIndex(CustomMiddleLayer, CustomMiddleLayer);
+ AddLayer(AutoTopLayer);
+ SetLayerZIndex(AutoTopLayer, AutoTopLayer);
+ AddLayer(CustomTopLayer);
+ SetLayerZIndex(CustomTopLayer, CustomTopLayer);
+
+ _dungeonTileMap = new DungeonTileMap(this);
+ _dungeonTileMap.SetFloorAtlasCoords(new List(new []{ _autoTileConfig.Floor.AutoTileCoord }));
+ }
+
+ //缩小
+ private void Shrink()
+ {
+ var pos = GetLocalMousePosition();
+ var scale = Scale / 1.1f;
+ if (scale.LengthSquared() >= 0.5f)
+ {
+ Scale = scale;
+ SetMapPosition(Position + pos * 0.1f * scale);
+ }
+ else
+ {
+ GD.Print("太小了");
+ }
+ }
+ //放大
+ private void Magnify()
+ {
+ var pos = GetLocalMousePosition();
+ var prevScale = Scale;
+ var scale = prevScale * 1.1f;
+ if (scale.LengthSquared() <= 2000)
+ {
+ Scale = scale;
+ SetMapPosition(Position - pos * 0.1f * prevScale);
+ }
+ else
+ {
+ GD.Print("太大了");
+ }
+ }
+
+ //绘制单个自动贴图
+ private void SetSingleAutoCell(Vector2I position)
+ {
+ SetCell(GetFloorLayer(), position, _sourceId, _autoTileConfig.Floor.AutoTileCoord);
+ if (!_autoCellLayerGrid.Contains(position.X, position.Y))
+ {
+ ResetGenerateTimer();
+ _autoCellLayerGrid.Set(position.X, position.Y, true);
+ }
+ }
+
+ //绘制区域自动贴图
+ private void SetRectAutoCell(Vector2I start, Vector2I end)
+ {
+ ResetGenerateTimer();
+
+ if (start.X > end.X)
+ {
+ var temp = end.X;
+ end.X = start.X;
+ start.X = temp;
+ }
+ if (start.Y > end.Y)
+ {
+ var temp = end.Y;
+ end.Y = start.Y;
+ start.Y = temp;
+ }
+
+ var width = end.X - start.X + 1;
+ var height = end.Y - start.Y + 1;
+ for (var i = 0; i < width; i++)
+ {
+ for (var j = 0; j < height; j++)
+ {
+ SetCell(GetFloorLayer(), new Vector2I(start.X + i, start.Y + j), _sourceId, _autoTileConfig.Floor.AutoTileCoord);
+ }
+ }
+
+ _autoCellLayerGrid.SetRect(start, new Vector2I(width, height), true);
+ }
+
+ //擦除单个自动图块
+ private void EraseSingleAutoCell(Vector2I position)
+ {
+ EraseCell(GetFloorLayer(), position);
+ if (_autoCellLayerGrid.Remove(position.X, position.Y))
+ {
+ ResetGenerateTimer();
+ }
+ }
+
+ //擦除一个区域内的自动贴图
+ private void EraseRectAutoCell(Vector2I start, Vector2I end)
+ {
+ ResetGenerateTimer();
+
+ if (start.X > end.X)
+ {
+ var temp = end.X;
+ end.X = start.X;
+ start.X = temp;
+ }
+ if (start.Y > end.Y)
+ {
+ var temp = end.Y;
+ end.Y = start.Y;
+ start.Y = temp;
+ }
+
+ var width = end.X - start.X + 1;
+ var height = end.Y - start.Y + 1;
+ for (var i = 0; i < width; i++)
+ {
+ for (var j = 0; j < height; j++)
+ {
+ EraseCell(GetFloorLayer(), new Vector2I(start.X + i, start.Y + j));
+ }
+ }
+ _autoCellLayerGrid.RemoveRect(start, new Vector2I(width, height));
+ }
+
+ //重置计时器
+ private void ResetGenerateTimer()
+ {
+ _generateTimer = _generateInterval;
+ _isGenerateTerrain = false;
+ _dungeonTileMap.ClearPolygonData();
+ ClearLayer(AutoTopLayer);
+ ClearLayer(AutoMiddleLayer);
+ }
+
+ //重新计算房间区域
+ private void CalcTileRect(bool refreshDoorTrans)
+ {
+ var rect = GetUsedRect();
+ _roomPosition = rect.Position;
+ SetMapSize(rect.Size, refreshDoorTrans);
+ }
+
+ //检测是否有不合规的图块, 返回true表示图块正常
+ private bool CheckTerrain()
+ {
+ var x = _roomPosition.X;
+ var y = _roomPosition.Y;
+ var w = _roomSize.X;
+ var h = _roomSize.Y;
+
+ for (var i = 0; i < w; i++)
+ {
+ for (var j = 0; j < h; j++)
+ {
+ var pos = new Vector2I(x + i, y + j);
+ if (GetCellSourceId(AutoFloorLayer, pos) == -1)
+ {
+ //先检测对边是否有地板
+ if ((_autoCellLayerGrid.Get(pos.X - 1, pos.Y) && _autoCellLayerGrid.Get(pos.X + 1, pos.Y)) //left & right
+ || (_autoCellLayerGrid.Get(pos.X, pos.Y + 1) && _autoCellLayerGrid.Get(pos.X, pos.Y - 1))) //top & down
+ {
+ _checkTerrainFlag = false;
+ _checkTerrainErrorPosition = pos;
+ return false;
+ }
+
+ //再检测对角是否有地板
+ var topLeft = _autoCellLayerGrid.Get(pos.X - 1, pos.Y + 1); //top-left
+ var downRight = _autoCellLayerGrid.Get(pos.X + 1, pos.Y - 1); //down-right
+ var downLeft = _autoCellLayerGrid.Get(pos.X - 1, pos.Y - 1); //down-left
+ var topRight = _autoCellLayerGrid.Get(pos.X + 1, pos.Y + 1); //top-right
+ if ((topLeft && downRight && !downLeft && !topRight) || (!topLeft && !downRight && downLeft && topRight))
+ {
+ _checkTerrainFlag = false;
+ _checkTerrainErrorPosition = pos;
+ return false;
+ }
+ }
+ }
+ }
+
+ _checkTerrainFlag = true;
+ return true;
+ }
+
+ //生成自动图块 (地形)
+ private void GenerateTerrain()
+ {
+ ClearLayer(AutoFloorLayer);
+
+ var list = new List();
+ _autoCellLayerGrid.ForEach((x, y, data) =>
+ {
+ if (data)
+ {
+ list.Add(new Vector2I(x, y));
+ }
+ });
+ var arr = new Array(list);
+ //绘制自动图块
+ SetCellsTerrainConnect(AutoFloorLayer, arr, _terrainSet, _terrain, false);
+ //计算区域
+ CalcTileRect(true);
+ //将墙壁移动到指定层
+ MoveTerrainCell();
+ }
+
+ //将自动生成的图块从 AutoFloorLayer 移动到指定图层中
+ private void MoveTerrainCell()
+ {
+ ClearLayer(AutoTopLayer);
+ ClearLayer(AutoMiddleLayer);
+
+ var x = _roomPosition.X;
+ var y = _roomPosition.Y;
+ var w = _roomSize.X;
+ var h = _roomSize.Y;
+
+ for (var i = 0; i < w; i++)
+ {
+ for (var j = 0; j < h; j++)
+ {
+ var pos = new Vector2I(x + i, y + j);
+ if (!_autoCellLayerGrid.Contains(pos) && GetCellSourceId(AutoFloorLayer, pos) != -1)
+ {
+ var atlasCoords = GetCellAtlasCoords(AutoFloorLayer, pos);
+ var layer = _autoTileConfig.GetLayer(atlasCoords);
+ if (layer == GameConfig.MiddleMapLayer)
+ {
+ layer = AutoMiddleLayer;
+ }
+ else if (layer == GameConfig.TopMapLayer)
+ {
+ layer = AutoTopLayer;
+ }
+ else
+ {
+ GD.PrintErr($"异常图块: {pos}, 这个图块的图集坐标'{atlasCoords}'不属于'MiddleMapLayer'和'TopMapLayer'!");
+ continue;
+ }
+ EraseCell(AutoFloorLayer, pos);
+ SetCell(layer, pos, _sourceId, atlasCoords);
+ }
+ }
+ }
+ }
+
+ //生成导航网格
+ private bool GenerateNavigation()
+ {
+ _dungeonTileMap.GenerateNavigationPolygon(AutoFloorLayer);
+ var result = _dungeonTileMap.GetGenerateNavigationResult();
+ if (result.Success)
+ {
+ CloseErrorCell();
+ }
+ else
+ {
+ SetErrorCell(result.Exception.Point);
+ }
+
+ return result.Success;
+ }
+
+ //设置显示的错误cell, 会标记上红色的闪烁动画
+ private void SetErrorCell(Vector2I pos)
+ {
+ MapEditorPanel.S_ErrorCell.Instance.Position = pos * CellQuadrantSize;
+ MapEditorPanel.S_ErrorCellAnimationPlayer.Instance.Play(AnimatorNames.Show);
+ }
+
+ //关闭显示的错误cell
+ private void CloseErrorCell()
+ {
+ MapEditorPanel.S_ErrorCellAnimationPlayer.Instance.Stop();
+ }
+
+ private int GetFloorLayer()
+ {
+ return AutoFloorLayer;
+ }
+
+ private int GetMiddleLayer()
+ {
+ return AutoMiddleLayer;
+ }
+
+ private int GetTopLayer()
+ {
+ return AutoTopLayer;
+ }
+
+ ///
+ /// 选中拖拽功能
+ ///
+ public void OnSelectHandTool(object arg)
+ {
+ MouseType = MouseButtonType.Drag;
+ }
+
+ ///
+ /// 选中画笔攻击
+ ///
+ public void OnSelectPenTool(object arg)
+ {
+ MouseType = MouseButtonType.Pen;
+ }
+
+ ///
+ /// 选中绘制区域功能
+ ///
+ public void OnSelectRectTool(object arg)
+ {
+ MouseType = MouseButtonType.Area;
+ }
+
+ ///
+ /// 选择编辑门区域
+ ///
+ public void OnSelectEditTool(object arg)
+ {
+ MouseType = MouseButtonType.Edit;
+ }
+
+ ///
+ /// 聚焦
+ ///
+ public void OnClickCenterTool(object arg)
+ {
+ var pos = MapEditorPanel.S_SubViewport.Instance.Size / 2;
+ if (_roomSize.X == 0 && _roomSize.Y == 0) //聚焦原点
+ {
+ SetMapPosition(pos);
+ }
+ else //聚焦地图中心点
+ {
+ SetMapPosition(pos - (_roomPosition + _roomSize / 2) * TileSet.TileSize * Scale);
+ }
+ }
+
+ ///
+ /// 创建地牢房间门区域
+ ///
+ /// 门方向
+ /// 起始坐标, 单位: 像素
+ /// 结束坐标, 单位: 像素
+ public DoorAreaInfo CreateDoorArea(DoorDirection direction, int start, int end)
+ {
+ var doorAreaInfo = new DoorAreaInfo();
+ doorAreaInfo.Direction = direction;
+ doorAreaInfo.Start = start;
+ doorAreaInfo.End = end;
+ //doorAreaInfo.CalcPosition(_roomPosition, _roomSize);
+ _doorConfigs.Add(doorAreaInfo);
+ return doorAreaInfo;
+ }
+
+ ///
+ /// 检测门区域数据是否可以提交
+ ///
+ /// 门方向
+ /// 起始坐标, 单位: 像素
+ /// 结束坐标, 单位: 像素
+ ///
+ public bool CheckDoorArea(DoorDirection direction, int start, int end)
+ {
+ foreach (var item in _doorConfigs)
+ {
+ if (item.Direction == direction)
+ {
+ if (CheckValueCollision(item.Start, item.End, start, end))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ ///
+ /// 检测门区域数据是否可以提交
+ ///
+ /// 需要检测的门
+ /// 起始坐标, 单位: 像素
+ /// 结束坐标, 单位: 像素
+ public bool CheckDoorArea(DoorAreaInfo target, int start, int end)
+ {
+ foreach (var item in _doorConfigs)
+ {
+ if (item.Direction == target.Direction && item != target)
+ {
+ if (CheckValueCollision(item.Start, item.End, start, end))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private bool CheckValueCollision(float o1, float o2, float h1, float h2)
+ {
+ var size = GameConfig.TileCellSize;
+ return !(h2 < o1 - 3 * size || o2 + 3 * size < h1);
+ }
+
+ ///
+ /// 移除门区域数据
+ ///
+ public void RemoveDoorArea(DoorAreaInfo doorAreaInfo)
+ {
+ _doorConfigs.Remove(doorAreaInfo);
+ }
+
+ //保存房间配置
+ private void SaveRoomInfoConfig()
+ {
+ //存入本地
+ var roomInfo = RoomSplit.RoomInfo;
+ var path = MapProjectManager.GetConfigPath(roomInfo.GroupName,roomInfo.RoomType, roomInfo.RoomName);
+ if (!Directory.Exists(path))
+ {
+ Directory.CreateDirectory(path);
+ }
+
+ roomInfo.Position = new SerializeVector2(_roomPosition);
+ roomInfo.Size = new SerializeVector2(_roomSize);
+ roomInfo.DoorAreaInfos.Clear();
+ roomInfo.DoorAreaInfos.AddRange(_doorConfigs);
+
+ path += "/" + MapProjectManager.GetRoomInfoConfigName(roomInfo.RoomName);
+ var jsonStr = JsonSerializer.Serialize(roomInfo);
+ File.WriteAllText(path, jsonStr);
+ }
+
+ //保存地块数据
+ public void SaveTileInfoConfig()
+ {
+ //存入本地
+ var roomInfo = RoomSplit.RoomInfo;
+ var path = MapProjectManager.GetConfigPath(roomInfo.GroupName,roomInfo.RoomType, roomInfo.RoomName);
+ if (!Directory.Exists(path))
+ {
+ Directory.CreateDirectory(path);
+ }
+
+ var tileInfo = RoomSplit.TileInfo;
+ tileInfo.NavigationList.Clear();
+ tileInfo.NavigationList.AddRange(_dungeonTileMap.GetPolygonData());
+ tileInfo.Floor.Clear();
+ tileInfo.Middle.Clear();
+ tileInfo.Top.Clear();
+
+ PushLayerDataToList(AutoFloorLayer, _sourceId, tileInfo.Floor);
+ PushLayerDataToList(AutoMiddleLayer, _sourceId, tileInfo.Middle);
+ PushLayerDataToList(AutoTopLayer, _sourceId, tileInfo.Top);
+
+ path += "/" + MapProjectManager.GetTileInfoConfigName(roomInfo.RoomName);
+ var jsonStr = JsonSerializer.Serialize(tileInfo);
+ File.WriteAllText(path, jsonStr);
+ }
+
+ //保存预设数据
+ public void SavePreinstallConfig()
+ {
+ //存入本地
+ var roomInfo = RoomSplit.RoomInfo;
+ var path = MapProjectManager.GetConfigPath(roomInfo.GroupName,roomInfo.RoomType, roomInfo.RoomName);
+ if (!Directory.Exists(path))
+ {
+ Directory.CreateDirectory(path);
+ }
+
+ path += "/" + MapProjectManager.GetRoomPreinstallConfigName(roomInfo.RoomName);
+ var jsonStr = JsonSerializer.Serialize(RoomSplit.Preinstall);
+ File.WriteAllText(path, jsonStr);
+ }
+
+ //设置地图坐标
+ private void SetMapPosition(Vector2 pos)
+ {
+ Position = pos;
+ MapEditorToolsPanel.SetToolTransform(pos, Scale);
+ }
+
+ //设置地图大小
+ private void SetMapSize(Vector2I size, bool refreshDoorTrans)
+ {
+ if (_roomSize != size)
+ {
+ _roomSize = size;
+
+ if (refreshDoorTrans)
+ {
+ MapEditorToolsPanel.SetDoorHoverToolTransform(_roomPosition, _roomSize);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMapBar.cs b/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMapBar.cs
new file mode 100644
index 0000000..1c9826f
--- /dev/null
+++ b/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMapBar.cs
@@ -0,0 +1,50 @@
+using Godot;
+
+namespace UI.MapEditor;
+
+public class EditorTileMapBar
+{
+ private MapEditor.TileMap _editorTileMap;
+ private EventFactory _eventFactory;
+
+ public EditorTileMapBar(MapEditorPanel editorPanel, MapEditor.TileMap editorTileMap)
+ {
+ _editorTileMap = editorTileMap;
+ _editorTileMap.Instance.MapEditorPanel = editorPanel;
+ _editorTileMap.Instance.MapEditorToolsPanel = editorPanel.S_MapEditorTools.Instance;
+
+ _editorTileMap.L_Brush.Instance.Draw += OnDrawGuides;
+ _eventFactory = EventManager.CreateEventFactory();
+ _eventFactory.AddEventListener(EventEnum.OnSelectDragTool, _editorTileMap.Instance.OnSelectHandTool);
+ _eventFactory.AddEventListener(EventEnum.OnSelectPenTool, _editorTileMap.Instance.OnSelectPenTool);
+ _eventFactory.AddEventListener(EventEnum.OnSelectRectTool, _editorTileMap.Instance.OnSelectRectTool);
+ _eventFactory.AddEventListener(EventEnum.OnSelectEditTool, _editorTileMap.Instance.OnSelectEditTool);
+ _eventFactory.AddEventListener(EventEnum.OnClickCenterTool, _editorTileMap.Instance.OnClickCenterTool);
+ }
+
+ public void OnShow()
+ {
+
+ }
+
+ public void OnHide()
+ {
+
+ }
+
+ public void Process(float delta)
+ {
+ _editorTileMap.L_Brush.Instance.QueueRedraw();
+ }
+
+ private void OnDrawGuides()
+ {
+ _editorTileMap.Instance.DrawGuides(_editorTileMap.L_Brush.Instance);
+ }
+
+ public void OnDestroy()
+ {
+ _editorTileMap.L_Brush.Instance.Draw -= OnDrawGuides;
+ _eventFactory.RemoveAllEventListener();
+ }
+}
\ No newline at end of file