mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 07:11:41 +00:00
[ecs] Split component registration from pool creation
While this does require an extra call after registering components, it allows for multiple component sets (ie, sub-systems) to be registered before the component pools are created. The base id for the registered component set is returned so it can be passed to the subsystem as needed.
This commit is contained in:
parent
3c4dccf801
commit
b230fe18ce
17 changed files with 54 additions and 26 deletions
|
@ -34,6 +34,7 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "QF/darray.h"
|
||||
#include "QF/qtypes.h"
|
||||
#include "QF/progs.h"//FIXME for PR_RESMAP
|
||||
|
||||
|
@ -58,22 +59,26 @@ typedef struct ecs_pool_s {
|
|||
uint32_t max_count; // current capacity for components/entity ids
|
||||
} ecs_pool_t;
|
||||
|
||||
typedef struct DARRAY_TYPE(component_t) componentset_t;
|
||||
|
||||
typedef struct ecs_registry_s {
|
||||
uint32_t *entities;
|
||||
uint32_t next;
|
||||
uint32_t available;
|
||||
uint32_t num_entities;
|
||||
uint32_t max_entities;
|
||||
const component_t *components;
|
||||
componentset_t components;
|
||||
ecs_pool_t *comp_pools;
|
||||
uint32_t num_components;
|
||||
PR_RESMAP (hierarchy_t) hierarchies;//FIXME find a better way
|
||||
} ecs_registry_t;
|
||||
|
||||
ecs_registry_t *ECS_NewRegistry (void);
|
||||
void ECS_DelRegistry (ecs_registry_t *registry);
|
||||
void ECS_RegisterComponents (ecs_registry_t *registry,
|
||||
const component_t *components, uint32_t count);
|
||||
uint32_t ECS_RegisterComponents (ecs_registry_t *registry,
|
||||
const component_t *components,
|
||||
uint32_t count);
|
||||
void ECS_CreateComponentPools (ecs_registry_t *registry);
|
||||
|
||||
|
||||
#ifndef __compar_d_fn_t_defined
|
||||
#define __compar_d_fn_t_defined
|
||||
|
|
|
@ -97,7 +97,7 @@ Ent_HasComponent (uint32_t ent, uint32_t comp, ecs_registry_t *reg)
|
|||
ENTINLINE void *
|
||||
Ent_GetComponent (uint32_t ent, uint32_t comp, ecs_registry_t *reg)
|
||||
{
|
||||
const component_t *component = ®->components[comp];
|
||||
const component_t *component = ®->components.a[comp];
|
||||
uint32_t ind = reg->comp_pools[comp].sparse[Ent_Index (ent)];
|
||||
byte *data = reg->comp_pools[comp].data;
|
||||
return data + ind * component->size;
|
||||
|
@ -113,10 +113,10 @@ Ent_SetComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry,
|
|||
{
|
||||
void *dst = Ent_AddComponent (ent, comp, registry);
|
||||
if (data) {
|
||||
return Component_CopyElements (®istry->components[comp],
|
||||
return Component_CopyElements (®istry->components.a[comp],
|
||||
dst, 0, data, 0, 1);
|
||||
} else {
|
||||
return Component_CreateElements (®istry->components[comp],
|
||||
return Component_CreateElements (®istry->components.a[comp],
|
||||
dst, 0, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,6 +49,9 @@ enum scene_components {
|
|||
scene_old_origin, //XXX FIXME XXX should not be here
|
||||
scene_colormap,
|
||||
|
||||
scene_canvas,
|
||||
scene_vref, //view hierarchy reference
|
||||
|
||||
//FIXME these should probably be private to the sw renderer (and in a
|
||||
//group, which needs to be implemented), but need to sort out a good
|
||||
//scheme for semi-dynamic components
|
||||
|
|
|
@ -21,7 +21,7 @@ extern vid_render_funcs_t *vid_render_funcs;
|
|||
#define vr_funcs vid_render_funcs
|
||||
|
||||
extern refdef_t r_refdef;
|
||||
#define SW_COMP(comp, id) ((void *)((byte *)r_refdef.registry->comp_pools[comp].data + (id) * r_refdef.registry->components[comp].size))
|
||||
#define SW_COMP(comp, id) ((void *)((byte *)r_refdef.registry->comp_pools[comp].data + (id) * r_refdef.registry->components.a[comp].size))
|
||||
extern int r_viewsize;
|
||||
|
||||
void R_LineGraph (int x, int y, int *h_vals, int count, int height);
|
||||
|
|
|
@ -266,6 +266,7 @@ HUD_Init (void)
|
|||
{
|
||||
hud_registry = ECS_NewRegistry ();
|
||||
ECS_RegisterComponents (hud_registry, hud_components, hud_comp_count);
|
||||
ECS_CreateComponentPools (hud_registry);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1023,6 +1023,7 @@ C_Init (void)
|
|||
{
|
||||
client_reg = ECS_NewRegistry ();
|
||||
ECS_RegisterComponents (client_reg, client_components, client_comp_count);
|
||||
ECS_CreateComponentPools (client_reg);
|
||||
|
||||
#ifdef __QNXNTO__
|
||||
setlocale (LC_ALL, "C-TRADITIONAL");
|
||||
|
|
|
@ -679,6 +679,7 @@ init (void)
|
|||
|
||||
server_reg = ECS_NewRegistry ();
|
||||
ECS_RegisterComponents (server_reg, server_components, server_comp_count);
|
||||
ECS_CreateComponentPools (server_reg);
|
||||
|
||||
get_size (&screen_x, &screen_y);
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ VISIBLE ecs_registry_t *
|
|||
ECS_NewRegistry (void)
|
||||
{
|
||||
ecs_registry_t *reg = calloc (1, sizeof (ecs_registry_t));
|
||||
reg->components = (componentset_t) DARRAY_STATIC_INIT (32);
|
||||
reg->next = Ent_Index (nullent);
|
||||
return reg;
|
||||
}
|
||||
|
@ -46,7 +47,7 @@ VISIBLE void
|
|||
ECS_DelRegistry (ecs_registry_t *registry)
|
||||
{
|
||||
free (registry->entities);
|
||||
for (uint32_t i = 0; i < registry->num_components; i++) {
|
||||
for (uint32_t i = 0; i < registry->components.size; i++) {
|
||||
free (registry->comp_pools[i].sparse);
|
||||
free (registry->comp_pools[i].dense);
|
||||
free (registry->comp_pools[i].data);
|
||||
|
@ -55,15 +56,24 @@ ECS_DelRegistry (ecs_registry_t *registry)
|
|||
free (registry);
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
VISIBLE uint32_t
|
||||
ECS_RegisterComponents (ecs_registry_t *registry,
|
||||
const component_t *components, uint32_t count)
|
||||
{
|
||||
registry->num_components = count;
|
||||
registry->components = components;
|
||||
uint32_t base = registry->components.size;
|
||||
DARRAY_RESIZE (®istry->components, base + count);
|
||||
memcpy (registry->components.a + base, components,
|
||||
count * sizeof (component_t));
|
||||
return base;
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
ECS_CreateComponentPools (ecs_registry_t *registry)
|
||||
{
|
||||
uint32_t count = registry->components.size;
|
||||
registry->comp_pools = calloc (count, sizeof (ecs_pool_t));
|
||||
size_t size = registry->max_entities * sizeof (uint32_t);
|
||||
for (uint32_t i = 0; i < registry->num_components; i++) {
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
registry->comp_pools[i].sparse = malloc (size);
|
||||
memset (registry->comp_pools[i].sparse, nullent, size);
|
||||
}
|
||||
|
@ -114,14 +124,14 @@ VISIBLE void
|
|||
ECS_SortComponentPool (ecs_registry_t *registry, uint32_t component,
|
||||
__compar_d_fn_t cmp, void *arg)
|
||||
{
|
||||
if (component >= registry->num_components) {
|
||||
if (component >= registry->components.size) {
|
||||
Sys_Error ("ECS_SortComponentPool: invalid component: %u", component);
|
||||
}
|
||||
ecs_pool_t *pool = ®istry->comp_pools[component];
|
||||
if (!pool->count) {
|
||||
return;
|
||||
}
|
||||
__auto_type comp = ®istry->components[component];
|
||||
__auto_type comp = ®istry->components.a[component];
|
||||
ecs_sort_t sortctx = { .cmp = cmp, .arg = arg, .pool = pool, .comp = comp };
|
||||
heapsort_s (pool->dense, pool->count, sizeof (uint32_t),
|
||||
ecs_compare, ecs_swap, &sortctx);
|
||||
|
@ -145,7 +155,7 @@ ECS_NewEntity (ecs_registry_t *registry)
|
|||
registry->max_entities += ENT_GROW;
|
||||
size_t size = registry->max_entities * sizeof (uint32_t);
|
||||
registry->entities = realloc (registry->entities, size);
|
||||
for (uint32_t i = 0; i < registry->num_components; i++) {
|
||||
for (uint32_t i = 0; i < registry->components.size; i++) {
|
||||
uint32_t *sparse = registry->comp_pools[i].sparse;
|
||||
sparse = realloc (sparse, size);
|
||||
memset (sparse + registry->max_entities - ENT_GROW, nullent,
|
||||
|
@ -169,7 +179,7 @@ ECS_DelEntity (ecs_registry_t *registry, uint32_t ent)
|
|||
registry->next = id;
|
||||
registry->available++;
|
||||
|
||||
for (uint32_t i = 0; i < registry->num_components; i++) {
|
||||
for (uint32_t i = 0; i < registry->components.size; i++) {
|
||||
Ent_RemoveComponent (ent, i, registry);
|
||||
}
|
||||
}
|
||||
|
@ -178,7 +188,7 @@ VISIBLE void
|
|||
ECS_RemoveEntities (ecs_registry_t *registry, uint32_t component)
|
||||
{
|
||||
ecs_pool_t *pool = ®istry->comp_pools[component];
|
||||
const component_t *comp = ®istry->components[component];
|
||||
const component_t *comp = ®istry->components.a[component];
|
||||
__auto_type destroy = comp->destroy;
|
||||
if (destroy) {
|
||||
byte *data = registry->comp_pools[component].data;
|
||||
|
|
|
@ -45,7 +45,7 @@ Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry)
|
|||
pool->max_count += COMP_GROW;
|
||||
pool->dense = realloc (pool->dense,
|
||||
pool->max_count * sizeof (uint32_t));
|
||||
Component_ResizeArray (®istry->components[comp], &pool->data,
|
||||
Component_ResizeArray (®istry->components.a[comp], &pool->data,
|
||||
pool->max_count);
|
||||
}
|
||||
uint32_t ind = pool->count++;
|
||||
|
@ -63,12 +63,12 @@ Ent_RemoveComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry)
|
|||
uint32_t ind = pool->sparse[id];
|
||||
if (ind < pool->count && pool->dense[ind] == ent) {
|
||||
uint32_t last = pool->count - 1;
|
||||
Component_DestroyElements (®istry->components[comp], pool->data,
|
||||
Component_DestroyElements (®istry->components.a[comp], pool->data,
|
||||
ind, 1);
|
||||
if (last > ind) {
|
||||
pool->sparse[Ent_Index (pool->dense[last])] = ind;
|
||||
pool->dense[ind] = pool->dense[last];
|
||||
Component_MoveElements (®istry->components[comp], pool->data,
|
||||
Component_MoveElements (®istry->components.a[comp], pool->data,
|
||||
ind, last, 1);
|
||||
}
|
||||
pool->count--;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include "QF/simd/types.h"
|
||||
#include "QF/mathlib.h"
|
||||
#include "QF/ecs/component.h"
|
||||
#include "QF/ecs.h"
|
||||
|
||||
enum test_components {
|
||||
test_position,
|
||||
|
@ -62,7 +62,7 @@ check_ent_components (const uint32_t *ents, uint32_t count, uint32_t comp,
|
|||
ecs_registry_t *reg)
|
||||
{
|
||||
ecs_pool_t *pool = ®->comp_pools[comp];
|
||||
const component_t *component = ®->components[comp];
|
||||
const component_t *component = ®->components.a[comp];
|
||||
if (pool->count != count) {
|
||||
printf ("%s pool has wrong object count: %d %d\n", component->name,
|
||||
pool->count, count);
|
||||
|
@ -106,6 +106,8 @@ main (void)
|
|||
{
|
||||
ecs_registry_t *reg = ECS_NewRegistry ();
|
||||
ECS_RegisterComponents (reg, test_components, test_num_components);
|
||||
ECS_CreateComponentPools (reg);
|
||||
|
||||
uint32_t enta = ECS_NewEntity (reg);
|
||||
uint32_t entb = ECS_NewEntity (reg);
|
||||
uint32_t entc = ECS_NewEntity (reg);
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "QF/ecs/component.h"
|
||||
#include "QF/ecs/hierarchy.h"
|
||||
#include "QF/ecs.h"
|
||||
|
||||
enum {
|
||||
test_href,
|
||||
|
@ -886,6 +885,7 @@ main (void)
|
|||
{
|
||||
test_reg = ECS_NewRegistry ();
|
||||
ECS_RegisterComponents (test_reg, test_components, test_num_components);
|
||||
ECS_CreateComponentPools (test_reg);
|
||||
|
||||
if (test_single_transform ()) { return 1; }
|
||||
if (test_parent_child_init ()) { return 1; }
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "QF/ecs/component.h"
|
||||
#include "QF/ecs.h"
|
||||
|
||||
static int
|
||||
test_new_del (void)
|
||||
|
|
|
@ -213,6 +213,7 @@ Scene_NewScene (void)
|
|||
|
||||
scene->reg = ECS_NewRegistry ();
|
||||
ECS_RegisterComponents (scene->reg, scene_components, scene_comp_count);
|
||||
ECS_CreateComponentPools (scene->reg);
|
||||
|
||||
scene_resources_t *res = calloc (1, sizeof (scene_resources_t));
|
||||
*(scene_resources_t **)&scene->resources = res;
|
||||
|
|
|
@ -280,6 +280,7 @@ main (void)
|
|||
|
||||
test_reg = ECS_NewRegistry ();
|
||||
ECS_RegisterComponents (test_reg, test_components, 1);
|
||||
ECS_CreateComponentPools (test_reg);
|
||||
|
||||
if (test_flow (right_down_views, right_down_count, view_flow_right_down)) {
|
||||
printf ("right-down failed\n");
|
||||
|
|
|
@ -280,6 +280,7 @@ main (void)
|
|||
|
||||
test_reg = ECS_NewRegistry ();
|
||||
ECS_RegisterComponents (test_reg, test_components, 1);
|
||||
ECS_CreateComponentPools (test_reg);
|
||||
|
||||
if (test_flow (right_down_views, right_down_count, view_flow_right_down)) {
|
||||
printf ("right-down failed\n");
|
||||
|
|
|
@ -64,6 +64,7 @@ main (void)
|
|||
int ret = 0;
|
||||
ecs_registry_t *registry = ECS_NewRegistry ();
|
||||
ECS_RegisterComponents (registry, test_components, 1);
|
||||
ECS_CreateComponentPools (registry);
|
||||
|
||||
passage_t *passage = Passage_New (registry, test_href);
|
||||
Passage_ParseText (passage, test_text);
|
||||
|
|
|
@ -92,6 +92,7 @@ Text_Init (void)
|
|||
{
|
||||
text_reg = ECS_NewRegistry ();
|
||||
ECS_RegisterComponents (text_reg, text_components, text_comp_count);
|
||||
ECS_CreateComponentPools (text_reg);
|
||||
}
|
||||
|
||||
typedef struct glyphnode_s {
|
||||
|
|
Loading…
Reference in a new issue