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