contiguous component storage
continuous-integration/drone/push Build is passing Details

pull/3/head
Evan Hemsley 2020-03-22 17:03:18 -07:00
parent e4d4df9fdd
commit 61845d752a
1 changed files with 41 additions and 20 deletions

View File

@ -15,17 +15,18 @@ namespace Encompass
internal class TypedComponentStore<TComponent> : TypedComponentStore where TComponent : struct
{
private readonly Dictionary<int, int> _indices = new Dictionary<int, int>(512);
private readonly Dictionary<int, int> _priorities = new Dictionary<int, int>(512);
private readonly TComponent[] _components = new TComponent[512]; // TODO: allow specify size
private readonly IDManager _idManager = new IDManager();
private int _nextID = 0;
private readonly Dictionary<int, int> _entityIDToStorageIndex = new Dictionary<int, int>(128);
private readonly Dictionary<int, int> _storageIndexToEntityID = new Dictionary<int, int>(128);
private readonly Dictionary<int, int> _priorities = new Dictionary<int, int>(128);
private TComponent[] _components = new TComponent[128];
public override int Count { get => _indices.Count; }
public override int Count { get => _entityIDToStorageIndex.Count; }
public ref TComponent Get(int entityID)
{
if (!_indices.ContainsKey(entityID)) { throw new Exceptions.NoComponentOfTypeOnEntityException("No component of type {0} exists on Entity with ID {1}", typeof(TComponent), entityID); }
return ref _components[_indices[entityID]];
if (!_entityIDToStorageIndex.ContainsKey(entityID)) { throw new Exceptions.NoComponentOfTypeOnEntityException("No component of type {0} exists on Entity with ID {1}", typeof(TComponent), entityID); }
return ref _components[_entityIDToStorageIndex[entityID]];
}
public void Set(int entityID, in TComponent component)
@ -47,12 +48,18 @@ namespace Encompass
private void InternalSet(int entityID, in TComponent component)
{
if (!_indices.ContainsKey(entityID))
if (!_entityIDToStorageIndex.ContainsKey(entityID))
{
_indices[entityID] = _idManager.NextID();
var index = _nextID++;
if (index >= _components.Length)
{
System.Array.Resize(ref _components, _components.Length * 2);
}
_entityIDToStorageIndex[entityID] = index;
_storageIndexToEntityID[index] = entityID;
}
_components[_indices[entityID]] = component;
_components[_entityIDToStorageIndex[entityID]] = component;
}
public override bool Remove(int entityID, int priority)
@ -69,26 +76,40 @@ namespace Encompass
public override void ForceRemove(int entityID)
{
if (_indices.ContainsKey(entityID))
if (_entityIDToStorageIndex.ContainsKey(entityID))
{
_idManager.Free(_indices[entityID]);
_indices.Remove(entityID);
var storageIndex = _entityIDToStorageIndex[entityID];
_entityIDToStorageIndex.Remove(entityID);
_storageIndexToEntityID.Remove(storageIndex);
_priorities.Remove(entityID);
// move a component into the hole to maintain contiguous memory
if (_nextID > 1 && storageIndex != _nextID - 1)
{
var lastStorageIndex = _nextID - 1;
var lastEntityID = _storageIndexToEntityID[lastStorageIndex];
_storageIndexToEntityID.Remove(lastStorageIndex);
_entityIDToStorageIndex[lastEntityID] = storageIndex;
_storageIndexToEntityID[storageIndex] = lastEntityID;
_components[storageIndex] = _components[lastStorageIndex];
}
_nextID--;
}
}
public override bool Has(int entityID)
{
return _indices.ContainsKey(entityID);
return _entityIDToStorageIndex.ContainsKey(entityID);
}
public override void Clear()
{
foreach (var mappedID in _indices.Values)
{
_idManager.Free(mappedID);
}
_indices.Clear();
_nextID = 0;
_entityIDToStorageIndex.Clear();
_storageIndexToEntityID.Clear();
_priorities.Clear();
}
@ -99,7 +120,7 @@ namespace Encompass
public IEnumerable<(TComponent, int)> All()
{
foreach (var kvp in _indices)
foreach (var kvp in _entityIDToStorageIndex)
{
yield return (_components[kvp.Value], kvp.Key);
}