using System; using System.Collections.Generic; using Godot; /// <summary> /// Ui网格组件 /// </summary> /// <typeparam name="TNodeType">原生Godot类型</typeparam> /// <typeparam name="TUiNodeType">Ui节点类型</typeparam> /// <typeparam name="TData">传给Cell的数据类型</typeparam> public partial class UiGrid<TUiCellNode, TData> : GridContainer, IDestroy where TUiCellNode : IUiCellNode { public bool IsDestroyed { get; private set; } private TUiCellNode _template; private Node _parent; private Type _cellType; private Stack<UiCell<TUiCellNode, TData>> _cellPool = new Stack<UiCell<TUiCellNode, TData>>(); private List<UiCell<TUiCellNode, TData>> _cellList = new List<UiCell<TUiCellNode, TData>>(); public UiGrid(TUiCellNode template, Type cellType, int columns, int offsetX, int offsetY) { _template = template; _cellType = cellType; var uiInstance = _template.GetUiInstance(); _parent = uiInstance.GetParent(); _parent.RemoveChild(uiInstance); _parent.AddChild(this); Columns = columns; AddThemeConstantOverride("h_separation", offsetX); AddThemeConstantOverride("v_separation", offsetY); } public override void _Ready() { if (_template.GetUiInstance() 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.GetUiInstance()); } 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.GetUiInstance()); 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<TUiCellNode, TData> GetCellInstance() { if (_cellPool.Count > 0) { return _cellPool.Pop(); } var uiCell = Activator.CreateInstance(_cellType) as UiCell<TUiCellNode, TData>; if (uiCell is null) { throw new Exception($"cellType 无法转为'{typeof(UiCell<TUiCellNode, TData>).FullName}'类型!"); } uiCell.CellNode = (TUiCellNode)_template.CloneUiCell(); uiCell.Grid = this; uiCell.OnInit(); return uiCell; } private void ReclaimCellInstance(UiCell<TUiCellNode, TData> cell) { RemoveChild(cell.CellNode.GetUiInstance()); _cellPool.Push(cell); } }