Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / ui / mapEditor / tileView / EditorTileMap.cs
@小李xl 小李xl on 25 Dec 2023 40 KB TileMap保存和读取导航网格
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Godot;
  5. using Godot.Collections;
  6. using UI.MapEditorTools;
  7.  
  8. namespace UI.MapEditor;
  9.  
  10. public partial class EditorTileMap : TileMap, IUiNodeScript
  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; private 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 InfiniteGrid<bool> _autoCellLayerGrid = new InfiniteGrid<bool>();
  96. //停止绘制多久后开始执行生成操作
  97. private float _generateInterval = 3f;
  98. //生成自动图块和导航网格的计时器
  99. private float _generateTimer = -1;
  100. //检测地形结果
  101. private bool _checkTerrainFlag = true;
  102. //错误地形位置
  103. private Vector2I _checkTerrainErrorPosition = Vector2I.Zero;
  104. //是否执行生成地形成功
  105. private bool _isGenerateTerrain = true;
  106. //导航网格数据
  107. private Vector2[][] _polygonData;
  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.  
  116. /// <summary>
  117. /// 正在编辑的房间数据
  118. /// </summary>
  119. public DungeonRoomSplit CurrRoomSplit;
  120. /// <summary>
  121. /// 数据是否脏了, 也就是是否有修改
  122. /// </summary>
  123. public bool IsDirty { get; private set; }
  124.  
  125. /// <summary>
  126. /// 地图是否有绘制错误
  127. /// </summary>
  128. public bool HasTerrainError => !_isGenerateTerrain;
  129.  
  130. //变动过的数据
  131. /// <summary>
  132. /// 地图位置, 单位: 格
  133. /// </summary>
  134. public Vector2I CurrRoomPosition { get; private set; }
  135. /// <summary>
  136. /// 当前地图大小, 单位: 格
  137. /// </summary>
  138. public Vector2I CurrRoomSize { get; private set; }
  139. /// <summary>
  140. /// 当前编辑的门数据
  141. /// </summary>
  142. public List<DoorAreaInfo> CurrDoorConfigs { get; } = new List<DoorAreaInfo>();
  143. //-------------------------------
  144. private MapEditor.TileMap _editorTileMap;
  145. private EventFactory _eventFactory;
  146.  
  147. public void SetUiNode(IUiNode uiNode)
  148. {
  149. _editorTileMap = (MapEditor.TileMap)uiNode;
  150. MapEditorPanel = _editorTileMap.UiPanel;
  151. MapEditorToolsPanel = _editorTileMap.UiPanel.S_MapEditorTools.Instance;
  152.  
  153. _editorTileMap.L_Brush.Instance.Draw += DrawGuides;
  154. _eventFactory = EventManager.CreateEventFactory();
  155. _eventFactory.AddEventListener(EventEnum.OnSelectDragTool, OnSelectHandTool);
  156. _eventFactory.AddEventListener(EventEnum.OnSelectPenTool, OnSelectPenTool);
  157. _eventFactory.AddEventListener(EventEnum.OnSelectRectTool, OnSelectRectTool);
  158. _eventFactory.AddEventListener(EventEnum.OnSelectEditTool, OnSelectEditTool);
  159. _eventFactory.AddEventListener(EventEnum.OnClickCenterTool, OnClickCenterTool);
  160. _eventFactory.AddEventListener(EventEnum.OnEditorDirty, OnEditorDirty);
  161.  
  162. RenderingServer.FramePostDraw += OnFramePostDraw;
  163. var navigationRegion = _editorTileMap.L_NavigationRegion.Instance;
  164. navigationRegion.Visible = false;
  165. navigationRegion.NavigationPolygon.AgentRadius = GameConfig.NavigationAgentRadius;
  166. navigationRegion.BakeFinished += OnBakeFinished;
  167. }
  168.  
  169. public void OnDestroy()
  170. {
  171. _eventFactory.RemoveAllEventListener();
  172. RenderingServer.FramePostDraw -= OnFramePostDraw;
  173. }
  174. public override void _Ready()
  175. {
  176. InitLayer();
  177. }
  178.  
  179. public override void _Process(double delta)
  180. {
  181. //触发绘制辅助线
  182. _editorTileMap.L_Brush.Instance.QueueRedraw();
  183. var newDelta = (float)delta;
  184. _drawFullRect = false;
  185. var position = GetLocalMousePosition();
  186. _mouseCellPosition = LocalToMap(position);
  187. _mousePosition = new Vector2(
  188. _mouseCellPosition.X * GameConfig.TileCellSize,
  189. _mouseCellPosition.Y * GameConfig.TileCellSize
  190. );
  191. if (!MapEditorToolsPanel.S_HBoxContainer.Instance.IsPositionOver(GetGlobalMousePosition())) //不在Ui节点上
  192. {
  193. //左键绘制
  194. if (_isLeftPressed)
  195. {
  196. if (MouseType == MouseButtonType.Pen) //绘制单格
  197. {
  198. if (_prevMouseCellPosition != _mouseCellPosition || !_changeFlag) //鼠标位置变过
  199. {
  200. _changeFlag = true;
  201. _prevMouseCellPosition = _mouseCellPosition;
  202. //绘制自动图块
  203. SetSingleAutoCell(_mouseCellPosition);
  204. }
  205. }
  206. else if (MouseType == MouseButtonType.Area) //绘制区域
  207. {
  208. _drawFullRect = true;
  209. }
  210. else if (MouseType == MouseButtonType.Drag) //拖拽
  211. {
  212. SetMapPosition(GetGlobalMousePosition() + _moveOffset);
  213. }
  214. }
  215. else if (_isRightPressed) //右键擦除
  216. {
  217. if (MouseType == MouseButtonType.Pen) //绘制单格
  218. {
  219. if (_prevMouseCellPosition != _mouseCellPosition || !_changeFlag) //鼠标位置变过
  220. {
  221. _changeFlag = true;
  222. _prevMouseCellPosition = _mouseCellPosition;
  223. EraseSingleAutoCell(_mouseCellPosition);
  224. }
  225. }
  226. else if (MouseType == MouseButtonType.Area) //绘制区域
  227. {
  228. _drawFullRect = true;
  229. }
  230. else if (MouseType == MouseButtonType.Drag) //拖拽
  231. {
  232. SetMapPosition(GetGlobalMousePosition() + _moveOffset);
  233. }
  234. }
  235. else if (_isMiddlePressed) //中键移动
  236. {
  237. SetMapPosition(GetGlobalMousePosition() + _moveOffset);
  238. }
  239. }
  240.  
  241. //绘制停止指定时间后, 生成导航网格
  242. if (_generateTimer > 0)
  243. {
  244. _generateTimer -= newDelta;
  245. if (_generateTimer <= 0)
  246. {
  247. //检测地形
  248. RunCheckHandler();
  249. }
  250. }
  251. }
  252.  
  253. /// <summary>
  254. /// 绘制辅助线
  255. /// </summary>
  256. public void DrawGuides()
  257. {
  258. if (_hasPreviewImage)
  259. {
  260. return;
  261. }
  262. CanvasItem canvasItem = _editorTileMap.L_Brush.Instance;
  263. //轴线
  264. canvasItem.DrawLine(new Vector2(0, 2000), new Vector2(0, -2000), Colors.Green);
  265. canvasItem.DrawLine(new Vector2(2000, 0), new Vector2( -2000, 0), Colors.Red);
  266. //绘制房间区域
  267. if (CurrRoomSize.X != 0 && CurrRoomSize.Y != 0)
  268. {
  269. var size = TileSet.TileSize;
  270. canvasItem.DrawRect(new Rect2(CurrRoomPosition * size, CurrRoomSize * size),
  271. Colors.Aqua, false, 5f / Scale.X);
  272. }
  273.  
  274. //绘制导航网格
  275. if (_checkTerrainFlag && _isGenerateTerrain && _polygonData != null)
  276. {
  277. foreach (var vector2s in _polygonData)
  278. {
  279. canvasItem.DrawPolygon(vector2s, new Color(0,1,1, 0.3f).MakeArray(vector2s.Length));
  280. }
  281. }
  282.  
  283. if (MouseType == MouseButtonType.Pen || MouseType == MouseButtonType.Area)
  284. {
  285. if (_drawFullRect) //绘制填充矩形
  286. {
  287. var size = TileSet.TileSize;
  288. var cellPos = _mouseStartCellPosition;
  289. var temp = size;
  290. if (_mouseStartCellPosition.X > _mouseCellPosition.X)
  291. {
  292. cellPos.X += 1;
  293. temp.X -= size.X;
  294. }
  295. if (_mouseStartCellPosition.Y > _mouseCellPosition.Y)
  296. {
  297. cellPos.Y += 1;
  298. temp.Y -= size.Y;
  299. }
  300.  
  301. var pos = cellPos * size;
  302. canvasItem.DrawRect(new Rect2(pos, _mousePosition - pos + temp), Colors.White, false, 2f / Scale.X);
  303. }
  304. else //绘制单格
  305. {
  306. canvasItem.DrawRect(new Rect2(_mousePosition, TileSet.TileSize), Colors.White, false, 2f / Scale.X);
  307. }
  308. }
  309. }
  310.  
  311. public override void _Input(InputEvent @event)
  312. {
  313. if (@event is InputEventMouseButton mouseButton)
  314. {
  315. if (mouseButton.ButtonIndex == MouseButton.Left) //左键
  316. {
  317. if (mouseButton.Pressed) //按下
  318. {
  319. _moveOffset = Position - GetGlobalMousePosition();
  320. _mouseStartCellPosition = LocalToMap(GetLocalMousePosition());
  321. }
  322. else
  323. {
  324. _changeFlag = false;
  325. if (_drawFullRect) //松开, 提交绘制的矩形区域
  326. {
  327. SetRectAutoCell(_mouseStartCellPosition, _mouseCellPosition);
  328. _drawFullRect = false;
  329. }
  330. }
  331.  
  332. _isLeftPressed = mouseButton.Pressed;
  333. }
  334. else if (mouseButton.ButtonIndex == MouseButton.Right) //右键
  335. {
  336. if (mouseButton.Pressed) //按下
  337. {
  338. _moveOffset = Position - GetGlobalMousePosition();
  339. _mouseStartCellPosition = LocalToMap(GetLocalMousePosition());
  340. }
  341. else
  342. {
  343. _changeFlag = false;
  344. if (_drawFullRect) //松开, 提交擦除的矩形区域
  345. {
  346. EraseRectAutoCell(_mouseStartCellPosition, _mouseCellPosition);
  347. _drawFullRect = false;
  348. }
  349. }
  350. _isRightPressed = mouseButton.Pressed;
  351. }
  352. else if (mouseButton.ButtonIndex == MouseButton.WheelDown)
  353. {
  354. //缩小
  355. Shrink();
  356. }
  357. else if (mouseButton.ButtonIndex == MouseButton.WheelUp)
  358. {
  359. //放大
  360. Magnify();
  361. }
  362. else if (mouseButton.ButtonIndex == MouseButton.Middle)
  363. {
  364. _isMiddlePressed = mouseButton.Pressed;
  365. if (_isMiddlePressed)
  366. {
  367. _moveOffset = Position - GetGlobalMousePosition();
  368. }
  369. }
  370. }
  371. }
  372.  
  373. /// <summary>
  374. /// 尝试运行检查, 如果已经运行过了, 则没有效果
  375. /// </summary>
  376. public void TryRunCheckHandler()
  377. {
  378. if (_generateTimer > 0)
  379. {
  380. _generateTimer = -1;
  381. RunCheckHandler();
  382. }
  383. }
  384. //执行检测地形操作
  385. private void RunCheckHandler()
  386. {
  387. _isGenerateTerrain = false;
  388. //计算区域
  389. CalcTileRect(false);
  390. Debug.Log("开始检测是否可以生成地形...");
  391. if (CheckTerrain())
  392. {
  393. Debug.Log("开始绘制自动贴图...");
  394. GenerateTerrain();
  395. _isGenerateTerrain = true;
  396. }
  397. else
  398. {
  399. SetErrorCell(_checkTerrainErrorPosition);
  400. }
  401. }
  402.  
  403. //将指定层数据存入list中
  404. private void PushLayerDataToList(int layer, int sourceId, List<int> list)
  405. {
  406. var layerArray = GetUsedCellsById(layer, sourceId);
  407. foreach (var pos in layerArray)
  408. {
  409. var atlasCoords = GetCellAtlasCoords(layer, pos);
  410. list.Add(pos.X);
  411. list.Add(pos.Y);
  412. list.Add(_sourceId);
  413. list.Add(atlasCoords.X);
  414. list.Add(atlasCoords.Y);
  415. }
  416. }
  417.  
  418. private void SetLayerDataFromList(int layer, List<int> list)
  419. {
  420. for (var i = 0; i < list.Count; i += 5)
  421. {
  422. var pos = new Vector2I(list[i], list[i + 1]);
  423. var sourceId = list[i + 2];
  424. var atlasCoords = new Vector2I(list[i + 3], list[i + 4]);
  425. SetCell(layer, pos, sourceId, atlasCoords);
  426. if (layer == AutoFloorLayer)
  427. {
  428. _autoCellLayerGrid.Set(pos, true);
  429. }
  430. }
  431. }
  432.  
  433. /// <summary>
  434. /// 触发保存地图数据
  435. /// </summary>
  436. public void TriggerSave(RoomErrorType errorType, Action finish)
  437. {
  438. Debug.Log("保存地牢房间数据...");
  439. //执行创建预览图流程
  440. RunSavePreviewImage(() =>
  441. {
  442. //执行保存数据流程
  443. CurrRoomSplit.ErrorType = errorType;
  444. SaveRoomInfoConfig();
  445. SaveTileInfoConfig();
  446. SavePreinstallConfig();
  447. IsDirty = false;
  448. MapEditorPanel.SetTitleDirty(false);
  449. //派发保存事件
  450. EventManager.EmitEvent(EventEnum.OnEditorSave);
  451. if (finish != null)
  452. {
  453. finish();
  454. }
  455. });
  456. }
  457.  
  458. /// <summary>
  459. /// 加载地牢, 返回是否加载成功
  460. /// </summary>
  461. public bool Load(DungeonRoomSplit roomSplit)
  462. {
  463. //重新加载数据
  464. roomSplit.ReloadRoomInfo();
  465. roomSplit.ReloadTileInfo();
  466. roomSplit.ReloadPreinstall();
  467. CurrRoomSplit = roomSplit;
  468. var roomInfo = roomSplit.RoomInfo;
  469. var tileInfo = roomSplit.TileInfo;
  470.  
  471. CurrRoomPosition = roomInfo.Position.AsVector2I();
  472. SetMapSize(roomInfo.Size.AsVector2I(), true);
  473. CurrDoorConfigs.Clear();
  474. foreach (var doorAreaInfo in roomInfo.DoorAreaInfos)
  475. {
  476. CurrDoorConfigs.Add(doorAreaInfo.Clone());
  477. }
  478.  
  479. //初始化层级数据
  480. InitLayer();
  481. //地块数据
  482. SetLayerDataFromList(AutoFloorLayer, tileInfo.Floor);
  483. SetLayerDataFromList(AutoMiddleLayer, tileInfo.Middle);
  484. SetLayerDataFromList(AutoTopLayer, tileInfo.Top);
  485.  
  486. //如果有图块错误, 则找出错误的点位
  487. if (roomSplit.ErrorType == RoomErrorType.TileError)
  488. {
  489. RunCheckHandler();
  490. }
  491. else
  492. {
  493. //导航网格
  494. if (tileInfo.NavigationPolygon != null && tileInfo.NavigationVertices != null)
  495. {
  496. var polygon = _editorTileMap.L_NavigationRegion.Instance.NavigationPolygon;
  497. polygon.Vertices = tileInfo.NavigationVertices.Select(v => v.AsVector2()).ToArray();
  498. foreach (var p in tileInfo.NavigationPolygon)
  499. {
  500. polygon.AddPolygon(p);
  501. }
  502.  
  503. OnBakeFinished();
  504. }
  505. }
  506. //聚焦
  507. //MapEditorPanel.CallDelay(0.1f, OnClickCenterTool);
  508. //CallDeferred(nameof(OnClickCenterTool), null);
  509. //加载门编辑区域
  510. foreach (var doorAreaInfo in CurrDoorConfigs)
  511. {
  512. MapEditorToolsPanel.CreateDoorTool(doorAreaInfo);
  513. }
  514. //聚焦
  515. OnClickCenterTool(null);
  516. return true;
  517. }
  518.  
  519. private void InitLayer()
  520. {
  521. if (_initLayer)
  522. {
  523. return;
  524. }
  525.  
  526. _initLayer = true;
  527. //初始化层级数据
  528. AddLayer(CustomFloorLayer);
  529. SetLayerZIndex(CustomFloorLayer, CustomFloorLayer);
  530. AddLayer(AutoMiddleLayer);
  531. SetLayerZIndex(AutoMiddleLayer, AutoMiddleLayer);
  532. AddLayer(CustomMiddleLayer);
  533. SetLayerZIndex(CustomMiddleLayer, CustomMiddleLayer);
  534. AddLayer(AutoTopLayer);
  535. SetLayerZIndex(AutoTopLayer, AutoTopLayer);
  536. AddLayer(CustomTopLayer);
  537. SetLayerZIndex(CustomTopLayer, CustomTopLayer);
  538. }
  539.  
  540. //缩小
  541. private void Shrink()
  542. {
  543. var pos = GetLocalMousePosition();
  544. var scale = Scale / 1.1f;
  545. if (scale.LengthSquared() >= 0.5f)
  546. {
  547. Scale = scale;
  548. SetMapPosition(Position + pos * 0.1f * scale);
  549. }
  550. }
  551. //放大
  552. private void Magnify()
  553. {
  554. var pos = GetLocalMousePosition();
  555. var prevScale = Scale;
  556. var scale = prevScale * 1.1f;
  557. if (scale.LengthSquared() <= 2000)
  558. {
  559. Scale = scale;
  560. SetMapPosition(Position - pos * 0.1f * prevScale);
  561. }
  562. }
  563.  
  564. //绘制单个自动贴图
  565. private void SetSingleAutoCell(Vector2I position)
  566. {
  567. var tileCellData = _autoTileConfig.Floor2;
  568. SetCell(GetFloorLayer(), position, tileCellData.SourceId, tileCellData.AutoTileCoords);
  569. //SetCell(GetFloorLayer(), position, _sourceId, _autoTileConfig.Floor.AutoTileCoords);
  570. if (!_autoCellLayerGrid.Contains(position.X, position.Y))
  571. {
  572. ResetGenerateTimer();
  573. _autoCellLayerGrid.Set(position.X, position.Y, true);
  574. }
  575. }
  576. //绘制区域自动贴图
  577. private void SetRectAutoCell(Vector2I start, Vector2I end)
  578. {
  579. ResetGenerateTimer();
  580. if (start.X > end.X)
  581. {
  582. var temp = end.X;
  583. end.X = start.X;
  584. start.X = temp;
  585. }
  586. if (start.Y > end.Y)
  587. {
  588. var temp = end.Y;
  589. end.Y = start.Y;
  590. start.Y = temp;
  591. }
  592.  
  593. var width = end.X - start.X + 1;
  594. var height = end.Y - start.Y + 1;
  595. for (var i = 0; i < width; i++)
  596. {
  597. for (var j = 0; j < height; j++)
  598. {
  599. var tileCellData = _autoTileConfig.Floor2;
  600. SetCell(GetFloorLayer(), new Vector2I(start.X + i, start.Y + j), tileCellData.SourceId, tileCellData.AutoTileCoords);
  601. }
  602. }
  603.  
  604. _autoCellLayerGrid.SetRect(start, new Vector2I(width, height), true);
  605. }
  606.  
  607. //擦除单个自动图块
  608. private void EraseSingleAutoCell(Vector2I position)
  609. {
  610. EraseCell(GetFloorLayer(), position);
  611. if (_autoCellLayerGrid.Remove(position.X, position.Y))
  612. {
  613. ResetGenerateTimer();
  614. }
  615. }
  616. //擦除一个区域内的自动贴图
  617. private void EraseRectAutoCell(Vector2I start, Vector2I end)
  618. {
  619. ResetGenerateTimer();
  620. if (start.X > end.X)
  621. {
  622. var temp = end.X;
  623. end.X = start.X;
  624. start.X = temp;
  625. }
  626. if (start.Y > end.Y)
  627. {
  628. var temp = end.Y;
  629. end.Y = start.Y;
  630. start.Y = temp;
  631. }
  632.  
  633. var width = end.X - start.X + 1;
  634. var height = end.Y - start.Y + 1;
  635. for (var i = 0; i < width; i++)
  636. {
  637. for (var j = 0; j < height; j++)
  638. {
  639. EraseCell(GetFloorLayer(), new Vector2I(start.X + i, start.Y + j));
  640. }
  641. }
  642. _autoCellLayerGrid.RemoveRect(start, new Vector2I(width, height));
  643. }
  644.  
  645. //重置计时器
  646. private void ResetGenerateTimer()
  647. {
  648. _generateTimer = _generateInterval;
  649. _isGenerateTerrain = false;
  650. ClearLayer(AutoTopLayer);
  651. ClearLayer(AutoMiddleLayer);
  652. CloseErrorCell();
  653. //标记有修改数据
  654. EventManager.EmitEvent(EventEnum.OnEditorDirty);
  655. }
  656.  
  657. //重新计算房间区域
  658. private void CalcTileRect(bool refreshDoorTrans)
  659. {
  660. var rect = GetUsedRect();
  661. CurrRoomPosition = rect.Position;
  662. SetMapSize(rect.Size, refreshDoorTrans);
  663. }
  664. //检测是否有不合规的图块, 返回true表示图块正常
  665. private bool CheckTerrain()
  666. {
  667. _checkTerrainFlag = true;
  668. _autoCellLayerGrid.ForEach((x, y, flag) =>
  669. {
  670. if (flag)
  671. {
  672. if (!_autoCellLayerGrid.Contains(x, y + 1) && _autoCellLayerGrid.Contains(x, y + 2))
  673. {
  674. _checkTerrainFlag = false;
  675. _checkTerrainErrorPosition = new Vector2I(x, y + 1);
  676. return false;
  677. }
  678. }
  679.  
  680. return true;
  681. });
  682. return _checkTerrainFlag;
  683. }
  684. //生成自动图块 (地形)
  685. private void GenerateTerrain()
  686. {
  687. //ClearLayer(AutoFloorLayer);
  688. var list = new List<Vector2I>();
  689. var xStart = int.MaxValue;
  690. var yStart = int.MaxValue;
  691. var xEnd = int.MinValue;
  692. var yEnd = int.MinValue;
  693. _autoCellLayerGrid.ForEach((x, y, flag) =>
  694. {
  695. if (flag)
  696. {
  697. //计算范围
  698. if (x < xStart)
  699. xStart = x;
  700. else if (x > xEnd)
  701. xEnd = x;
  702.  
  703. if (y < yStart)
  704. yStart = y;
  705. else if (y > yEnd)
  706. yEnd = y;
  707. //填充墙壁
  708. if (!_autoCellLayerGrid.Contains(x, y - 1))
  709. {
  710. var left = _autoCellLayerGrid.Contains(x - 1, y - 1);
  711. var right = _autoCellLayerGrid.Contains(x + 1, y - 1);
  712. TileCellData tileCellData;
  713. if (left && right)
  714. {
  715. tileCellData = _autoTileConfig.WallSingle;
  716. }
  717. else if (left)
  718. {
  719. tileCellData = _autoTileConfig.WallLeft;
  720. }
  721. else if (right)
  722. {
  723. tileCellData = _autoTileConfig.WallRight;
  724. }
  725. else
  726. {
  727. tileCellData = _autoTileConfig.WallCenter;
  728. }
  729. SetCell(GetFloorLayer(), new Vector2I(x, y - 1), tileCellData.SourceId, tileCellData.AutoTileCoords);
  730. }
  731. }
  732.  
  733. return true;
  734. });
  735. //绘制临时边界
  736. var pos = new List<Vector2I>();
  737. for (var x = xStart - 2; x <= xEnd + 2; x++)
  738. {
  739. var p1 = new Vector2I(x, yStart - 3);
  740. var p2 = new Vector2I(x, yEnd + 2);
  741. pos.Add(p1);
  742. pos.Add(p2);
  743. //上横
  744. SetCell(GetFloorLayer(), p1, _autoTileConfig.TopMask.SourceId, _autoTileConfig.TopMask.AutoTileCoords);
  745. //下横
  746. SetCell(GetFloorLayer(), p2, _autoTileConfig.TopMask.SourceId, _autoTileConfig.TopMask.AutoTileCoords);
  747. }
  748. for (var y = yStart - 3; y <= yEnd + 2; y++)
  749. {
  750. var p1 = new Vector2I(xStart - 2, y);
  751. var p2 = new Vector2I(xEnd + 2, y);
  752. pos.Add(p1);
  753. pos.Add(p2);
  754. //左竖
  755. SetCell(GetFloorLayer(), p1, _autoTileConfig.TopMask.SourceId, _autoTileConfig.TopMask.AutoTileCoords);
  756. //右竖
  757. SetCell(GetFloorLayer(), p2, _autoTileConfig.TopMask.SourceId, _autoTileConfig.TopMask.AutoTileCoords);
  758. }
  759. //计算需要绘制的图块
  760. for (var x = xStart - 1; x <= xEnd + 1; x++)
  761. {
  762. for (var y = yStart - 2; y <= yEnd + 1; y++)
  763. {
  764. if (!_autoCellLayerGrid.Contains(x, y) && !_autoCellLayerGrid.Contains(x, y + 1))
  765. {
  766. list.Add(new Vector2I(x, y));
  767. }
  768. }
  769. }
  770. var arr = new Array<Vector2I>(list);
  771. //绘制自动图块
  772. SetCellsTerrainConnect(AutoFloorLayer, arr, _terrainSet, _terrain, false);
  773. //擦除临时边界
  774. for (var i = 0; i < pos.Count; i++)
  775. {
  776. EraseCell(GetFloorLayer(), pos[i]);
  777. }
  778.  
  779. //计算区域
  780. CalcTileRect(true);
  781. //开始绘制导航网格
  782. GenerateNavigation();
  783.  
  784. //将墙壁移动到指定层
  785. MoveTerrainCell();
  786. }
  787.  
  788. //将自动生成的图块从 AutoFloorLayer 移动到指定图层中
  789. private void MoveTerrainCell()
  790. {
  791. ClearLayer(AutoTopLayer);
  792. ClearLayer(AutoMiddleLayer);
  793. var x = CurrRoomPosition.X;
  794. var y = CurrRoomPosition.Y;
  795. var w = CurrRoomSize.X;
  796. var h = CurrRoomSize.Y;
  797.  
  798. for (var i = 0; i < w; i++)
  799. {
  800. for (var j = 0; j < h; j++)
  801. {
  802. var pos = new Vector2I(x + i, y + j);
  803. if (!_autoCellLayerGrid.Contains(pos) && GetCellSourceId(AutoFloorLayer, pos) != -1)
  804. {
  805. var atlasCoords = GetCellAtlasCoords(AutoFloorLayer, pos);
  806. var layer = _autoTileConfig.GetLayer2(atlasCoords);
  807. if (layer == GameConfig.MiddleMapLayer)
  808. {
  809. layer = AutoMiddleLayer;
  810. }
  811. else if (layer == GameConfig.TopMapLayer)
  812. {
  813. layer = AutoTopLayer;
  814. }
  815. else
  816. {
  817. Debug.LogError($"异常图块: {pos}, 这个图块的图集坐标'{atlasCoords}'不属于'MiddleMapLayer'和'TopMapLayer'!");
  818. continue;
  819. }
  820. EraseCell(AutoFloorLayer, pos);
  821. SetCell(layer, pos, _sourceId, atlasCoords);
  822. }
  823. }
  824. }
  825. }
  826.  
  827. //生成导航网格
  828. private void GenerateNavigation()
  829. {
  830. var navigationRegion = _editorTileMap.L_NavigationRegion.Instance;
  831. var navigationPolygon = navigationRegion.NavigationPolygon;
  832. navigationPolygon.Clear();
  833. navigationPolygon.ClearPolygons();
  834. navigationPolygon.ClearOutlines();
  835. var endPos = CurrRoomPosition + CurrRoomSize;
  836. navigationPolygon.AddOutline(new []
  837. {
  838. CurrRoomPosition * GameConfig.TileCellSize,
  839. new Vector2(endPos.X, CurrRoomPosition.Y) * GameConfig.TileCellSize,
  840. endPos * GameConfig.TileCellSize,
  841. new Vector2(CurrRoomPosition.X, endPos.Y) * GameConfig.TileCellSize
  842. });
  843. navigationRegion.BakeNavigationPolygon(false);
  844. }
  845.  
  846. //设置显示的错误cell, 会标记上红色的闪烁动画
  847. private void SetErrorCell(Vector2I pos)
  848. {
  849. MapEditorPanel.S_ErrorCell.Instance.Position = pos * GameConfig.TileCellSize;
  850. MapEditorPanel.S_ErrorCellAnimationPlayer.Instance.Play(AnimatorNames.Show);
  851. }
  852.  
  853. //关闭显示的错误cell
  854. private void CloseErrorCell()
  855. {
  856. MapEditorPanel.S_ErrorCellAnimationPlayer.Instance.Stop();
  857. }
  858.  
  859. private int GetFloorLayer()
  860. {
  861. return AutoFloorLayer;
  862. }
  863.  
  864. private int GetMiddleLayer()
  865. {
  866. return AutoMiddleLayer;
  867. }
  868.  
  869. private int GetTopLayer()
  870. {
  871. return AutoTopLayer;
  872. }
  873.  
  874. /// <summary>
  875. /// 选中拖拽功能
  876. /// </summary>
  877. private void OnSelectHandTool(object arg)
  878. {
  879. MouseType = MouseButtonType.Drag;
  880. }
  881. /// <summary>
  882. /// 选中画笔攻击
  883. /// </summary>
  884. private void OnSelectPenTool(object arg)
  885. {
  886. MouseType = MouseButtonType.Pen;
  887. }
  888.  
  889. /// <summary>
  890. /// 选中绘制区域功能
  891. /// </summary>
  892. private void OnSelectRectTool(object arg)
  893. {
  894. MouseType = MouseButtonType.Area;
  895. }
  896.  
  897. /// <summary>
  898. /// 选择编辑门区域
  899. /// </summary>
  900. private void OnSelectEditTool(object arg)
  901. {
  902. MouseType = MouseButtonType.Edit;
  903. }
  904.  
  905. /// <summary>
  906. /// 聚焦
  907. /// </summary>
  908. private void OnClickCenterTool(object arg)
  909. {
  910. var pos = MapEditorPanel.S_SubViewport.Instance.Size / 2;
  911. if (CurrRoomSize.X == 0 && CurrRoomSize.Y == 0) //聚焦原点
  912. {
  913. SetMapPosition(pos);
  914. }
  915. else //聚焦地图中心点
  916. {
  917. SetMapPosition(pos - (CurrRoomPosition + CurrRoomSize / 2) * TileSet.TileSize * Scale);
  918. }
  919. }
  920. //房间数据有修改
  921. private void OnEditorDirty(object obj)
  922. {
  923. IsDirty = true;
  924. MapEditorPanel.SetTitleDirty(true);
  925. }
  926.  
  927. /// <summary>
  928. /// 创建地牢房间门区域
  929. /// </summary>
  930. /// <param name="direction">门方向</param>
  931. /// <param name="start">起始坐标, 单位: 像素</param>
  932. /// <param name="end">结束坐标, 单位: 像素</param>
  933. public DoorAreaInfo CreateDoorArea(DoorDirection direction, int start, int end)
  934. {
  935. var doorAreaInfo = new DoorAreaInfo();
  936. doorAreaInfo.Direction = direction;
  937. doorAreaInfo.Start = start;
  938. doorAreaInfo.End = end;
  939. //doorAreaInfo.CalcPosition(_roomPosition, _roomSize);
  940. CurrDoorConfigs.Add(doorAreaInfo);
  941. return doorAreaInfo;
  942. }
  943.  
  944. /// <summary>
  945. /// 检测门区域数据是否可以提交
  946. /// </summary>
  947. /// <param name="direction">门方向</param>
  948. /// <param name="start">起始坐标, 单位: 像素</param>
  949. /// <param name="end">结束坐标, 单位: 像素</param>
  950. /// <returns></returns>
  951. public bool CheckDoorArea(DoorDirection direction, int start, int end)
  952. {
  953. foreach (var item in CurrDoorConfigs)
  954. {
  955. if (item.Direction == direction)
  956. {
  957. if (CheckValueCollision(item.Start, item.End, start, end))
  958. {
  959. return false;
  960. }
  961. }
  962. }
  963.  
  964. return true;
  965. }
  966. /// <summary>
  967. /// 检测门区域数据是否可以提交
  968. /// </summary>
  969. /// <param name="target">需要检测的门</param>
  970. /// <param name="start">起始坐标, 单位: 像素</param>
  971. /// <param name="end">结束坐标, 单位: 像素</param>
  972. public bool CheckDoorArea(DoorAreaInfo target, int start, int end)
  973. {
  974. foreach (var item in CurrDoorConfigs)
  975. {
  976. if (item.Direction == target.Direction && item != target)
  977. {
  978. if (CheckValueCollision(item.Start, item.End, start, end))
  979. {
  980. return false;
  981. }
  982. }
  983. }
  984.  
  985. return true;
  986. }
  987. private bool CheckValueCollision(float o1, float o2, float h1, float h2)
  988. {
  989. var size = GameConfig.TileCellSize;
  990. return !(h2 < o1 - 3 * size || o2 + 3 * size < h1);
  991. }
  992.  
  993. /// <summary>
  994. /// 移除门区域数据
  995. /// </summary>
  996. public void RemoveDoorArea(DoorAreaInfo doorAreaInfo)
  997. {
  998. CurrDoorConfigs.Remove(doorAreaInfo);
  999. }
  1000. //保存房间配置
  1001. private void SaveRoomInfoConfig()
  1002. {
  1003. //存入本地
  1004. var roomInfo = CurrRoomSplit.RoomInfo;
  1005. if (!HasTerrainError) //没有绘制错误
  1006. {
  1007. roomInfo.Size = new SerializeVector2(CurrRoomSize);
  1008. roomInfo.Position = new SerializeVector2(CurrRoomPosition);
  1009. }
  1010. else
  1011. {
  1012. roomInfo.Position = new SerializeVector2(CurrRoomPosition - Vector2I.One);
  1013. roomInfo.Size = new SerializeVector2(CurrRoomSize + new Vector2I(2, 2));
  1014. }
  1015.  
  1016. roomInfo.DoorAreaInfos.Clear();
  1017. roomInfo.DoorAreaInfos.AddRange(CurrDoorConfigs);
  1018. roomInfo.ClearCompletionDoorArea();
  1019. MapProjectManager.SaveRoomInfo(CurrRoomSplit);
  1020. }
  1021.  
  1022. //保存地块数据
  1023. public void SaveTileInfoConfig()
  1024. {
  1025. //存入本地
  1026. var tileInfo = CurrRoomSplit.TileInfo;
  1027. if (tileInfo.NavigationPolygon == null)
  1028. {
  1029. tileInfo.NavigationPolygon = new List<int[]>();
  1030. }
  1031. else
  1032. {
  1033. tileInfo.NavigationPolygon.Clear();
  1034. }
  1035. if (tileInfo.NavigationVertices == null)
  1036. {
  1037. tileInfo.NavigationVertices = new List<SerializeVector2>();
  1038. }
  1039. else
  1040. {
  1041. tileInfo.NavigationVertices.Clear();
  1042. }
  1043. var polygon = _editorTileMap.L_NavigationRegion.Instance.NavigationPolygon;
  1044. tileInfo.NavigationPolygon.AddRange(polygon.Polygons);
  1045. tileInfo.NavigationVertices.AddRange(polygon.Vertices.Select(v => new SerializeVector2(v)));
  1046. tileInfo.Floor.Clear();
  1047. tileInfo.Middle.Clear();
  1048. tileInfo.Top.Clear();
  1049.  
  1050. PushLayerDataToList(AutoFloorLayer, _sourceId, tileInfo.Floor);
  1051. PushLayerDataToList(AutoMiddleLayer, _sourceId, tileInfo.Middle);
  1052. PushLayerDataToList(AutoTopLayer, _sourceId, tileInfo.Top);
  1053. MapProjectManager.SaveRoomTileInfo(CurrRoomSplit);
  1054. }
  1055.  
  1056. /// <summary>
  1057. /// 保存预设数据
  1058. /// </summary>
  1059. public void SavePreinstallConfig()
  1060. {
  1061. //存入本地
  1062. MapProjectManager.SaveRoomPreinstall(CurrRoomSplit);
  1063. }
  1064.  
  1065. /// <summary>
  1066. /// 获取相机中心点坐标
  1067. /// </summary>
  1068. public Vector2I GetCenterPosition()
  1069. {
  1070. var pos = ToLocal(MapEditorPanel.S_SubViewport.Instance.Size / 2);
  1071. return new Vector2I((int)pos.X, (int)pos.Y);
  1072. }
  1073. /// <summary>
  1074. /// 设置相机看向的点
  1075. /// </summary>
  1076. public void SetLookPosition(Vector2 pos)
  1077. {
  1078. SetMapPosition(-pos * Scale + MapEditorPanel.S_SubViewport.Instance.Size / 2);
  1079. //SetMapPosition(pos * Scale);
  1080. //SetMapPosition(pos + MapEditorPanel.S_SubViewport.Instance.Size / 2);
  1081. }
  1082. /// <summary>
  1083. /// 设置地图坐标
  1084. /// </summary>
  1085. public void SetMapPosition(Vector2 pos)
  1086. {
  1087. Position = pos;
  1088. MapEditorToolsPanel.SetToolTransform(pos, Scale);
  1089. }
  1090.  
  1091. //设置地图大小
  1092. private void SetMapSize(Vector2I size, bool refreshDoorTrans)
  1093. {
  1094. if (CurrRoomSize != size)
  1095. {
  1096. CurrRoomSize = size;
  1097.  
  1098. if (refreshDoorTrans)
  1099. {
  1100. MapEditorToolsPanel.SetDoorHoverToolTransform(CurrRoomPosition, CurrRoomSize);
  1101. }
  1102. }
  1103. }
  1104.  
  1105. private bool _hasPreviewImage = false;
  1106. private Action _previewFinish;
  1107. private int _previewIndex = 0;
  1108. private Vector2I _tempViewportSize;
  1109. private Vector2 _tempMapPos;
  1110. private Vector2 _tempMapScale;
  1111. private bool _tempAutoFloorLayer;
  1112. private bool _tempCustomFloorLayer;
  1113. private bool _tempAutoMiddleLayer;
  1114. private bool _tempCustomMiddleLayer;
  1115. private bool _tempAutoTopLayer;
  1116. private bool _tempCustomTopLayer;
  1117.  
  1118. private void RunSavePreviewImage(Action action)
  1119. {
  1120. if (_hasPreviewImage)
  1121. {
  1122. return;
  1123. }
  1124.  
  1125. _previewIndex = 0;
  1126. _previewFinish = action;
  1127. _hasPreviewImage = true;
  1128. //先截图, 将图像数据放置到 S_MapView2 节点上
  1129. var subViewport = MapEditorPanel.S_SubViewport.Instance;
  1130. var viewportTexture = subViewport.GetTexture();
  1131. var tex = ImageTexture.CreateFromImage(viewportTexture.GetImage());
  1132. var textureRect = MapEditorPanel.S_MapView2.Instance;
  1133. textureRect.Texture = tex;
  1134. textureRect.Visible = true;
  1135. //调整绘制视图大小
  1136. _tempViewportSize = subViewport.Size;
  1137. subViewport.Size = new Vector2I(GameConfig.PreviewImageSize, GameConfig.PreviewImageSize);
  1138. //调整tileMap
  1139. _tempMapPos = Position;
  1140. _tempMapScale = Scale;
  1141. //中心点
  1142. var pos = new Vector2(GameConfig.PreviewImageSize / 2f, GameConfig.PreviewImageSize / 2f);
  1143. if (CurrRoomSize.X == 0 && CurrRoomSize.Y == 0) //聚焦原点
  1144. {
  1145. Position = pos;
  1146. }
  1147. else //聚焦地图中心点
  1148. {
  1149. var tempPos = new Vector2(CurrRoomSize.X + 2, CurrRoomSize.Y + 2);
  1150. var mapSize = tempPos * TileSet.TileSize;
  1151. var axis = Mathf.Max(mapSize.X, mapSize.Y);
  1152. var targetScale = GameConfig.PreviewImageSize / axis;
  1153. Scale = new Vector2(targetScale, targetScale);
  1154. Position = pos - (CurrRoomPosition + tempPos / 2f - Vector2.One) * TileSet.TileSize * targetScale;
  1155. }
  1156. //隐藏工具栏
  1157. MapEditorToolsPanel.Visible = false;
  1158. //显示所有层级
  1159. _tempAutoFloorLayer = IsLayerEnabled(AutoFloorLayer);
  1160. _tempCustomFloorLayer = IsLayerEnabled(CustomFloorLayer);
  1161. _tempAutoMiddleLayer = IsLayerEnabled(AutoMiddleLayer);
  1162. _tempCustomMiddleLayer = IsLayerEnabled(CustomMiddleLayer);
  1163. _tempAutoTopLayer = IsLayerEnabled(AutoTopLayer);
  1164. _tempCustomTopLayer = IsLayerEnabled(CustomTopLayer);
  1165.  
  1166. SetLayerEnabled(AutoFloorLayer, true);
  1167. SetLayerEnabled(CustomFloorLayer, true);
  1168. SetLayerEnabled(AutoMiddleLayer, true);
  1169. SetLayerEnabled(CustomMiddleLayer, true);
  1170. SetLayerEnabled(AutoTopLayer, true);
  1171. SetLayerEnabled(CustomTopLayer, true);
  1172. }
  1173.  
  1174. private void OnFramePostDraw()
  1175. {
  1176. if (_hasPreviewImage)
  1177. {
  1178. _previewIndex++;
  1179. if (_previewIndex == 2)
  1180. {
  1181. var textureRect = MapEditorPanel.S_MapView2.Instance;
  1182. var texture = textureRect.Texture;
  1183. textureRect.Texture = null;
  1184. texture.Dispose();
  1185. textureRect.Visible = false;
  1186. //还原工具栏
  1187. MapEditorToolsPanel.Visible = true;
  1188. //还原层级显示
  1189. SetLayerEnabled(AutoFloorLayer, _tempAutoFloorLayer);
  1190. SetLayerEnabled(CustomFloorLayer, _tempCustomFloorLayer);
  1191. SetLayerEnabled(AutoMiddleLayer, _tempAutoMiddleLayer);
  1192. SetLayerEnabled(CustomMiddleLayer, _tempCustomMiddleLayer);
  1193. SetLayerEnabled(AutoTopLayer, _tempAutoTopLayer);
  1194. SetLayerEnabled(CustomTopLayer, _tempCustomTopLayer);
  1195.  
  1196. //保存预览图
  1197. var subViewport = MapEditorPanel.S_SubViewport.Instance;
  1198. var viewportTexture = subViewport.GetTexture();
  1199. var image = viewportTexture.GetImage();
  1200. image.Resize(GameConfig.PreviewImageSize, GameConfig.PreviewImageSize, Image.Interpolation.Nearest);
  1201. CurrRoomSplit.PreviewImage = ImageTexture.CreateFromImage(image);
  1202. MapProjectManager.SaveRoomPreviewImage(CurrRoomSplit, image);
  1203. //还原tileMap
  1204. Position = _tempMapPos;
  1205. Scale = _tempMapScale;
  1206. //还原绘制视图
  1207. subViewport.Size = _tempViewportSize;
  1208. _previewFinish();
  1209. _hasPreviewImage = false;
  1210. }
  1211. }
  1212. }
  1213. private void OnBakeFinished()
  1214. {
  1215. var polygonData = _editorTileMap.L_NavigationRegion.Instance.NavigationPolygon;
  1216. var polygons = polygonData.Polygons;
  1217. var vertices = polygonData.Vertices;
  1218. _polygonData = new Vector2[polygons.Count][];
  1219. for (var i = 0; i < polygons.Count; i++)
  1220. {
  1221. var polygon = polygons[i];
  1222. var v2Array = new Vector2[polygon.Length];
  1223. for (var j = 0; j < polygon.Length; j++)
  1224. {
  1225. v2Array[j] = vertices[polygon[j]];
  1226. }
  1227. _polygonData[i] = v2Array;
  1228. }
  1229. }
  1230. }