From 97a6ce833efb0a2d8c6a54b8ccd5a5d44b1a14b1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Nov 2022 17:36:49 +0900 Subject: [PATCH] [ecs] Adjust the source root during self insertions This improves the behavior of hierarchies when self-inserting, but nq's sbar still crashes when trying to do so. However, its tree is a fair bit more complex than the test case (that does pass now), so I need to try to replicate the important parts of the tree with fewer objects (180 is too many to work with). --- libs/ecs/hierarchy.c | 50 ++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/libs/ecs/hierarchy.c b/libs/ecs/hierarchy.c index 7d2057d4e..6061b6dcf 100644 --- a/libs/ecs/hierarchy.c +++ b/libs/ecs/hierarchy.c @@ -170,10 +170,12 @@ hierarchy_move (hierarchy_t *dst, const hierarchy_t *src, memset (&src->ent[srcIndex], nullent, count * sizeof(dst->ent[0])); for (uint32_t i = 0; i < count; i++) { - uint32_t ent = dst->ent[dstIndex + i]; - hierref_t *ref = Ent_GetComponent (ent, href, reg); - ref->hierarchy = dst; - ref->index = dstIndex + i; + if (dst->ent[dstIndex + i] != nullent) { + uint32_t ent = dst->ent[dstIndex + i]; + hierref_t *ref = Ent_GetComponent (ent, href, reg); + ref->hierarchy = dst; + ref->index = dstIndex + i; + } } if (dst->type) { for (uint32_t i = 0; i < dst->type->num_components; i++) { @@ -205,7 +207,7 @@ hierarchy_init (hierarchy_t *dst, uint32_t index, static uint32_t hierarchy_insert (hierarchy_t *dst, const hierarchy_t *src, - uint32_t dstParent, uint32_t srcRoot, uint32_t count) + uint32_t dstParent, uint32_t *srcRoot, uint32_t count) { uint32_t insertIndex; // where the objects will be inserted uint32_t childIndex; // where the objects' children will inserted @@ -237,8 +239,11 @@ hierarchy_insert (hierarchy_t *dst, const hierarchy_t *src, childIndex += count; hierarchy_open (dst, insertIndex, count); + if (dst == src && insertIndex <= *srcRoot) { + *srcRoot += count; + } if (src) { - hierarchy_move (dst, src, insertIndex, srcRoot, count); + hierarchy_move (dst, src, insertIndex, *srcRoot, count); } else { hierarchy_init (dst, insertIndex, dstParent, childIndex, count); } @@ -254,25 +259,27 @@ hierarchy_insert (hierarchy_t *dst, const hierarchy_t *src, static void hierarchy_insert_children (hierarchy_t *dst, const hierarchy_t *src, - uint32_t dstParent, uint32_t srcRoot) + uint32_t dstParent, uint32_t *srcRoot) { uint32_t insertIndex; - uint32_t childIndex = src->childIndex[srcRoot]; - uint32_t childCount = src->childCount[srcRoot]; + uint32_t childIndex = src->childIndex[*srcRoot]; + uint32_t childCount = src->childCount[*srcRoot]; if (childCount) { insertIndex = hierarchy_insert (dst, src, dstParent, - childIndex, childCount); - for (uint32_t i = 0; i < childCount; i++) { - hierarchy_insert_children (dst, src, insertIndex + i, - childIndex + i); + &childIndex, childCount); + if (dst == src && insertIndex <= *srcRoot) { + *srcRoot += childCount; + } + for (uint32_t i = 0; i < childCount; i++, childIndex++) { + hierarchy_insert_children (dst, src, insertIndex + i, &childIndex); } } } -uint32_t -Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, - uint32_t dstParent, uint32_t srcRoot) +static uint32_t +hierarchy_insertHierarchy (hierarchy_t *dst, const hierarchy_t *src, + uint32_t dstParent, uint32_t *srcRoot) { uint32_t insertIndex; @@ -282,7 +289,7 @@ Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, } hierarchy_open (dst, 0, 1); if (src) { - hierarchy_move (dst, src, 0, srcRoot, 1); + hierarchy_move (dst, src, 0, *srcRoot, 1); } dst->parentIndex[0] = nullent; dst->childIndex[0] = 1; @@ -301,6 +308,13 @@ Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, return insertIndex; } +uint32_t +Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, + uint32_t dstParent, uint32_t srcRoot) +{ + return hierarchy_insertHierarchy (dst, src, dstParent, &srcRoot); +} + static void hierarchy_remove_children (hierarchy_t *hierarchy, uint32_t index) { @@ -437,7 +451,7 @@ Hierarchy_SetParent (hierarchy_t *dst, uint32_t dstParent, dst = Hierarchy_New (src->reg, src->type, 0); } r.hierarchy = dst; - r.index = Hierarchy_InsertHierarchy (dst, src, dstParent, srcRoot); + r.index = hierarchy_insertHierarchy (dst, src, dstParent, &srcRoot); Hierarchy_RemoveHierarchy (src, srcRoot); if (!src->num_objects) { Hierarchy_Delete (src);