From 8ffa6fcf47dd025c45b73f7ace4e8764d4110f78 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 24 Oct 2025 14:09:00 +1100 Subject: [PATCH] Fix #7267. Bug where duplicating a drawing would cause annotation references to be associated with both the original and duplicate. --- .../bonsai/bim/module/drawing/operator.py | 6 ------ src/bonsai/bonsai/core/drawing.py | 1 + src/bonsai/bonsai/tool/drawing.py | 17 +++++++++++++++++ 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/drawing/operator.py b/src/bonsai/bonsai/bim/module/drawing/operator.py index f3e7d9ebe2..d657166346 100644 --- a/src/bonsai/bonsai/bim/module/drawing/operator.py +++ b/src/bonsai/bonsai/bim/module/drawing/operator.py @@ -210,12 +210,6 @@ class DuplicateDrawing(bpy.types.Operator, tool.Ifc.Operator): should_duplicate_annotations=self.should_duplicate_annotations, ) - # TODO: Why need to resync active drawing, if it wasn't changed. - drawing = props.get_active_drawing() - if drawing is None: - return - core.sync_references(tool.Ifc, tool.Collector, tool.Drawing, drawing=drawing) - class CreateDrawing(bpy.types.Operator): """Creates/refreshes a .svg drawing diff --git a/src/bonsai/bonsai/core/drawing.py b/src/bonsai/bonsai/core/drawing.py index aa56504a75..2e2d07c96c 100644 --- a/src/bonsai/bonsai/core/drawing.py +++ b/src/bonsai/bonsai/core/drawing.py @@ -316,6 +316,7 @@ def duplicate_drawing( ) -> ifcopenshell.entity_instance: drawing_name = drawing_tool.ensure_unique_drawing_name(drawing_tool.get_name(drawing)) new_drawing = ifc.run("root.copy_class", product=drawing) + drawing_tool.clear_annotation_relationships(new_drawing) drawing_tool.copy_representation(drawing, new_drawing) drawing_tool.set_name(new_drawing, drawing_name) group = drawing_tool.get_drawing_group(new_drawing) diff --git a/src/bonsai/bonsai/tool/drawing.py b/src/bonsai/bonsai/tool/drawing.py index 857ceb39f0..a53272b408 100644 --- a/src/bonsai/bonsai/tool/drawing.py +++ b/src/bonsai/bonsai/tool/drawing.py @@ -1620,6 +1620,8 @@ class Drawing(bonsai.core.tool.Drawing): tool.Geometry.run_edit_object_placement(obj) element.Name = storey.Name or "Unnamed" builder = ShapeBuilder(tool.Ifc.get()) + unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get()) + points = [p / unit_scale for p in points] representation = builder.get_representation(context, [builder.polyline(points)]) ifcopenshell.api.geometry.assign_representation(tool.Ifc.get(), element, representation) bonsai.core.geometry.switch_representation(tool.Ifc, tool.Geometry, obj=obj, representation=representation) @@ -1662,6 +1664,8 @@ class Drawing(bonsai.core.tool.Drawing): tool.Ifc.get(), product=annotation, representation=representation ) builder = ShapeBuilder(tool.Ifc.get()) + unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get()) + new_points = [p / unit_scale for p in new_points] representation = builder.get_representation(context, [builder.polyline(new_points)]) ifcopenshell.api.geometry.assign_representation(tool.Ifc.get(), annotation, representation) @@ -1727,6 +1731,8 @@ class Drawing(bonsai.core.tool.Drawing): ) element.Name = section.Name or "Unnamed" builder = ShapeBuilder(tool.Ifc.get()) + unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get()) + points = [p / unit_scale for p in points] representation = builder.get_representation(context, [builder.polyline(points)]) ifcopenshell.api.geometry.assign_representation(tool.Ifc.get(), element, representation) bonsai.core.geometry.switch_representation(tool.Ifc, tool.Geometry, obj=obj, representation=representation) @@ -1775,6 +1781,8 @@ class Drawing(bonsai.core.tool.Drawing): tool.Ifc.get(), product=annotation, representation=representation ) builder = ShapeBuilder(tool.Ifc.get()) + unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get()) + new_points = [p / unit_scale for p in new_points] representation = builder.get_representation(context, [builder.polyline(new_points)]) ifcopenshell.api.geometry.assign_representation(tool.Ifc.get(), annotation, representation) if obj := tool.Ifc.get_object(annotation): @@ -1893,6 +1901,8 @@ class Drawing(bonsai.core.tool.Drawing): ) element.Name = axis.AxisTag or "-" builder = ShapeBuilder(tool.Ifc.get()) + unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get()) + points = [p / unit_scale for p in points] representation = builder.get_representation(context, [builder.polyline(points)]) ifcopenshell.api.geometry.assign_representation(tool.Ifc.get(), element, representation) bonsai.core.geometry.switch_representation(tool.Ifc, tool.Geometry, obj=obj, representation=representation) @@ -1941,6 +1951,8 @@ class Drawing(bonsai.core.tool.Drawing): tool.Ifc.get(), product=annotation, representation=representation ) builder = ShapeBuilder(tool.Ifc.get()) + unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get()) + new_points = [p / unit_scale for p in new_points] representation = builder.get_representation(context, [builder.polyline(new_points)]) ifcopenshell.api.geometry.assign_representation(tool.Ifc.get(), annotation, representation) if obj := tool.Ifc.get_object(annotation): @@ -2769,3 +2781,8 @@ class Drawing(bonsai.core.tool.Drawing): for element in tool.Ifc.get().by_type("IfcAnnotation"): if element.ObjectType == "DRAWING" and (obj := tool.Ifc.get_object(element)): tool.Blender.get_layer_collection(obj.users_collection[0]).hide_viewport = True + + @classmethod + def clear_annotation_relationships(cls, drawing: ifcopenshell.entity_instance) -> None: + for rel in drawing.ReferencedBy: + tool.Ifc.get().remove(rel)