Theater-ECS/src/ComponentManager.bf

109 lines
2.7 KiB
Beef
Raw Normal View History

2024-11-11 18:00:37 +01:00
namespace Theater_ECS;
using System;
using System.Threading;
using System.Collections;
class ComponentManager
{
private Monitor _Lock = new .() ~ delete _;
private int_cosize _ComponentSize = -1;
private readonly int _IndexSize = sizeof(int_cosize);
private int_cosize _Next = 0;
private List<uint8> _Data = null ~ delete _;
private List<int_cosize> _Available = new .() ~ delete _;
private HashSet<int_cosize> _Deleted = new .() ~ delete _;
///Make the component manager useable for a specific type of component
public void Initialize<T>(int_cosize count) where T : struct
{
_ComponentSize = sizeof(T);
_Data = new .( //So that we dont have to realloc as frequently
(_IndexSize + _ComponentSize) * count
);
}
///Creates space for a new component instance and returns a pointer to it
public (Component, void*) Create(Entity owner)
{
if (_Available.Count > 0)
{
var idx = _Available.PopFront();
_Deleted.Remove(idx);
*(int_cosize*)(void*)&_Data[idx * (_ComponentSize + _IndexSize)] = owner;
void* toReturn = (void*)&_Data[idx * (_ComponentSize + _IndexSize) + _IndexSize];
return (
idx,
toReturn
);
}
else
{
Grow();
*(int_cosize*)(void*)(_Data.Ptr + (_Next * (_ComponentSize + _IndexSize))) = owner;
//This calculates to the next biggest position + the offset of the index
void* toReturn = (void*)(_Data.Ptr + (_Next * (_ComponentSize + _IndexSize) + _IndexSize));
return (
_Next++,
toReturn
);
}
}
///Remove an entry, and returns a pointer to the removed object, if you want to
public Result<void*> Remove(int_cosize idx)
{
if (idx >= _Next || _Deleted.Contains(idx))
return .Err;
*(int_cosize*)(void*)&_Data[idx * (_ComponentSize + _IndexSize)] = -1;
_Deleted.Add(idx);
return .Ok(
(void*)(_Data.Ptr + idx * (_ComponentSize + _IndexSize) + _IndexSize)
);
}
public int_cosize Count
{
get
{
return (.)(_Data.Count / (_ComponentSize + _IndexSize));
}
}
public Span<(Entity, T)> GetAll<T>() where T : struct
{
return .((.)(void*)_Data.Ptr, Count);
}
[Unchecked]
public T* Get<T>(int_cosize idx) where T : struct
{
return (T*)(void*)(_Data.Ptr + idx * (_ComponentSize + _IndexSize) + _IndexSize);
}
[Unchecked]
public void GetEntities(List<Entity> list)
{
var ec = (_Data.Count / (_ComponentSize + _IndexSize));
list.GrowUninitialized(ec);
for (int i < ec)
*(list.Ptr + (i)) = *(Entity*)(void*)(_Data.Ptr +i * (_ComponentSize + _IndexSize));
}
public void Use() => _Lock.Enter();
public void StopUsing() => _Lock.Exit();
public void Grow(int_cosize amount = 1)
{ //Make more size useable
_Data.GrowUninitialized((_ComponentSize + _IndexSize) * amount);
}
}