Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / ui / mapEditorTools / MapEditorToolsPanel.cs
  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. EditorMap = ((MapEditorPanel)ParentUi).S_TileMap;
  53. S_N_HoverArea.Instance.Init(this, DoorDirection.N);
  54. S_S_HoverArea.Instance.Init(this, DoorDirection.S);
  55. S_W_HoverArea.Instance.Init(this, DoorDirection.W);
  56. S_E_HoverArea.Instance.Init(this, DoorDirection.E);
  57. S_ToolRoot.Instance.RemoveChild(S_DoorToolTemplate.Instance);
  58. S_MarkTemplate.Instance.Visible = false;
  59.  
  60. _toolGrid = new UiGrid<ToolButton, ToolBtnData>(S_ToolButton, typeof(ToolButtonCell));
  61. _toolGrid.SetColumns(10);
  62. //拖拽按钮
  63. _toolGrid.Add(new ToolBtnData(true, ResourcePath.resource_sprite_ui_commonIcon_DragTool_png, () =>
  64. {
  65. EventManager.EmitEvent(EventEnum.OnSelectDragTool);
  66. }));
  67. //画笔按钮
  68. _toolGrid.Add(new ToolBtnData(true, ResourcePath.resource_sprite_ui_commonIcon_PenTool_png, () =>
  69. {
  70. EventManager.EmitEvent(EventEnum.OnSelectPenTool);
  71. }));
  72. //绘制区域按钮
  73. _toolGrid.Add(new ToolBtnData(true, ResourcePath.resource_sprite_ui_commonIcon_AreaTool_png, () =>
  74. {
  75. EventManager.EmitEvent(EventEnum.OnSelectRectTool);
  76. }));
  77. //编辑攻击按钮
  78. _toolGrid.Add(new ToolBtnData(true, ResourcePath.resource_sprite_ui_commonIcon_DoorTool_png, () =>
  79. {
  80. EventManager.EmitEvent(EventEnum.OnSelectEditTool);
  81. }));
  82. _editToolIndex = _toolGrid.Count - 1;
  83. //聚焦按钮
  84. _toolGrid.Add(new ToolBtnData(false, ResourcePath.resource_sprite_ui_commonIcon_CenterTool_png, () =>
  85. {
  86. EventManager.EmitEvent(EventEnum.OnClickCenterTool);
  87. }));
  88. _toolGrid.SelectIndex = 1;
  89. }
  90.  
  91. public override void OnShowUi()
  92. {
  93. _eventFactory = EventManager.CreateEventFactory();
  94. _eventFactory.AddEventListener(EventEnum.OnSelectWave, OnSelectWaveTool);
  95. _eventFactory.AddEventListener(EventEnum.OnCreateMark, OnCreateMarkTool);
  96. _eventFactory.AddEventListener(EventEnum.OnSelectMark, OnSelectMarkTool);
  97. _eventFactory.AddEventListener(EventEnum.OnDeleteMark, OnDeleteMarkTool);
  98. _eventFactory.AddEventListener(EventEnum.OnEditMark, OnEditMarkTool);
  99. _eventFactory.AddEventListener(EventEnum.OnSelectPreinstall, RefreshMark);
  100. }
  101.  
  102. public override void OnHideUi()
  103. {
  104. _eventFactory.RemoveAllEventListener();
  105. _eventFactory = null;
  106. }
  107.  
  108. public override void OnDestroyUi()
  109. {
  110. S_DoorToolTemplate.Instance.QueueFree();
  111. _toolGrid.Destroy();
  112. }
  113.  
  114. public override void Process(float delta)
  115. {
  116. S_HoverPreviewRoot.Instance.Visible = ActiveHoverArea != null && !DoorHoverArea.IsDrag;
  117. if (EditorMap.Instance.MouseType == EditorTileMap.MouseButtonType.Edit)
  118. {
  119. S_ToolRoot.Instance.Modulate = new Color(1, 1, 1, 1);
  120. }
  121. else
  122. {
  123. S_ToolRoot.Instance.Modulate = new Color(1, 1, 1, 0.4f);
  124. }
  125.  
  126. IsOpenPopUps = UiManager.GetUiInstanceCount(UiManager.UiName.EditorWindow) > 0;
  127. }
  128.  
  129. //刷新标记
  130. private void RefreshMark(object arg)
  131. {
  132. ActiveMark = null;
  133. //删除之前的数据
  134. foreach (var keyValuePair in _currMarkToolsMap)
  135. {
  136. keyValuePair.Value.QueueFree();
  137. }
  138. _currMarkToolsMap.Clear();
  139. //添加新的数据
  140. var selectPreinstall = EditorMap.Instance.SelectPreinstall;
  141. if (selectPreinstall != null)
  142. {
  143. foreach (var markInfos in selectPreinstall.WaveList)
  144. {
  145. foreach (var markInfo in markInfos)
  146. {
  147. CreateMarkTool(markInfo);
  148. }
  149. }
  150. }
  151. }
  152.  
  153. //选中波数
  154. private void OnSelectWaveTool(object arg)
  155. {
  156. var selectIndex = (int)arg;
  157. var waveList = EditorMap.Instance.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. if (arg is MarkInfo markInfo)
  197. {
  198. if (ActiveMark == null || markInfo != ActiveMark.MarkInfo)
  199. {
  200. if (_currMarkToolsMap.TryGetValue(markInfo, out var markTemplate))
  201. {
  202. SetActiveMark(markTemplate.Instance);
  203. }
  204. }
  205.  
  206. //选中编辑工具
  207. if (_toolGrid.SelectIndex != _editToolIndex)
  208. {
  209. _toolGrid.Click(_editToolIndex);
  210. }
  211. }
  212. }
  213.  
  214. //删除标记
  215. private void OnDeleteMarkTool(object arg)
  216. {
  217. if (arg is MarkInfo markInfo)
  218. {
  219. if (_currMarkToolsMap.TryGetValue(markInfo, out var markTemplate))
  220. {
  221. if (ActiveMark == markTemplate.Instance)
  222. {
  223. SetActiveMark(null);
  224. }
  225. markTemplate.QueueFree();
  226. _currMarkToolsMap.Remove(markInfo);
  227. }
  228. }
  229. }
  230.  
  231. //编辑标记
  232. private void OnEditMarkTool(object arg)
  233. {
  234. if (arg is MarkInfo markInfo)
  235. {
  236. if (_currMarkToolsMap.TryGetValue(markInfo, out var markTemplate))
  237. {
  238. //更新坐标
  239. markTemplate.Instance.Position = markInfo.Position.AsVector2();
  240. }
  241. }
  242. }
  243. /// <summary>
  244. /// 获取门区域对象
  245. /// </summary>
  246. public DoorHoverArea GetDoorHoverArea(DoorDirection direction)
  247. {
  248. switch (direction)
  249. {
  250. case DoorDirection.E: return S_E_HoverArea.Instance;
  251. case DoorDirection.N: return S_N_HoverArea.Instance;
  252. case DoorDirection.W: return S_W_HoverArea.Instance;
  253. case DoorDirection.S: return S_S_HoverArea.Instance;
  254. }
  255. return null;
  256. }
  257. /// <summary>
  258. /// 获取门区域根节点
  259. /// </summary>
  260. public Control GetDoorHoverAreaRoot(DoorDirection direction)
  261. {
  262. switch (direction)
  263. {
  264. case DoorDirection.E: return S_E_HoverRoot.Instance;
  265. case DoorDirection.N: return S_N_HoverRoot.Instance;
  266. case DoorDirection.W: return S_W_HoverRoot.Instance;
  267. case DoorDirection.S: return S_S_HoverRoot.Instance;
  268. }
  269. return null;
  270. }
  271.  
  272. /// <summary>
  273. /// 设置活动的鼠标悬停的区域
  274. /// </summary>
  275. public void SetActiveHoverArea(DoorHoverArea hoverArea)
  276. {
  277. ActiveHoverArea = hoverArea;
  278. if (hoverArea != null)
  279. {
  280. S_HoverPreviewRoot.Instance.Reparent(hoverArea.GetParent(), false);
  281. }
  282. else
  283. {
  284. S_HoverPreviewRoot.Instance.Reparent(S_ToolRoot.Instance, false);
  285. }
  286. }
  287.  
  288. /// <summary>
  289. /// 设置当前活动的标记
  290. /// </summary>
  291. public void SetActiveMark(MarkTool markTool)
  292. {
  293. if (ActiveMark == markTool)
  294. {
  295. return;
  296. }
  297.  
  298. if (ActiveMark != null) //取消选中上一个
  299. {
  300. ActiveMark.OnUnSelect();
  301. }
  302. ActiveMark = markTool;
  303. if (markTool != null) //选中当前
  304. {
  305. ActiveMark.OnSelect();
  306. EventManager.EmitEvent(EventEnum.OnSelectMark, markTool.MarkInfo);
  307. }
  308. else
  309. {
  310. EventManager.EmitEvent(EventEnum.OnSelectMark);
  311. }
  312. }
  313.  
  314. /// <summary>
  315. /// 创建门区域设置工具
  316. /// </summary>
  317. /// <param name="doorAreaInfo">门区域数据</param>
  318. public DoorToolTemplate CreateDoorTool(DoorAreaInfo doorAreaInfo)
  319. {
  320. var doorHoverArea = GetDoorHoverArea(doorAreaInfo.Direction);
  321. var inst = CreateDoorToolInstance(doorHoverArea);
  322. inst.Instance.DoorAreaInfo = doorAreaInfo;
  323. inst.Instance.SetDoorAreaPosition(GetDoorHoverAreaRoot(doorAreaInfo.Direction).Position);
  324. inst.Instance.SetDoorAreaRange(doorAreaInfo.Start, doorAreaInfo.End);
  325. return inst;
  326. }
  327.  
  328. /// <summary>
  329. /// 创建拖拽状态下的门区域工具, 用于创建门区域
  330. /// </summary>
  331. /// <param name="doorHoverArea">悬停区域</param>
  332. /// <param name="start">起始位置, 单位: 像素</param>
  333. /// <param name="onSubmit">成功提交时回调, 参数1为方向, 参数2为起始点, 参数3为大小</param>
  334. /// <param name="onCancel">取消提交时调用</param>
  335. public DoorToolTemplate CreateDragDoorTool(DoorHoverArea doorHoverArea, int start,
  336. Action<DoorDirection, int, int> onSubmit, Action onCancel)
  337. {
  338. var inst = CreateDoorToolInstance(doorHoverArea);
  339. inst.Instance.SetDoorAreaPosition(GetDoorHoverAreaRoot(doorHoverArea.Direction).Position);
  340. inst.Instance.SetDoorAreaRange(start, start);
  341. inst.Instance.MakeDragMode(onSubmit, () =>
  342. {
  343. RemoveDoorTool(inst);
  344. onCancel();
  345. });
  346. return inst;
  347. }
  348.  
  349. /// <summary>
  350. /// 移除门区域设置工具
  351. /// </summary>
  352. public void RemoveDoorTool(DoorToolTemplate toolInstance)
  353. {
  354. _doorTools.Remove(toolInstance);
  355. if (toolInstance.Instance.DoorAreaInfo != null)
  356. {
  357. EditorMap.Instance.RemoveDoorArea(toolInstance.Instance.DoorAreaInfo);
  358. }
  359. toolInstance.Instance.QueueFree();
  360. }
  361.  
  362. /// <summary>
  363. /// 设置工具根节点的大小和缩放
  364. /// </summary>
  365. /// <param name="pos">坐标</param>
  366. /// <param name="scale">缩放</param>
  367. public void SetToolTransform(Vector2 pos, Vector2 scale)
  368. {
  369. S_ToolRoot.Instance.Position = pos;
  370. S_ToolRoot.Instance.Scale = scale;
  371. }
  372.  
  373. /// <summary>
  374. /// 设置鼠标悬停区域位置和大小
  375. /// </summary>
  376. /// <param name="position">房间起始点, 单位: 格</param>
  377. /// <param name="size">房间大小, 单位: 格</param>
  378. public void SetDoorHoverToolTransform(Vector2I position, Vector2I size)
  379. {
  380. position *= GameConfig.TileCellSize;
  381. size *= GameConfig.TileCellSize;
  382.  
  383. var nPos1 = S_N_HoverRoot.Instance.Position;
  384. var ePos1 = S_E_HoverRoot.Instance.Position;
  385. var sPos1 = S_S_HoverRoot.Instance.Position;
  386. var wPos1 = S_W_HoverRoot.Instance.Position;
  387. var nPos2 = position + GameConfig.TileCellSizeVector2I;
  388. var ePos2 = new Vector2(position.X + size.X - GameConfig.TileCellSize, position.Y + GameConfig.TileCellSize);
  389. var sPos2 = new Vector2(position.X + GameConfig.TileCellSize, position.Y + size.Y - GameConfig.TileCellSize);
  390. var wPos2 = position + GameConfig.TileCellSizeVector2I;
  391.  
  392. var nSize2 = new Vector2(size.X - GameConfig.TileCellSize * 2, S_N_HoverArea.Instance.Size.Y);
  393. var eSize2 = new Vector2(size.Y - GameConfig.TileCellSize * 2, S_E_HoverArea.Instance.Size.Y);
  394. var sSize2 = new Vector2(size.X - GameConfig.TileCellSize * 2, S_S_HoverArea.Instance.Size.Y);
  395. var wSize2 = new Vector2(size.Y - GameConfig.TileCellSize * 2, S_W_HoverArea.Instance.Size.Y);
  396. S_N_HoverRoot.Instance.Position = nPos2;
  397. S_E_HoverRoot.Instance.Position = ePos2;
  398. S_S_HoverRoot.Instance.Position = sPos2;
  399. S_W_HoverRoot.Instance.Position = wPos2;
  400. S_N_HoverArea.Instance.Size = nSize2;
  401. S_E_HoverArea.Instance.Size = eSize2;
  402. S_S_HoverArea.Instance.Size = sSize2;
  403. S_W_HoverArea.Instance.Size = wSize2;
  404. //调整门区域
  405. for (var i = 0; i < _doorTools.Count; i++)
  406. {
  407. var doorTool = _doorTools[i];
  408. var direction = doorTool.Instance.Direction;
  409. var areaRoot = GetDoorHoverAreaRoot(direction);
  410. var doorAreaRange = doorTool.Instance.GetDoorAreaRange();
  411. doorTool.Instance.SetDoorAreaPosition(areaRoot.Position);
  412.  
  413. if (direction == DoorDirection.N)
  414. {
  415. var hOffset = (int)(nPos2.X - nPos1.X);
  416. doorAreaRange.X -= hOffset;
  417. doorAreaRange.Y -= hOffset;
  418.  
  419. if (doorAreaRange.X >= 0 && doorAreaRange.Y <= nSize2.X) //允许提交
  420. {
  421. doorTool.Instance.SetDoorAreaRange(doorAreaRange.X, doorAreaRange.Y);
  422. if (doorTool.Instance.DoorAreaInfo != null)
  423. {
  424. doorTool.Instance.DoorAreaInfo.Start = doorAreaRange.X;
  425. doorTool.Instance.DoorAreaInfo.End = doorAreaRange.Y;
  426. }
  427. }
  428. else //如果超出区域, 则删除
  429. {
  430. RemoveDoorTool(doorTool);
  431. i--;
  432. }
  433. }
  434. else if (direction == DoorDirection.S)
  435. {
  436. var hOffset = (int)(sPos2.X - sPos1.X);
  437. doorAreaRange.X -= hOffset;
  438. doorAreaRange.Y -= hOffset;
  439.  
  440. if (doorAreaRange.X >= 0 && doorAreaRange.Y <= sSize2.X) //允许提交
  441. {
  442. doorTool.Instance.SetDoorAreaRange(doorAreaRange.X, doorAreaRange.Y);
  443. if (doorTool.Instance.DoorAreaInfo != null)
  444. {
  445. doorTool.Instance.DoorAreaInfo.Start = doorAreaRange.X;
  446. doorTool.Instance.DoorAreaInfo.End = doorAreaRange.Y;
  447. }
  448. }
  449. else //如果超出区域, 则删除
  450. {
  451. RemoveDoorTool(doorTool);
  452. i--;
  453. }
  454. }
  455. else if (direction == DoorDirection.E)
  456. {
  457. var vOffset = (int)(ePos2.Y - ePos1.Y);
  458. doorAreaRange.X -= vOffset;
  459. doorAreaRange.Y -= vOffset;
  460.  
  461. if (doorAreaRange.X >= 0 && doorAreaRange.Y <= eSize2.X) //允许提交
  462. {
  463. doorTool.Instance.SetDoorAreaRange(doorAreaRange.X, doorAreaRange.Y);
  464. if (doorTool.Instance.DoorAreaInfo != null)
  465. {
  466. doorTool.Instance.DoorAreaInfo.Start = doorAreaRange.X;
  467. doorTool.Instance.DoorAreaInfo.End = doorAreaRange.Y;
  468. }
  469. }
  470. else //如果超出区域, 则删除
  471. {
  472. RemoveDoorTool(doorTool);
  473. i--;
  474. }
  475. }
  476. else if (direction == DoorDirection.W)
  477. {
  478. var vOffset = (int)(wPos2.Y - wPos1.Y);
  479. doorAreaRange.X -= vOffset;
  480. doorAreaRange.Y -= vOffset;
  481.  
  482. if (doorAreaRange.X >= 0 && doorAreaRange.Y <= wSize2.X) //允许提交
  483. {
  484. doorTool.Instance.SetDoorAreaRange(doorAreaRange.X, doorAreaRange.Y);
  485. if (doorTool.Instance.DoorAreaInfo != null)
  486. {
  487. doorTool.Instance.DoorAreaInfo.Start = doorAreaRange.X;
  488. doorTool.Instance.DoorAreaInfo.End = doorAreaRange.Y;
  489. }
  490. }
  491. else //如果超出区域, 则删除
  492. {
  493. RemoveDoorTool(doorTool);
  494. i--;
  495. }
  496. }
  497. }
  498. }
  499. private DoorToolTemplate CreateDoorToolInstance(DoorHoverArea doorHoverArea)
  500. {
  501. var doorTool = S_DoorToolTemplate.Clone();
  502. S_ToolRoot.Instance.AddChild(doorTool.Instance);
  503. doorTool.Instance.SetDoorDragAreaNode(doorTool);
  504. doorTool.L_StartBtn.Instance.SetMapEditorToolsPanel(this);
  505. doorTool.L_EndBtn.Instance.SetMapEditorToolsPanel(this);
  506. doorTool.Instance.SetDoorHoverArea(doorHoverArea);
  507. _doorTools.Add(doorTool);
  508. return doorTool;
  509. }
  510. }