2024-08-18 04:30:29 +00:00
|
|
|
// 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]) {
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Retrieve the component list for the given component id
|
|
|
|
// static void *haloo_ecs_getcomponents(haloo_ecs *ecs, int cid) {
|
|
|
|
// // Let the user fail in spectacular ways if cid is bad
|
|
|
|
// return ecs->components[cid];
|
|
|
|
// }
|
|
|
|
|
|
|
|
// static void * haloo_ecs_entitycomponent(haloo_ecs *ecs, int eid, int cid) {
|
|
|
|
// // Let the user fail in spectacular ways if cid is bad
|
|
|
|
// return haloo_ecs_getcomponents(ecs, cid)
|
|
|
|
// }
|
|
|
|
|
|
|
|
// Convert component id into flag for use with system identification
|
|
|
|
#define HECS_CIDF(id) (1ULL << id)
|
|
|
|
// Create the storage for a new component within the entity system. Will
|
|
|
|
// create a variable within the given scope with the given name. DOES
|
|
|
|
// NOT MALLOC
|
|
|
|
#define HECS_NEWCOMPONENT(type, name) type name[HECS_MAXENTITIES];
|
|
|
|
// 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) \
|
|
|
|
HECS_NEWCOMPONENT(type, __##type); \
|
|
|
|
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)
|
|
|
|
//__ecs_cpos[playerid] = (ecs_cpos){.x = 1, .y = 1};
|
|
|
|
// 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)
|
|
|
|
// ecs.compenents[ecs.numcomponents++] = __ecs__type;
|
|
|
|
|
|
|
|
// 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, ...) \
|
|
|
|
{ \
|
2024-08-18 05:26:07 +00:00
|
|
|
const hecs_cidt _hecstemp[] = {__VA_ARGS__}; \
|
|
|
|
const int _hecsnumargs = sizeof(_hecstemp) / sizeof(hecs_cidt); \
|
2024-08-18 04:30:29 +00:00
|
|
|
hecs_cidt _hecsflags = 0; \
|
2024-08-18 05:26:07 +00:00
|
|
|
for (int _hecsi = 0; _hecsi < _hecsnumargs; _hecsi++) { \
|
2024-08-18 04:30:29 +00:00
|
|
|
_hecsflags |= _hecstemp[_hecsi]; \
|
|
|
|
} \
|
|
|
|
if (haloo_ecs_match(ecs, eid, _hecsflags)) { \
|
|
|
|
func(ecs, eid, __VA_ARGS__); \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|