From 46a0c4b00af195e97611394f0bb69622834a2a79 Mon Sep 17 00:00:00 2001 From: Ryan Schultz Date: Mon, 20 Jul 2026 19:03:56 -0500 Subject: [PATCH] Bonsai: add toggle to show only drawings placed on sheets (#8824) Adds a "Show Only Drawings on Sheets" toggle below the drawing list. When enabled, the list is filtered to drawings referenced by at least one sheet (target-view headers with no sheeted drawings are hidden too), and bim.select_all_drawings only acts on the visible/filtered drawings. A drawing is considered sheeted when its drawing document Location matches a document reference Location on any SHEET-scoped IfcDocumentInformation. Filtering is computed live so it reflects sheet edits without reloading. Closes #8823 Co-authored-by: Claude Opus 4.8 (cherry picked from commit 2d59ea19883d18fb5801170d2b5b5f4b88d1fb64) --- .../bonsai/bim/module/drawing/operator.py | 4 ++ src/bonsai/bonsai/bim/module/drawing/prop.py | 7 ++++ src/bonsai/bonsai/bim/module/drawing/ui.py | 37 +++++++++++++++++++ src/bonsai/bonsai/tool/drawing.py | 21 +++++++++++ 4 files changed, 69 insertions(+) diff --git a/src/bonsai/bonsai/bim/module/drawing/operator.py b/src/bonsai/bonsai/bim/module/drawing/operator.py index 735b2a8c39..e7add156e4 100644 --- a/src/bonsai/bonsai/bim/module/drawing/operator.py +++ b/src/bonsai/bonsai/bim/module/drawing/operator.py @@ -2293,7 +2293,11 @@ class SelectAllDrawings(bpy.types.Operator): def execute(self, context): props = tool.Drawing.get_document_props() + # When filtering to sheeted drawings only, act on the visible drawings only. + sheeted_ids = tool.Drawing.get_sheeted_drawing_ids() if props.show_drawings_on_sheets_only else None for drawing in props.drawings: + if sheeted_ids is not None and drawing.is_drawing and drawing.ifc_definition_id not in sheeted_ids: + continue if drawing.is_selected != self.select_all: drawing.is_selected = self.select_all return {"FINISHED"} diff --git a/src/bonsai/bonsai/bim/module/drawing/prop.py b/src/bonsai/bonsai/bim/module/drawing/prop.py index f22d7128d8..bc10632a19 100644 --- a/src/bonsai/bonsai/bim/module/drawing/prop.py +++ b/src/bonsai/bonsai/bim/module/drawing/prop.py @@ -409,6 +409,12 @@ class DocProperties(PropertyGroup): options=set(), ) is_editing_drawings: BoolProperty(name="Is Editing Drawings", default=False) + show_drawings_on_sheets_only: BoolProperty( + name="Show Only Drawings on Sheets", + description="Only show drawings that are placed on a sheet", + default=False, + options=set(), + ) is_editing_schedules: BoolProperty(name="Is Editing Schedules", default=False) is_editing_references: BoolProperty(name="Is Editing References", default=False) target_view: EnumProperty( @@ -439,6 +445,7 @@ class DocProperties(PropertyGroup): should_use_annotation_cache: bool should_draw_linked_projects: bool is_editing_drawings: bool + show_drawings_on_sheets_only: bool is_editing_schedules: bool is_editing_references: bool target_view: Literal["PLAN_VIEW", "ELEVATION_VIEW", "SECTION_VIEW", "REFLECTED_PLAN_VIEW", "MODEL_VIEW"] diff --git a/src/bonsai/bonsai/bim/module/drawing/ui.py b/src/bonsai/bonsai/bim/module/drawing/ui.py index 04f6b80669..51fc864a88 100644 --- a/src/bonsai/bonsai/bim/module/drawing/ui.py +++ b/src/bonsai/bonsai/bim/module/drawing/ui.py @@ -341,6 +341,7 @@ class BIM_PT_drawings(Panel): self.layout.template_list( "BIM_UL_drawinglist", "", self.props, "drawings", self.props, "active_drawing_index" ) + self.layout.prop(self.props, "show_drawings_on_sheets_only") class BIM_PT_schedules(Panel): @@ -917,6 +918,42 @@ class BIM_UL_drawinglist(bpy.types.UIList): op.option = "EXPAND" row.prop(item, "name", text="", icon=icon, emboss=False) + def filter_items(self, context, data: DocProperties, propname: str): + drawings = getattr(data, propname) + helper_funcs = bpy.types.UI_UL_list + + flt_flags = [] + flt_neworder = [] + + if self.filter_name: + flt_flags = helper_funcs.filter_items_by_name( + self.filter_name, + self.bitflag_filter_item, + drawings, + "name", + reverse=self.use_filter_sort_reverse, + ) + if not flt_flags: + flt_flags = [self.bitflag_filter_item] * len(drawings) + + props = tool.Drawing.get_document_props() + if props.show_drawings_on_sheets_only: + ifc_file = tool.Ifc.get() + sheeted_ids = tool.Drawing.get_sheeted_drawing_ids() + # Target view headers are only shown if they contain a sheeted drawing. + sheeted_target_views = { + tool.Drawing.get_drawing_target_view(ifc_file.by_id(drawing_id)) for drawing_id in sheeted_ids + } + for i, item in enumerate(drawings): + if item.is_drawing: + is_visible = item.ifc_definition_id in sheeted_ids + else: + is_visible = item.target_view in sheeted_target_views + if not is_visible: + flt_flags[i] &= ~self.bitflag_filter_item + + return flt_flags, flt_neworder + class BIM_UL_sheets(bpy.types.UIList): def draw_item( diff --git a/src/bonsai/bonsai/tool/drawing.py b/src/bonsai/bonsai/tool/drawing.py index 8c10151d37..b9c8875a97 100644 --- a/src/bonsai/bonsai/tool/drawing.py +++ b/src/bonsai/bonsai/tool/drawing.py @@ -2889,6 +2889,27 @@ class Drawing(bonsai.core.tool.Drawing): break return sheet_references + @classmethod + def get_sheeted_drawing_ids(cls) -> set[int]: + """Get the IFC ids of all drawings that are placed on at least one sheet.""" + ifc_file = tool.Ifc.get() + sheet_locations: set[Union[str, None]] = set() + for sheet in ifc_file.by_type("IfcDocumentInformation"): + if sheet.Scope != "SHEET": + continue + for reference in cls.get_document_references(sheet): + sheet_locations.add(reference.Location) + if not sheet_locations: + return set() + result: set[int] = set() + for drawing in ifc_file.by_type("IfcAnnotation"): + if drawing.ObjectType != "DRAWING": + continue + drawing_document = cls.get_drawing_document(drawing) + if drawing_document and drawing_document.Location in sheet_locations: + result.add(drawing.id()) + return result + @classmethod def get_camera_matrix(cls, camera: bpy.types.Object) -> Matrix: matrix_world = camera.matrix_world.copy().normalized()