Bonsai: fix Activate Drawing crash for punctuated drawing names

The sheets panel matched a sheet's DRAWING reference to its IfcAnnotation
by stripping ".svg" from the reference's filename and comparing it against
each annotation's Name after removing commas only. The on-disk filename is
generated by sanitise_filename(), which strips every character outside
[A-Za-z0-9._- ], not just commas, so any drawing Name containing other
punctuation (parentheses, colons, quotes) never matches. The lookup then
silently leaves op.drawing at 0, and clicking the button crashes at
by_id(0) since IFC entity ids never include 0.

Replace the name-based lookup with an exact Location match against
get_drawing_document(), mirroring the same Location comparison
AddDrawingToSheet already uses to detect an existing sheet reference, so
no filesystem-sanitised name has to be reversed.

Fixes #7167.

Generated with the assistance of an AI coding tool.
This commit is contained in:
Petru Conduraru
2026-07-16 12:33:28 +03:00
parent 821cf7b671
commit 281f4045ff
3 changed files with 31 additions and 14 deletions
+4 -14
View File
@@ -483,20 +483,10 @@ class BIM_PT_sheets(Panel):
op = row3.operator("bim.activate_drawing_from_sheet", icon="OUTLINER_OB_CAMERA", text="")
if active_sheet.reference_type == "DRAWING":
drawingnamesvg = active_sheet.name
drawingname = drawingnamesvg.split(".svg")[0]
ifc_file = tool.Ifc.get()
ifc_annotations = ifc_file.by_type("IfcAnnotation")
drawingid = None
for annotation in ifc_annotations:
if annotation.ObjectType != "DRAWING":
continue
Annotation_Name = annotation.Name.replace(",", "") # Remove commas
if Annotation_Name == drawingname:
drawingid = annotation.id()
break
if drawingid is not None:
op.drawing = drawingid
active_reference = tool.Ifc.get().by_id(active_sheet.ifc_definition_id)
drawing = tool.Drawing.get_drawing_for_sheet_reference(active_reference)
if drawing is not None:
op.drawing = drawing.id()
row3.separator(factor=0.5, type="SPACE")
+1
View File
@@ -381,6 +381,7 @@ class Drawing:
def get_document_uri(cls, document, description=None): pass
def get_drawing_collection(cls, drawing): pass
def get_drawing_document(cls, drawing): pass
def get_drawing_for_sheet_reference(cls, reference): pass
def get_drawing_group(cls, drawing): pass
def get_drawing_references(cls, drawing): pass
def get_drawing_target_view(cls, drawing): pass
+26
View File
@@ -762,6 +762,32 @@ class Drawing(bonsai.core.tool.Drawing):
if rel.is_a("IfcRelAssociatesDocument"):
return rel.RelatingDocument
@classmethod
def get_drawing_for_sheet_reference(
cls, reference: ifcopenshell.entity_instance
) -> Union[ifcopenshell.entity_instance, None]:
"""Find the IfcAnnotation drawing that a sheet's "DRAWING" reference item represents.
A sheet's document reference is a standalone copy created by
`bim.add_drawing_to_sheet` (see `AddDrawingToSheet`): it only shares
the drawing's `Location` (the on-disk SVG path) and has no direct IFC
relationship back to the originating `IfcAnnotation`. Match on that
`Location` instead of re-deriving the drawing's name from the
(filesystem-sanitised) filename, which silently fails to match
whenever the drawing's `Name` contains characters stripped by
`sanitise_filename()` (e.g. parentheses, colons, quotes).
"""
location = getattr(reference, "Location", None)
if not location:
return None
for drawing in tool.Ifc.get().by_type("IfcAnnotation"):
if drawing.ObjectType != "DRAWING":
continue
drawing_reference = cls.get_drawing_document(drawing)
if drawing_reference and drawing_reference.Location == location:
return drawing
return None
@classmethod
def get_drawing_references(cls, drawing: ifcopenshell.entity_instance) -> set[ifcopenshell.entity_instance]:
results: set[ifcopenshell.entity_instance] = set()