Files

165 lines
4.1 KiB
C#

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<T> : IColumn where T : unmanaged, ISimulationComponent
{
private NativeList<T> _data;
public Column(int capacity)
{
_data = new NativeList<T>(capacity, Allocator.Persistent);
}
public NativeList<T> 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<IColumn> _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<T> Register<T>(int capacity) where T : unmanaged, ISimulationComponent
{
Column<T> column = new Column<T>(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;
}
}
}