Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / ui / mapEditorTools / MapEditorToolsPanel.cs
@小李xl 小李xl on 20 Jan 2024 18 KB TileMap编辑器小细节优化
  1. using System;
  2. using System.Collections.Generic;
  3. using Godot;
  4. using UI.MapEditor;
  5.  
  6. namespace UI.MapEditorTools;
  7.  
  8. public partial class MapEditorToolsPanel : MapEditorTools
  9. {
  10. public class ToolBtnData
  11. {
  12. //是否可以选中
  13. public bool CanSelect = false;
  14. //工具图标
  15. public string Icon;
  16. //点击时回调
  17. public Action OnClick;
  18.  
  19. public ToolBtnData(bool canSelect, string icon, Action onClick)
  20. {
  21. CanSelect = canSelect;
  22. Icon = icon;
  23. OnClick = onClick;
  24. }
  25. }
  26. /// <summary>
  27. /// 鼠标悬停区域
  28. /// </summary>
  29. public DoorHoverArea ActiveHoverArea { get; private set; }
  30. /// <summary>
  31. /// 鼠标选中的标记对象
  32. /// </summary>
  33. public MarkTool ActiveMark { get; private set; }
  34.  
  35. /// <summary>
  36. /// 所属编辑器Tile对象
  37. /// </summary>
  38. public MapEditor.MapEditor.TileMap EditorMap { get; private set; }
  39. /// <summary>
  40. /// 是否打开弹窗
  41. /// </summary>
  42. public bool IsOpenPopUps { get; private set; }
  43. private List<DoorToolTemplate> _doorTools = new List<DoorToolTemplate>();
  44. private UiGrid<ToolButton, ToolBtnData> _toolGrid;
  45. //当前预设的所有标记
  46. private Dictionary<MarkInfo, MarkTemplate> _currMarkToolsMap = new Dictionary<MarkInfo, MarkTemplate>();
  47. private EventFactory _eventFactory;
  48. private int _editToolIndex;
  49.  
  50. public override void OnCreateUi()
  51. {
  52. var mapEditorPanel = (MapEditorPanel)ParentUi;
  53. EditorMap = mapEditorPanel.S_TileMap;
  54. S_N_HoverArea.Instance.Init(this, DoorDirection.N);
  55. S_S_HoverArea.Instance.Init(this, DoorDirection.S);
  56. S_W_HoverArea.Instance.Init(this, DoorDirection.W);
  57. S_E_HoverArea.Instance.Init(this, DoorDirection.E);
  58. S_ToolRoot.Instance.RemoveChild(S_DoorToolTemplate.Instance);
  59. S_MarkTemplate.Instance.Visible = false;
  60.  
  61. _toolGrid = new UiGrid<ToolButton, ToolBtnData>(S_ToolButton, typeof(ToolButtonCell));
  62. _toolGrid.SetColumns(10);
  63. //拖拽按钮
  64. _toolGrid.Add(new ToolBtnData(true, ResourcePath.resource_sprite_ui_commonIcon_DragTool_png, () =>
  65. {
  66. EventManager.EmitEvent(EventEnum.OnSelectDragTool);
  67. }));
  68. //画笔按钮
  69. _toolGrid.Add(new ToolBtnData(true, ResourcePath.resource_sprite_ui_commonIcon_PenTool_png, () =>
  70. {
  71. EventManager.EmitEvent(EventEnum.OnSelectPenTool);
  72. }));
  73. //绘制区域按钮
  74. _toolGrid.Add(new ToolBtnData(true, ResourcePath.resource_sprite_ui_commonIcon_AreaTool_png, () =>
  75. {
  76. EventManager.EmitEvent(EventEnum.OnSelectRectTool);
  77. }));
  78. //编辑工具按钮
  79. _toolGrid.Add(new ToolBtnData(true, ResourcePath.resource_sprite_ui_commonIcon_DoorTool_png, () =>
  80. {
  81. EventManager.EmitEvent(EventEnum.OnSelectEditTool);
  82. mapEditorPanel.S_MapEditorMapLayer.Instance.SetLayerVisible(MapLayer.MarkLayer, true);
  83. }));
  84. _editToolIndex = _toolGrid.Count - 1;
  85. //聚焦按钮
  86. _toolGrid.Add(new ToolBtnData(false, ResourcePath.resource_sprite_ui_commonIcon_CenterTool_png, () =>
  87. {
  88. EventManager.EmitEvent(EventEnum.OnClickCenterTool);
  89. }));
  90. _toolGrid.SelectIndex = 1;
  91. _eventFactory = EventManager.CreateEventFactory();
  92. _eventFactory.AddEventListener(EventEnum.OnSelectWave, OnSelectWaveTool);
  93. _eventFactory.AddEventListener(EventEnum.OnCreateMark, OnCreateMarkTool);
  94. _eventFactory.AddEventListener(EventEnum.OnSelectMark, OnSelectMarkTool);
  95. _eventFactory.AddEventListener(EventEnum.OnDeleteMark, OnDeleteMarkTool);
  96. _eventFactory.AddEventListener(EventEnum.OnSetMarkVisible, OnSetMarkVisible);
  97. _eventFactory.AddEventListener(EventEnum.OnEditMark, OnEditMarkTool);
  98. _eventFactory.AddEventListener(EventEnum.OnSelectPreinstall, RefreshMark);
  99. }
  100.  
  101. public override void OnDestroyUi()
  102. {
  103. _eventFactory.RemoveAllEventListener();
  104. _eventFactory = null;
  105. S_DoorToolTemplate.Instance.QueueFree();
  106. _toolGrid.Destroy();
  107. }
  108.  
  109. public override void Process(float delta)
  110. {
  111. S_HoverPreviewRoot.Instance.Visible = ActiveHoverArea != null && !DoorHoverArea.IsDrag;
  112. if (EditorMap.Instance.MouseType == EditorTileMap.MouseButtonType.Edit)
  113. {
  114. S_ToolRoot.Instance.Modulate = new Color(1, 1, 1, 1);
  115. }
  116. else
  117. {
  118. S_ToolRoot.Instance.Modulate = new Color(1, 1, 1, 0.4f);
  119. }
  120.  
  121. IsOpenPopUps = UiManager.GetUiInstanceCount(UiManager.UiNames.EditorWindow) > 0;
  122. }
  123.  
  124. //刷新标记
  125. private void RefreshMark(object arg)
  126. {
  127. ActiveMark = null;
  128. //删除之前的数据
  129. foreach (var keyValuePair in _currMarkToolsMap)
  130. {
  131. keyValuePair.Value.QueueFree();
  132. }
  133. _currMarkToolsMap.Clear();
  134. //添加新的数据
  135. var selectPreinstall = EditorTileMapManager.SelectPreinstall;
  136. if (selectPreinstall != null)
  137. {
  138. foreach (var markInfos in selectPreinstall.WaveList)
  139. {
  140. foreach (var markInfo in markInfos)
  141. {
  142. CreateMarkTool(markInfo);
  143. }
  144. }
  145. }
  146. }
  147.  
  148. //选中波数
  149. private void OnSelectWaveTool(object arg)
  150. {
  151. //选中编辑工具
  152. if (_toolGrid.SelectIndex != _editToolIndex)
  153. {
  154. _toolGrid.Click(_editToolIndex);
  155. }
  156. var selectIndex = EditorTileMapManager.SelectWaveIndex;
  157. var waveList = EditorTileMapManager.SelectPreinstall.WaveList;
  158. for (var i = 0; i < waveList.Count; i++)
  159. {
  160. var wave = waveList[i];
  161. foreach (var markInfo in wave)
  162. {
  163. if (_currMarkToolsMap.TryGetValue(markInfo, out var markTemplate))
  164. {
  165. if (i == selectIndex) //选中当前波数, 透明度改为1
  166. {
  167. markTemplate.Instance.SetModulateAlpha(1f);
  168. }
  169. else //未选中当前波数, 透明度改为0.6
  170. {
  171. markTemplate.Instance.SetModulateAlpha(0.45f);
  172. }
  173. }
  174. }
  175. }
  176. }
  177. //创建标记
  178. private void OnCreateMarkTool(object arg)
  179. {
  180. var markInfo = (MarkInfo)arg;
  181. CreateMarkTool(markInfo);
  182. }
  183.  
  184. //创建标记
  185. private void CreateMarkTool(MarkInfo markInfo)
  186. {
  187. var cloneAndPut = S_MarkTemplate.CloneAndPut();
  188. _currMarkToolsMap.Add(markInfo, cloneAndPut);
  189. cloneAndPut.Instance.Visible = true;
  190. cloneAndPut.Instance.InitData(markInfo);
  191. }
  192.  
  193. //选中标记
  194. private void OnSelectMarkTool(object arg)
  195. {
  196. //选中编辑工具
  197. if (_toolGrid.SelectIndex != _editToolIndex)
  198. {
  199. _toolGrid.Click(_editToolIndex);
  200. }
  201. if (arg is MarkInfo markInfo)
  202. {
  203. if (ActiveMark == null || markInfo != ActiveMark.MarkInfo)
  204. {
  205. if (_currMarkToolsMap.TryGetValue(markInfo, out var markTemplate))
  206. {
  207. SetActiveMark(markTemplate.Instance);
  208. }
  209. }
  210. }
  211. else if (arg == null && ActiveMark != null)
  212. {
  213. SetActiveMark(null);
  214. }
  215. }
  216.  
  217. //删除标记
  218. private void OnDeleteMarkTool(object arg)
  219. {
  220. if (arg is MarkInfo markInfo)
  221. {
  222. if (_currMarkToolsMap.TryGetValue(markInfo, out var markTemplate))
  223. {
  224. if (ActiveMark == markTemplate.Instance)
  225. {
  226. SetActiveMark(null);
  227. }
  228. markTemplate.QueueFree();
  229. _currMarkToolsMap.Remove(markInfo);
  230. }
  231. }
  232. }
  233.  
  234. //设置标记显示状态
  235. private void OnSetMarkVisible(object arg)
  236. {
  237. var data = (MarkInfoVisibleData)arg;
  238. if (_currMarkToolsMap.TryGetValue(data.MarkInfo, out var markTemplate))
  239. {
  240. markTemplate.Instance.Visible = data.Visible;
  241. }
  242. }
  243. //编辑标记
  244. private void OnEditMarkTool(object arg)
  245. {
  246. if (arg is MarkInfo markInfo)
  247. {
  248. if (_currMarkToolsMap.TryGetValue(markInfo, out var markTemplate))
  249. {
  250. //刷新数据
  251. markTemplate.Instance.RefreshData();
  252. }
  253. }
  254. }
  255. /// <summary>
  256. /// 获取门区域对象
  257. /// </summary>
  258. public DoorHoverArea GetDoorHoverArea(DoorDirection direction)
  259. {
  260. switch (direction)
  261. {
  262. case DoorDirection.E: return S_E_HoverArea.Instance;
  263. case DoorDirection.N: return S_N_HoverArea.Instance;
  264. case DoorDirection.W: return S_W_HoverArea.Instance;
  265. case DoorDirection.S: return S_S_HoverArea.Instance;
  266. }
  267. return null;
  268. }
  269. /// <summary>
  270. /// 获取门区域根节点
  271. /// </summary>
  272. public Control GetDoorHoverAreaRoot(DoorDirection direction)
  273. {
  274. switch (direction)
  275. {
  276. case DoorDirection.E: return S_E_HoverRoot.Instance;
  277. case DoorDirection.N: return S_N_HoverRoot.Instance;
  278. case DoorDirection.W: return S_W_HoverRoot.Instance;
  279. case DoorDirection.S: return S_S_HoverRoot.Instance;
  280. }
  281. return null;
  282. }
  283.  
  284. /// <summary>
  285. /// 设置活动的鼠标悬停的区域
  286. /// </summary>
  287. public void SetActiveHoverArea(DoorHoverArea hoverArea)
  288. {
  289. ActiveHoverArea = hoverArea;
  290. if (hoverArea != null)
  291. {
  292. S_HoverPreviewRoot.Instance.Reparent(hoverArea.GetParent(), false);
  293. }
  294. else
  295. {
  296. S_HoverPreviewRoot.Instance.Reparent(S_ToolRoot.Instance, false);
  297. }
  298. }
  299.  
  300. /// <summary>
  301. /// 设置当前活动的标记
  302. /// </summary>
  303. public void SetActiveMark(MarkTool markTool)
  304. {
  305. if (ActiveMark == markTool)
  306. {
  307. return;
  308. }
  309.  
  310. if (ActiveMark != null) //取消选中上一个
  311. {
  312. ActiveMark.OnUnSelect();
  313. }
  314. ActiveMark = markTool;
  315. if (markTool != null) //选中当前
  316. {
  317. ActiveMark.OnSelect();
  318. EditorTileMapManager.SetSelectMark(markTool.MarkInfo);
  319. }
  320. else
  321. {
  322. EditorTileMapManager.SetSelectMark(null);
  323. }
  324. }
  325.  
  326. /// <summary>
  327. /// 创建门区域设置工具
  328. /// </summary>
  329. /// <param name="doorAreaInfo">门区域数据</param>
  330. public DoorToolTemplate CreateDoorTool(DoorAreaInfo doorAreaInfo)
  331. {
  332. var doorHoverArea = GetDoorHoverArea(doorAreaInfo.Direction);
  333. var inst = CreateDoorToolInstance(doorHoverArea);
  334. inst.Instance.DoorAreaInfo = doorAreaInfo;
  335. inst.Instance.SetDoorAreaPosition(GetDoorHoverAreaRoot(doorAreaInfo.Direction).Position);
  336. inst.Instance.SetDoorAreaRange(doorAreaInfo.Start, doorAreaInfo.End);
  337. return inst;
  338. }
  339.  
  340. /// <summary>
  341. /// 创建拖拽状态下的门区域工具, 用于创建门区域
  342. /// </summary>
  343. /// <param name="doorHoverArea">悬停区域</param>
  344. /// <param name="start">起始位置, 单位: 像素</param>
  345. /// <param name="onSubmit">成功提交时回调, 参数1为方向, 参数2为起始点, 参数3为大小</param>
  346. /// <param name="onCancel">取消提交时调用</param>
  347. public DoorToolTemplate CreateDragDoorTool(DoorHoverArea doorHoverArea, int start,
  348. Action<DoorDirection, int, int> onSubmit, Action onCancel)
  349. {
  350. var inst = CreateDoorToolInstance(doorHoverArea);
  351. inst.Instance.SetDoorAreaPosition(GetDoorHoverAreaRoot(doorHoverArea.Direction).Position);
  352. inst.Instance.SetDoorAreaRange(start, start);
  353. inst.Instance.MakeDragMode(onSubmit, () =>
  354. {
  355. RemoveDoorTool(inst);
  356. onCancel();
  357. });
  358. return inst;
  359. }
  360.  
  361. /// <summary>
  362. /// 移除门区域设置工具
  363. /// </summary>
  364. public void RemoveDoorTool(DoorToolTemplate toolInstance)
  365. {
  366. _doorTools.Remove(toolInstance);
  367. if (toolInstance.Instance.DoorAreaInfo != null)
  368. {
  369. EditorMap.Instance.RemoveDoorArea(toolInstance.Instance.DoorAreaInfo);
  370. }
  371. toolInstance.Instance.QueueFree();
  372. //派发修改数据修改事件
  373. EventManager.EmitEvent(EventEnum.OnTileMapDirty);
  374. }
  375.  
  376. /// <summary>
  377. /// 设置工具根节点的大小和缩放
  378. /// </summary>
  379. /// <param name="pos">坐标</param>
  380. /// <param name="scale">缩放</param>
  381. public void SetToolTransform(Vector2 pos, Vector2 scale)
  382. {
  383. S_ToolRoot.Instance.Position = pos;
  384. S_ToolRoot.Instance.Scale = scale;
  385. }
  386.  
  387. /// <summary>
  388. /// 设置鼠标悬停区域位置和大小
  389. /// </summary>
  390. /// <param name="position">房间起始点, 单位: 格</param>
  391. /// <param name="size">房间大小, 单位: 格</param>
  392. public void SetDoorHoverToolTransform(Vector2I position, Vector2I size)
  393. {
  394. position *= GameConfig.TileCellSize;
  395. size *= GameConfig.TileCellSize;
  396.  
  397. var nPos1 = S_N_HoverRoot.Instance.Position;
  398. var ePos1 = S_E_HoverRoot.Instance.Position;
  399. var sPos1 = S_S_HoverRoot.Instance.Position;
  400. var wPos1 = S_W_HoverRoot.Instance.Position;
  401. var nPos2 = position + new Vector2I(GameConfig.TileCellSize * 2, GameConfig.TileCellSize * 3);
  402. var ePos2 = new Vector2(position.X + size.X - GameConfig.TileCellSize * 2, position.Y + GameConfig.TileCellSize * 3);
  403. var sPos2 = new Vector2(position.X + GameConfig.TileCellSize * 2, position.Y + size.Y - GameConfig.TileCellSize * 2);
  404. var wPos2 = position + new Vector2I(GameConfig.TileCellSize * 2, GameConfig.TileCellSize * 3);
  405.  
  406. var nSize2 = new Vector2(size.X - GameConfig.TileCellSize * 4, S_N_HoverArea.Instance.Size.Y);
  407. var eSize2 = new Vector2(size.Y - GameConfig.TileCellSize * 5, S_E_HoverArea.Instance.Size.Y);
  408. var sSize2 = new Vector2(size.X - GameConfig.TileCellSize * 4, S_S_HoverArea.Instance.Size.Y);
  409. var wSize2 = new Vector2(size.Y - GameConfig.TileCellSize * 5, S_W_HoverArea.Instance.Size.Y);
  410. S_N_HoverRoot.Instance.Position = nPos2;
  411. S_E_HoverRoot.Instance.Position = ePos2;
  412. S_S_HoverRoot.Instance.Position = sPos2;
  413. S_W_HoverRoot.Instance.Position = wPos2;
  414. S_N_HoverArea.Instance.Size = nSize2;
  415. S_E_HoverArea.Instance.Size = eSize2;
  416. S_S_HoverArea.Instance.Size = sSize2;
  417. S_W_HoverArea.Instance.Size = wSize2;
  418. //调整门区域
  419. for (var i = 0; i < _doorTools.Count; i++)
  420. {
  421. var doorTool = _doorTools[i];
  422. var direction = doorTool.Instance.Direction;
  423. var areaRoot = GetDoorHoverAreaRoot(direction);
  424. var doorAreaRange = doorTool.Instance.GetDoorAreaRange();
  425. doorTool.Instance.SetDoorAreaPosition(areaRoot.Position);
  426.  
  427. if (direction == DoorDirection.N)
  428. {
  429. var hOffset = (int)(nPos2.X - nPos1.X);
  430. doorAreaRange.X -= hOffset;
  431. doorAreaRange.Y -= hOffset;
  432.  
  433. if (doorAreaRange.X >= 0 && doorAreaRange.Y <= nSize2.X) //允许提交
  434. {
  435. doorTool.Instance.SetDoorAreaRange(doorAreaRange.X, doorAreaRange.Y);
  436. if (doorTool.Instance.DoorAreaInfo != null)
  437. {
  438. doorTool.Instance.DoorAreaInfo.Start = doorAreaRange.X;
  439. doorTool.Instance.DoorAreaInfo.End = doorAreaRange.Y;
  440. }
  441. }
  442. else //如果超出区域, 则删除
  443. {
  444. RemoveDoorTool(doorTool);
  445. i--;
  446. }
  447. }
  448. else if (direction == DoorDirection.S)
  449. {
  450. var hOffset = (int)(sPos2.X - sPos1.X);
  451. doorAreaRange.X -= hOffset;
  452. doorAreaRange.Y -= hOffset;
  453.  
  454. if (doorAreaRange.X >= 0 && doorAreaRange.Y <= sSize2.X) //允许提交
  455. {
  456. doorTool.Instance.SetDoorAreaRange(doorAreaRange.X, doorAreaRange.Y);
  457. if (doorTool.Instance.DoorAreaInfo != null)
  458. {
  459. doorTool.Instance.DoorAreaInfo.Start = doorAreaRange.X;
  460. doorTool.Instance.DoorAreaInfo.End = doorAreaRange.Y;
  461. }
  462. }
  463. else //如果超出区域, 则删除
  464. {
  465. RemoveDoorTool(doorTool);
  466. i--;
  467. }
  468. }
  469. else if (direction == DoorDirection.E)
  470. {
  471. var vOffset = (int)(ePos2.Y - ePos1.Y);
  472. doorAreaRange.X -= vOffset;
  473. doorAreaRange.Y -= vOffset;
  474.  
  475. if (doorAreaRange.X >= 0 && doorAreaRange.Y <= eSize2.X) //允许提交
  476. {
  477. doorTool.Instance.SetDoorAreaRange(doorAreaRange.X, doorAreaRange.Y);
  478. if (doorTool.Instance.DoorAreaInfo != null)
  479. {
  480. doorTool.Instance.DoorAreaInfo.Start = doorAreaRange.X;
  481. doorTool.Instance.DoorAreaInfo.End = doorAreaRange.Y;
  482. }
  483. }
  484. else //如果超出区域, 则删除
  485. {
  486. RemoveDoorTool(doorTool);
  487. i--;
  488. }
  489. }
  490. else if (direction == DoorDirection.W)
  491. {
  492. var vOffset = (int)(wPos2.Y - wPos1.Y);
  493. doorAreaRange.X -= vOffset;
  494. doorAreaRange.Y -= vOffset;
  495.  
  496. if (doorAreaRange.X >= 0 && doorAreaRange.Y <= wSize2.X) //允许提交
  497. {
  498. doorTool.Instance.SetDoorAreaRange(doorAreaRange.X, doorAreaRange.Y);
  499. if (doorTool.Instance.DoorAreaInfo != null)
  500. {
  501. doorTool.Instance.DoorAreaInfo.Start = doorAreaRange.X;
  502. doorTool.Instance.DoorAreaInfo.End = doorAreaRange.Y;
  503. }
  504. }
  505. else //如果超出区域, 则删除
  506. {
  507. RemoveDoorTool(doorTool);
  508. i--;
  509. }
  510. }
  511. }
  512. }
  513. private DoorToolTemplate CreateDoorToolInstance(DoorHoverArea doorHoverArea)
  514. {
  515. var doorTool = S_DoorToolTemplate.Clone();
  516. S_ToolRoot.Instance.AddChild(doorTool.Instance);
  517. doorTool.Instance.SetDoorDragAreaNode(doorTool);
  518. doorTool.L_StartBtn.Instance.SetMapEditorToolsPanel(this);
  519. doorTool.L_EndBtn.Instance.SetMapEditorToolsPanel(this);
  520. doorTool.Instance.SetDoorHoverArea(doorHoverArea);
  521. _doorTools.Add(doorTool);
  522. return doorTool;
  523. }
  524. }