becs/becs2.h

189 lines
5.5 KiB
C

#ifndef BECS_H
#define BECS_H
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <assert.h>
typedef struct Entity Entity;
typedef struct BECS_Properties BECS_Properties;
typedef struct BECS_ComponentArray BECS_ComponentArray;
typedef struct BECS_ECS BECS_ECS;
size_t BECS_GetMinMemorySize(BECS_Properties props);
BECS_ECS *BECS_Init(void *memory, size_t size, BECS_Properties props);
void *BECS_AddComponent(BECS_ECS *ecs, uint32_t entityID, uint32_t componentIndex);
void *BECS_GetComponent(BECS_ECS *ecs, uint32_t entityID, uint32_t componentIndex);
//#define MAX_ENTITIES 100:
//#define NUM_COMPONENTS 2
#ifdef MAX_ENTITIES
#ifdef NUM_COMPONENTS
#ifdef BECS_IMPLEMENTATION
#define BECS_NULL_INDEX MAX_ENTITIES + 1
struct Entity {
uint64_t componentBitMask;
};
struct BECS_Properties {
size_t componentSizes[NUM_COMPONENTS];
};
struct BECS_ComponentArray {
uint32_t lastEntityAdded;
size_t unitSize;
uint32_t sparseArray[MAX_ENTITIES];
void *denseArray;
uint32_t denseArraylength;
};
struct BECS_ECS {
Entity entities[MAX_ENTITIES];
BECS_Properties props;
BECS_ComponentArray componentArrays[NUM_COMPONENTS];
};
size_t BECS_GetMinMemorySize(BECS_Properties props)
{
size_t totalSize = 0;
totalSize += sizeof(BECS_ECS);
totalSize += sizeof(BECS_ComponentArray) * NUM_COMPONENTS;
for (uint32_t i = 0; i < NUM_COMPONENTS; i++)
{
totalSize += props.componentSizes[i] * MAX_ENTITIES;
}
return totalSize;
}
BECS_ECS *BECS_Init(void *memory, size_t size, BECS_Properties props)
{
assert(memory);
BECS_ECS *ecs = (BECS_ECS *)memory;
ecs->props = props;
for (uint32_t i = 0; i < NUM_COMPONENTS; i++)
{
ecs->componentArrays[i].lastEntityAdded = BECS_NULL_INDEX;
ecs->componentArrays[i].unitSize = props.componentSizes[i];
ecs->componentArrays[i].denseArraylength = 0;
for (uint32_t j = 0; j < MAX_ENTITIES; j++)
{
ecs->componentArrays[i].sparseArray[j] = BECS_NULL_INDEX;
}
}
uintptr_t startOfComponentArrays = (uintptr_t)(ecs + 1);
for (uint32_t i = 0; i < NUM_COMPONENTS; i++)
{
startOfComponentArrays += props.componentSizes[i] * MAX_ENTITIES;
ecs->componentArrays[i].denseArray = (void *)startOfComponentArrays;
}
return ecs;
}
void *BECS_AddComponent(BECS_ECS *ecs, uint32_t entityID, uint32_t componentIndex)
{
if (entityID > MAX_ENTITIES)
{
return NULL;
}
uint64_t componentBitMask = 0 | (1 << (componentIndex + 1));
if (ecs->entities[entityID].componentBitMask & componentBitMask)
{
return NULL;
}
ecs->entities[entityID].componentBitMask |= componentBitMask;
BECS_ComponentArray *componentArray = &ecs->componentArrays[componentIndex];
componentArray->sparseArray[entityID] = componentArray->denseArraylength;
size_t componentSize = ecs->props.componentSizes[componentIndex];
uint32_t componentOffset = componentSize * componentArray->sparseArray[entityID];
void *component = (void *)((uintptr_t)componentArray->denseArray + componentOffset);
componentArray->denseArraylength++;
componentArray->lastEntityAdded = entityID;
return component;
}
int32_t BECS_RemoveComponent(BECS_ECS *ecs, uint32_t entityID, uint32_t componentIndex)
{
assert(entityID < MAX_ENTITIES);
uint64_t componentBitMask = 0 | (1 << (componentIndex + 1));
if (!(ecs->entities[entityID].componentBitMask & componentBitMask))
{
return 2;
}
BECS_ComponentArray * componentArray = &ecs->componentArrays[componentIndex];
if (entityID == componentArray->lastEntityAdded)
{
componentArray->sparseArray[entityID] = BECS_NULL_INDEX;
componentArray->denseArraylength--;
for (uint32_t i = 0; i < MAX_ENTITIES; i++)
{
if (componentArray->sparseArray[i] == componentArray->denseArraylength - 1)
{
componentArray->lastEntityAdded = componentArray->sparseArray[i];
break;
}
}
ecs->entities[entityID].componentBitMask &= ~(1 << (componentIndex + 1));
return 0;
}
uint32_t lastEntityAddedIndex = componentArray->sparseArray[componentArray->lastEntityAdded];
uint32_t deletedCompIndex = componentArray->sparseArray[entityID];
uintptr_t denseArray = (uintptr_t)componentArray->denseArray;
uintptr_t lastEntityAdded = denseArray + (lastEntityAddedIndex * componentArray->unitSize);
uintptr_t deletedComp = denseArray + (lastEntityAddedIndex * componentArray->unitSize);
memcpy((void *)deletedComp, (void*)lastEntityAdded, componentArray->unitSize);
componentArray->sparseArray[entityID] = lastEntityAddedIndex;
componentArray->denseArraylength--;
ecs->entities[entityID].componentBitMask &= ~(1 << (componentIndex + 1));
return 0;
}
void *BECS_GetComponent(BECS_ECS *ecs, uint32_t entityID, uint32_t componentIndex)
{
assert(entityID < MAX_ENTITIES);
assert(componentIndex < NUM_COMPONENTS);
void *component = NULL;
BECS_ComponentArray *componentArray = &ecs->componentArrays[componentIndex];
uint32_t componentDenseIndex = componentArray->sparseArray[entityID];
if (componentDenseIndex == BECS_NULL_INDEX)
{
return component;
} else {
size_t componentSize = componentArray->unitSize;
component = (void *)((uintptr_t)componentArray->denseArray + (componentSize * componentDenseIndex));
}
return component;
}
#endif
#endif
#endif
#endif