[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).
This commit is contained in:
Bill Currie 2022-11-06 17:36:49 +09:00
parent ecf59c8141
commit 97a6ce833e

View file

@ -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);