Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / ui / grid / UiGrid.cs
@lijincheng lijincheng on 1 Jul 2023 3 KB 主动道具接口
  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<TNodeType, TUiNodeType, TData> : GridContainer, IDestroy where TNodeType : Node where TUiNodeType : IUiNode<TNodeType, TUiNodeType>
  14. {
  15. public bool IsDestroyed { get; private set; }
  16. private TUiNodeType _template;
  17. private Node _parent;
  18. private Type _cellType;
  19. private Stack<UiCell<TNodeType, TUiNodeType, TData>> _cellPool = new Stack<UiCell<TNodeType, TUiNodeType, TData>>();
  20. private List<UiCell<TNodeType, TUiNodeType, TData>> _cellList = new List<UiCell<TNodeType, TUiNodeType, TData>>();
  21.  
  22. public UiGrid(TUiNodeType template, Type cellType, int columns, int offsetX, int offsetY)
  23. {
  24. _template = template;
  25. _cellType = cellType;
  26. _parent = _template.Instance.GetParent();
  27. _parent.RemoveChild(_template.Instance);
  28. _parent.AddChild(this);
  29. Columns = columns;
  30. AddThemeConstantOverride("h_separation", offsetX);
  31. AddThemeConstantOverride("v_separation", offsetY);
  32. }
  33.  
  34. public override void _Ready()
  35. {
  36. if (_template.Instance is Control control)
  37. {
  38. Position = control.Position;
  39. }
  40. }
  41.  
  42. public void SetDataList(TData[] array)
  43. {
  44. if (array.Length > _cellList.Count)
  45. {
  46. do
  47. {
  48. var cell = GetCellInstance();
  49. _cellList.Add(cell);
  50. AddChild(cell.CellNode.Instance);
  51. } while (array.Length > _cellList.Count);
  52. }
  53. else if(array.Length < _cellList.Count)
  54. {
  55. do
  56. {
  57. var cell = _cellList[_cellList.Count - 1];
  58. _cellList.RemoveAt(_cellList.Count - 1);
  59. ReclaimCellInstance(cell);
  60. } while (array.Length < _cellList.Count);
  61. }
  62.  
  63. for (var i = 0; i < _cellList.Count; i++)
  64. {
  65. var data = array[i];
  66. _cellList[i].OnSetData(data);
  67. }
  68. }
  69.  
  70. public void Add(TData data)
  71. {
  72. var cell = GetCellInstance();
  73. _cellList.Add(cell);
  74. AddChild(cell.CellNode.Instance);
  75. cell.OnSetData(data);
  76. }
  77. public void Destroy()
  78. {
  79. if (IsDestroyed)
  80. {
  81. return;
  82. }
  83.  
  84. IsDestroyed = true;
  85. for (var i = 0; i < _cellList.Count; i++)
  86. {
  87. _cellList[i].Destroy();
  88. }
  89. foreach (var uiCell in _cellPool)
  90. {
  91. uiCell.Destroy();
  92. }
  93. _cellList = null;
  94. _cellPool = null;
  95. }
  96.  
  97. private UiCell<TNodeType, TUiNodeType, TData> GetCellInstance()
  98. {
  99. if (_cellPool.Count > 0)
  100. {
  101. return _cellPool.Pop();
  102. }
  103.  
  104. var uiCell = Activator.CreateInstance(_cellType) as UiCell<TNodeType, TUiNodeType, TData>;
  105. if (uiCell is null)
  106. {
  107. throw new Exception($"cellType 无法转为'{typeof(UiCell<TNodeType, TUiNodeType, TData>).FullName}'类型!");
  108. }
  109. uiCell.CellNode = _template.Clone();
  110. uiCell.Grid = this;
  111. uiCell.OnInit();
  112. return uiCell;
  113. }
  114.  
  115. private void ReclaimCellInstance(UiCell<TNodeType, TUiNodeType, TData> cell)
  116. {
  117. RemoveChild(cell.CellNode.Instance);
  118. _cellPool.Push(cell);
  119. }
  120. }