165 lines
4.1 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|