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