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.OnSetMarkVisible, OnSetMarkVisible);
  95. _eventFactory.AddEventListener(EventEnum.OnEditMark, OnEditMarkTool);
  96. _eventFactory.AddEventListener(EventEnum.OnSelectPreinstall, RefreshMark);
  97. }
  98.  
  99. public override void OnDestroyUi()
  100. {
  101. _eventFactory.RemoveAllEventListener();
  102. _eventFactory = null;
  103. S_DoorToolTemplate.Instance.QueueFree();
  104. _toolGrid.Destroy();
  105. }
  106.  
  107. public override void Process(float delta)
  108. {
  109. S_HoverPreviewRoot.Instance.Visible = ActiveHoverArea != null && !DoorHoverArea.IsDrag;
  110. if (EditorMap.Instance.MouseType == EditorTileMap.MouseButtonType.Edit)
  111. {
  112. S_ToolRoot.Instance.Modulate = new Color(1, 1, 1, 1);
  113. }
  114. else
  115. {
  116. S_ToolRoot.Instance.Modulate = new Color(1, 1, 1, 0.4f);
  117. }
  118.  
  119. IsOpenPopUps = UiManager.GetUiInstanceCount(UiManager.UiNames.EditorWindow) > 0;
  120. }
  121.  
  122. //刷新标记
  123. private void RefreshMark(object arg)
  124. {
  125. ActiveMark = null;
  126. //删除之前的数据
  127. foreach (var keyValuePair in _currMarkToolsMap)
  128. {
  129. keyValuePair.Value.QueueFree();
  130. }
  131. _currMarkToolsMap.Clear();
  132. //添加新的数据
  133. var selectPreinstall = EditorManager.SelectPreinstall;
  134. if (selectPreinstall != null)
  135. {
  136. foreach (var markInfos in selectPreinstall.WaveList)
  137. {
  138. foreach (var markInfo in markInfos)
  139. {
  140. CreateMarkTool(markInfo);
  141. }
  142. }
  143. }
  144. }
  145.  
  146. //选中波数
  147. private void OnSelectWaveTool(object arg)
  148. {
  149. //选中编辑工具
  150. if (_toolGrid.SelectIndex != _editToolIndex)
  151. {
  152. _toolGrid.Click(_editToolIndex);
  153. }
  154. var selectIndex = EditorManager.SelectWaveIndex;
  155. var waveList = EditorManager.SelectPreinstall.WaveList;
  156. for (var i = 0; i < waveList.Count; i++)
  157. {
  158. var wave = waveList[i];
  159. foreach (var markInfo in wave)
  160. {
  161. if (_currMarkToolsMap.TryGetValue(markInfo, out var markTemplate))
  162. {
  163. if (i == selectIndex) //选中当前波数, 透明度改为1
  164. {
  165. markTemplate.Instance.SetModulateAlpha(1f);
  166. }
  167. else //未选中当前波数, 透明度改为0.6
  168. {
  169. markTemplate.Instance.SetModulateAlpha(0.45f);
  170. }
  171. }
  172. }
  173. }
  174. }
  175. //创建标记
  176. private void OnCreateMarkTool(object arg)
  177. {
  178. var markInfo = (MarkInfo)arg;
  179. CreateMarkTool(markInfo);
  180. }
  181.  
  182. //创建标记
  183. private void CreateMarkTool(MarkInfo markInfo)
  184. {
  185. var cloneAndPut = S_MarkTemplate.CloneAndPut();
  186. _currMarkToolsMap.Add(markInfo, cloneAndPut);
  187. cloneAndPut.Instance.Visible = true;
  188. cloneAndPut.Instance.InitData(markInfo);
  189. }
  190.  
  191. //选中标记
  192. private void OnSelectMarkTool(object arg)
  193. {
  194. //选中编辑工具
  195. if (_toolGrid.SelectIndex != _editToolIndex)
  196. {
  197. _toolGrid.Click(_editToolIndex);
  198. }
  199. if (arg is MarkInfo markInfo)
  200. {
  201. if (ActiveMark == null || markInfo != ActiveMark.MarkInfo)
  202. {
  203. if (_currMarkToolsMap.TryGetValue(markInfo, out var markTemplate))
  204. {
  205. SetActiveMark(markTemplate.Instance);
  206. }
  207. }
  208. }
  209. else if (arg == null && ActiveMark != null)
  210. {
  211. SetActiveMark(null);
  212. }
  213. }
  214.  
  215. //删除标记
  216. private void OnDeleteMarkTool(object arg)
  217. {
  218. if (arg is MarkInfo markInfo)
  219. {
  220. if (_currMarkToolsMap.TryGetValue(markInfo, out var markTemplate))
  221. {
  222. if (ActiveMark == markTemplate.Instance)
  223. {
  224. SetActiveMark(null);
  225. }
  226. markTemplate.QueueFree();
  227. _currMarkToolsMap.Remove(markInfo);
  228. }
  229. }
  230. }
  231.  
  232. //设置标记显示状态
  233. private void OnSetMarkVisible(object arg)
  234. {
  235. var data = (MarkInfoVisibleData)arg;
  236. if (_currMarkToolsMap.TryGetValue(data.MarkInfo, out var markTemplate))
  237. {
  238. markTemplate.Instance.Visible = data.Visible;
  239. }
  240. }
  241. //编辑标记
  242. private void OnEditMarkTool(object arg)
  243. {
  244. if (arg is MarkInfo markInfo)
  245. {
  246. if (_currMarkToolsMap.TryGetValue(markInfo, out var markTemplate))
  247. {
  248. //刷新数据
  249. markTemplate.Instance.RefreshData();
  250. }
  251. }
  252. }
  253. /// <summary>
  254. /// 获取门区域对象
  255. /// </summary>
  256. public DoorHoverArea GetDoorHoverArea(DoorDirection direction)
  257. {
  258. switch (direction)
  259. {
  260. case DoorDirection.E: return S_E_HoverArea.Instance;
  261. case DoorDirection.N: return S_N_HoverArea.Instance;
  262. case DoorDirection.W: return S_W_HoverArea.Instance;
  263. case DoorDirection.S: return S_S_HoverArea.Instance;
  264. }
  265. return null;
  266. }
  267. /// <summary>
  268. /// 获取门区域根节点
  269. /// </summary>
  270. public Control GetDoorHoverAreaRoot(DoorDirection direction)
  271. {
  272. switch (direction)
  273. {
  274. case DoorDirection.E: return S_E_HoverRoot.Instance;
  275. case DoorDirection.N: return S_N_HoverRoot.Instance;
  276. case DoorDirection.W: return S_W_HoverRoot.Instance;
  277. case DoorDirection.S: return S_S_HoverRoot.Instance;
  278. }
  279. return null;
  280. }
  281.  
  282. /// <summary>
  283. /// 设置活动的鼠标悬停的区域
  284. /// </summary>
  285. public void SetActiveHoverArea(DoorHoverArea hoverArea)
  286. {
  287. ActiveHoverArea = hoverArea;
  288. if (hoverArea != null)
  289. {
  290. S_HoverPreviewRoot.Instance.Reparent(hoverArea.GetParent(), false);
  291. }
  292. else
  293. {
  294. S_HoverPreviewRoot.Instance.Reparent(S_ToolRoot.Instance, false);
  295. }
  296. }
  297.  
  298. /// <summary>
  299. /// 设置当前活动的标记
  300. /// </summary>
  301. public void SetActiveMark(MarkTool markTool)
  302. {
  303. if (ActiveMark == markTool)
  304. {
  305. return;
  306. }
  307.  
  308. if (ActiveMark != null) //取消选中上一个
  309. {
  310. ActiveMark.OnUnSelect();
  311. }
  312. ActiveMark = markTool;
  313. if (markTool != null) //选中当前
  314. {
  315. ActiveMark.OnSelect();
  316. EditorManager.SetSelectMark(markTool.MarkInfo);
  317. }
  318. else
  319. {
  320. EditorManager.SetSelectMark(null);
  321. }
  322. }
  323.  
  324. /// <summary>
  325. /// 创建门区域设置工具
  326. /// </summary>
  327. /// <param name="doorAreaInfo">门区域数据</param>
  328. public DoorToolTemplate CreateDoorTool(DoorAreaInfo doorAreaInfo)
  329. {
  330. var doorHoverArea = GetDoorHoverArea(doorAreaInfo.Direction);
  331. var inst = CreateDoorToolInstance(doorHoverArea);
  332. inst.Instance.DoorAreaInfo = doorAreaInfo;
  333. inst.Instance.SetDoorAreaPosition(GetDoorHoverAreaRoot(doorAreaInfo.Direction).Position);
  334. inst.Instance.SetDoorAreaRange(doorAreaInfo.Start, doorAreaInfo.End);
  335. return inst;
  336. }
  337.  
  338. /// <summary>
  339. /// 创建拖拽状态下的门区域工具, 用于创建门区域
  340. /// </summary>
  341. /// <param name="doorHoverArea">悬停区域</param>
  342. /// <param name="start">起始位置, 单位: 像素</param>
  343. /// <param name="onSubmit">成功提交时回调, 参数1为方向, 参数2为起始点, 参数3为大小</param>
  344. /// <param name="onCancel">取消提交时调用</param>
  345. public DoorToolTemplate CreateDragDoorTool(DoorHoverArea doorHoverArea, int start,
  346. Action<DoorDirection, int, int> onSubmit, Action onCancel)
  347. {
  348. var inst = CreateDoorToolInstance(doorHoverArea);
  349. inst.Instance.SetDoorAreaPosition(GetDoorHoverAreaRoot(doorHoverArea.Direction).Position);
  350. inst.Instance.SetDoorAreaRange(start, start);
  351. inst.Instance.MakeDragMode(onSubmit, () =>
  352. {
  353. RemoveDoorTool(inst);
  354. onCancel();
  355. });
  356. return inst;
  357. }
  358.  
  359. /// <summary>
  360. /// 移除门区域设置工具
  361. /// </summary>
  362. public void RemoveDoorTool(DoorToolTemplate toolInstance)
  363. {
  364. _doorTools.Remove(toolInstance);
  365. if (toolInstance.Instance.DoorAreaInfo != null)
  366. {
  367. EditorMap.Instance.RemoveDoorArea(toolInstance.Instance.DoorAreaInfo);
  368. }
  369. toolInstance.Instance.QueueFree();
  370. //派发修改数据修改事件
  371. EventManager.EmitEvent(EventEnum.OnEditorDirty);
  372. }
  373.  
  374. /// <summary>
  375. /// 设置工具根节点的大小和缩放
  376. /// </summary>
  377. /// <param name="pos">坐标</param>
  378. /// <param name="scale">缩放</param>
  379. public void SetToolTransform(Vector2 pos, Vector2 scale)
  380. {
  381. S_ToolRoot.Instance.Position = pos;
  382. S_ToolRoot.Instance.Scale = scale;
  383. }
  384.  
  385. /// <summary>
  386. /// 设置鼠标悬停区域位置和大小
  387. /// </summary>
  388. /// <param name="position">房间起始点, 单位: 格</param>
  389. /// <param name="size">房间大小, 单位: 格</param>
  390. public void SetDoorHoverToolTransform(Vector2I position, Vector2I size)
  391. {
  392. position *= GameConfig.TileCellSize;
  393. size *= GameConfig.TileCellSize;
  394.  
  395. var nPos1 = S_N_HoverRoot.Instance.Position;
  396. var ePos1 = S_E_HoverRoot.Instance.Position;
  397. var sPos1 = S_S_HoverRoot.Instance.Position;
  398. var wPos1 = S_W_HoverRoot.Instance.Position;
  399. var nPos2 = position + GameConfig.TileCellSizeVector2I;
  400. var ePos2 = new Vector2(position.X + size.X - GameConfig.TileCellSize, position.Y + GameConfig.TileCellSize);
  401. var sPos2 = new Vector2(position.X + GameConfig.TileCellSize, position.Y + size.Y - GameConfig.TileCellSize);
  402. var wPos2 = position + GameConfig.TileCellSizeVector2I;
  403.  
  404. var nSize2 = new Vector2(size.X - GameConfig.TileCellSize * 2, S_N_HoverArea.Instance.Size.Y);
  405. var eSize2 = new Vector2(size.Y - GameConfig.TileCellSize * 2, S_E_HoverArea.Instance.Size.Y);
  406. var sSize2 = new Vector2(size.X - GameConfig.TileCellSize * 2, S_S_HoverArea.Instance.Size.Y);
  407. var wSize2 = new Vector2(size.Y - GameConfig.TileCellSize * 2, S_W_HoverArea.Instance.Size.Y);
  408. S_N_HoverRoot.Instance.Position = nPos2;
  409. S_E_HoverRoot.Instance.Position = ePos2;
  410. S_S_HoverRoot.Instance.Position = sPos2;
  411. S_W_HoverRoot.Instance.Position = wPos2;
  412. S_N_HoverArea.Instance.Size = nSize2;
  413. S_E_HoverArea.Instance.Size = eSize2;
  414. S_S_HoverArea.Instance.Size = sSize2;
  415. S_W_HoverArea.Instance.Size = wSize2;
  416. //调整门区域
  417. for (var i = 0; i < _doorTools.Count; i++)
  418. {
  419. var doorTool = _doorTools[i];
  420. var direction = doorTool.Instance.Direction;
  421. var areaRoot = GetDoorHoverAreaRoot(direction);
  422. var doorAreaRange = doorTool.Instance.GetDoorAreaRange();
  423. doorTool.Instance.SetDoorAreaPosition(areaRoot.Position);
  424.  
  425. if (direction == DoorDirection.N)
  426. {
  427. var hOffset = (int)(nPos2.X - nPos1.X);
  428. doorAreaRange.X -= hOffset;
  429. doorAreaRange.Y -= hOffset;
  430.  
  431. if (doorAreaRange.X >= 0 && doorAreaRange.Y <= nSize2.X) //允许提交
  432. {
  433. doorTool.Instance.SetDoorAreaRange(doorAreaRange.X, doorAreaRange.Y);
  434. if (doorTool.Instance.DoorAreaInfo != null)
  435. {
  436. doorTool.Instance.DoorAreaInfo.Start = doorAreaRange.X;
  437. doorTool.Instance.DoorAreaInfo.End = doorAreaRange.Y;
  438. }
  439. }
  440. else //如果超出区域, 则删除
  441. {
  442. RemoveDoorTool(doorTool);
  443. i--;
  444. }
  445. }
  446. else if (direction == DoorDirection.S)
  447. {
  448. var hOffset = (int)(sPos2.X - sPos1.X);
  449. doorAreaRange.X -= hOffset;
  450. doorAreaRange.Y -= hOffset;
  451.  
  452. if (doorAreaRange.X >= 0 && doorAreaRange.Y <= sSize2.X) //允许提交
  453. {
  454. doorTool.Instance.SetDoorAreaRange(doorAreaRange.X, doorAreaRange.Y);
  455. if (doorTool.Instance.DoorAreaInfo != null)
  456. {
  457. doorTool.Instance.DoorAreaInfo.Start = doorAreaRange.X;
  458. doorTool.Instance.DoorAreaInfo.End = doorAreaRange.Y;
  459. }
  460. }
  461. else //如果超出区域, 则删除
  462. {
  463. RemoveDoorTool(doorTool);
  464. i--;
  465. }
  466. }
  467. else if (direction == DoorDirection.E)
  468. {
  469. var vOffset = (int)(ePos2.Y - ePos1.Y);
  470. doorAreaRange.X -= vOffset;
  471. doorAreaRange.Y -= vOffset;
  472.  
  473. if (doorAreaRange.X >= 0 && doorAreaRange.Y <= eSize2.X) //允许提交
  474. {
  475. doorTool.Instance.SetDoorAreaRange(doorAreaRange.X, doorAreaRange.Y);
  476. if (doorTool.Instance.DoorAreaInfo != null)
  477. {
  478. doorTool.Instance.DoorAreaInfo.Start = doorAreaRange.X;
  479. doorTool.Instance.DoorAreaInfo.End = doorAreaRange.Y;
  480. }
  481. }
  482. else //如果超出区域, 则删除
  483. {
  484. RemoveDoorTool(doorTool);
  485. i--;
  486. }
  487. }
  488. else if (direction == DoorDirection.W)
  489. {
  490. var vOffset = (int)(wPos2.Y - wPos1.Y);
  491. doorAreaRange.X -= vOffset;
  492. doorAreaRange.Y -= vOffset;
  493.  
  494. if (doorAreaRange.X >= 0 && doorAreaRange.Y <= wSize2.X) //允许提交
  495. {
  496. doorTool.Instance.SetDoorAreaRange(doorAreaRange.X, doorAreaRange.Y);
  497. if (doorTool.Instance.DoorAreaInfo != null)
  498. {
  499. doorTool.Instance.DoorAreaInfo.Start = doorAreaRange.X;
  500. doorTool.Instance.DoorAreaInfo.End = doorAreaRange.Y;
  501. }
  502. }
  503. else //如果超出区域, 则删除
  504. {
  505. RemoveDoorTool(doorTool);
  506. i--;
  507. }
  508. }
  509. }
  510. }
  511. private DoorToolTemplate CreateDoorToolInstance(DoorHoverArea doorHoverArea)
  512. {
  513. var doorTool = S_DoorToolTemplate.Clone();
  514. S_ToolRoot.Instance.AddChild(doorTool.Instance);
  515. doorTool.Instance.SetDoorDragAreaNode(doorTool);
  516. doorTool.L_StartBtn.Instance.SetMapEditorToolsPanel(this);
  517. doorTool.L_EndBtn.Instance.SetMapEditorToolsPanel(this);
  518. doorTool.Instance.SetDoorHoverArea(doorHoverArea);
  519. _doorTools.Add(doorTool);
  520. return doorTool;
  521. }
  522. }