using System; using System.Collections.Generic; using Godot; public partial class UiGrid<TNodeType, TUiNodeType, TData> : GridContainer, IDestroy where TNodeType : Node where TUiNodeType : IUiNode<TNodeType, TUiNodeType> { public bool IsDestroyed { get; private set; } private TUiNodeType _template; private Node _parent; private Type _cellType; private Stack<UiCell<TNodeType, TUiNodeType, TData>> _cellPool = new Stack<UiCell<TNodeType, TUiNodeType, TData>>(); private List<UiCell<TNodeType, TUiNodeType, TData>> _cellList = new List<UiCell<TNodeType, TUiNodeType, TData>>(); public UiGrid(TUiNodeType template, Type cellType, int columns, int offsetX, int offsetY) { _template = template; _cellType = cellType; _parent = _template.Instance.GetParent(); _parent.RemoveChild(_template.Instance); _parent.AddChild(this); Columns = columns; AddThemeConstantOverride("h_separation", offsetX); AddThemeConstantOverride("v_separation", offsetY); } public override void _Ready() { if (_template.Instance is Control control) { Position = control.Position; } } public void SetDataList(TData[] array) { if (array.Length > _cellList.Count) { do { var cell = GetCellInstance(); _cellList.Add(cell); AddChild(cell.CellNode.Instance); } while (array.Length > _cellList.Count); } else if(array.Length < _cellList.Count) { do { var cell = _cellList[_cellList.Count - 1]; _cellList.RemoveAt(_cellList.Count - 1); ReclaimCellInstance(cell); } while (array.Length < _cellList.Count); } for (var i = 0; i < _cellList.Count; i++) { var data = array[i]; _cellList[i].OnSetData(data); } } public void Add(TData data) { var cell = GetCellInstance(); _cellList.Add(cell); AddChild(cell.CellNode.Instance); cell.OnSetData(data); } public void Destroy() { if (IsDestroyed) { return; } IsDestroyed = true; for (var i = 0; i < _cellList.Count; i++) { _cellList[i].Destroy(); } foreach (var uiCell in _cellPool) { uiCell.Destroy(); } _cellList = null; _cellPool = null; } private UiCell<TNodeType, TUiNodeType, TData> GetCellInstance() { if (_cellPool.Count > 0) { return _cellPool.Pop(); } var cell = Activator.CreateInstance(_cellType); var uiCell = (UiCell<TNodeType, TUiNodeType, TData>)cell; uiCell.CellNode = _template.Clone(); uiCell.Grid = this; uiCell.OnInit(); return uiCell; } private void ReclaimCellInstance(UiCell<TNodeType, TUiNodeType, TData> cell) { RemoveChild(cell.CellNode.Instance); _cellPool.Push(cell); } }