From 9f8a4d25b58141c59e198535e5c0b4ac5cd60150 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Thu, 25 Dec 2025 12:21:12 +0500 Subject: [PATCH 1/5] cmake export - fix issue finding `zstd` config on Windows --- cmake/CMakeLists.txt | 1 + cmake/IfcOpenShellConfig.cmake.in | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 43b9ba8913..9e88026ac7 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -242,6 +242,7 @@ if(WITH_ROCKSDB) # find it's zstd dependency on Windows. # Only do it on Windows, otherwise it might create problems as # findzstd and zstd-config target names do not match. + # https://github.com/facebook/rocksdb/pull/13975 if(WIN32) set(TEMP CMAKE_FIND_PACKAGE_PREFER_CONFIG) set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE) diff --git a/cmake/IfcOpenShellConfig.cmake.in b/cmake/IfcOpenShellConfig.cmake.in index 414066668d..95df6180f9 100644 --- a/cmake/IfcOpenShellConfig.cmake.in +++ b/cmake/IfcOpenShellConfig.cmake.in @@ -19,7 +19,20 @@ find_dependency(Eigen3 CONFIG) if(IFCOPENSHELL_WITH_ROCKSDB) find_dependency(zstd CONFIG) + + # Temporaily mess with CMAKE_FIND_PACKAGE_PREFER_CONFIG to help RocksDB + # find it's zstd dependency on Windows. + # Only do it on Windows, otherwise it might create problems as + # findzstd and zstd-config target names do not match. + # https://github.com/facebook/rocksdb/pull/13975 + if(WIN32) + set(TEMP CMAKE_FIND_PACKAGE_PREFER_CONFIG) + set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE) + endif() find_dependency(RocksDB CONFIG) + if(WIN32) + set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ${TEMP}) + endif() endif() if(IFCOPENSHELL_IFCXML) From 05f7ffcbccdcce0a17654089225e3fbe4417ff15 Mon Sep 17 00:00:00 2001 From: Ryan Schultz Date: Thu, 25 Dec 2025 18:32:03 -0600 Subject: [PATCH 2/5] fix #6682: avoid applying styles directly to geometry when inherited from material When duplicating elements, skip assign_body_styles if the element's constituent materials already have style representations. This prevents creating redundant IfcStyledItem entities on the geometry when styles should be inherited from the material definition. --- src/bonsai/bonsai/core/root.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/bonsai/bonsai/core/root.py b/src/bonsai/bonsai/core/root.py index d43c20a343..957298c044 100644 --- a/src/bonsai/bonsai/core/root.py +++ b/src/bonsai/bonsai/core/root.py @@ -18,6 +18,7 @@ from __future__ import annotations from typing import TYPE_CHECKING, Optional +import ifcopenshell.util.element if TYPE_CHECKING: import bpy @@ -53,11 +54,32 @@ def copy_class( geometry.copy_data_links(data, copied_entities) geometry.change_object_data(obj, data, is_global=True) geometry.rename_object(data, geometry.get_representation_name(ifc.get_entity(data))) - root.assign_body_styles(new, obj) + # Only assign styles if element doesn't get them from material + if not _has_material_styles(ifc, new): + root.assign_body_styles(new, obj) collector.assign(obj) return new +def _has_material_styles(ifc: type[tool.Ifc], element: ifcopenshell.entity_instance) -> bool: + """Check if element has styles defined through its material. + + Returns True if any constituent material has a style representation, + which means styles should NOT be applied directly to the geometry. + """ + materials = ifcopenshell.util.element.get_materials(element) + + if not materials: + return False + + # Check if any of the constituent materials have styles + for material in materials: + if hasattr(material, 'HasRepresentation') and material.HasRepresentation: + return True + + return False + + def assign_class( ifc: type[tool.Ifc], collector: type[tool.Collector], From 96fe9b5398e26f6d53c3e7e0dadd4dfc67acf514 Mon Sep 17 00:00:00 2001 From: Ryan Schultz Date: Thu, 25 Dec 2025 19:05:30 -0600 Subject: [PATCH 3/5] Use hide_set() for IfcSpaces instead of hide_viewport Moves IfcSpace hiding from collection assignment to after scene addition, allowing hide_set() to work properly once objects are in the view layer. Fixes RuntimeError during IFC import. --- src/bonsai/bonsai/bim/import_ifc.py | 8 ++++++++ src/bonsai/bonsai/tool/collector.py | 6 ++---- src/bonsai/bonsai/tool/spatial.py | 8 ++++---- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/bonsai/bonsai/bim/import_ifc.py b/src/bonsai/bonsai/bim/import_ifc.py index 05bcbed01a..7669edbd14 100644 --- a/src/bonsai/bonsai/bim/import_ifc.py +++ b/src/bonsai/bonsai/bim/import_ifc.py @@ -290,6 +290,7 @@ class IfcImporter: self.profile_code("Load linked models") self.add_project_to_scene() self.profile_code("Add project to scene") + self.hide_ifc_spaces() if self.ifc_import_settings.should_clean_mesh and len(self.file.by_type("IfcElement")) < 1000: self.clean_mesh() self.profile_code("Mesh cleaning") @@ -1286,6 +1287,13 @@ class IfcImporter: properties={"Aggregate_Index": aggregate_index, "Name": name}, ) + def hide_ifc_spaces(self): + """Hide IfcSpace objects after they've been added to the scene.""" + for ifc_definition_id, obj in self.added_data.items(): + if isinstance(obj, bpy.types.Object): + element = self.file.by_id(ifc_definition_id) + if element.is_a("IfcSpace"): + obj.hide_set(True) class IfcImportSettings: """ diff --git a/src/bonsai/bonsai/tool/collector.py b/src/bonsai/bonsai/tool/collector.py index 65d5ae49bd..e91c52d3d0 100644 --- a/src/bonsai/bonsai/tool/collector.py +++ b/src/bonsai/bonsai/tool/collector.py @@ -52,12 +52,12 @@ class Collector(bonsai.core.tool.Collector): tool.Geometry.lock_object(obj) element = (element.PartOfU or element.PartOfV or element.PartOfW)[0] if not tool.Spatial.get_grid_props().is_visible: - obj.hide_viewport = True + obj.hide_set(True) elif element.is_a("IfcGrid"): if tool.Geometry.is_locked(element): tool.Geometry.lock_object(obj) if not tool.Spatial.get_grid_props().is_visible: - obj.hide_viewport = True + obj.hide_set(True) if element.is_a("IfcProject"): if tool.Geometry.is_locked(element): @@ -73,8 +73,6 @@ class Collector(bonsai.core.tool.Collector): tool.Geometry.lock_object(obj) collection = cls._create_project_child_collection("IfcSpace") cls.link_collection_object_safe(collection, obj) - if not tool.Spatial.get_spatial_props().is_visible: - obj.hide_viewport = True elif element.is_a("IfcStructuralItem"): collection = cls._create_project_child_collection("IfcStructuralItem") cls.link_collection_object_safe(collection, obj) diff --git a/src/bonsai/bonsai/tool/spatial.py b/src/bonsai/bonsai/tool/spatial.py index a177a237e8..6ca29343e9 100644 --- a/src/bonsai/bonsai/tool/spatial.py +++ b/src/bonsai/bonsai/tool/spatial.py @@ -1213,18 +1213,18 @@ class Spatial(bonsai.core.tool.Spatial): for element in elements: if obj := tool.Ifc.get_object(element): if obj.hide_viewport is True and is_visible: - obj.hide_viewport = False + obj.hide_set(False) elif obj.hide_viewport is False and not is_visible: - obj.hide_viewport = True + obj.hide_set(True) @classmethod def set_grid_visibility(cls, is_visible: bool) -> None: for element in tool.Ifc.get().by_type("IfcGrid") + tool.Ifc.get().by_type("IfcGridAxis"): if obj := tool.Ifc.get_object(element): if obj.hide_viewport is True and is_visible: - obj.hide_viewport = False + obj.hide_set(False) elif obj.hide_viewport is False and not is_visible: - obj.hide_viewport = True + obj.hide_set(True) @classmethod def toggle_spaces_visibility_wired_and_textured(cls, spaces: list[ifcopenshell.entity_instance]) -> None: From 19534e225f0a2d585352baa7b9cbd4e2752930f0 Mon Sep 17 00:00:00 2001 From: Ryan Schultz Date: Thu, 25 Dec 2025 19:29:57 -0600 Subject: [PATCH 4/5] Fix #6661: Have `update_drawing_name` function update the camera object's name in Blender, as well. --- src/bonsai/bonsai/core/drawing.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/bonsai/bonsai/core/drawing.py b/src/bonsai/bonsai/core/drawing.py index fd721cd4be..407bb19cb0 100644 --- a/src/bonsai/bonsai/core/drawing.py +++ b/src/bonsai/bonsai/core/drawing.py @@ -397,6 +397,12 @@ def update_drawing_name( ) -> None: if drawing_tool.get_name(drawing) != name: ifc.run("attribute.edit_attributes", product=drawing, attributes={"Name": name}) + + # Update the camera object name + camera = ifc.get_object(drawing) + if camera and camera.name != name: + camera.name = name + group = drawing_tool.get_drawing_group(drawing) if drawing_tool.get_name(group) != name: ifc.run("attribute.edit_attributes", product=group, attributes={"Name": name}) From bc6209ad91dbb0c09d011f25b0ecb130629410fb Mon Sep 17 00:00:00 2001 From: Ryan Schultz Date: Thu, 25 Dec 2025 21:18:22 -0600 Subject: [PATCH 5/5] Fix #7372: Increase almost_zero tolerance to handle matrix transformation precision Changed tolerance from 1e-5 to 1e-4 to account for floating-point errors introduced by matrix transformations. Fixes section annotations being incorrectly excluded from drawings when they should be visible. --- src/bonsai/bonsai/bim/module/drawing/helper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bonsai/bonsai/bim/module/drawing/helper.py b/src/bonsai/bonsai/bim/module/drawing/helper.py index 3943e8fd2f..01a78aad11 100644 --- a/src/bonsai/bonsai/bim/module/drawing/helper.py +++ b/src/bonsai/bonsai/bim/module/drawing/helper.py @@ -507,7 +507,7 @@ def ortho_view_frame( def almost_zero(v): - return abs(v) < 1e-5 + return abs(v) < 1e-4 def clip_segment(bounds, segm):