diff --git a/include/QF/ecs/hierarchy.h b/include/QF/ecs/hierarchy.h index 2dcde3306..5a8056617 100644 --- a/include/QF/ecs/hierarchy.h +++ b/include/QF/ecs/hierarchy.h @@ -72,6 +72,9 @@ void Hierarchy_Delete (hierarchy_t *hierarchy); uint32_t Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, uint32_t dstParent, uint32_t srcRoot); void Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index); + +hierref_t Hierarchy_SetParent (hierarchy_t *dst, uint32_t dstParent, + hierarchy_t *src, uint32_t srcIndex); ///@} #endif//__QF_ecs_hierarchy_h diff --git a/libs/ecs/hierarchy.c b/libs/ecs/hierarchy.c index 38fd4523b..cc5f0705e 100644 --- a/libs/ecs/hierarchy.c +++ b/libs/ecs/hierarchy.c @@ -400,7 +400,31 @@ Hierarchy_Copy (ecs_registry_t *dstReg, const hierarchy_t *src) dst->components[i], 0, src->components[i], 0, count); } - // Just in case the source hierarchy has modified objects - //Hierarchy_UpdateMatrices (dst); return dst; } + +hierref_t +Hierarchy_SetParent (hierarchy_t *dst, uint32_t dstParent, + hierarchy_t *src, uint32_t srcRoot) +{ + hierref_t r = {}; + if (dst && dstParent != nullent) { + if (dst->type != src->type) { + Sys_Error ("Can't set parent in hierarcy of different type"); + } + } else { + if (!srcRoot) { + r.hierarchy = src; + r.index = 0; + return r; + } + dst = Hierarchy_New (src->reg, src->type, 0); + } + r.hierarchy = dst; + r.index = Hierarchy_InsertHierarchy (dst, src, dstParent, srcRoot); + Hierarchy_RemoveHierarchy (src, srcRoot); + if (!src->num_objects) { + Hierarchy_Delete (src); + } + return r; +} diff --git a/libs/scene/transform.c b/libs/scene/transform.c index b6ab7b2f6..a01867b44 100644 --- a/libs/scene/transform.c +++ b/libs/scene/transform.c @@ -262,34 +262,22 @@ Transform_NewNamed (ecs_registry_t *reg, transform_t parent, const char *name) void Transform_SetParent (transform_t transform, transform_t parent) { - if (parent.reg && parent.id != nullent) { - __auto_type ref = Transform_GetRef (transform); - __auto_type tref = *ref; - __auto_type pref = Transform_GetRef (parent); - ref->index = Hierarchy_InsertHierarchy (pref->hierarchy, - tref.hierarchy, - pref->index, tref.index); - ref->hierarchy = pref->hierarchy; - Hierarchy_RemoveHierarchy (tref.hierarchy, tref.index); - if (!tref.hierarchy->num_objects) { - Hierarchy_Delete (tref.hierarchy); - } - } else { - __auto_type ref = Transform_GetRef (transform); - __auto_type tref = *ref; - // null parent -> make transform root - if (!tref.index) { - // already root - return; - } - ref->hierarchy = Hierarchy_New (transform.reg, &transform_type, 0); - Hierarchy_InsertHierarchy (ref->hierarchy, tref.hierarchy, nullent, - tref.index); - Hierarchy_RemoveHierarchy (tref.hierarchy, tref.index); - if (!tref.hierarchy->num_objects) { - Hierarchy_Delete (tref.hierarchy); - } + hierarchy_t *dst = 0; + uint32_t dstParent = nullent; + hierarchy_t *src = 0; + uint32_t srcIndex = 0; + if (Transform_Valid (parent)) { + __auto_type ref = Transform_GetRef (parent); + dst = ref->hierarchy; + dstParent = ref->index; } + { + __auto_type ref = Transform_GetRef (transform); + src = ref->hierarchy; + srcIndex = ref->index; + } + Hierarchy_SetParent (dst, dstParent, src, srcIndex); + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; byte *modified = h->components[transform_type_modified]; diff --git a/libs/ui/view.c b/libs/ui/view.c index 712c237e9..5c71ec0fc 100644 --- a/libs/ui/view.c +++ b/libs/ui/view.c @@ -265,32 +265,22 @@ View_UpdateHierarchy (view_t view) void View_SetParent (view_t view, view_t parent) { - if (parent.reg && parent.id != nullent) { - __auto_type ref = View_GetRef (view); - __auto_type vref = *ref; - __auto_type pref = View_GetRef (parent); - ref->index = Hierarchy_InsertHierarchy (pref->hierarchy, - vref.hierarchy, - pref->index, vref.index); - ref->hierarchy = pref->hierarchy; - Hierarchy_RemoveHierarchy (vref.hierarchy, vref.index); - if (!vref.hierarchy->num_objects) { - Hierarchy_Delete (vref.hierarchy); - } - } else { - __auto_type ref = View_GetRef (view); - __auto_type vref = *ref; - if (!vref.index) { - return; - } - ref->hierarchy = Hierarchy_New (view.reg, &view_type, 0); - Hierarchy_InsertHierarchy (ref->hierarchy, vref.hierarchy, nullent, - vref.index); - Hierarchy_RemoveHierarchy (vref.hierarchy, vref.index); - if (!vref.hierarchy->num_objects) { - Hierarchy_Delete (vref.hierarchy); - } + hierarchy_t *dst = 0; + uint32_t dstParent = nullent; + hierarchy_t *src = 0; + uint32_t srcIndex = 0; + if (View_Valid (parent)) { + __auto_type ref = View_GetRef (parent); + dst = ref->hierarchy; + dstParent = ref->index; } + { + __auto_type ref = View_GetRef (view); + src = ref->hierarchy; + srcIndex = ref->index; + } + Hierarchy_SetParent (dst, dstParent, src, srcIndex); + __auto_type ref = View_GetRef (view); hierarchy_t *h = ref->hierarchy; byte *modified = h->components[view_modified];