Duplicating a linked aggregate (Ctrl+Shift+D) that is itself nested inside
another aggregate dropped the copy outside its parent instead of keeping
it nested.
Root cause: DuplicateMoveLinkedAggregate.execute_ifc_duplicate_linked_aggregate_operator
called tool.Root.recreate_aggregate(old_to_new) a second time, after
execute_ifc_duplicate_operator had already called it once (via
duplicate_ifc_objects) and, for the case where the parent aggregate itself
was not part of the duplication set, had already correctly restored the
new nested aggregate's assignment to that original parent. On the second,
redundant call, recreate_aggregate looks up the parent aggregate in
old_to_new again, still does not find it there (since the parent was
never duplicated), and its "parent not found" branch actively unassigns
the just-restored link, stranding the duplicate outside its parent.
Fix: drop the redundant second call. The plain duplicate path already
handles both cases correctly (parent duplicated and parent not duplicated).
Verified live in headless Blender 5.2 / Bonsai on the repo's own
test/files/linked-aggregates.ifc: nested Wall_01/Wall_02 wrapped into a
new aggregate "Nested" inside the existing "Assembly" aggregate, then
duplicated via bim.object_duplicate_move_linked_aggregate. Before the fix,
the new "Nested_01" aggregate had no parent aggregate; after the fix it
correctly remains aggregated by "Assembly". Also added a regression
scenario to test/bim/feature/geometry.feature covering this exact case,
manually traced against the existing step definitions (the full
pytest-bdd harness needs a network-provisioned Blender python to run
locally, so it hasn't been executed through pytest itself; CI will run
it). black + ruff clean.
Generated with the assistance of an AI coding tool.
When a project has a ifc file associated, selecting non-ifc objects and duplicating them with SHIFT + D now correctly both duplicate them, keep the new objects selected and starts the transform modal. IFC objects behaviour is unaffected.
Added steps to set 'is_visible' to TRUE and 'is_locked' to FALSE in the 'Spatial Decomposition' panel for the 'Override paste buffer - with active IFC data' scenario. This ensures the test covers visibility and lock state handling for IFC objects.