Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / ui / mapEditor / TileView / EditorTileMap.cs
@小李xl 小李xl on 15 Aug 2023 30 KB 创建房间标记, 开发中
  1. using System.Collections.Generic;
  2. using System.IO;
  3. using System.Text.Json;
  4. using Godot;
  5. using Godot.Collections;
  6. using UI.MapEditorTools;
  7.  
  8. namespace UI.MapEditor;
  9.  
  10. public partial class EditorTileMap : TileMap
  11. {
  12. public enum MouseButtonType
  13. {
  14. /// <summary>
  15. /// 无状态
  16. /// </summary>
  17. None,
  18. /// <summary>
  19. /// 拖拽模式
  20. /// </summary>
  21. Drag,
  22. /// <summary>
  23. /// 笔
  24. /// </summary>
  25. Pen,
  26. /// <summary>
  27. /// 绘制区域模式
  28. /// </summary>
  29. Area,
  30. /// <summary>
  31. /// 编辑门区域模式
  32. /// </summary>
  33. Door,
  34. }
  35. /// <summary>
  36. /// 自动图块地板层
  37. /// </summary>
  38. public const int AutoFloorLayer = 0;
  39. /// <summary>
  40. /// 自定义图块地板层
  41. /// </summary>
  42. public const int CustomFloorLayer = 1;
  43. /// <summary>
  44. /// 自动图块中间层
  45. /// </summary>
  46. public const int AutoMiddleLayer = 2;
  47. /// <summary>
  48. /// 自定义图块中间层
  49. /// </summary>
  50. public const int CustomMiddleLayer = 3;
  51. /// <summary>
  52. /// 自动图块顶层
  53. /// </summary>
  54. public const int AutoTopLayer = 4;
  55. /// <summary>
  56. /// 自定义图块顶层
  57. /// </summary>
  58. public const int CustomTopLayer = 5;
  59. /// <summary>
  60. /// 所属地图编辑器UI
  61. /// </summary>
  62. public MapEditorPanel MapEditorPanel { get; set; }
  63. /// <summary>
  64. /// 编辑器工具UI
  65. /// </summary>
  66. public MapEditorToolsPanel MapEditorToolsPanel { get; set; }
  67. /// <summary>
  68. /// 左键功能
  69. /// </summary>
  70. public MouseButtonType MouseType { get; set; } = MouseButtonType.Pen;
  71. //鼠标坐标
  72. private Vector2 _mousePosition;
  73. //鼠标所在的cell坐标
  74. private Vector2I _mouseCellPosition;
  75. //上一帧鼠标所在的cell坐标
  76. private Vector2I _prevMouseCellPosition = new Vector2I(-99999, -99999);
  77. //单次绘制是否改变过tile数据
  78. private bool _changeFlag = false;
  79. //左键开始按下时鼠标所在的坐标
  80. private Vector2I _mouseStartCellPosition;
  81. //鼠标中建是否按下
  82. private bool _isMiddlePressed = false;
  83. private Vector2 _moveOffset;
  84. //左键是否按下
  85. private bool _isLeftPressed = false;
  86. //右键是否按下
  87. private bool _isRightPressed = false;
  88. //绘制填充区域
  89. private bool _drawFullRect = false;
  90. //负责存储自动图块数据
  91. private Grid<bool> _autoCellLayerGrid = new Grid<bool>();
  92. //用于生成导航网格
  93. private DungeonTileMap _dungeonTileMap;
  94. //停止绘制多久后开始执行生成操作
  95. private float _generateInterval = 3f;
  96. //生成自动图块和导航网格的计时器
  97. private float _generateTimer = -1;
  98. //检测地形结果
  99. private bool _checkTerrainFlag = true;
  100. //错误地形位置
  101. private Vector2I _checkTerrainErrorPosition = Vector2I.Zero;
  102. //是否执行生成地形成功
  103. private bool _isGenerateTerrain = false;
  104. private bool _initLayer = false;
  105.  
  106. //--------- 配置数据 -------------
  107. private int _sourceId = 0;
  108. private int _terrainSet = 0;
  109. private int _terrain = 0;
  110. private AutoTileConfig _autoTileConfig = new AutoTileConfig();
  111. /// <summary>
  112. /// 正在编辑的房间数据
  113. /// </summary>
  114. public DungeonRoomSplit RoomSplit { get; private set; }
  115. /// <summary>
  116. /// 波数网格选中的索引
  117. /// </summary>
  118. public int SelectWaveIndex { get; set; } = -1;
  119.  
  120. /// <summary>
  121. /// 选中的预设
  122. /// </summary>
  123. public int SelectPreinstallIndex
  124. {
  125. get => _selectPreinstallIndex;
  126. set
  127. {
  128. if (_selectPreinstallIndex != value)
  129. {
  130. _selectPreinstallIndex = value;
  131. EventManager.EmitEvent(EventEnum.OnSelectPreinstall);
  132. }
  133. }
  134. }
  135.  
  136. private int _selectPreinstallIndex = -1;
  137.  
  138. /// <summary>
  139. /// 当前选中的预设
  140. /// </summary>
  141. public RoomPreinstall SelectPreinstall
  142. {
  143. get
  144. {
  145. if (SelectPreinstallIndex == -1 || SelectPreinstallIndex >= RoomSplit.Preinstall.Count)
  146. {
  147. return null;
  148. }
  149.  
  150. return RoomSplit.Preinstall[SelectPreinstallIndex];
  151. }
  152. }
  153.  
  154. //变动过的数据
  155. //地图位置, 单位: 格
  156. private Vector2I _roomPosition;
  157. //地图大小, 单位: 格
  158. private Vector2I _roomSize;
  159. private List<DoorAreaInfo> _doorConfigs = new List<DoorAreaInfo>();
  160. //-------------------------------
  161.  
  162. public override void _Ready()
  163. {
  164. InitLayer();
  165. }
  166.  
  167. public override void _Process(double delta)
  168. {
  169. var newDelta = (float)delta;
  170. _drawFullRect = false;
  171. var position = GetLocalMousePosition();
  172. _mouseCellPosition = LocalToMap(position);
  173. _mousePosition = new Vector2(
  174. _mouseCellPosition.X * GameConfig.TileCellSize,
  175. _mouseCellPosition.Y * GameConfig.TileCellSize
  176. );
  177. if (!MapEditorToolsPanel.S_HBoxContainer.Instance.IsPositionOver(GetGlobalMousePosition())) //不在Ui节点上
  178. {
  179. //左键绘制
  180. if (_isLeftPressed)
  181. {
  182. if (MouseType == MouseButtonType.Pen) //绘制单格
  183. {
  184. if (_prevMouseCellPosition != _mouseCellPosition || !_changeFlag) //鼠标位置变过
  185. {
  186. _changeFlag = true;
  187. _prevMouseCellPosition = _mouseCellPosition;
  188. //绘制自动图块
  189. SetSingleAutoCell(_mouseCellPosition);
  190. }
  191. }
  192. else if (MouseType == MouseButtonType.Area) //绘制区域
  193. {
  194. _drawFullRect = true;
  195. }
  196. else if (MouseType == MouseButtonType.Drag) //拖拽
  197. {
  198. SetMapPosition(GetGlobalMousePosition() + _moveOffset);
  199. }
  200. }
  201. else if (_isRightPressed) //右键擦除
  202. {
  203. if (MouseType == MouseButtonType.Pen) //绘制单格
  204. {
  205. if (_prevMouseCellPosition != _mouseCellPosition || !_changeFlag) //鼠标位置变过
  206. {
  207. _changeFlag = true;
  208. _prevMouseCellPosition = _mouseCellPosition;
  209. EraseSingleAutoCell(_mouseCellPosition);
  210. }
  211. }
  212. else if (MouseType == MouseButtonType.Area) //绘制区域
  213. {
  214. _drawFullRect = true;
  215. }
  216. else if (MouseType == MouseButtonType.Drag) //拖拽
  217. {
  218. SetMapPosition(GetGlobalMousePosition() + _moveOffset);
  219. }
  220. }
  221. else if (_isMiddlePressed) //中键移动
  222. {
  223. SetMapPosition(GetGlobalMousePosition() + _moveOffset);
  224. }
  225. }
  226.  
  227. //绘制停止指定时间后, 生成导航网格
  228. if (_generateTimer > 0)
  229. {
  230. _generateTimer -= newDelta;
  231. if (_generateTimer <= 0)
  232. {
  233. //计算区域
  234. CalcTileRect(false);
  235. GD.Print("开始检测是否可以生成地形...");
  236. if (CheckTerrain())
  237. {
  238. GD.Print("开始绘制导航网格...");
  239. if (GenerateNavigation())
  240. {
  241. GD.Print("开始绘制自动贴图...");
  242. GenerateTerrain();
  243. _isGenerateTerrain = true;
  244. }
  245. }
  246. else
  247. {
  248. SetErrorCell(_checkTerrainErrorPosition);
  249. }
  250. }
  251. }
  252. }
  253.  
  254. /// <summary>
  255. /// 绘制辅助线
  256. /// </summary>
  257. public void DrawGuides(CanvasItem canvasItem)
  258. {
  259. //轴线
  260. canvasItem.DrawLine(new Vector2(0, 2000), new Vector2(0, -2000), Colors.Green);
  261. canvasItem.DrawLine(new Vector2(2000, 0), new Vector2( -2000, 0), Colors.Red);
  262. //绘制房间区域
  263. if (_roomSize.X != 0 && _roomSize.Y != 0)
  264. {
  265. var size = TileSet.TileSize;
  266. canvasItem.DrawRect(new Rect2(_roomPosition * size, _roomSize * size),
  267. Colors.Aqua, false, 5f / Scale.X);
  268. }
  269. if (_checkTerrainFlag) //已经通过地形检测
  270. {
  271. //绘制导航网格
  272. var result = _dungeonTileMap.GetGenerateNavigationResult();
  273. if (result != null && result.Success)
  274. {
  275. var polygonData = _dungeonTileMap.GetPolygonData();
  276. Utils.DrawNavigationPolygon(canvasItem, polygonData, 3f / Scale.X);
  277. }
  278. }
  279.  
  280. if (MouseType == MouseButtonType.Pen || MouseType == MouseButtonType.Area)
  281. {
  282. if (_drawFullRect) //绘制填充矩形
  283. {
  284. var size = TileSet.TileSize;
  285. var cellPos = _mouseStartCellPosition;
  286. var temp = size;
  287. if (_mouseStartCellPosition.X > _mouseCellPosition.X)
  288. {
  289. cellPos.X += 1;
  290. temp.X -= size.X;
  291. }
  292. if (_mouseStartCellPosition.Y > _mouseCellPosition.Y)
  293. {
  294. cellPos.Y += 1;
  295. temp.Y -= size.Y;
  296. }
  297.  
  298. var pos = cellPos * size;
  299. canvasItem.DrawRect(new Rect2(pos, _mousePosition - pos + temp), Colors.White, false, 2f / Scale.X);
  300. }
  301. else //绘制单格
  302. {
  303. canvasItem.DrawRect(new Rect2(_mousePosition, TileSet.TileSize), Colors.White, false, 2f / Scale.X);
  304. }
  305. }
  306. }
  307.  
  308. public override void _Input(InputEvent @event)
  309. {
  310. if (@event is InputEventMouseButton mouseButton)
  311. {
  312. if (mouseButton.ButtonIndex == MouseButton.Left) //左键
  313. {
  314. if (mouseButton.Pressed) //按下
  315. {
  316. _moveOffset = Position - GetGlobalMousePosition();
  317. _mouseStartCellPosition = LocalToMap(GetLocalMousePosition());
  318. }
  319. else
  320. {
  321. _changeFlag = false;
  322. if (_drawFullRect) //松开, 提交绘制的矩形区域
  323. {
  324. SetRectAutoCell(_mouseStartCellPosition, _mouseCellPosition);
  325. _drawFullRect = false;
  326. }
  327. }
  328.  
  329. _isLeftPressed = mouseButton.Pressed;
  330. }
  331. else if (mouseButton.ButtonIndex == MouseButton.Right) //右键
  332. {
  333. if (mouseButton.Pressed) //按下
  334. {
  335. _moveOffset = Position - GetGlobalMousePosition();
  336. _mouseStartCellPosition = LocalToMap(GetLocalMousePosition());
  337. }
  338. else
  339. {
  340. _changeFlag = false;
  341. if (_drawFullRect) //松开, 提交擦除的矩形区域
  342. {
  343. EraseRectAutoCell(_mouseStartCellPosition, _mouseCellPosition);
  344. _drawFullRect = false;
  345. }
  346. }
  347. _isRightPressed = mouseButton.Pressed;
  348. }
  349. else if (mouseButton.ButtonIndex == MouseButton.WheelDown)
  350. {
  351. //缩小
  352. Shrink();
  353. }
  354. else if (mouseButton.ButtonIndex == MouseButton.WheelUp)
  355. {
  356. //放大
  357. Magnify();
  358. }
  359. else if (mouseButton.ButtonIndex == MouseButton.Middle)
  360. {
  361. _isMiddlePressed = mouseButton.Pressed;
  362. if (_isMiddlePressed)
  363. {
  364. _moveOffset = Position - GetGlobalMousePosition();
  365. }
  366. }
  367. }
  368. else if (@event is InputEventKey eventKey)
  369. {
  370. if (eventKey.Pressed && eventKey.Keycode == Key.M)
  371. {
  372. GD.Print("保存地牢房间数据...");
  373. TriggerSave();
  374. }
  375. }
  376. }
  377.  
  378. //将指定层数据存入list中
  379. private void PushLayerDataToList(int layer, int sourceId, List<int> list)
  380. {
  381. var layerArray = GetUsedCellsById(layer, sourceId);
  382. foreach (var pos in layerArray)
  383. {
  384. var atlasCoords = GetCellAtlasCoords(layer, pos);
  385. list.Add(pos.X);
  386. list.Add(pos.Y);
  387. list.Add(_sourceId);
  388. list.Add(atlasCoords.X);
  389. list.Add(atlasCoords.Y);
  390. }
  391. }
  392.  
  393. private void SetLayerDataFromList(int layer, List<int> list)
  394. {
  395. for (var i = 0; i < list.Count; i += 5)
  396. {
  397. var pos = new Vector2I(list[i], list[i + 1]);
  398. var sourceId = list[i + 2];
  399. var atlasCoords = new Vector2I(list[i + 3], list[i + 4]);
  400. SetCell(layer, pos, sourceId, atlasCoords);
  401. if (layer == AutoFloorLayer)
  402. {
  403. _autoCellLayerGrid.Set(pos, true);
  404. }
  405. }
  406. }
  407.  
  408. //保存地牢
  409. private void TriggerSave()
  410. {
  411. SaveRoomInfoConfig();
  412. SaveTileInfoConfig();
  413. SavePreinstallConfig();
  414. }
  415.  
  416. /// <summary>
  417. /// 加载地牢, 返回是否加载成功
  418. /// </summary>
  419. public bool Load(DungeonRoomSplit roomSplit)
  420. {
  421. //重新加载数据
  422. roomSplit.ReloadRoomInfo();
  423. roomSplit.ReloadTileInfo();
  424. roomSplit.ReloadPreinstall();
  425. RoomSplit = roomSplit;
  426. var roomInfo = roomSplit.RoomInfo;
  427. var tileInfo = roomSplit.TileInfo;
  428.  
  429. _roomPosition = roomInfo.Position.AsVector2I();
  430. SetMapSize(roomInfo.Size.AsVector2I(), true);
  431. _doorConfigs.Clear();
  432. foreach (var doorAreaInfo in roomInfo.DoorAreaInfos)
  433. {
  434. _doorConfigs.Add(doorAreaInfo.Clone());
  435. }
  436.  
  437. //初始化层级数据
  438. InitLayer();
  439. //地块数据
  440. SetLayerDataFromList(AutoFloorLayer, tileInfo.Floor);
  441. SetLayerDataFromList(AutoMiddleLayer, tileInfo.Middle);
  442. SetLayerDataFromList(AutoTopLayer, tileInfo.Top);
  443. //导航网格数据
  444. _dungeonTileMap.SetPolygonData(tileInfo.NavigationList);
  445.  
  446. //聚焦
  447. //MapEditorPanel.CallDelay(0.1f, OnClickCenterTool);
  448. //CallDeferred(nameof(OnClickCenterTool), null);
  449. //加载门编辑区域
  450. foreach (var doorAreaInfo in _doorConfigs)
  451. {
  452. MapEditorToolsPanel.CreateDoorTool(doorAreaInfo);
  453. }
  454. //聚焦
  455. OnClickCenterTool(null);
  456. return true;
  457. }
  458.  
  459. private void InitLayer()
  460. {
  461. if (_initLayer)
  462. {
  463. return;
  464. }
  465.  
  466. _initLayer = true;
  467. //初始化层级数据
  468. AddLayer(CustomFloorLayer);
  469. SetLayerZIndex(CustomFloorLayer, CustomFloorLayer);
  470. AddLayer(AutoMiddleLayer);
  471. SetLayerZIndex(AutoMiddleLayer, AutoMiddleLayer);
  472. AddLayer(CustomMiddleLayer);
  473. SetLayerZIndex(CustomMiddleLayer, CustomMiddleLayer);
  474. AddLayer(AutoTopLayer);
  475. SetLayerZIndex(AutoTopLayer, AutoTopLayer);
  476. AddLayer(CustomTopLayer);
  477. SetLayerZIndex(CustomTopLayer, CustomTopLayer);
  478.  
  479. _dungeonTileMap = new DungeonTileMap(this);
  480. _dungeonTileMap.SetFloorAtlasCoords(new List<Vector2I>(new []{ _autoTileConfig.Floor.AutoTileCoord }));
  481. }
  482.  
  483. //缩小
  484. private void Shrink()
  485. {
  486. var pos = GetLocalMousePosition();
  487. var scale = Scale / 1.1f;
  488. if (scale.LengthSquared() >= 0.5f)
  489. {
  490. Scale = scale;
  491. SetMapPosition(Position + pos * 0.1f * scale);
  492. }
  493. else
  494. {
  495. GD.Print("太小了");
  496. }
  497. }
  498. //放大
  499. private void Magnify()
  500. {
  501. var pos = GetLocalMousePosition();
  502. var prevScale = Scale;
  503. var scale = prevScale * 1.1f;
  504. if (scale.LengthSquared() <= 2000)
  505. {
  506. Scale = scale;
  507. SetMapPosition(Position - pos * 0.1f * prevScale);
  508. }
  509. else
  510. {
  511. GD.Print("太大了");
  512. }
  513. }
  514.  
  515. //绘制单个自动贴图
  516. private void SetSingleAutoCell(Vector2I position)
  517. {
  518. SetCell(GetFloorLayer(), position, _sourceId, _autoTileConfig.Floor.AutoTileCoord);
  519. if (!_autoCellLayerGrid.Contains(position.X, position.Y))
  520. {
  521. ResetGenerateTimer();
  522. _autoCellLayerGrid.Set(position.X, position.Y, true);
  523. }
  524. }
  525. //绘制区域自动贴图
  526. private void SetRectAutoCell(Vector2I start, Vector2I end)
  527. {
  528. ResetGenerateTimer();
  529. if (start.X > end.X)
  530. {
  531. var temp = end.X;
  532. end.X = start.X;
  533. start.X = temp;
  534. }
  535. if (start.Y > end.Y)
  536. {
  537. var temp = end.Y;
  538. end.Y = start.Y;
  539. start.Y = temp;
  540. }
  541.  
  542. var width = end.X - start.X + 1;
  543. var height = end.Y - start.Y + 1;
  544. for (var i = 0; i < width; i++)
  545. {
  546. for (var j = 0; j < height; j++)
  547. {
  548. SetCell(GetFloorLayer(), new Vector2I(start.X + i, start.Y + j), _sourceId, _autoTileConfig.Floor.AutoTileCoord);
  549. }
  550. }
  551.  
  552. _autoCellLayerGrid.SetRect(start, new Vector2I(width, height), true);
  553. }
  554.  
  555. //擦除单个自动图块
  556. private void EraseSingleAutoCell(Vector2I position)
  557. {
  558. EraseCell(GetFloorLayer(), position);
  559. if (_autoCellLayerGrid.Remove(position.X, position.Y))
  560. {
  561. ResetGenerateTimer();
  562. }
  563. }
  564. //擦除一个区域内的自动贴图
  565. private void EraseRectAutoCell(Vector2I start, Vector2I end)
  566. {
  567. ResetGenerateTimer();
  568. if (start.X > end.X)
  569. {
  570. var temp = end.X;
  571. end.X = start.X;
  572. start.X = temp;
  573. }
  574. if (start.Y > end.Y)
  575. {
  576. var temp = end.Y;
  577. end.Y = start.Y;
  578. start.Y = temp;
  579. }
  580.  
  581. var width = end.X - start.X + 1;
  582. var height = end.Y - start.Y + 1;
  583. for (var i = 0; i < width; i++)
  584. {
  585. for (var j = 0; j < height; j++)
  586. {
  587. EraseCell(GetFloorLayer(), new Vector2I(start.X + i, start.Y + j));
  588. }
  589. }
  590. _autoCellLayerGrid.RemoveRect(start, new Vector2I(width, height));
  591. }
  592.  
  593. //重置计时器
  594. private void ResetGenerateTimer()
  595. {
  596. _generateTimer = _generateInterval;
  597. _isGenerateTerrain = false;
  598. _dungeonTileMap.ClearPolygonData();
  599. ClearLayer(AutoTopLayer);
  600. ClearLayer(AutoMiddleLayer);
  601. }
  602.  
  603. //重新计算房间区域
  604. private void CalcTileRect(bool refreshDoorTrans)
  605. {
  606. var rect = GetUsedRect();
  607. _roomPosition = rect.Position;
  608. SetMapSize(rect.Size, refreshDoorTrans);
  609. }
  610. //检测是否有不合规的图块, 返回true表示图块正常
  611. private bool CheckTerrain()
  612. {
  613. var x = _roomPosition.X;
  614. var y = _roomPosition.Y;
  615. var w = _roomSize.X;
  616. var h = _roomSize.Y;
  617.  
  618. for (var i = 0; i < w; i++)
  619. {
  620. for (var j = 0; j < h; j++)
  621. {
  622. var pos = new Vector2I(x + i, y + j);
  623. if (GetCellSourceId(AutoFloorLayer, pos) == -1)
  624. {
  625. //先检测对边是否有地板
  626. if ((_autoCellLayerGrid.Get(pos.X - 1, pos.Y) && _autoCellLayerGrid.Get(pos.X + 1, pos.Y)) //left & right
  627. || (_autoCellLayerGrid.Get(pos.X, pos.Y + 1) && _autoCellLayerGrid.Get(pos.X, pos.Y - 1))) //top & down
  628. {
  629. _checkTerrainFlag = false;
  630. _checkTerrainErrorPosition = pos;
  631. return false;
  632. }
  633. //再检测对角是否有地板
  634. var topLeft = _autoCellLayerGrid.Get(pos.X - 1, pos.Y + 1); //top-left
  635. var downRight = _autoCellLayerGrid.Get(pos.X + 1, pos.Y - 1); //down-right
  636. var downLeft = _autoCellLayerGrid.Get(pos.X - 1, pos.Y - 1); //down-left
  637. var topRight = _autoCellLayerGrid.Get(pos.X + 1, pos.Y + 1); //top-right
  638. if ((topLeft && downRight && !downLeft && !topRight) || (!topLeft && !downRight && downLeft && topRight))
  639. {
  640. _checkTerrainFlag = false;
  641. _checkTerrainErrorPosition = pos;
  642. return false;
  643. }
  644. }
  645. }
  646. }
  647.  
  648. _checkTerrainFlag = true;
  649. return true;
  650. }
  651. //生成自动图块 (地形)
  652. private void GenerateTerrain()
  653. {
  654. ClearLayer(AutoFloorLayer);
  655. var list = new List<Vector2I>();
  656. _autoCellLayerGrid.ForEach((x, y, data) =>
  657. {
  658. if (data)
  659. {
  660. list.Add(new Vector2I(x, y));
  661. }
  662. });
  663. var arr = new Array<Vector2I>(list);
  664. //绘制自动图块
  665. SetCellsTerrainConnect(AutoFloorLayer, arr, _terrainSet, _terrain, false);
  666. //计算区域
  667. CalcTileRect(true);
  668. //将墙壁移动到指定层
  669. MoveTerrainCell();
  670. }
  671.  
  672. //将自动生成的图块从 AutoFloorLayer 移动到指定图层中
  673. private void MoveTerrainCell()
  674. {
  675. ClearLayer(AutoTopLayer);
  676. ClearLayer(AutoMiddleLayer);
  677. var x = _roomPosition.X;
  678. var y = _roomPosition.Y;
  679. var w = _roomSize.X;
  680. var h = _roomSize.Y;
  681.  
  682. for (var i = 0; i < w; i++)
  683. {
  684. for (var j = 0; j < h; j++)
  685. {
  686. var pos = new Vector2I(x + i, y + j);
  687. if (!_autoCellLayerGrid.Contains(pos) && GetCellSourceId(AutoFloorLayer, pos) != -1)
  688. {
  689. var atlasCoords = GetCellAtlasCoords(AutoFloorLayer, pos);
  690. var layer = _autoTileConfig.GetLayer(atlasCoords);
  691. if (layer == GameConfig.MiddleMapLayer)
  692. {
  693. layer = AutoMiddleLayer;
  694. }
  695. else if (layer == GameConfig.TopMapLayer)
  696. {
  697. layer = AutoTopLayer;
  698. }
  699. else
  700. {
  701. GD.PrintErr($"异常图块: {pos}, 这个图块的图集坐标'{atlasCoords}'不属于'MiddleMapLayer'和'TopMapLayer'!");
  702. continue;
  703. }
  704. EraseCell(AutoFloorLayer, pos);
  705. SetCell(layer, pos, _sourceId, atlasCoords);
  706. }
  707. }
  708. }
  709. }
  710.  
  711. //生成导航网格
  712. private bool GenerateNavigation()
  713. {
  714. _dungeonTileMap.GenerateNavigationPolygon(AutoFloorLayer);
  715. var result = _dungeonTileMap.GetGenerateNavigationResult();
  716. if (result.Success)
  717. {
  718. CloseErrorCell();
  719. }
  720. else
  721. {
  722. SetErrorCell(result.Exception.Point);
  723. }
  724.  
  725. return result.Success;
  726. }
  727.  
  728. //设置显示的错误cell, 会标记上红色的闪烁动画
  729. private void SetErrorCell(Vector2I pos)
  730. {
  731. MapEditorPanel.S_ErrorCell.Instance.Position = pos * CellQuadrantSize;
  732. MapEditorPanel.S_ErrorCellAnimationPlayer.Instance.Play(AnimatorNames.Show);
  733. }
  734.  
  735. //关闭显示的错误cell
  736. private void CloseErrorCell()
  737. {
  738. MapEditorPanel.S_ErrorCellAnimationPlayer.Instance.Stop();
  739. }
  740.  
  741. private int GetFloorLayer()
  742. {
  743. return AutoFloorLayer;
  744. }
  745.  
  746. private int GetMiddleLayer()
  747. {
  748. return AutoMiddleLayer;
  749. }
  750.  
  751. private int GetTopLayer()
  752. {
  753. return AutoTopLayer;
  754. }
  755.  
  756. /// <summary>
  757. /// 选中拖拽功能
  758. /// </summary>
  759. public void OnSelectHandTool(object arg)
  760. {
  761. MouseType = MouseButtonType.Drag;
  762. }
  763. /// <summary>
  764. /// 选中画笔攻击
  765. /// </summary>
  766. public void OnSelectPenTool(object arg)
  767. {
  768. MouseType = MouseButtonType.Pen;
  769. }
  770.  
  771. /// <summary>
  772. /// 选中绘制区域功能
  773. /// </summary>
  774. public void OnSelectRectTool(object arg)
  775. {
  776. MouseType = MouseButtonType.Area;
  777. }
  778.  
  779. /// <summary>
  780. /// 选择编辑门区域
  781. /// </summary>
  782. public void OnSelectDoorTool(object arg)
  783. {
  784. MouseType = MouseButtonType.Door;
  785. }
  786.  
  787. /// <summary>
  788. /// 聚焦
  789. /// </summary>
  790. public void OnClickCenterTool(object arg)
  791. {
  792. var pos = MapEditorPanel.S_SubViewport.Instance.Size / 2;
  793. if (_roomSize.X == 0 && _roomSize.Y == 0) //聚焦原点
  794. {
  795. SetMapPosition(pos);
  796. }
  797. else //聚焦地图中心点
  798. {
  799. SetMapPosition(pos - (_roomPosition + _roomSize / 2) * TileSet.TileSize * Scale);
  800. }
  801. }
  802.  
  803. /// <summary>
  804. /// 创建地牢房间门区域
  805. /// </summary>
  806. /// <param name="direction">门方向</param>
  807. /// <param name="start">起始坐标, 单位: 像素</param>
  808. /// <param name="end">结束坐标, 单位: 像素</param>
  809. public DoorAreaInfo CreateDoorArea(DoorDirection direction, int start, int end)
  810. {
  811. var doorAreaInfo = new DoorAreaInfo();
  812. doorAreaInfo.Direction = direction;
  813. doorAreaInfo.Start = start;
  814. doorAreaInfo.End = end;
  815. //doorAreaInfo.CalcPosition(_roomPosition, _roomSize);
  816. _doorConfigs.Add(doorAreaInfo);
  817. return doorAreaInfo;
  818. }
  819.  
  820. /// <summary>
  821. /// 检测门区域数据是否可以提交
  822. /// </summary>
  823. /// <param name="direction">门方向</param>
  824. /// <param name="start">起始坐标, 单位: 像素</param>
  825. /// <param name="end">结束坐标, 单位: 像素</param>
  826. /// <returns></returns>
  827. public bool CheckDoorArea(DoorDirection direction, int start, int end)
  828. {
  829. foreach (var item in _doorConfigs)
  830. {
  831. if (item.Direction == direction)
  832. {
  833. if (CheckValueCollision(item.Start, item.End, start, end))
  834. {
  835. return false;
  836. }
  837. }
  838. }
  839.  
  840. return true;
  841. }
  842. /// <summary>
  843. /// 检测门区域数据是否可以提交
  844. /// </summary>
  845. /// <param name="target">需要检测的门</param>
  846. /// <param name="start">起始坐标, 单位: 像素</param>
  847. /// <param name="end">结束坐标, 单位: 像素</param>
  848. public bool CheckDoorArea(DoorAreaInfo target, int start, int end)
  849. {
  850. foreach (var item in _doorConfigs)
  851. {
  852. if (item.Direction == target.Direction && item != target)
  853. {
  854. if (CheckValueCollision(item.Start, item.End, start, end))
  855. {
  856. return false;
  857. }
  858. }
  859. }
  860.  
  861. return true;
  862. }
  863. private bool CheckValueCollision(float o1, float o2, float h1, float h2)
  864. {
  865. var size = GameConfig.TileCellSize;
  866. return !(h2 < o1 - 3 * size || o2 + 3 * size < h1);
  867. }
  868.  
  869. /// <summary>
  870. /// 移除门区域数据
  871. /// </summary>
  872. public void RemoveDoorArea(DoorAreaInfo doorAreaInfo)
  873. {
  874. _doorConfigs.Remove(doorAreaInfo);
  875. }
  876. //保存房间配置
  877. private void SaveRoomInfoConfig()
  878. {
  879. //存入本地
  880. var roomInfo = RoomSplit.RoomInfo;
  881. var path = MapProjectManager.GetConfigPath(roomInfo.GroupName,roomInfo.RoomType, roomInfo.RoomName);
  882. if (!Directory.Exists(path))
  883. {
  884. Directory.CreateDirectory(path);
  885. }
  886. roomInfo.Position = new SerializeVector2(_roomPosition);
  887. roomInfo.Size = new SerializeVector2(_roomSize);
  888. roomInfo.DoorAreaInfos.Clear();
  889. roomInfo.DoorAreaInfos.AddRange(_doorConfigs);
  890.  
  891. path += "/" + MapProjectManager.GetRoomInfoConfigName(roomInfo.RoomName);
  892. var jsonStr = JsonSerializer.Serialize(roomInfo);
  893. File.WriteAllText(path, jsonStr);
  894. }
  895.  
  896. //保存地块数据
  897. public void SaveTileInfoConfig()
  898. {
  899. //存入本地
  900. var roomInfo = RoomSplit.RoomInfo;
  901. var path = MapProjectManager.GetConfigPath(roomInfo.GroupName,roomInfo.RoomType, roomInfo.RoomName);
  902. if (!Directory.Exists(path))
  903. {
  904. Directory.CreateDirectory(path);
  905. }
  906.  
  907. var tileInfo = RoomSplit.TileInfo;
  908. tileInfo.NavigationList.Clear();
  909. tileInfo.NavigationList.AddRange(_dungeonTileMap.GetPolygonData());
  910. tileInfo.Floor.Clear();
  911. tileInfo.Middle.Clear();
  912. tileInfo.Top.Clear();
  913.  
  914. PushLayerDataToList(AutoFloorLayer, _sourceId, tileInfo.Floor);
  915. PushLayerDataToList(AutoMiddleLayer, _sourceId, tileInfo.Middle);
  916. PushLayerDataToList(AutoTopLayer, _sourceId, tileInfo.Top);
  917. path += "/" + MapProjectManager.GetTileInfoConfigName(roomInfo.RoomName);
  918. var jsonStr = JsonSerializer.Serialize(tileInfo);
  919. File.WriteAllText(path, jsonStr);
  920. }
  921.  
  922. //保存预设数据
  923. public void SavePreinstallConfig()
  924. {
  925. //存入本地
  926. var roomInfo = RoomSplit.RoomInfo;
  927. var path = MapProjectManager.GetConfigPath(roomInfo.GroupName,roomInfo.RoomType, roomInfo.RoomName);
  928. if (!Directory.Exists(path))
  929. {
  930. Directory.CreateDirectory(path);
  931. }
  932.  
  933. path += "/" + MapProjectManager.GetRoomPreinstallConfigName(roomInfo.RoomName);
  934. var jsonStr = JsonSerializer.Serialize(RoomSplit.Preinstall);
  935. File.WriteAllText(path, jsonStr);
  936. }
  937.  
  938. //设置地图坐标
  939. private void SetMapPosition(Vector2 pos)
  940. {
  941. Position = pos;
  942. MapEditorToolsPanel.SetToolTransform(pos, Scale);
  943. }
  944.  
  945. //设置地图大小
  946. private void SetMapSize(Vector2I size, bool refreshDoorTrans)
  947. {
  948. if (_roomSize != size)
  949. {
  950. _roomSize = size;
  951.  
  952. if (refreshDoorTrans)
  953. {
  954. MapEditorToolsPanel.SetDoorHoverToolTransform(_roomPosition, _roomSize);
  955. }
  956. }
  957. }
  958. }