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. _eventFactory = EventManager.CreateEventFactory();
  90. _eventFactory.AddEventListener(EventEnum.OnSelectWave, OnSelectWaveTool);
  91. _eventFactory.AddEventListener(EventEnum.OnCreateMark, OnCreateMarkTool);
  92. _eventFactory.AddEventListener(EventEnum.OnSelectMark, OnSelectMarkTool);
  93. _eventFactory.AddEventListener(EventEnum.OnDeleteMark, OnDeleteMarkTool);
  94. _eventFactory.AddEventListener(EventEnum.OnEditMark, OnEditMarkTool);
  95. _eventFactory.AddEventListener(EventEnum.OnSelectPreinstall, RefreshMark);
  96. }
  97.  
  98. public override void OnDestroyUi()
  99. {
  100. _eventFactory.RemoveAllEventListener();
  101. _eventFactory = null;
  102. S_DoorToolTemplate.Instance.QueueFree();
  103. _toolGrid.Destroy();
  104. }
  105.  
  106. public override void Process(float delta)
  107. {
  108. S_HoverPreviewRoot.Instance.Visible = ActiveHoverArea != null && !DoorHoverArea.IsDrag;
  109. if (EditorMap.Instance.MouseType == EditorTileMap.MouseButtonType.Edit)
  110. {
  111. S_ToolRoot.Instance.Modulate = new Color(1, 1, 1, 1);
  112. }
  113. else
  114. {
  115. S_ToolRoot.Instance.Modulate = new Color(1, 1, 1, 0.4f);
  116. }
  117.  
  118. IsOpenPopUps = UiManager.GetUiInstanceCount(UiManager.UiName.EditorWindow) > 0;
  119. }
  120.  
  121. //刷新标记
  122. private void RefreshMark(object arg)
  123. {
  124. ActiveMark = null;
  125. //删除之前的数据
  126. foreach (var keyValuePair in _currMarkToolsMap)
  127. {
  128. keyValuePair.Value.QueueFree();
  129. }
  130. _currMarkToolsMap.Clear();
  131. //添加新的数据
  132. var selectPreinstall = EditorManager.SelectPreinstall;
  133. if (selectPreinstall != null)
  134. {
  135. foreach (var markInfos in selectPreinstall.WaveList)
  136. {
  137. foreach (var markInfo in markInfos)
  138. {
  139. CreateMarkTool(markInfo);
  140. }
  141. }
  142. }
  143. }
  144.  
  145. //选中波数
  146. private void OnSelectWaveTool(object arg)
  147. {
  148. //选中编辑工具
  149. if (_toolGrid.SelectIndex != _editToolIndex)
  150. {
  151. _toolGrid.Click(_editToolIndex);
  152. }
  153. var selectIndex = EditorManager.SelectWaveIndex;
  154. var waveList = EditorManager.SelectPreinstall.WaveList;
  155. for (var i = 0; i < waveList.Count; i++)
  156. {
  157. var wave = waveList[i];
  158. foreach (var markInfo in wave)
  159. {
  160. if (_currMarkToolsMap.TryGetValue(markInfo, out var markTemplate))
  161. {
  162. if (i == selectIndex) //选中当前波数, 透明度改为1
  163. {
  164. markTemplate.Instance.SetModulateAlpha(1f);
  165. }
  166. else //未选中当前波数, 透明度改为0.6
  167. {
  168. markTemplate.Instance.SetModulateAlpha(0.45f);
  169. }
  170. }
  171. }
  172. }
  173. }
  174. //创建标记
  175. private void OnCreateMarkTool(object arg)
  176. {
  177. var markInfo = (MarkInfo)arg;
  178. CreateMarkTool(markInfo);
  179. }
  180.  
  181. //创建标记
  182. private void CreateMarkTool(MarkInfo markInfo)
  183. {
  184. var cloneAndPut = S_MarkTemplate.CloneAndPut();
  185. _currMarkToolsMap.Add(markInfo, cloneAndPut);
  186. cloneAndPut.Instance.Visible = true;
  187. cloneAndPut.Instance.InitData(markInfo);
  188. }
  189.  
  190. //选中标记
  191. private void OnSelectMarkTool(object arg)
  192. {
  193. //选中编辑工具
  194. if (_toolGrid.SelectIndex != _editToolIndex)
  195. {
  196. _toolGrid.Click(_editToolIndex);
  197. }
  198. if (arg is MarkInfo markInfo)
  199. {
  200. if (ActiveMark == null || markInfo != ActiveMark.MarkInfo)
  201. {
  202. if (_currMarkToolsMap.TryGetValue(markInfo, out var markTemplate))
  203. {
  204. SetActiveMark(markTemplate.Instance);
  205. }
  206. }
  207. }
  208. else if (arg == null && ActiveMark != null)
  209. {
  210. SetActiveMark(null);
  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. EditorManager.SetSelectMark(markTool.MarkInfo);
  307. }
  308. else
  309. {
  310. EditorManager.SetSelectMark(null);
  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. EventManager.EmitEvent(EventEnum.OnEditorDirty);
  362. }
  363.  
  364. /// <summary>
  365. /// 设置工具根节点的大小和缩放
  366. /// </summary>
  367. /// <param name="pos">坐标</param>
  368. /// <param name="scale">缩放</param>
  369. public void SetToolTransform(Vector2 pos, Vector2 scale)
  370. {
  371. S_ToolRoot.Instance.Position = pos;
  372. S_ToolRoot.Instance.Scale = scale;
  373. }
  374.  
  375. /// <summary>
  376. /// 设置鼠标悬停区域位置和大小
  377. /// </summary>
  378. /// <param name="position">房间起始点, 单位: 格</param>
  379. /// <param name="size">房间大小, 单位: 格</param>
  380. public void SetDoorHoverToolTransform(Vector2I position, Vector2I size)
  381. {
  382. position *= GameConfig.TileCellSize;
  383. size *= GameConfig.TileCellSize;
  384.  
  385. var nPos1 = S_N_HoverRoot.Instance.Position;
  386. var ePos1 = S_E_HoverRoot.Instance.Position;
  387. var sPos1 = S_S_HoverRoot.Instance.Position;
  388. var wPos1 = S_W_HoverRoot.Instance.Position;
  389. var nPos2 = position + GameConfig.TileCellSizeVector2I;
  390. var ePos2 = new Vector2(position.X + size.X - GameConfig.TileCellSize, position.Y + GameConfig.TileCellSize);
  391. var sPos2 = new Vector2(position.X + GameConfig.TileCellSize, position.Y + size.Y - GameConfig.TileCellSize);
  392. var wPos2 = position + GameConfig.TileCellSizeVector2I;
  393.  
  394. var nSize2 = new Vector2(size.X - GameConfig.TileCellSize * 2, S_N_HoverArea.Instance.Size.Y);
  395. var eSize2 = new Vector2(size.Y - GameConfig.TileCellSize * 2, S_E_HoverArea.Instance.Size.Y);
  396. var sSize2 = new Vector2(size.X - GameConfig.TileCellSize * 2, S_S_HoverArea.Instance.Size.Y);
  397. var wSize2 = new Vector2(size.Y - GameConfig.TileCellSize * 2, S_W_HoverArea.Instance.Size.Y);
  398. S_N_HoverRoot.Instance.Position = nPos2;
  399. S_E_HoverRoot.Instance.Position = ePos2;
  400. S_S_HoverRoot.Instance.Position = sPos2;
  401. S_W_HoverRoot.Instance.Position = wPos2;
  402. S_N_HoverArea.Instance.Size = nSize2;
  403. S_E_HoverArea.Instance.Size = eSize2;
  404. S_S_HoverArea.Instance.Size = sSize2;
  405. S_W_HoverArea.Instance.Size = wSize2;
  406. //调整门区域
  407. for (var i = 0; i < _doorTools.Count; i++)
  408. {
  409. var doorTool = _doorTools[i];
  410. var direction = doorTool.Instance.Direction;
  411. var areaRoot = GetDoorHoverAreaRoot(direction);
  412. var doorAreaRange = doorTool.Instance.GetDoorAreaRange();
  413. doorTool.Instance.SetDoorAreaPosition(areaRoot.Position);
  414.  
  415. if (direction == DoorDirection.N)
  416. {
  417. var hOffset = (int)(nPos2.X - nPos1.X);
  418. doorAreaRange.X -= hOffset;
  419. doorAreaRange.Y -= hOffset;
  420.  
  421. if (doorAreaRange.X >= 0 && doorAreaRange.Y <= nSize2.X) //允许提交
  422. {
  423. doorTool.Instance.SetDoorAreaRange(doorAreaRange.X, doorAreaRange.Y);
  424. if (doorTool.Instance.DoorAreaInfo != null)
  425. {
  426. doorTool.Instance.DoorAreaInfo.Start = doorAreaRange.X;
  427. doorTool.Instance.DoorAreaInfo.End = doorAreaRange.Y;
  428. }
  429. }
  430. else //如果超出区域, 则删除
  431. {
  432. RemoveDoorTool(doorTool);
  433. i--;
  434. }
  435. }
  436. else if (direction == DoorDirection.S)
  437. {
  438. var hOffset = (int)(sPos2.X - sPos1.X);
  439. doorAreaRange.X -= hOffset;
  440. doorAreaRange.Y -= hOffset;
  441.  
  442. if (doorAreaRange.X >= 0 && doorAreaRange.Y <= sSize2.X) //允许提交
  443. {
  444. doorTool.Instance.SetDoorAreaRange(doorAreaRange.X, doorAreaRange.Y);
  445. if (doorTool.Instance.DoorAreaInfo != null)
  446. {
  447. doorTool.Instance.DoorAreaInfo.Start = doorAreaRange.X;
  448. doorTool.Instance.DoorAreaInfo.End = doorAreaRange.Y;
  449. }
  450. }
  451. else //如果超出区域, 则删除
  452. {
  453. RemoveDoorTool(doorTool);
  454. i--;
  455. }
  456. }
  457. else if (direction == DoorDirection.E)
  458. {
  459. var vOffset = (int)(ePos2.Y - ePos1.Y);
  460. doorAreaRange.X -= vOffset;
  461. doorAreaRange.Y -= vOffset;
  462.  
  463. if (doorAreaRange.X >= 0 && doorAreaRange.Y <= eSize2.X) //允许提交
  464. {
  465. doorTool.Instance.SetDoorAreaRange(doorAreaRange.X, doorAreaRange.Y);
  466. if (doorTool.Instance.DoorAreaInfo != null)
  467. {
  468. doorTool.Instance.DoorAreaInfo.Start = doorAreaRange.X;
  469. doorTool.Instance.DoorAreaInfo.End = doorAreaRange.Y;
  470. }
  471. }
  472. else //如果超出区域, 则删除
  473. {
  474. RemoveDoorTool(doorTool);
  475. i--;
  476. }
  477. }
  478. else if (direction == DoorDirection.W)
  479. {
  480. var vOffset = (int)(wPos2.Y - wPos1.Y);
  481. doorAreaRange.X -= vOffset;
  482. doorAreaRange.Y -= vOffset;
  483.  
  484. if (doorAreaRange.X >= 0 && doorAreaRange.Y <= wSize2.X) //允许提交
  485. {
  486. doorTool.Instance.SetDoorAreaRange(doorAreaRange.X, doorAreaRange.Y);
  487. if (doorTool.Instance.DoorAreaInfo != null)
  488. {
  489. doorTool.Instance.DoorAreaInfo.Start = doorAreaRange.X;
  490. doorTool.Instance.DoorAreaInfo.End = doorAreaRange.Y;
  491. }
  492. }
  493. else //如果超出区域, 则删除
  494. {
  495. RemoveDoorTool(doorTool);
  496. i--;
  497. }
  498. }
  499. }
  500. }
  501. private DoorToolTemplate CreateDoorToolInstance(DoorHoverArea doorHoverArea)
  502. {
  503. var doorTool = S_DoorToolTemplate.Clone();
  504. S_ToolRoot.Instance.AddChild(doorTool.Instance);
  505. doorTool.Instance.SetDoorDragAreaNode(doorTool);
  506. doorTool.L_StartBtn.Instance.SetMapEditorToolsPanel(this);
  507. doorTool.L_EndBtn.Instance.SetMapEditorToolsPanel(this);
  508. doorTool.Instance.SetDoorHoverArea(doorHoverArea);
  509. _doorTools.Add(doorTool);
  510. return doorTool;
  511. }
  512. }