mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 21:01:52 +00:00
Added generic World Enumerators
also moved WorldEnumerators out of EcsWorld
This commit is contained in:
@@ -10,15 +10,15 @@ namespace GlitchyEngine.World
|
|||||||
{
|
{
|
||||||
const int MaxEntities = 1024;
|
const int MaxEntities = 1024;
|
||||||
|
|
||||||
typealias BitmaskEntry = (Entity ID, BitArray ComponentMask);
|
internal typealias BitmaskEntry = (Entity ID, BitArray ComponentMask);
|
||||||
List<BitmaskEntry> _entities = new .();
|
internal List<BitmaskEntry> _entities = new .();
|
||||||
|
|
||||||
List<uint32> _freeIndices = new List<uint32>() ~ delete _;
|
List<uint32> _freeIndices = new List<uint32>() ~ delete _;
|
||||||
|
|
||||||
typealias DisposeFunction = function void(void* component);
|
typealias DisposeFunction = function void(void* component);
|
||||||
|
|
||||||
typealias ComponentPoolEntry = (uint32 Id, ComponentPool Pool, DisposeFunction DisposeFunction);
|
internal typealias ComponentPoolEntry = (uint32 Id, ComponentPool Pool, DisposeFunction DisposeFunction);
|
||||||
Dictionary<Type, ComponentPoolEntry> _componentPools = new .();
|
internal Dictionary<Type, ComponentPoolEntry> _componentPools = new .();
|
||||||
|
|
||||||
/// A list containing all pools whose components need to be disposed before removal.
|
/// A list containing all pools whose components need to be disposed before removal.
|
||||||
List<ComponentPoolEntry*> _disposingPools = new .() ~ delete _;
|
List<ComponentPoolEntry*> _disposingPools = new .() ~ delete _;
|
||||||
@@ -68,6 +68,16 @@ namespace GlitchyEngine.World
|
|||||||
_disposingPools.Add(&poolInDictionary);
|
_disposingPools.Add(&poolInDictionary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief Returns the component pool for the given component type.
|
||||||
|
* @param TComponent The type of the component whose component pool will be returned.
|
||||||
|
* @returns A reference to the component pool.
|
||||||
|
*/
|
||||||
|
[Inline]
|
||||||
|
internal ref ComponentPoolEntry GetComponentPool<TComponent>()
|
||||||
|
{
|
||||||
|
return ref _componentPools[typeof(TComponent)];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Entity and returns its ID.
|
* Creates a new Entity and returns its ID.
|
||||||
*/
|
*/
|
||||||
@@ -230,54 +240,21 @@ namespace GlitchyEngine.World
|
|||||||
return WorldEnumerator(this, componentTypes);
|
return WorldEnumerator(this, componentTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct WorldEnumerator : IEnumerator<Entity>, IDisposable
|
public WorldEnumerator<TComponent> Enumerate<TComponent>() where TComponent : struct
|
||||||
{
|
{
|
||||||
private EcsWorld _world;
|
return WorldEnumerator<TComponent>(this);
|
||||||
private BitArray _bitMask;
|
|
||||||
private BitmaskEntry* _currentEntry;
|
|
||||||
private BitmaskEntry* _endEntry;
|
|
||||||
|
|
||||||
public this(EcsWorld world, Type[] componentTypes)
|
|
||||||
{
|
|
||||||
_world = world;
|
|
||||||
_currentEntry = _world._entities.Ptr;
|
|
||||||
_endEntry = _world._entities.Ptr + _world._entities.Count;
|
|
||||||
|
|
||||||
_bitMask = new BitArray(_world._componentPools.Count);
|
|
||||||
for(var type in componentTypes)
|
|
||||||
{
|
|
||||||
Log.EngineLogger.AssertDebug(type.IsStruct, "Components can only be structs.");
|
|
||||||
|
|
||||||
var result = _world._componentPools.GetValue(type);
|
|
||||||
|
|
||||||
if(result case .Ok(let entry))
|
|
||||||
{
|
|
||||||
_bitMask[entry.Id] = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.EngineLogger.AssertDebug(false, "Queried component is not registered for this world. This is invalid because the query would never return any results.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result<Entity> GetNext() mut
|
public WorldEnumerator<TComponent0, TComponent1> Enumerate<TComponent0, TComponent1>() where TComponent0 : struct
|
||||||
|
where TComponent1 : struct
|
||||||
{
|
{
|
||||||
while(_currentEntry < _endEntry)
|
return WorldEnumerator<TComponent0, TComponent1>(this);
|
||||||
{
|
|
||||||
BitmaskEntry* entry = _currentEntry++;
|
|
||||||
// Check whether or not mask matches
|
|
||||||
if(entry.ComponentMask.MaskMatch(_bitMask))
|
|
||||||
return entry.ID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return .Err;
|
public WorldEnumerator<TComponent0, TComponent1, TComponent2> Enumerate<TComponent0, TComponent1, TComponent2>()
|
||||||
}
|
where TComponent0 : struct where TComponent1 : struct where TComponent2 : struct
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
{
|
||||||
delete _bitMask;
|
return WorldEnumerator<TComponent0, TComponent1, TComponent2>(this);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Test()
|
public static void Test()
|
||||||
|
|||||||
@@ -0,0 +1,137 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System;
|
||||||
|
using GlitchyEngine.Math;
|
||||||
|
|
||||||
|
using internal GlitchyEngine.World;
|
||||||
|
|
||||||
|
namespace GlitchyEngine.World
|
||||||
|
{
|
||||||
|
public struct WorldEnumerator : IEnumerator<Entity>, IDisposable
|
||||||
|
{
|
||||||
|
internal EcsWorld _world;
|
||||||
|
internal BitArray _bitMask;
|
||||||
|
internal EcsWorld.BitmaskEntry* _currentEntry;
|
||||||
|
internal EcsWorld.BitmaskEntry* _endEntry;
|
||||||
|
|
||||||
|
public this(EcsWorld world, Type[] componentTypes)
|
||||||
|
{
|
||||||
|
_world = world;
|
||||||
|
_currentEntry = _world._entities.Ptr;
|
||||||
|
_endEntry = _world._entities.Ptr + _world._entities.Count;
|
||||||
|
|
||||||
|
_bitMask = new BitArray(_world._componentPools.Count);
|
||||||
|
for(var type in componentTypes)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.AssertDebug(type.IsStruct, "Components can only be structs.");
|
||||||
|
|
||||||
|
var result = _world._componentPools.GetValue(type);
|
||||||
|
|
||||||
|
if(result case .Ok(let entry))
|
||||||
|
{
|
||||||
|
_bitMask[entry.Id] = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.EngineLogger.AssertDebug(false, "Queried component is not registered for this world. This is invalid because the query would never return any results.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<Entity> GetNext() mut
|
||||||
|
{
|
||||||
|
while(_currentEntry < _endEntry)
|
||||||
|
{
|
||||||
|
EcsWorld.BitmaskEntry* entry = _currentEntry++;
|
||||||
|
// Check whether or not mask matches
|
||||||
|
if(entry.ComponentMask.MaskMatch(_bitMask))
|
||||||
|
return entry.ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
delete _bitMask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct WorldEnumerator<TComponent> : WorldEnumerator, IEnumerator<(Entity Entity, TComponent* Component)> where TComponent : struct
|
||||||
|
{
|
||||||
|
internal EcsWorld.ComponentPoolEntry* _componentPool;
|
||||||
|
|
||||||
|
public this(EcsWorld world) : base(world, scope Type[](typeof(TComponent)))
|
||||||
|
{
|
||||||
|
_componentPool = &world.GetComponentPool<TComponent>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public new Result<(Entity Entity, TComponent* Component)> GetNext() mut
|
||||||
|
{
|
||||||
|
Result<Entity> entity = base.GetNext();
|
||||||
|
|
||||||
|
if(entity case .Err)
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
TComponent* component = (.)_componentPool.Pool.Get(entity.Value.Index);
|
||||||
|
|
||||||
|
return .Ok((entity.Value, component));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct WorldEnumerator<TComponent0, TComponent1> : WorldEnumerator,
|
||||||
|
IEnumerator<(Entity Entity, TComponent0* Component0, TComponent1* Component1)>
|
||||||
|
where TComponent0 : struct where TComponent1 : struct
|
||||||
|
{
|
||||||
|
internal EcsWorld.ComponentPoolEntry* _componentPool0;
|
||||||
|
internal EcsWorld.ComponentPoolEntry* _componentPool1;
|
||||||
|
|
||||||
|
public this(EcsWorld world) : base(world, scope Type[](typeof(TComponent0), typeof(TComponent1)))
|
||||||
|
{
|
||||||
|
_componentPool0 = &world.GetComponentPool<TComponent0>();
|
||||||
|
_componentPool1 = &world.GetComponentPool<TComponent1>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public new Result<(Entity Entity, TComponent0* Component0, TComponent1* Component1)> GetNext() mut
|
||||||
|
{
|
||||||
|
Result<Entity> entity = base.GetNext();
|
||||||
|
|
||||||
|
if(entity case .Err)
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
TComponent0* component0 = (.)_componentPool0.Pool.Get(entity.Value.Index);
|
||||||
|
TComponent1* component1 = (.)_componentPool1.Pool.Get(entity.Value.Index);
|
||||||
|
|
||||||
|
return .Ok((entity.Value, component0, component1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct WorldEnumerator<TComponent0, TComponent1, TComponent2> : WorldEnumerator,
|
||||||
|
IEnumerator<(Entity Entity, TComponent0* Component0, TComponent1* Component1, TComponent2* Component2)>
|
||||||
|
where TComponent0 : struct where TComponent1 : struct where TComponent2 : struct
|
||||||
|
{
|
||||||
|
internal EcsWorld.ComponentPoolEntry* _componentPool0;
|
||||||
|
internal EcsWorld.ComponentPoolEntry* _componentPool1;
|
||||||
|
internal EcsWorld.ComponentPoolEntry* _componentPool2;
|
||||||
|
|
||||||
|
public this(EcsWorld world) : base(world, scope Type[](typeof(TComponent0), typeof(TComponent1), typeof(TComponent2)))
|
||||||
|
{
|
||||||
|
_componentPool0 = &world.GetComponentPool<TComponent0>();
|
||||||
|
_componentPool1 = &world.GetComponentPool<TComponent1>();
|
||||||
|
_componentPool2 = &world.GetComponentPool<TComponent2>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public new Result<(Entity Entity, TComponent0* Component0, TComponent1* Component1, TComponent2* Component2)> GetNext() mut
|
||||||
|
{
|
||||||
|
Result<Entity> entity = base.GetNext();
|
||||||
|
|
||||||
|
if(entity case .Err)
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
TComponent0* component0 = (.)_componentPool0.Pool.Get(entity.Value.Index);
|
||||||
|
TComponent1* component1 = (.)_componentPool1.Pool.Get(entity.Value.Index);
|
||||||
|
TComponent2* component2 = (.)_componentPool2.Pool.Get(entity.Value.Index);
|
||||||
|
|
||||||
|
return .Ok((entity.Value, component0, component1, component2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user