From 9d2de117a93078f2c22b86ee13e16f505f970726 Mon Sep 17 00:00:00 2001 From: Gorgious56 Date: Thu, 2 Jul 2026 09:13:04 +0200 Subject: [PATCH] Bonsai: sync filling placements on wall regen recalculate_walls commits the wall's own placement to IFC before recreating its geometry but did not touch its fillings. A door moved along the wall's reference line therefore stayed cut at its old position when the user pressed SHIFT+G on the wall, because the wall recut ran against the still-stale opening placement in IFC. Walk each wall's HasOpenings and, for every filling whose Blender matrix_world differs from its committed IFC placement (tool.Ifc.is_moved), commit the filling's placement and propagate the new matrix to the enclosing opening via ifcopenshell.api.geometry.edit_object_placement. The subsequent recreate_wall pass then sees the fresh opening positions and cuts at the right spot. Generated with the assistance of an AI coding tool. --- src/bonsai/bonsai/tool/model.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/bonsai/bonsai/tool/model.py b/src/bonsai/bonsai/tool/model.py index ad3af1f59c..9babc968ba 100644 --- a/src/bonsai/bonsai/tool/model.py +++ b/src/bonsai/bonsai/tool/model.py @@ -3148,6 +3148,26 @@ class Model(bonsai.core.tool.Model): obj = tool.Ifc.get_object(rel.RelatingElement) tool.Geometry.commit_placement_if_moved(obj) queue.add((rel.RelatingElement, obj)) + + # Sync filling and opening placements so subsequent wall recuts + # operate on the up-to-date opening positions — a filling moved + # along the wall's reference line otherwise stays cut at its old + # spot. + for element, wall in queue: + if not wall: + continue + for rel in getattr(element, "HasOpenings", []) or []: + opening = rel.RelatedOpeningElement + for fill_rel in getattr(opening, "HasFillings", []) or []: + filling = fill_rel.RelatedBuildingElement + filling_obj = tool.Ifc.get_object(filling) + if filling_obj is None or not tool.Ifc.is_moved(filling_obj): + continue + bonsai.core.geometry.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=filling_obj) + ifcopenshell.api.geometry.edit_object_placement( + tool.Ifc.get(), product=opening, matrix=filling_obj.matrix_world + ) + for element, wall in queue: if not wall: continue