Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / ui / grid / UiGrid.cs
  1.  
  2.  
  3. using System;
  4. using System.Collections.Generic;
  5. using Godot;
  6.  
  7. /// <summary>
  8. /// Ui网格组件
  9. /// </summary>
  10. /// <typeparam name="TNodeType">原生Godot类型</typeparam>
  11. /// <typeparam name="TUiNodeType">Ui节点类型</typeparam>
  12. /// <typeparam name="TData">传给Cell的数据类型</typeparam>
  13. public partial class UiGrid<TUiCellNode, TData> : GridContainer, IDestroy where TUiCellNode : IUiCellNode
  14. {
  15. public bool IsDestroyed { get; private set; }
  16. private TUiCellNode _template;
  17. private Node _parent;
  18. private Type _cellType;
  19. private Stack<UiCell<TUiCellNode, TData>> _cellPool = new Stack<UiCell<TUiCellNode, TData>>();
  20. private List<UiCell<TUiCellNode, TData>> _cellList = new List<UiCell<TUiCellNode, TData>>();
  21.  
  22. public UiGrid(TUiCellNode template, Type cellType, int columns, int offsetX, int offsetY)
  23. {
  24. _template = template;
  25. _cellType = cellType;
  26. var uiInstance = _template.GetUiInstance();
  27. _parent = uiInstance.GetParent();
  28. _parent.RemoveChild(uiInstance);
  29. _parent.AddChild(this);
  30. Columns = columns;
  31. AddThemeConstantOverride("h_separation", offsetX);
  32. AddThemeConstantOverride("v_separation", offsetY);
  33. }
  34.  
  35. public override void _Ready()
  36. {
  37. if (_template.GetUiInstance() is Control control)
  38. {
  39. Position = control.Position;
  40. }
  41. }
  42.  
  43. public void SetDataList(TData[] array)
  44. {
  45. if (array.Length > _cellList.Count)
  46. {
  47. do
  48. {
  49. var cell = GetCellInstance();
  50. _cellList.Add(cell);
  51. AddChild(cell.CellNode.GetUiInstance());
  52. } while (array.Length > _cellList.Count);
  53. }
  54. else if(array.Length < _cellList.Count)
  55. {
  56. do
  57. {
  58. var cell = _cellList[_cellList.Count - 1];
  59. _cellList.RemoveAt(_cellList.Count - 1);
  60. ReclaimCellInstance(cell);
  61. } while (array.Length < _cellList.Count);
  62. }
  63.  
  64. for (var i = 0; i < _cellList.Count; i++)
  65. {
  66. var data = array[i];
  67. _cellList[i].OnSetData(data);
  68. }
  69. }
  70.  
  71. public void Add(TData data)
  72. {
  73. var cell = GetCellInstance();
  74. _cellList.Add(cell);
  75. AddChild(cell.CellNode.GetUiInstance());
  76. cell.OnSetData(data);
  77. }
  78. public void Destroy()
  79. {
  80. if (IsDestroyed)
  81. {
  82. return;
  83. }
  84.  
  85. IsDestroyed = true;
  86. for (var i = 0; i < _cellList.Count; i++)
  87. {
  88. _cellList[i].Destroy();
  89. }
  90. foreach (var uiCell in _cellPool)
  91. {
  92. uiCell.Destroy();
  93. }
  94. _cellList = null;
  95. _cellPool = null;
  96. }
  97.  
  98. private UiCell<TUiCellNode, TData> GetCellInstance()
  99. {
  100. if (_cellPool.Count > 0)
  101. {
  102. return _cellPool.Pop();
  103. }
  104.  
  105. var uiCell = Activator.CreateInstance(_cellType) as UiCell<TUiCellNode, TData>;
  106. if (uiCell is null)
  107. {
  108. throw new Exception($"cellType 无法转为'{typeof(UiCell<TUiCellNode, TData>).FullName}'类型!");
  109. }
  110. uiCell.CellNode = (TUiCellNode)_template.CloneUiCell();
  111. uiCell.Grid = this;
  112. uiCell.OnInit();
  113. return uiCell;
  114. }
  115.  
  116. private void ReclaimCellInstance(UiCell<TUiCellNode, TData> cell)
  117. {
  118. RemoveChild(cell.CellNode.GetUiInstance());
  119. _cellPool.Push(cell);
  120. }
  121. }