[ecs] Make hierarchy ownership of entities optional

I'm not sure this is what I want.
This commit is contained in:
Bill Currie 2023-12-31 14:38:00 +09:00
parent 292e4ca132
commit 60c22e8fda
9 changed files with 63 additions and 20 deletions

View file

@ -54,6 +54,7 @@ typedef struct hierarchy_s {
uint32_t num_objects;
uint32_t max_objects;
uint32_t *ent;
uint8_t *own;
uint32_t *childCount;
uint32_t *childIndex;
uint32_t *parentIndex;

View file

@ -140,7 +140,8 @@ typedef void (*view_move_f) (view_t view, view_pos_t abs);
VIEWINLINE view_t View_FromEntity (ecs_system_t viewsys, uint32_t ent);
view_t View_New (ecs_system_t viewsys, view_t parent);
view_t View_AddToEntity (uint32_t ent, ecs_system_t viewsys, view_t parent);
view_t View_AddToEntity (uint32_t ent, ecs_system_t viewsys, view_t parent,
bool own);
VIEWINLINE void View_Delete (view_t view);
void View_SetParent (view_t view, view_t parent);
void View_UpdateHierarchy (view_t view);

View file

@ -40,6 +40,7 @@
#include "QF/ecs.h"
static component_t ent_component = { .size = sizeof (uint32_t) };
static component_t own_component = { .size = sizeof (uint8_t) };
static component_t childCount_component = { .size = sizeof (uint32_t) };
static component_t childIndex_component = { .size = sizeof (uint32_t) };
static component_t parentIndex_component = { .size = sizeof (uint32_t) };
@ -77,6 +78,20 @@ hierarchy_InvalidateReferences (hierarchy_t *hierarchy, uint32_t start,
}
}
static void
hierarchy_remove_reference (hierarchy_t *hierarchy, uint32_t index)
{
uint32_t ent = hierarchy->ent[index];
uint32_t href = hierarchy->href_comp;
auto reg = hierarchy->reg;
if (ECS_EntValid (ent, reg) && Ent_HasComponent (ent, href, reg)) {
hierref_t *ref = Ent_GetComponent (ent, href, reg);
ref->id = nullent;
ref->index = nullindex;
Ent_RemoveComponent (ent, href, reg);
}
}
static void
hierarchy_UpdateChildIndices (hierarchy_t *hierarchy, uint32_t start,
int offset)
@ -105,6 +120,8 @@ Hierarchy_Reserve (hierarchy_t *hierarchy, uint32_t count)
Component_ResizeArray (&ent_component,
(void **) &hierarchy->ent, new_max);
Component_ResizeArray (&own_component,
(void **) &hierarchy->own, new_max);
Component_ResizeArray (&childCount_component,
(void **) &hierarchy->childCount, new_max);
Component_ResizeArray (&childIndex_component,
@ -139,6 +156,8 @@ hierarchy_open (hierarchy_t *hierarchy, uint32_t index, uint32_t count)
}
Component_MoveElements (&ent_component,
hierarchy->ent, dstIndex, index, count);
Component_MoveElements (&own_component,
hierarchy->own, dstIndex, index, count);
Component_MoveElements (&childCount_component,
hierarchy->childCount, dstIndex, index, count);
Component_MoveElements (&childIndex_component,
@ -169,6 +188,8 @@ hierarchy_close (hierarchy_t *hierarchy, uint32_t index, uint32_t count)
count = hierarchy->num_objects - index;
Component_MoveElements (&ent_component,
hierarchy->ent, index, srcIndex, count);
Component_MoveElements (&own_component,
hierarchy->own, index, srcIndex, count);
Component_MoveElements (&childCount_component,
hierarchy->childCount, index, srcIndex, count);
Component_MoveElements (&childIndex_component,
@ -197,10 +218,14 @@ hierarchy_move (hierarchy_t *dst, uint32_t dstid, const hierarchy_t *src,
Component_CopyElements (&ent_component,
dst->ent, dstIndex,
src->ent, srcIndex, count);
Component_CopyElements (&own_component,
dst->own, dstIndex,
src->own, srcIndex, count);
// Actually move (as in C++ move semantics) source hierarchy object
// references so that their indices do not get updated when the objects
// are removed from the source hierarchy
memset (&src->ent[srcIndex], nullent, count * sizeof(dst->ent[0]));
memset (&src->own[srcIndex], false, count * sizeof(dst->own[0]));
for (uint32_t i = 0; i < count; i++) {
if (dst->ent[dstIndex + i] != nullent) {
@ -223,7 +248,8 @@ static void
hierarchy_init (hierarchy_t *dst, uint32_t index,
uint32_t parentIndex, uint32_t childIndex, uint32_t count)
{
memset (&dst->ent[index], nullent, count * sizeof(uint32_t));
memset (&dst->ent[index], nullent, count * sizeof(dst->ent[0]));
memset (&dst->own[index], false, count * sizeof(dst->own[0]));
for (uint32_t i = 0; i < count; i++) {
dst->parentIndex[index + i] = parentIndex;
@ -428,7 +454,11 @@ hierarchy_remove_children (hierarchy_t *hierarchy, uint32_t index,
if (delEntities) {
hierarchy_InvalidateReferences (hierarchy, childIndex, childCount);
for (uint32_t i = 0; i < childCount; i++) {
ECS_DelEntity (hierarchy->reg, hierarchy->ent[childIndex + i]);
if (hierarchy->own[childIndex + i]) {
ECS_DelEntity (hierarchy->reg, hierarchy->ent[childIndex + i]);
} else {
hierarchy_remove_reference (hierarchy, childIndex + i);
}
}
}
hierarchy_close (hierarchy, childIndex, childCount);
@ -455,7 +485,11 @@ Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index,
hierarchy_remove_children (hierarchy, index, delEntities);
if (delEntities) {
hierarchy_InvalidateReferences (hierarchy, index, 1);
ECS_DelEntity (hierarchy->reg, hierarchy->ent[index]);
if (hierarchy->own[index]) {
ECS_DelEntity (hierarchy->reg, hierarchy->ent[index]);
} else {
hierarchy_remove_reference (hierarchy, index);
}
}
hierarchy_close (hierarchy, index, 1);
@ -477,11 +511,8 @@ Hierarchy_Create (hierarchy_t *hierarchy)
static void
hierarchy_destroy (hierarchy_t *hierarchy)
{
hierarchy_InvalidateReferences (hierarchy, 0, hierarchy->num_objects);
for (uint32_t i = 0; i < hierarchy->num_objects; i++) {
ECS_DelEntity (hierarchy->reg, hierarchy->ent[i]);
}
free (hierarchy->ent);
free (hierarchy->own);
free (hierarchy->childCount);
free (hierarchy->childIndex);
free (hierarchy->parentIndex);
@ -544,6 +575,7 @@ copy_one_node (hierarchy_t *dst, const hierarchy_t *src,
dst->childIndex[dstIndex] = childIndex;
dst->childCount[dstIndex] = childCount;
dst->ent[dstIndex] = src->ent[srcIndex];
dst->own[dstIndex] = src->own[srcIndex];
if (dst->type) {
for (uint32_t i = 0; i < dst->type->num_components; i++) {
Component_CopyElements (&dst->type->components[i],
@ -645,6 +677,7 @@ Hierarchy_SetTreeMode (hierarchy_t *hierarchy, bool tree_mode)
}
swap_pointers (&tmp.ent, &src->ent);
swap_pointers (&tmp.own, &src->own);
swap_pointers (&tmp.childCount, &src->childCount);
swap_pointers (&tmp.childIndex, &src->childIndex);
swap_pointers (&tmp.parentIndex, &src->parentIndex);
@ -678,6 +711,7 @@ Hierarchy_Copy (ecs_registry_t *dstReg, uint32_t href_comp,
.index = i,
};
Ent_SetComponent (dst->ent[i], href_comp, dstReg, &ref);
dst->own[i] = true;
}
Component_CopyElements (&childCount_component,

View file

@ -157,7 +157,7 @@ dump_hierarchy (hierref_t href)
{
hierarchy_t *h = Ent_GetComponent (href.id, ecs_hierarchy, test_reg);
ecs_registry_t *reg = h->reg;
puts ("in: ri pa ci cc en name");
puts ("in: ri pa ci cc en ow name");
for (uint32_t i = 0; i < h->num_objects; i++) {
uint32_t rind = nullent;
static char fake_name[] = ONG "null" DFL;
@ -170,12 +170,13 @@ dump_hierarchy (hierref_t href)
name = Ent_GetComponent (h->ent[i], t_name, reg);
}
}
printf ("%2d: %s%2d %s%2d %s%2d %s%2d %s%2d"DFL" %s%s"DFL"\n", i,
printf ("%2d: %s%2d %s%2d %s%2d %s%2d %s%2d"DFL" %2d %s%s"DFL"\n", i,
ref_index_color (i, rind), rind,
parent_index_color (h, i), h->parentIndex[i],
child_index_color (h, i), h->childIndex[i],
child_count_color (h, i), h->childCount[i],
entity_color (h, i), h->ent[i],
h->own[i],
highlight_color (h, i), *name);
}
puts ("");
@ -191,7 +192,7 @@ dump_tree (hierref_t href, int level)
return;
}
if (!level) {
puts ("in: pa ci cc en|name");
puts ("in: pa ci cc en ow|name");
}
static char fake_name[] = ONG "null" DFL;
static char *fake_nameptr = fake_name;
@ -201,11 +202,12 @@ dump_tree (hierref_t href, int level)
&& Ent_HasComponent (h->ent[ind], t_name, reg)) {
name = Ent_GetComponent (h->ent[ind], t_name, reg);;
}
printf ("%2d: %s%2d %s%2d %s%2d %s%2d"DFL"|%*s%s%s"DFL"\n", ind,
printf ("%2d: %s%2d %s%2d %s%2d %s%2d"DFL" %2d|%*s%s%s"DFL"\n", ind,
parent_index_color (h, ind), h->parentIndex[ind],
child_index_color (h, ind), h->childIndex[ind],
child_count_color (h, ind), h->childCount[ind],
entity_color (h, ind), h->ent[ind],
h->own[ind],
level * 3, "", highlight_color (h, ind), *name);
if (h->childIndex[ind] > ind) {
@ -274,6 +276,7 @@ create_ent (uint32_t parent, const char *name)
}
hierarchy_t *h = Ent_GetComponent (ref->id, ecs_hierarchy, test_reg);
h->ent[ref->index] = ent;
h->own[ref->index] = true;
return ent;
}

View file

@ -415,6 +415,7 @@ create_ent (uint32_t parent, const char *name)
static void
set_tree_mode (hierref_t href, bool tree_mode)
{
printf ("set_tree_mode: %s\n", tree_mode ? "true" : "false");
hierarchy_t *h = Ent_GetComponent (href.id, ecs_hierarchy, test_reg);
Hierarchy_SetTreeMode (h, tree_mode);
}
@ -608,8 +609,9 @@ test_build_hierarchy2 (void)
if (!check_next_last_indices (*ref)) { return 1; }
if (!check_for_loops (*ref)) { return 1; }
ECS_PrintEntity (test_reg, root);
set_tree_mode (*ref, false);
puts("set_tree_mode");
ECS_PrintEntity (test_reg, root);
dump_hierarchy (*ref);
dump_tree (*ref, 0);

View file

@ -556,7 +556,7 @@ Canvas_AddToEntity (canvas_system_t canvas_sys, uint32_t ent)
canvas_sys.reg)) {
View_AddToEntity (ent, (ecs_system_t) { canvas_sys.reg,
canvas_sys.view_base },
nullview);
nullview, true);
}
}

View file

@ -407,7 +407,7 @@ IMUI_BeginFrame (imui_ctx_t *ctx)
// delete and recreate the root view (but not the root entity)
Ent_RemoveComponent (root_ent, ctx->root_view.comp, ctx->root_view.reg);
ctx->root_view = View_AddToEntity (root_ent, ctx->vsys, nullview);
ctx->root_view = View_AddToEntity (root_ent, ctx->vsys, nullview, true);
set_hierarchy_tree_mode (ctx, View_GetRef (ctx->root_view), true);
View_SetLen (ctx->root_view, root_size.x, root_size.y);

View file

@ -274,7 +274,8 @@ Text_PassageView (text_system_t textsys, view_t parent,
}
}
ecs_system_t viewsys = { reg, textsys.view_base };
view_t passage_view = View_AddToEntity (h->ent[0], viewsys, parent);
view_t passage_view = View_AddToEntity (h->ent[0], viewsys, parent,
false);
glyphref_t passage_ref = {};
glyphobj_t *glyphs = malloc (glyph_count * sizeof (glyphobj_t));
glyphnode_t *g = glyph_nodes;
@ -283,12 +284,12 @@ Text_PassageView (text_system_t textsys, view_t parent,
for (uint32_t i = 0; i < h->childCount[0]; i++) {
uint32_t paragraph = h->childIndex[0] + i;
view_t paraview = View_AddToEntity (h->ent[paragraph], viewsys,
passage_view);
passage_view, false);
glyphref_t pararef = { .start = passage_ref.count };
for (uint32_t j = 0; j < h->childCount[paragraph]; j++, g = g->next) {
uint32_t to = h->childIndex[paragraph] + j;
view_t textview = View_AddToEntity (h->ent[to], viewsys,
paraview);
paraview, false);
configure_textview (textview, glyphs, g, passage_ref.count,
c_glyphs);
View_SetGravity (textview, grav_flow);

View file

@ -144,7 +144,7 @@ static const hierarchy_type_t view_type = {
};
view_t
View_AddToEntity (uint32_t ent, ecs_system_t viewsys, view_t parent)
View_AddToEntity (uint32_t ent, ecs_system_t viewsys, view_t parent, bool own)
{
uint32_t href_comp = viewsys.base + view_href;
hierref_t *ref = Ent_AddComponent (ent, href_comp, viewsys.reg);
@ -158,6 +158,7 @@ View_AddToEntity (uint32_t ent, ecs_system_t viewsys, view_t parent)
}
hierarchy_t *h = Ent_GetComponent (ref->id, ecs_hierarchy, viewsys.reg);
h->ent[ref->index] = ent;
h->own[ref->index] = own;
return (view_t) { .reg = viewsys.reg, .id = ent, .comp = href_comp };
}
@ -165,7 +166,7 @@ view_t
View_New (ecs_system_t viewsys, view_t parent)
{
uint32_t view = ECS_NewEntity (viewsys.reg);
return View_AddToEntity (view, viewsys, parent);
return View_AddToEntity (view, viewsys, parent, true);
}
void