Update: place asserts and extend test/main.c
This commit is contained in:
parent
cf562b26b0
commit
fbc351daa3
89
becs.h
89
becs.h
|
|
@ -22,7 +22,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#ifdef BECS_SLOW
|
#ifndef BECS_NO_ASSERT
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#else
|
#else
|
||||||
#define assert(expression)
|
#define assert(expression)
|
||||||
|
|
@ -59,7 +59,7 @@ bool BECS_ComponentHas(BECS_ECS *ecs, BECS_Entity entity, BECS_ComponentID compo
|
||||||
#define BECS_MAX_COMPONENTS 64
|
#define BECS_MAX_COMPONENTS 64
|
||||||
#endif /* BECS_MAX_COMPONENTS */
|
#endif /* BECS_MAX_COMPONENTS */
|
||||||
|
|
||||||
#define BECS_NULL_ENTITY BECS_MAX_COMPONENTS + 1
|
#define BECS_NULL_ENTITY BECS_MAX_ENTITIES + 1
|
||||||
#define BECS_INVALID_COMPONENT_ID UINT32_MAX
|
#define BECS_INVALID_COMPONENT_ID UINT32_MAX
|
||||||
|
|
||||||
typedef uint64_t BECS_Signature;
|
typedef uint64_t BECS_Signature;
|
||||||
|
|
@ -86,7 +86,7 @@ struct BECS_ECS {
|
||||||
BECS_Entity nextEntity;
|
BECS_Entity nextEntity;
|
||||||
uint32_t entityCount;
|
uint32_t entityCount;
|
||||||
BECS_Signature entitySignatures[BECS_MAX_ENTITIES];
|
BECS_Signature entitySignatures[BECS_MAX_ENTITIES];
|
||||||
bool aliveEntites[BECS_MAX_ENTITIES];
|
bool aliveEntities[BECS_MAX_ENTITIES];
|
||||||
|
|
||||||
BECS_Entity freeEntities[BECS_MAX_ENTITIES];
|
BECS_Entity freeEntities[BECS_MAX_ENTITIES];
|
||||||
uint32_t freeEntityCount;
|
uint32_t freeEntityCount;
|
||||||
|
|
@ -116,6 +116,10 @@ static bool BECS_SignatureMatches(BECS_Signature entitySig, BECS_Signature query
|
||||||
|
|
||||||
BECS_Arena BECS_CreateArena(void *memory, size_t capacity)
|
BECS_Arena BECS_CreateArena(void *memory, size_t capacity)
|
||||||
{
|
{
|
||||||
|
assert(memory != NULL);
|
||||||
|
assert(capacity > 0);
|
||||||
|
|
||||||
|
/* Align base offset to 64 byte boundary */
|
||||||
uintptr_t baseOffset = 64 - ((uintptr_t)memory % 64);
|
uintptr_t baseOffset = 64 - ((uintptr_t)memory % 64);
|
||||||
BECS_Arena arena = {};
|
BECS_Arena arena = {};
|
||||||
arena.nextAllocation = baseOffset;
|
arena.nextAllocation = baseOffset;
|
||||||
|
|
@ -126,6 +130,9 @@ BECS_Arena BECS_CreateArena(void *memory, size_t capacity)
|
||||||
|
|
||||||
static void *BECS_AllocateMemory(BECS_Arena *arena, size_t size)
|
static void *BECS_AllocateMemory(BECS_Arena *arena, size_t size)
|
||||||
{
|
{
|
||||||
|
assert(arena != NULL);
|
||||||
|
assert(size > 0);
|
||||||
|
|
||||||
size_t totalSizeBytes = size;
|
size_t totalSizeBytes = size;
|
||||||
uintptr_t nextAllocOffset = arena->nextAllocation + ((64 - (arena->nextAllocation % 64)) & 63);
|
uintptr_t nextAllocOffset = arena->nextAllocation + ((64 - (arena->nextAllocation % 64)) & 63);
|
||||||
if (nextAllocOffset + totalSizeBytes <= arena->capacity)
|
if (nextAllocOffset + totalSizeBytes <= arena->capacity)
|
||||||
|
|
@ -144,6 +151,9 @@ static void *BECS_AllocateMemory(BECS_Arena *arena, size_t size)
|
||||||
static void BECS_ComponentPoolInit
|
static void BECS_ComponentPoolInit
|
||||||
(BECS_Arena *arena, BECS_ComponentPool *pool ,size_t componentSize, size_t capacity)
|
(BECS_Arena *arena, BECS_ComponentPool *pool ,size_t componentSize, size_t capacity)
|
||||||
{
|
{
|
||||||
|
assert(arena != NULL);
|
||||||
|
assert(capacity <= BECS_MAX_ENTITIES);
|
||||||
|
|
||||||
pool->unitSize = componentSize;
|
pool->unitSize = componentSize;
|
||||||
pool->capacity = capacity;
|
pool->capacity = capacity;
|
||||||
pool->count = 0;
|
pool->count = 0;
|
||||||
|
|
@ -160,6 +170,9 @@ static void BECS_ComponentPoolInit
|
||||||
|
|
||||||
static void *BECS_ComponentPoolAdd(BECS_ComponentPool *pool, BECS_Entity entity)
|
static void *BECS_ComponentPoolAdd(BECS_ComponentPool *pool, BECS_Entity entity)
|
||||||
{
|
{
|
||||||
|
assert(pool->count < pool->capacity);
|
||||||
|
assert(entity < BECS_MAX_ENTITIES);
|
||||||
|
|
||||||
uint32_t index = pool->count;
|
uint32_t index = pool->count;
|
||||||
pool->count++;
|
pool->count++;
|
||||||
pool->denseEntityMapping[index] = entity;
|
pool->denseEntityMapping[index] = entity;
|
||||||
|
|
@ -170,6 +183,8 @@ static void *BECS_ComponentPoolAdd(BECS_ComponentPool *pool, BECS_Entity entity)
|
||||||
|
|
||||||
static void BECS_ComponentPoolRemove(BECS_ComponentPool *pool, BECS_Entity entity)
|
static void BECS_ComponentPoolRemove(BECS_ComponentPool *pool, BECS_Entity entity)
|
||||||
{
|
{
|
||||||
|
assert(entity < BECS_MAX_ENTITIES);
|
||||||
|
|
||||||
uint32_t index = pool->sparseArray[entity];
|
uint32_t index = pool->sparseArray[entity];
|
||||||
if (index == UINT32_MAX)
|
if (index == UINT32_MAX)
|
||||||
{
|
{
|
||||||
|
|
@ -194,6 +209,8 @@ static void BECS_ComponentPoolRemove(BECS_ComponentPool *pool, BECS_Entity entit
|
||||||
|
|
||||||
static void *BECS_ComponentPoolGet(BECS_ComponentPool *pool, BECS_Entity entity)
|
static void *BECS_ComponentPoolGet(BECS_ComponentPool *pool, BECS_Entity entity)
|
||||||
{
|
{
|
||||||
|
assert(entity < BECS_MAX_ENTITIES);
|
||||||
|
|
||||||
uint32_t index = pool->sparseArray[entity];
|
uint32_t index = pool->sparseArray[entity];
|
||||||
if (index == UINT32_MAX)
|
if (index == UINT32_MAX)
|
||||||
{
|
{
|
||||||
|
|
@ -205,6 +222,7 @@ static void *BECS_ComponentPoolGet(BECS_ComponentPool *pool, BECS_Entity entity)
|
||||||
|
|
||||||
static bool BECS_ComponentPoolHas(BECS_ComponentPool *pool, BECS_Entity entity)
|
static bool BECS_ComponentPoolHas(BECS_ComponentPool *pool, BECS_Entity entity)
|
||||||
{
|
{
|
||||||
|
assert(entity < BECS_MAX_ENTITIES);
|
||||||
return pool->sparseArray[entity] != UINT32_MAX;
|
return pool->sparseArray[entity] != UINT32_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -212,7 +230,9 @@ static bool BECS_ComponentPoolHas(BECS_ComponentPool *pool, BECS_Entity entity)
|
||||||
|
|
||||||
size_t BECS_GetMinMemoryArenaSize(size_t *componentSizes, size_t arrayLength)
|
size_t BECS_GetMinMemoryArenaSize(size_t *componentSizes, size_t arrayLength)
|
||||||
{
|
{
|
||||||
assert(arrayLength < BECS_MAX_COMPONENTS);
|
assert(componentSizes != NULL);
|
||||||
|
assert(arrayLength <= BECS_MAX_COMPONENTS);
|
||||||
|
|
||||||
size_t totalSize = 0;
|
size_t totalSize = 0;
|
||||||
totalSize += sizeof(BECS_ECS);
|
totalSize += sizeof(BECS_ECS);
|
||||||
totalSize += sizeof(BECS_ComponentPool) * BECS_MAX_COMPONENTS;
|
totalSize += sizeof(BECS_ComponentPool) * BECS_MAX_COMPONENTS;
|
||||||
|
|
@ -235,11 +255,14 @@ size_t BECS_GetMinMemoryArenaSize(size_t *componentSizes, size_t arrayLength)
|
||||||
|
|
||||||
BECS_ECS BECS_InitECS(void *memory, size_t size)
|
BECS_ECS BECS_InitECS(void *memory, size_t size)
|
||||||
{
|
{
|
||||||
|
assert(memory != NULL);
|
||||||
|
assert(size > 0);
|
||||||
|
|
||||||
BECS_ECS ecs;
|
BECS_ECS ecs;
|
||||||
ecs.arena = BECS_CreateArena(memory, size);
|
ecs.arena = BECS_CreateArena(memory, size);
|
||||||
ecs.entityCount = 0;
|
ecs.entityCount = 0;
|
||||||
memset(ecs.entitySignatures, 0, sizeof(BECS_Signature) * BECS_MAX_ENTITIES);
|
memset(ecs.entitySignatures, 0, sizeof(BECS_Signature) * BECS_MAX_ENTITIES);
|
||||||
memset(ecs.aliveEntites, false, sizeof(bool) * BECS_MAX_ENTITIES);
|
memset(ecs.aliveEntities, false, sizeof(bool) * BECS_MAX_ENTITIES);
|
||||||
memset(ecs.freeEntities, BECS_NULL_ENTITY, sizeof(BECS_Entity) * BECS_MAX_ENTITIES);
|
memset(ecs.freeEntities, BECS_NULL_ENTITY, sizeof(BECS_Entity) * BECS_MAX_ENTITIES);
|
||||||
ecs.freeEntityCount = 0;
|
ecs.freeEntityCount = 0;
|
||||||
ecs.nextEntity = 0;
|
ecs.nextEntity = 0;
|
||||||
|
|
@ -257,10 +280,15 @@ BECS_ECS BECS_InitECS(void *memory, size_t size)
|
||||||
|
|
||||||
void BECS_ResetECS(BECS_ECS *ecs)
|
void BECS_ResetECS(BECS_ECS *ecs)
|
||||||
{
|
{
|
||||||
|
if (!ecs)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ecs->arena = BECS_CreateArena(ecs->arena.memory, ecs->arena.capacity);
|
ecs->arena = BECS_CreateArena(ecs->arena.memory, ecs->arena.capacity);
|
||||||
ecs->entityCount = 0;
|
ecs->entityCount = 0;
|
||||||
memset(ecs->entitySignatures, 0, sizeof(BECS_Signature) * BECS_MAX_ENTITIES);
|
memset(ecs->entitySignatures, 0, sizeof(BECS_Signature) * BECS_MAX_ENTITIES);
|
||||||
memset(ecs->aliveEntites, false, sizeof(bool) * BECS_MAX_ENTITIES);
|
memset(ecs->aliveEntities, false, sizeof(bool) * BECS_MAX_ENTITIES);
|
||||||
memset(ecs->freeEntities, BECS_NULL_ENTITY, sizeof(BECS_Entity) * BECS_MAX_ENTITIES);
|
memset(ecs->freeEntities, BECS_NULL_ENTITY, sizeof(BECS_Entity) * BECS_MAX_ENTITIES);
|
||||||
ecs->freeEntityCount = 0;
|
ecs->freeEntityCount = 0;
|
||||||
ecs->nextEntity = 0;
|
ecs->nextEntity = 0;
|
||||||
|
|
@ -278,9 +306,11 @@ void BECS_ResetECS(BECS_ECS *ecs)
|
||||||
|
|
||||||
BECS_Entity BECS_EntityCreate(BECS_ECS *ecs)
|
BECS_Entity BECS_EntityCreate(BECS_ECS *ecs)
|
||||||
{
|
{
|
||||||
|
assert(ecs != NULL);
|
||||||
|
|
||||||
BECS_Entity entity = BECS_NULL_ENTITY;
|
BECS_Entity entity = BECS_NULL_ENTITY;
|
||||||
|
|
||||||
if (ecs->nextEntity + 1 > BECS_NULL_ENTITY)
|
if (ecs->nextEntity + 1 > BECS_MAX_ENTITIES)
|
||||||
{
|
{
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
@ -290,12 +320,12 @@ BECS_Entity BECS_EntityCreate(BECS_ECS *ecs)
|
||||||
/* Pop entity off the back of the free list */
|
/* Pop entity off the back of the free list */
|
||||||
entity = ecs->freeEntities[--ecs->freeEntityCount];
|
entity = ecs->freeEntities[--ecs->freeEntityCount];
|
||||||
ecs->entitySignatures[entity] = 0;
|
ecs->entitySignatures[entity] = 0;
|
||||||
ecs->aliveEntites[entity] = true;
|
ecs->aliveEntities[entity] = true;
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
entity = ecs->nextEntity;
|
entity = ecs->nextEntity;
|
||||||
ecs->aliveEntites[entity] = true;
|
ecs->aliveEntities[entity] = true;
|
||||||
ecs->entitySignatures[entity] = 0;
|
ecs->entitySignatures[entity] = 0;
|
||||||
ecs->nextEntity++;
|
ecs->nextEntity++;
|
||||||
ecs->entityCount++;
|
ecs->entityCount++;
|
||||||
|
|
@ -304,7 +334,10 @@ BECS_Entity BECS_EntityCreate(BECS_ECS *ecs)
|
||||||
|
|
||||||
void BECS_EntityDestroy(BECS_ECS *ecs, BECS_Entity entity)
|
void BECS_EntityDestroy(BECS_ECS *ecs, BECS_Entity entity)
|
||||||
{
|
{
|
||||||
if (!ecs->aliveEntites[entity])
|
assert(ecs != NULL);
|
||||||
|
assert(entity >= 0 && entity < BECS_MAX_ENTITIES);
|
||||||
|
|
||||||
|
if (!ecs->aliveEntities[entity])
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -319,7 +352,7 @@ void BECS_EntityDestroy(BECS_ECS *ecs, BECS_Entity entity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ecs->aliveEntites[entity] = false;
|
ecs->aliveEntities[entity] = false;
|
||||||
ecs->entitySignatures[entity] = 0;
|
ecs->entitySignatures[entity] = 0;
|
||||||
ecs->freeEntities[ecs->freeEntityCount] = entity;
|
ecs->freeEntities[ecs->freeEntityCount] = entity;
|
||||||
ecs->entityCount--;
|
ecs->entityCount--;
|
||||||
|
|
@ -328,13 +361,23 @@ void BECS_EntityDestroy(BECS_ECS *ecs, BECS_Entity entity)
|
||||||
|
|
||||||
bool BECS_IsEntityAlive(BECS_ECS *ecs, BECS_Entity entity)
|
bool BECS_IsEntityAlive(BECS_ECS *ecs, BECS_Entity entity)
|
||||||
{
|
{
|
||||||
return ecs->aliveEntites[entity];
|
assert(ecs != NULL);
|
||||||
|
|
||||||
|
if (entity >= BECS_MAX_ENTITIES || entity == BECS_NULL_ENTITY)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return ecs->aliveEntities[entity];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Component API Functions */
|
/* Component API Functions */
|
||||||
|
|
||||||
BECS_ComponentID BECS_ComponentRegister(BECS_ECS *ecs, size_t componentSize, size_t maximumComponentCount)
|
BECS_ComponentID BECS_ComponentRegister(BECS_ECS *ecs, size_t componentSize, size_t maximumComponentCount)
|
||||||
{
|
{
|
||||||
|
assert(ecs != NULL);
|
||||||
|
assert(ecs->componentTypeCount < BECS_MAX_COMPONENTS);
|
||||||
|
assert(componentSize > 0);
|
||||||
|
|
||||||
if (maximumComponentCount == 0)
|
if (maximumComponentCount == 0)
|
||||||
{
|
{
|
||||||
maximumComponentCount = BECS_MAX_ENTITIES;
|
maximumComponentCount = BECS_MAX_ENTITIES;
|
||||||
|
|
@ -350,6 +393,11 @@ BECS_ComponentID BECS_ComponentRegister(BECS_ECS *ecs, size_t componentSize, siz
|
||||||
|
|
||||||
void *BECS_ComponentAdd(BECS_ECS *ecs, BECS_Entity entity, BECS_ComponentID componentId)
|
void *BECS_ComponentAdd(BECS_ECS *ecs, BECS_Entity entity, BECS_ComponentID componentId)
|
||||||
{
|
{
|
||||||
|
assert(ecs != NULL);
|
||||||
|
assert(entity >= 0 && entity < BECS_MAX_ENTITIES);
|
||||||
|
assert(componentId < ecs->componentTypeCount);
|
||||||
|
assert(ecs->aliveEntities[entity]);
|
||||||
|
|
||||||
void *component = BECS_ComponentPoolAdd(&ecs->componentPools[componentId], entity);
|
void *component = BECS_ComponentPoolAdd(&ecs->componentPools[componentId], entity);
|
||||||
ecs->entitySignatures[entity] = BECS_SignatureSet(ecs->entitySignatures[entity], componentId);
|
ecs->entitySignatures[entity] = BECS_SignatureSet(ecs->entitySignatures[entity], componentId);
|
||||||
memset(component, 0, ecs->componentPools[componentId].unitSize);
|
memset(component, 0, ecs->componentPools[componentId].unitSize);
|
||||||
|
|
@ -358,7 +406,11 @@ void *BECS_ComponentAdd(BECS_ECS *ecs, BECS_Entity entity, BECS_ComponentID comp
|
||||||
|
|
||||||
void BECS_ComponentRemove(BECS_ECS *ecs, BECS_Entity entity, BECS_ComponentID componentId)
|
void BECS_ComponentRemove(BECS_ECS *ecs, BECS_Entity entity, BECS_ComponentID componentId)
|
||||||
{
|
{
|
||||||
if (!ecs->aliveEntites[entity])
|
assert(ecs != NULL);
|
||||||
|
assert(entity >= 0 && entity < BECS_MAX_ENTITIES);
|
||||||
|
assert(componentId < ecs->componentTypeCount);
|
||||||
|
|
||||||
|
if (!ecs->aliveEntities[entity])
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -368,8 +420,11 @@ void BECS_ComponentRemove(BECS_ECS *ecs, BECS_Entity entity, BECS_ComponentID co
|
||||||
|
|
||||||
void *BECS_ComponentGet(BECS_ECS *ecs, BECS_Entity entity, BECS_ComponentID componentId)
|
void *BECS_ComponentGet(BECS_ECS *ecs, BECS_Entity entity, BECS_ComponentID componentId)
|
||||||
{
|
{
|
||||||
|
assert(ecs != NULL);
|
||||||
|
assert(entity >= 0 && entity < BECS_MAX_ENTITIES);
|
||||||
|
assert(componentId < ecs->componentTypeCount);
|
||||||
|
|
||||||
if (!ecs->aliveEntites[entity])
|
if (!ecs->aliveEntities[entity])
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -378,7 +433,11 @@ void *BECS_ComponentGet(BECS_ECS *ecs, BECS_Entity entity, BECS_ComponentID comp
|
||||||
|
|
||||||
bool BECS_ComponentHas(BECS_ECS *ecs, BECS_Entity entity, BECS_ComponentID componentId)
|
bool BECS_ComponentHas(BECS_ECS *ecs, BECS_Entity entity, BECS_ComponentID componentId)
|
||||||
{
|
{
|
||||||
if (!ecs->aliveEntites[entity])
|
assert(ecs != NULL);
|
||||||
|
assert(entity >= 0 && entity < BECS_MAX_ENTITIES);
|
||||||
|
assert(componentId < ecs->componentTypeCount);
|
||||||
|
|
||||||
|
if (!ecs->aliveEntities[entity])
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
23
test/main.c
23
test/main.c
|
|
@ -48,6 +48,20 @@ int main(void) {
|
||||||
BECS_Entity entity1 = BECS_EntityCreate(&ecs);
|
BECS_Entity entity1 = BECS_EntityCreate(&ecs);
|
||||||
BECS_Entity entity2 = BECS_EntityCreate(&ecs);
|
BECS_Entity entity2 = BECS_EntityCreate(&ecs);
|
||||||
|
|
||||||
|
uint32_t i;
|
||||||
|
for (i = 0; i < BECS_MAX_ENTITIES; i++)
|
||||||
|
{
|
||||||
|
BECS_Entity entity = BECS_EntityCreate(&ecs);
|
||||||
|
if (entity != BECS_NULL_ENTITY)
|
||||||
|
{
|
||||||
|
printf("%u\n", entity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Reached Max Entity Count\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BECS_ComponentAdd(&ecs, entity1, COMPA);
|
BECS_ComponentAdd(&ecs, entity1, COMPA);
|
||||||
BECS_ComponentAdd(&ecs, entity2, COMPB);
|
BECS_ComponentAdd(&ecs, entity2, COMPB);
|
||||||
|
|
||||||
|
|
@ -74,5 +88,14 @@ int main(void) {
|
||||||
printf("Entity:%u has compB\n", entity2);
|
printf("Entity:%u has compB\n", entity2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compA *thingA = (compA *)BECS_ComponentGet(&ecs, entity1, COMPA);
|
||||||
|
compB *thingB = (compB *)BECS_ComponentGet(&ecs, entity1, COMPB);
|
||||||
|
|
||||||
|
BECS_ComponentRemove(&ecs, entity1, COMPA);
|
||||||
|
BECS_ComponentRemove(&ecs, entity2, COMPB);
|
||||||
|
|
||||||
|
BECS_ComponentRemove(&ecs, entity1, COMPB);
|
||||||
|
BECS_ComponentRemove(&ecs, entity2, COMPA);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue