87 lines
No EOL
2.1 KiB
Beef
87 lines
No EOL
2.1 KiB
Beef
namespace Theater_ECS.Internal.Containers;
|
|
|
|
using System;
|
|
using System.Collections;
|
|
|
|
class PagedSparseSet
|
|
{
|
|
public const uint32 PageSize = 4096;
|
|
|
|
private List<List<Entity>> _sparse = new .()~ DeleteContainerAndItems!(_);
|
|
private List<Entity> _packed = new .() ~ delete _;
|
|
private UList _packedEntities ~ delete _;
|
|
|
|
private function void(void* data) _deallocationFunction = null;
|
|
|
|
public this(int_cosize size)
|
|
{
|
|
_packedEntities = new .(size);
|
|
}
|
|
|
|
public bool Contains(Entity e)
|
|
{
|
|
return _sparse[e.Index/PageSize][e.Index % PageSize] != Entity.Null;
|
|
}
|
|
|
|
public void Add(Entity e, void* toAdd)
|
|
{
|
|
EnsureLoadedPage(e.Index/PageSize);
|
|
_packed.Add(e);
|
|
_packedEntities.Add(toAdd);
|
|
_sparse[e.Index/PageSize][e.Index % PageSize] = (.)_packed.Count-1;
|
|
}
|
|
|
|
public bool Remove(Entity e, bool cleanup = false)
|
|
{
|
|
EnsurePage(e.Index/PageSize);
|
|
if(_sparse[e.Index/PageSize] == null)
|
|
return false;
|
|
|
|
if(_deallocationFunction != null && !cleanup)
|
|
_deallocationFunction(_packedEntities[(.)(_sparse[e.Index/PageSize][e.Index % PageSize].Index)]);
|
|
|
|
let toRm = _packed[_sparse[e.Index/PageSize][e.Index % PageSize].Index];
|
|
let b = _packed.Back;
|
|
_packed[_sparse[e.Index/PageSize][e.Index % PageSize].Index] = b;
|
|
_packed.Back = toRm;
|
|
|
|
_sparse[b.Index/PageSize][b.Index % PageSize] = Entity(e.Index, b.Version);
|
|
_sparse[e.Index/PageSize][e.Index % PageSize] = Entity.Null;
|
|
|
|
_packed.PopBack();
|
|
return true;
|
|
}
|
|
|
|
[Inline, Unchecked]
|
|
public void* Get(Entity e)
|
|
{
|
|
return _packedEntities[(.)(_sparse[e.Index/PageSize][e.Index % PageSize].Index)];
|
|
}
|
|
|
|
public Span<Entity> GetAll()
|
|
{
|
|
return _packed;
|
|
}
|
|
|
|
public int_cosize Count() => (.)_packed.Count;
|
|
|
|
///Ensure that a page exist and is loaded
|
|
public void EnsureLoadedPage(uint32 page)
|
|
{
|
|
EnsurePage(page);
|
|
if(_sparse[page] == null)
|
|
{
|
|
_sparse[page] = new List<Entity>(PageSize);
|
|
_sparse[page].[Friend]Count = 4096;
|
|
_sparse[page].SetAll(Entity.Null);
|
|
|
|
}
|
|
}
|
|
|
|
///Ensure that a page exists, it might be null though
|
|
private void EnsurePage(uint32 page)
|
|
{
|
|
while(_sparse.Count < page+1)
|
|
_sparse.Add(null);
|
|
}
|
|
} |