187 lines
5.1 KiB
C
187 lines
5.1 KiB
C
#ifndef BECS_H
|
|
#define BECS_H
|
|
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
|
|
#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 {
|
|
uint32_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;
|
|
}
|
|
|
|
void BECS_InitComponentArray(BECS_ECS *ecs, size_t size, uint32_t componentIndex)
|
|
{
|
|
ecs->componentArrays[componentIndex] = {};
|
|
ecs->componentArrays[componentIndex].lastEntityAdded = BECS_NULL_INDEX;
|
|
ecs->componentArrays[componentIndex].unitSize = size;
|
|
ecs->componentArrays[componentIndex].denseArraylength= 0;
|
|
ecs->componentArrays[componentIndex].denseArray = NULL;
|
|
}
|
|
|
|
BECS_ECS *BECS_Init
|
|
(void *memory, size_t size, BECS_Properties props)
|
|
{
|
|
BECS_ECS *ecs = (BECS_ECS *)memory;
|
|
*ecs = {};
|
|
ecs->props = props;
|
|
|
|
for (uint32_t i = 0; i < NUM_COMPONENTS; i++)
|
|
{
|
|
ecs->componentArrays[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; i < MAX_ENTITIES; i++)
|
|
{
|
|
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)
|
|
{
|
|
if (entityID > MAX_ENTITIES)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
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->denseArraylength--;
|
|
componentArray->sparseArray[entityID] = lastEntityAddedIndex;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void *BECS_GetComponent(BECS_ECS *ecs, uint32_t entityID, uint32_t componentIndex)
|
|
{
|
|
void *component = NULL;
|
|
if (componentIndex > NUM_COMPONENTS)
|
|
return component;
|
|
|
|
BECS_ComponentArray *componentArray = &ecs->componentArrays[componentIndex];
|
|
|
|
uint32_t componentDenseIndex = componentArray->sparseArray[entityID];
|
|
|
|
if (componentDenseIndex == BECS_NULL_INDEX)
|
|
{
|
|
return component;
|
|
} else {
|
|
component = componentArray->denseArray;
|
|
}
|
|
|
|
return component;
|
|
}
|
|
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
#endif
|