104 lines
4.0 KiB
C
104 lines
4.0 KiB
C
// A very simple library for constructing the basis of EXTREMELY simple ecs
|
|
// systems. Made mostly for fun
|
|
|
|
#ifndef __HALOO3D_ECS_H
|
|
#define __HALOO3D_ECS_H
|
|
|
|
#include <math.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
#ifndef HECS_MAXENTITIES
|
|
#define HECS_MAXENTITIES 1024
|
|
#endif
|
|
|
|
typedef uint64_t hecs_cidt;
|
|
typedef int hecs_eidt;
|
|
|
|
#define HECS_MAXCTYPES 63 // One minus the thing
|
|
|
|
typedef struct {
|
|
hecs_cidt e_components[HECS_MAXENTITIES];
|
|
void *components[HECS_MAXCTYPES];
|
|
int numcomponents;
|
|
hecs_eidt entitytop;
|
|
} haloo_ecs;
|
|
|
|
static void haloo_ecs_init(haloo_ecs *ecs) {
|
|
memset(ecs, 0, sizeof(haloo_ecs));
|
|
}
|
|
|
|
// Add an entity with given components to ecs system.
|
|
static hecs_eidt haloo_ecs_newentity(haloo_ecs *ecs, hecs_cidt basecomponents) {
|
|
for (int i = 0; i < HECS_MAXENTITIES; i++) {
|
|
hecs_eidt id = ecs->entitytop++;
|
|
if (ecs->e_components[id] == 0) {
|
|
// Utilize the very last bit to indicate that the entity is active
|
|
ecs->e_components[id] = (1ULL << HECS_MAXCTYPES) | basecomponents;
|
|
return id;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static int haloo_ecs_match(haloo_ecs *ecs, hecs_eidt eid, hecs_cidt comps) {
|
|
hecs_cidt realcomps = (1ULL << HECS_MAXCTYPES) | comps;
|
|
return (ecs->e_components[eid] & realcomps) == realcomps;
|
|
}
|
|
|
|
static void haloo_ecs_removeentity(haloo_ecs *ecs, int eid) {
|
|
if (eid >= 0 && eid < HECS_MAXENTITIES)
|
|
ecs->e_components[eid] = 0;
|
|
}
|
|
|
|
// Add a new component to ecs. Create the type or storage with
|
|
// HECS_NEWCOMPONENT(type, name)
|
|
static int haloo_ecs_newcomponent(haloo_ecs *ecs, void *component) {
|
|
int id = ecs->numcomponents++;
|
|
ecs->components[id] = component;
|
|
return id;
|
|
}
|
|
|
|
// Convert component id into flag for use with system identification
|
|
#define HECS_CIDF(id) (1ULL << id)
|
|
|
|
// Shortcut to both create the storage and add it to the given ecs.
|
|
// Automatically stores the name as __type. Stores the id for the component in
|
|
// type_id. For convenience, another variable of type_f is created for the flag
|
|
// version of the component id
|
|
#define HECS_ADDNEWCOMPONENT(type, ecs) \
|
|
type __##type[HECS_MAXENTITIES]; \
|
|
hecs_cidt type##_id = haloo_ecs_newcomponent(ecs, __##type); \
|
|
hecs_cidt type##_f = HECS_CIDF(type##_id);
|
|
|
|
// Set component values on a given entity, also sets the flag indicating this
|
|
// component is now registered with the given entity. You should follow this
|
|
// statement immediately with the values for your component.
|
|
// Example: HECS_SETCOMPONENT(mytype, &ecs, playerid) { .x = 1, .y = 2 }
|
|
#define HECS_SETCOMPONENT(type, ecs, eid) \
|
|
(ecs)->e_components[eid] |= type##_f; \
|
|
__##type[eid] = (type)
|
|
|
|
// Retrieve a component for a single entity from the entity system,
|
|
// casting it to the given type
|
|
#define HECS_ENTITYCOMPONENT(type, eid, cid, ecs) \
|
|
(((type)ecs->components[cid]) + eid)
|
|
|
|
// Run a function against ecs using the given limiting components. Note that
|
|
// components MUST be passed in the EXACT order the function expects them!
|
|
#define HECS_RUNSYS(ecs, eid, func, ...) \
|
|
{ \
|
|
const hecs_cidt _hecstemp[] = {__VA_ARGS__}; \
|
|
const int _hecsnumargs = sizeof(_hecstemp) / sizeof(hecs_cidt); \
|
|
hecs_cidt _hecsflags = 0; \
|
|
/*eprintf("MADE ARGS: %d\n", _hecsnumargs);*/ \
|
|
for (int _hecsi = 0; _hecsi < _hecsnumargs; _hecsi++) { \
|
|
_hecsflags |= HECS_CIDF(_hecstemp[_hecsi]); \
|
|
} \
|
|
if (haloo_ecs_match(ecs, eid, _hecsflags)) { \
|
|
func(ecs, eid, __VA_ARGS__); \
|
|
} \
|
|
}
|
|
|
|
#endif
|