diff --git a/include/QF/ecs/hierarchy.h b/include/QF/ecs/hierarchy.h index 669490940..94ea9841e 100644 --- a/include/QF/ecs/hierarchy.h +++ b/include/QF/ecs/hierarchy.h @@ -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; diff --git a/include/QF/ui/view.h b/include/QF/ui/view.h index 0851b7a34..6efe73747 100644 --- a/include/QF/ui/view.h +++ b/include/QF/ui/view.h @@ -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); diff --git a/libs/ecs/hierarchy.c b/libs/ecs/hierarchy.c index 3eccf41c6..6e41d3b51 100644 --- a/libs/ecs/hierarchy.c +++ b/libs/ecs/hierarchy.c @@ -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, diff --git a/libs/ecs/test/test-hierarchy.c b/libs/ecs/test/test-hierarchy.c index 84d24279c..a4bfe69b4 100644 --- a/libs/ecs/test/test-hierarchy.c +++ b/libs/ecs/test/test-hierarchy.c @@ -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; } diff --git a/libs/ecs/test/test-treehierarchy.c b/libs/ecs/test/test-treehierarchy.c index 0cfcbc888..a0b7f1cc4 100644 --- a/libs/ecs/test/test-treehierarchy.c +++ b/libs/ecs/test/test-treehierarchy.c @@ -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); diff --git a/libs/ui/canvas.c b/libs/ui/canvas.c index 8ae1e9c15..8700361dc 100644 --- a/libs/ui/canvas.c +++ b/libs/ui/canvas.c @@ -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); } } diff --git a/libs/ui/imui.c b/libs/ui/imui.c index 3ddc75bb7..db3c6fe9d 100644 --- a/libs/ui/imui.c +++ b/libs/ui/imui.c @@ -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); diff --git a/libs/ui/text.c b/libs/ui/text.c index 6f1db0f7d..538533ec1 100644 --- a/libs/ui/text.c +++ b/libs/ui/text.c @@ -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); diff --git a/libs/ui/view.c b/libs/ui/view.c index 3baae1d3c..bfce0937d 100644 --- a/libs/ui/view.c +++ b/libs/ui/view.c @@ -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