diff --git a/becs3.h b/becs3.h index 05a01b0..c79ccaf 100644 --- a/becs3.h +++ b/becs3.h @@ -1,8 +1,15 @@ /* * Usage: - * Define BECS_IMPLEMENTATION in exactly _one_ file before including this file * - * Eg: + * Define BECS_MAX_ENTITIES and BECS_MAX_COMPONENTS. Otherwise they will have + * the following defaults: + * + * #define BECS_MAX_ENTITIES 4096 + * #define BECS_MAX_COMPONENTS 64 + * + * Then define BECS_IMPLEMENTATION in exactly _one_ file before including this + * file as follows: + * * #define BECS_IMPLEMENTATION * #include "becs.h" */ @@ -28,6 +35,10 @@ typedef struct BECS_ECS BECS_ECS; typedef uint32_t BECS_Entity; typedef uint32_t BECS_ComponentID; +size_t BECS_GetMinMemoryArenaSize(size_t *componentSizes, size_t arrayLength); +BECS_ECS BECS_InitECS(void *memory, size_t size); +void BECS_ResetECS(BECS_ECS *ecs); + BECS_Entity BECS_EntityCreate(BECS_ECS *ecs); void BECS_EntityDestroy(BECS_ECS *ecs, BECS_Entity entity); bool BECS_IsEntityAlive(BECS_ECS *ecs, BECS_Entity entity); @@ -35,7 +46,7 @@ bool BECS_IsEntityAlive(BECS_ECS *ecs, BECS_Entity entity); BECS_ComponentID BECS_ComponentRegister(BECS_ECS *ecs, size_t componentSize, size_t maximumComponentCount); void *BECS_ComponentAdd(BECS_ECS *ecs, BECS_Entity entity, BECS_ComponentID componentId); void BECS_ComponentRemove(BECS_ECS *ecs, BECS_Entity entity, BECS_ComponentID componentId); -void* BECS_ComponentGet(BECS_ECS *ecs, BECS_Entity entity, BECS_ComponentID componentId); +void *BECS_ComponentGet(BECS_ECS *ecs, BECS_Entity entity, BECS_ComponentID componentId); bool BECS_ComponentHas(BECS_ECS *ecs, BECS_Entity entity, BECS_ComponentID componentId); #ifdef BECS_IMPLEMENTATION @@ -72,6 +83,7 @@ struct BECS_ECS { BECS_Arena arena; /* Entity Management */ + BECS_Entity nextEntity; uint32_t entityCount; BECS_Signature entitySignatures[BECS_MAX_ENTITIES]; bool aliveEntites[BECS_MAX_ENTITIES]; @@ -90,12 +102,12 @@ static BECS_Signature BECS_SignatureSet(BECS_Signature sig, BECS_ComponentID com return sig | (1ULL << componentId); } -static bool ecs_signature_has(BECS_Signature sig, BECS_ComponentID component_id) +static bool BECS_SignatureHas(BECS_Signature sig, BECS_ComponentID component_id) { return (sig & (1ULL << component_id)) != 0; } -static bool ecs_signature_matches(BECS_Signature entitySig, BECS_Signature querySig) +static bool BECS_SignatureMatches(BECS_Signature entitySig, BECS_Signature querySig) { return (entitySig & querySig) == querySig; } @@ -197,6 +209,29 @@ static bool BECS_ComponentPoolHas(BECS_ComponentPool *pool, BECS_Entity entity) return pool->sparseArray[entity] != UINT32_MAX; } +/* Helper API Functions */ + +size_t BECS_GetMinMemoryArenaSize(size_t *componentSizes, size_t arrayLength) +{ + assert(arrayLength < BECS_MAX_COMPONENTS); + size_t totalSize = 0; + totalSize += sizeof(BECS_ECS); + totalSize += sizeof(BECS_ComponentPool) * BECS_MAX_COMPONENTS; + totalSize += sizeof(BECS_Entity) * BECS_MAX_ENTITIES * BECS_MAX_COMPONENTS; + + size_t sumCompSizes = 0; + uint32_t i; + for (i = 0; i < arrayLength; i++) + { + sumCompSizes += componentSizes[i]; + } + + sumCompSizes *= BECS_MAX_ENTITIES; + totalSize += sumCompSizes; + + return totalSize; +} + /* World API Functions */ BECS_ECS BECS_InitECS(void *memory, size_t size) @@ -205,9 +240,10 @@ BECS_ECS BECS_InitECS(void *memory, size_t size) ecs.arena = BECS_CreateArena(memory, size); ecs.entityCount = 0; memset(ecs.entitySignatures, 0, sizeof(BECS_Signature) * BECS_MAX_ENTITIES); - memset(ecs.aliveEntites, 0, sizeof(bool) * BECS_MAX_ENTITIES); + memset(ecs.aliveEntites, false, sizeof(bool) * BECS_MAX_ENTITIES); memset(ecs.freeEntities, BECS_NULL_ENTITY, sizeof(BECS_Entity) * BECS_MAX_ENTITIES); ecs.freeEntityCount = 0; + ecs.nextEntity = 0; ecs.componentTypeCount = 0; uint32_t i; @@ -225,9 +261,10 @@ void BECS_ResetECS(BECS_ECS *ecs) ecs->arena = BECS_CreateArena(ecs->arena.memory, ecs->arena.capacity); ecs->entityCount = 0; memset(ecs->entitySignatures, 0, sizeof(BECS_Signature) * BECS_MAX_ENTITIES); - memset(ecs->aliveEntites, 0, sizeof(bool) * BECS_MAX_ENTITIES); + memset(ecs->aliveEntites, false, sizeof(bool) * BECS_MAX_ENTITIES); memset(ecs->freeEntities, BECS_NULL_ENTITY, sizeof(BECS_Entity) * BECS_MAX_ENTITIES); ecs->freeEntityCount = 0; + ecs->nextEntity = 0; ecs->componentTypeCount = 0; uint32_t i; @@ -240,20 +277,60 @@ void BECS_ResetECS(BECS_ECS *ecs) /* Entity API Functions */ -/* TODO: Implement Entity API Functions - BECS_Entity BECS_EntityCreate(BECS_ECS *ecs) { + BECS_Entity entity = BECS_NULL_ENTITY; + + if (ecs->nextEntity + 1 > BECS_NULL_ENTITY) + { + return entity; + } + + if (ecs->freeEntityCount) + { + /* Pop entity off the back of the free list */ + entity = ecs->freeEntities[--ecs->freeEntityCount]; + ecs->entitySignatures[entity] = 0; + ecs->aliveEntites[entity] = true; + return entity; + } + + entity = ecs->nextEntity; + ecs->aliveEntites[entity] = true; + ecs->entitySignatures[entity] = 0; + ecs->nextEntity++; + ecs->entityCount++; + return entity; } void BECS_EntityDestroy(BECS_ECS *ecs, BECS_Entity entity) { + if (!ecs->aliveEntites[entity]) + { + return; + } + + uint32_t i; + for (i = 0; i < BECS_MAX_COMPONENTS; i++) + { + BECS_Signature sig = ecs->entitySignatures[entity]; + if (BECS_SignatureHas(sig, i)) + { + BECS_ComponentRemove(ecs, entity, i); + } + } + + ecs->aliveEntites[entity] = false; + ecs->entitySignatures[entity] = 0; + ecs->freeEntities[ecs->freeEntityCount] = entity; + ecs->entityCount--; + ecs->freeEntityCount++; } bool BECS_IsEntityAlive(BECS_ECS *ecs, BECS_Entity entity) { + return ecs->aliveEntites[entity]; } -*/ /* Component API Functions */ @@ -290,7 +367,7 @@ void BECS_ComponentRemove(BECS_ECS *ecs, BECS_Entity entity, BECS_ComponentID co ecs->entitySignatures[entity] &= ~(1ULL << componentId); } -void* BECS_ComponentGet(BECS_ECS *ecs, BECS_Entity entity, BECS_ComponentID componentId) +void *BECS_ComponentGet(BECS_ECS *ecs, BECS_Entity entity, BECS_ComponentID componentId) { if (!ecs->aliveEntites[entity]) @@ -306,7 +383,7 @@ bool BECS_ComponentHas(BECS_ECS *ecs, BECS_Entity entity, BECS_ComponentID compo { return false; } - return ecs_signature_has(ecs->entitySignatures[entity], componentId); + return BECS_SignatureHas(ecs->entitySignatures[entity], componentId); } #endif /* BECS_IMPLEMENTATION */