diff --git a/include/QF/ecs.h b/include/QF/ecs.h index 540ea09d6..dc082c016 100644 --- a/include/QF/ecs.h +++ b/include/QF/ecs.h @@ -63,13 +63,14 @@ typedef struct ecs_pool_s { typedef struct DARRAY_TYPE(component_t) componentset_t; typedef struct ecs_range_s { + uint32_t start; uint32_t end; } ecs_range_t; typedef struct ecs_subpool_s { - ecs_range_t *ranges; uint32_t *rangeids; uint32_t *sorted; + uint32_t *ranges; uint32_t next; uint32_t available; uint32_t num_ranges; @@ -98,6 +99,10 @@ typedef struct ecs_system_s { uint32_t base; } ecs_system_t; +#include "QF/ecs/entity.h" + +#define ECSINLINE GNU89INLINE inline + ecs_registry_t *ECS_NewRegistry (void); void ECS_DelRegistry (ecs_registry_t *registry); uint32_t ECS_RegisterComponents (ecs_registry_t *registry, @@ -120,11 +125,31 @@ void ECS_RemoveEntities (ecs_registry_t *registry, uint32_t component); uint32_t ECS_NewSubpoolRange (ecs_registry_t *registry, uint32_t component); void ECS_DelSubpoolRange (ecs_registry_t *registry, uint32_t component, uint32_t id); +ECSINLINE ecs_range_t ECS_GetSubpoolRange (ecs_registry_t *registry, + uint32_t component, uint32_t id); + +#undef ECSINLINE +#ifndef IMPLEMENT_ECS_Funcs +#define ECSINLINE GNU89INLINE inline +#else +#define ECSINLINE VISIBLE +#endif + +ECSINLINE +ecs_range_t +ECS_GetSubpoolRange (ecs_registry_t *registry, uint32_t component, uint32_t id) +{ + ecs_subpool_t *subpool = ®istry->subpools[component]; + uint32_t ind = subpool->sorted[Ent_Index (id)]; + ecs_range_t range = { + .start = ind ? subpool->ranges[ind - 1] : 0, + .end = subpool->ranges[ind], + }; + return range; +} #undef ECSINLINE ///@} -#include "QF/ecs/entity.h" - #endif//__QF_ecs_h diff --git a/libs/ecs/entity.c b/libs/ecs/entity.c index e86898d59..1f7892c37 100644 --- a/libs/ecs/entity.c +++ b/libs/ecs/entity.c @@ -67,11 +67,11 @@ Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) uint32_t rangeind = subpool->sorted[Ent_Index (rangeid)]; printf ("ent:%d rangeid:%d rangeind:%d\n", ent, rangeid, rangeind); while (rind-- > rangeind) { - if (subpool->ranges[rind].end == ind) { - subpool->ranges[rind].end++; + if (subpool->ranges[rind] == ind) { + subpool->ranges[rind]++; continue; } - uint32_t end = subpool->ranges[rind].end++; + uint32_t end = subpool->ranges[rind]++; Component_MoveElements (c, pool->data, ind, end, 1); swap_inds (&pool->sparse[Ent_Index (pool->dense[end])], &pool->sparse[Ent_Index (pool->dense[ind])]); @@ -87,24 +87,24 @@ static int range_cmp (const void *_key, const void *_range, void *_subpool) { const uint32_t *key = _key; - const ecs_range_t *range = _range; + const uint32_t *range = _range; ecs_subpool_t *subpool = _subpool; - if (*key >= range->end) { + if (*key >= *range) { return -1; } if (range - subpool->ranges > 0) { - return *key >= range[-1].end ? 0 : -1; + return *key >= range[-1] ? 0 : -1; } return 0; } -static ecs_range_t * +static uint32_t * find_range (ecs_subpool_t *subpool, uint32_t ind) { return bsearch_r (&ind, subpool->ranges, subpool->num_ranges - subpool->available, - sizeof (ecs_range_t), range_cmp, subpool); + sizeof (uint32_t), range_cmp, subpool); } VISIBLE void @@ -120,9 +120,9 @@ Ent_RemoveComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) Component_DestroyElements (c, pool->data, ind, 1); if (subpool->num_ranges - subpool->available) { uint32_t range_count = subpool->num_ranges - subpool->available; - ecs_range_t *range = find_range (subpool, ind); + uint32_t *range = find_range (subpool, ind); while (range - subpool->ranges < range_count) { - uint32_t end = --range->end; + uint32_t end = --*range; range++; pool->sparse[Ent_Index (pool->dense[end])] = ind; pool->dense[ind] = pool->dense[end]; diff --git a/libs/ecs/subpool.c b/libs/ecs/subpool.c index ba229e805..8da0b6f6a 100644 --- a/libs/ecs/subpool.c +++ b/libs/ecs/subpool.c @@ -64,11 +64,9 @@ ECS_NewSubpoolRange (ecs_registry_t *registry, uint32_t component) } uint32_t end = 0; if (num_ranges) { - end = subpool->ranges[num_ranges - 1].end; + end = subpool->ranges[num_ranges - 1]; } - subpool->ranges[Ent_Index (id)] = (ecs_range_t) { - .end = end, - }; + subpool->ranges[subpool->sorted[Ent_Index (id)]] = end; return id; } diff --git a/libs/ecs/test/test-subpools.c b/libs/ecs/test/test-subpools.c index 16fea08bb..9e51d31b7 100644 --- a/libs/ecs/test/test-subpools.c +++ b/libs/ecs/test/test-subpools.c @@ -52,13 +52,13 @@ static int check_subpool_ranges (ecs_subpool_t *subpool, uint32_t *expect) { uint32_t count = subpool->num_ranges - subpool->available; - ecs_range_t *range = subpool->ranges; + uint32_t *range = subpool->ranges; while (count--) { - ecs_range_t *r = range++; - uint32_t e = *expect++; - printf ("%d: %d %d\n", (int)(r - subpool->ranges), r->end, e); - if (r->end != e++) { + uint32_t *r = range++; + uint32_t e = *expect++; + printf ("%d: %d %d\n", (int)(r - subpool->ranges), *r, e); + if (*r != e++) { return 1; } } @@ -109,9 +109,9 @@ main (void) return 1; } for (uint32_t i = 0; i < reg->subpools[base + test_obj].num_ranges; i++) { - if (reg->subpools[base + test_obj].ranges[i].end != 0) { + if (reg->subpools[base + test_obj].ranges[i] != 0) { printf ("end %d not 0 count: %d\n", i, - reg->subpools[base + test_obj].ranges[i].end); + reg->subpools[base + test_obj].ranges[i]); return 1; } } @@ -234,6 +234,11 @@ main (void) sp2 = ECS_NewSubpoolRange (reg, base + test_obj); printf ("sp2: %d\n", sp2); + if (check_subpool_ranges (®->subpools[base + test_obj], + (uint32_t[]) { 2, 4, 4 })) { + printf ("oops\n"); + return 1; + } Ent_SetComponent (entc, base + test_subpool, reg, &sp2); Ent_SetComponent (entf, base + test_subpool, reg, &sp2); Ent_SetComponent (entg, base + test_subpool, reg, &sp2);