Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / ui / mapEditor / TileView / EditorTileMap.cs
@lijincheng lijincheng on 14 Jul 2023 13 KB 小修改
  1. using System.Collections.Generic;
  2. using Godot;
  3. using Godot.Collections;
  4.  
  5. namespace UI.MapEditor;
  6.  
  7. public partial class EditorTileMap : TileMap
  8. {
  9. /// <summary>
  10. /// 自动图块地板层
  11. /// </summary>
  12. public const int AutoFloorLayer = 0;
  13. /// <summary>
  14. /// 自定义图块地板层
  15. /// </summary>
  16. public const int CustomFloorLayer = 1;
  17. /// <summary>
  18. /// 自动图块中间层
  19. /// </summary>
  20. public const int AutoMiddleLayer = 2;
  21. /// <summary>
  22. /// 自定义图块中间层
  23. /// </summary>
  24. public const int CustomMiddleLayer = 3;
  25. /// <summary>
  26. /// 自动图块顶层
  27. /// </summary>
  28. public const int AutoTopLayer = 4;
  29. /// <summary>
  30. /// 自定义图块顶层
  31. /// </summary>
  32. public const int CustomTopLayer = 5;
  33. /// <summary>
  34. /// 所属地图编辑器UI
  35. /// </summary>
  36. public MapEditorPanel MapEditorPanel { get; set; }
  37. //鼠标坐标
  38. private Vector2 _mousePosition;
  39. //鼠标所在的cell坐标
  40. private Vector2I _mouseCellPosition;
  41. //上一帧鼠标所在的cell坐标
  42. private Vector2I _prevMouseCellPosition = new Vector2I(-99999, -99999);
  43. //单次绘制是否改变过tile数据
  44. private bool _changeFlag = false;
  45. //左键开始按下时鼠标所在的坐标
  46. private Vector2I _mouseStartCellPosition;
  47. //鼠标中建是否按下
  48. private bool _isMiddlePressed = false;
  49. private Vector2 _moveOffset;
  50. //左键是否按下
  51. private bool _isLeftPressed = false;
  52. //右键是否按下
  53. private bool _isRightPressed = false;
  54. //绘制填充区域
  55. private bool _drawFullRect = false;
  56. //负责存储自动图块数据
  57. private Grid<bool> _autoCellLayerGrid = new Grid<bool>();
  58. //用于生成导航网格
  59. private DungeonTile _dungeonTile;
  60. private float _generateNavigationTimer = -1;
  61. //--------- 配置数据 -------------
  62. private int _sourceId = 0;
  63. private int _terrainSet = 0;
  64. private int _terrain = 0;
  65. private Vector2I _floorAtlasCoords = new Vector2I(0, 8);
  66. //-------------------------------
  67.  
  68. public override void _Ready()
  69. {
  70. //初始化层级数据
  71. AddLayer(CustomFloorLayer);
  72. SetLayerZIndex(CustomFloorLayer, CustomFloorLayer);
  73. AddLayer(AutoMiddleLayer);
  74. SetLayerZIndex(AutoMiddleLayer, AutoMiddleLayer);
  75. AddLayer(CustomMiddleLayer);
  76. SetLayerZIndex(CustomMiddleLayer, CustomMiddleLayer);
  77. AddLayer(AutoTopLayer);
  78. SetLayerZIndex(AutoTopLayer, AutoTopLayer);
  79. AddLayer(CustomTopLayer);
  80. SetLayerZIndex(CustomTopLayer, CustomTopLayer);
  81.  
  82. _dungeonTile = new DungeonTile(this);
  83. _dungeonTile.SetFloorAtlasCoords(new List<Vector2I>(new []{ _floorAtlasCoords }));
  84. }
  85.  
  86. public override void _Process(double delta)
  87. {
  88. var newDelta = (float)delta;
  89. _drawFullRect = false;
  90. var position = GetLocalMousePosition();
  91. _mouseCellPosition = LocalToMap(position);
  92. _mousePosition = new Vector2(
  93. _mouseCellPosition.X * GameConfig.TileCellSize,
  94. _mouseCellPosition.Y * GameConfig.TileCellSize
  95. );
  96.  
  97. if (!MapEditorPanel.ToolsPanel.S_HBoxContainer.Instance.IsPositionOver(GetGlobalMousePosition())) //不在Ui节点上
  98. {
  99. //左键绘制
  100. if (_isLeftPressed)
  101. {
  102. if (Input.IsKeyPressed(Key.Shift)) //按住shift绘制矩形
  103. {
  104. _drawFullRect = true;
  105. }
  106. else if (_prevMouseCellPosition != _mouseCellPosition || !_changeFlag) //鼠标位置变过
  107. {
  108. _changeFlag = true;
  109. _prevMouseCellPosition = _mouseCellPosition;
  110. //绘制自动图块
  111. SetSingleAutoCell(_mouseCellPosition);
  112. }
  113. }
  114. else if (_isRightPressed) //右键擦除
  115. {
  116. if (Input.IsKeyPressed(Key.Shift)) //按住shift擦除矩形
  117. {
  118. _drawFullRect = true;
  119. }
  120. else if (_prevMouseCellPosition != _mouseCellPosition || !_changeFlag) //鼠标位置变过
  121. {
  122. _changeFlag = true;
  123. _prevMouseCellPosition = _mouseCellPosition;
  124. EraseSingleAutoCell(_mouseCellPosition);
  125. }
  126. }
  127. else if (_isMiddlePressed) //中建移动
  128. {
  129. //GD.Print("移动...");
  130. Position = GetGlobalMousePosition() + _moveOffset;
  131. }
  132. }
  133.  
  134. //绘制停止指定时间后, 生成导航网格
  135. if (_generateNavigationTimer > 0)
  136. {
  137. _generateNavigationTimer -= newDelta;
  138. if (_generateNavigationTimer <= 0)
  139. {
  140. GD.Print("开始绘制导航网格...");
  141. GenerateNavigation();
  142. }
  143. }
  144. }
  145.  
  146. /// <summary>
  147. /// 绘制辅助线
  148. /// </summary>
  149. public void DrawGuides(CanvasItem canvasItem)
  150. {
  151. //轴线
  152. canvasItem.DrawLine(new Vector2(0, 2000), new Vector2(0, -2000), Colors.Green);
  153. canvasItem.DrawLine(new Vector2(2000, 0), new Vector2( -2000, 0), Colors.Red);
  154.  
  155. //绘制导航网格
  156. var result = _dungeonTile.GetGenerateNavigationResult();
  157. if (result != null && result.Success)
  158. {
  159. var polygonData = _dungeonTile.GetPolygonData();
  160. Utils.DrawNavigationPolygon(canvasItem, polygonData, 1);
  161. }
  162.  
  163. if (_drawFullRect) //绘制填充矩形
  164. {
  165. var size = TileSet.TileSize;
  166. var cellPos = _mouseStartCellPosition;
  167. var temp = size;
  168. if (_mouseStartCellPosition.X > _mouseCellPosition.X)
  169. {
  170. cellPos.X += 1;
  171. temp.X -= size.X;
  172. }
  173. if (_mouseStartCellPosition.Y > _mouseCellPosition.Y)
  174. {
  175. cellPos.Y += 1;
  176. temp.Y -= size.Y;
  177. }
  178.  
  179. var pos = cellPos * size;
  180. canvasItem.DrawRect(new Rect2(pos, _mousePosition - pos + temp), Colors.Wheat, false);
  181. }
  182. else //绘制单格
  183. {
  184. canvasItem.DrawRect(new Rect2(_mousePosition, TileSet.TileSize), Colors.Wheat, false);
  185. }
  186. }
  187.  
  188. public override void _Input(InputEvent @event)
  189. {
  190. if (@event is InputEventMouseButton mouseButton)
  191. {
  192. if (mouseButton.ButtonIndex == MouseButton.Left) //左键
  193. {
  194. if (mouseButton.Pressed) //按下
  195. {
  196. _mouseStartCellPosition = LocalToMap(GetLocalMousePosition());
  197. }
  198. else
  199. {
  200. _changeFlag = false;
  201. if (_drawFullRect) //松开, 提交绘制的矩形区域
  202. {
  203. SetRectAutoCell(_mouseStartCellPosition, _mouseCellPosition);
  204. _drawFullRect = false;
  205. }
  206. }
  207.  
  208. _isLeftPressed = mouseButton.Pressed;
  209. }
  210. else if (mouseButton.ButtonIndex == MouseButton.Right) //右键
  211. {
  212. if (mouseButton.Pressed) //按下
  213. {
  214. _mouseStartCellPosition = LocalToMap(GetLocalMousePosition());
  215. }
  216. else
  217. {
  218. _changeFlag = false;
  219. if (_drawFullRect) //松开, 提交擦除的矩形区域
  220. {
  221. EraseRectAutoCell(_mouseStartCellPosition, _mouseCellPosition);
  222. _drawFullRect = false;
  223. }
  224. }
  225. _isRightPressed = mouseButton.Pressed;
  226. }
  227. else if (mouseButton.ButtonIndex == MouseButton.WheelDown)
  228. {
  229. //缩小
  230. Shrink();
  231. }
  232. else if (mouseButton.ButtonIndex == MouseButton.WheelUp)
  233. {
  234. //放大
  235. Magnify();
  236. }
  237. else if (mouseButton.ButtonIndex == MouseButton.Middle)
  238. {
  239. _isMiddlePressed = mouseButton.Pressed;
  240. if (_isMiddlePressed)
  241. {
  242. _moveOffset = Position - mouseButton.GlobalPosition;
  243. }
  244. }
  245. }
  246. else if (@event is InputEventKey eventKey)
  247. {
  248. //测试生成自动图块
  249. if (eventKey.KeyLabel == Key.M && eventKey.Pressed)
  250. {
  251. GenerateTerrain();
  252. }
  253. }
  254. }
  255.  
  256. //缩小
  257. private void Shrink()
  258. {
  259. var pos = GetLocalMousePosition();
  260. var scale = Scale / 1.1f;
  261. if (scale.LengthSquared() >= 0.5f)
  262. {
  263. Scale = scale;
  264. Position += pos * 0.1f * scale;
  265. }
  266. else
  267. {
  268. GD.Print("太小了");
  269. }
  270. }
  271. //放大
  272. private void Magnify()
  273. {
  274. var pos = GetLocalMousePosition();
  275. var prevScale = Scale;
  276. var scale = prevScale * 1.1f;
  277. if (scale.LengthSquared() <= 2000)
  278. {
  279. Scale = scale;
  280. Position -= pos * 0.1f * prevScale;
  281. }
  282. else
  283. {
  284. GD.Print("太大了");
  285. }
  286. }
  287.  
  288. //绘制单个自动贴图
  289. private void SetSingleAutoCell(Vector2I position)
  290. {
  291. _generateNavigationTimer = 3;
  292. SetCell(GetFloorLayer(), position, _sourceId, _floorAtlasCoords);
  293. _autoCellLayerGrid.Set(position.X, position.Y, true);
  294. }
  295. //绘制区域自动贴图
  296. private void SetRectAutoCell(Vector2I start, Vector2I end)
  297. {
  298. _generateNavigationTimer = 3;
  299. if (start.X > end.X)
  300. {
  301. var temp = end.X;
  302. end.X = start.X;
  303. start.X = temp;
  304. }
  305. if (start.Y > end.Y)
  306. {
  307. var temp = end.Y;
  308. end.Y = start.Y;
  309. start.Y = temp;
  310. }
  311.  
  312. var width = end.X - start.X + 1;
  313. var height = end.Y - start.Y + 1;
  314. for (var i = 0; i < width; i++)
  315. {
  316. for (var j = 0; j < height; j++)
  317. {
  318. SetCell(GetFloorLayer(), new Vector2I(start.X + i, start.Y + j), _sourceId, _floorAtlasCoords);
  319. }
  320. }
  321.  
  322. _autoCellLayerGrid.SetRect(start, new Vector2I(width, height), true);
  323. }
  324.  
  325. //擦除单个自动图块
  326. private void EraseSingleAutoCell(Vector2I position)
  327. {
  328. _generateNavigationTimer = 3;
  329. EraseCell(GetFloorLayer(), position);
  330. _autoCellLayerGrid.Remove(position.X, position.Y);
  331. }
  332. //擦除一个区域内的自动贴图
  333. private void EraseRectAutoCell(Vector2I start, Vector2I end)
  334. {
  335. _generateNavigationTimer = 3;
  336. if (start.X > end.X)
  337. {
  338. var temp = end.X;
  339. end.X = start.X;
  340. start.X = temp;
  341. }
  342. if (start.Y > end.Y)
  343. {
  344. var temp = end.Y;
  345. end.Y = start.Y;
  346. start.Y = temp;
  347. }
  348.  
  349. var width = end.X - start.X + 1;
  350. var height = end.Y - start.Y + 1;
  351. for (var i = 0; i < width; i++)
  352. {
  353. for (var j = 0; j < height; j++)
  354. {
  355. EraseCell(GetFloorLayer(), new Vector2I(start.X + i, start.Y + j));
  356. }
  357. }
  358. _autoCellLayerGrid.RemoveRect(start, new Vector2I(width, height));
  359. }
  360.  
  361. private bool CheckTerrain()
  362. {
  363. var usedRect = GetUsedRect();
  364. var x = usedRect.Position.X;
  365. var y = usedRect.Position.Y;
  366. var w = usedRect.Size.X;
  367. var h = usedRect.Size.Y;
  368. //执行刷墙逻辑
  369. // //先检测对角是否有地板
  370. // var left = _autoCellLayerGrid.Get(position.X - 1, position.Y);
  371. // var right = _autoCellLayerGrid.Get(position.X + 1, position.Y);
  372. // var top = _autoCellLayerGrid.Get(position.X, position.Y + 1);
  373. // var down = _autoCellLayerGrid.Get(position.X, position.Y - 1);
  374. //
  375. // if ((left && right) || (top && down))
  376. // {
  377. // GD.Print("错误的地图块...");
  378. // }
  379. return true;
  380. }
  381. //生成自动图块 (地形)
  382. private void GenerateTerrain()
  383. {
  384. ClearLayer(AutoFloorLayer);
  385. var list = new List<Vector2I>();
  386. _autoCellLayerGrid.ForEach((x, y, data) =>
  387. {
  388. if (data)
  389. {
  390. list.Add(new Vector2I(x, y));
  391. }
  392. });
  393. var arr = new Array<Vector2I>(list);
  394. SetCellsTerrainConnect(AutoFloorLayer, arr, _terrainSet, _terrain, false);
  395. }
  396.  
  397. //生成导航网格
  398. private void GenerateNavigation()
  399. {
  400. _dungeonTile.GenerateNavigationPolygon(AutoFloorLayer);
  401. var result = _dungeonTile.GetGenerateNavigationResult();
  402. if (result.Success)
  403. {
  404. MapEditorPanel.S_ErrorCellAnimationPlayer.Instance.Stop();
  405. }
  406. else
  407. {
  408. MapEditorPanel.S_ErrorCell.Instance.Position = result.Exception.Point * CellQuadrantSize;
  409. MapEditorPanel.S_ErrorCellAnimationPlayer.Instance.Play(AnimatorNames.Show);
  410. }
  411. }
  412.  
  413. private int GetFloorLayer()
  414. {
  415. return AutoFloorLayer;
  416. }
  417.  
  418. private int GetMiddleLayer()
  419. {
  420. return AutoMiddleLayer;
  421. }
  422.  
  423. private int GetTopLayer()
  424. {
  425. return AutoTopLayer;
  426. }
  427.  
  428. /// <summary>
  429. /// 选中拖拽功能
  430. /// </summary>
  431. public void OnSelectHandTool()
  432. {
  433. }
  434. /// <summary>
  435. /// 选中画笔攻击
  436. /// </summary>
  437. public void OnSelectPenTool()
  438. {
  439. }
  440.  
  441. /// <summary>
  442. /// 选中绘制区域功能
  443. /// </summary>
  444. public void OnSelectRectTool()
  445. {
  446. }
  447.  
  448. /// <summary>
  449. /// 聚焦
  450. /// </summary>
  451. public void OnClickCenterTool()
  452. {
  453. Position = MapEditorPanel.S_SubViewport.Instance.Size / 2;
  454. }
  455. }