using System.Collections.Generic; using Unity.Collections; namespace SepCore.Simulation { internal abstract class EntityComponentStore { internal interface IColumn { bool IsCreated { get; } void EnsureCapacity(int count); void SwapBackRemove(int index, int lastIndex); void Clear(); void Dispose(); } internal sealed class Column : IColumn where T : unmanaged, ISimulationComponent { private NativeList _data; public Column(int capacity) { _data = new NativeList(capacity, Allocator.Persistent); } public NativeList Data => _data; public bool IsCreated => _data.IsCreated; public ref T this[int index] => ref _data.ElementAt(index); public void EnsureCapacity(int count) { if (_data.IsCreated && _data.Capacity < count) { _data.Capacity = count; } } public void SwapBackRemove(int index, int lastIndex) { if (index != lastIndex) { _data[index] = _data[lastIndex]; } _data.RemoveAt(lastIndex); } public void Clear() { if (_data.IsCreated) { _data.Clear(); } } public void Dispose() { if (_data.IsCreated) { _data.Dispose(); } _data = default; } } private readonly EntityBinding _binding = new(); private readonly List _columns = new(); private int _count; public int Count => _count; public bool IsCreated { get; private set; } public void EnsureCapacity(int count) { for (int i = 0; i < _columns.Count; i++) { _columns[i].EnsureCapacity(count); } } public bool TryGetSimulationIndex(int entityId, out int index) { return _binding.TryGetSimulationIndex(entityId, out index); } public bool RemoveByEntityId(int entityId) { if (!_binding.TryGetSimulationIndex(entityId, out int index)) { return false; } int lastIndex = _count - 1; bool hasMovedRow = index != lastIndex; int movedEntityId = 0; if (hasMovedRow) { _binding.TryGetEntityId(lastIndex, out movedEntityId); } for (int i = 0; i < _columns.Count; i++) { _columns[i].SwapBackRemove(index, lastIndex); } _binding.UnbindByEntityId(entityId); if (hasMovedRow) { _binding.RemapIndex(movedEntityId, index); } _count--; return true; } public void Clear() { for (int i = 0; i < _columns.Count; i++) { _columns[i].Clear(); } _binding.Clear(); _count = 0; } public virtual void Dispose() { for (int i = 0; i < _columns.Count; i++) { _columns[i].Dispose(); } _columns.Clear(); _binding.Clear(); _count = 0; IsCreated = false; } protected Column Register(int capacity) where T : unmanaged, ISimulationComponent { Column column = new Column(capacity); _columns.Add(column); return column; } protected void MarkInitialized() { IsCreated = true; } protected int AppendRow(int entityId) { int index = _count; _binding.Bind(entityId, index); _count++; return index; } } }