diff --git a/src/bonsai/bonsai/bim/module/profile/data.py b/src/bonsai/bonsai/bim/module/profile/data.py index 2402192aad..2ea97a9a20 100644 --- a/src/bonsai/bonsai/bim/module/profile/data.py +++ b/src/bonsai/bonsai/bim/module/profile/data.py @@ -29,6 +29,7 @@ def refresh(): class ProfileData: data = {} + failed_previews: set[int] = set() preview_collection = bpy.utils.previews.new() is_loaded = False diff --git a/src/bonsai/bonsai/bim/module/profile/prop.py b/src/bonsai/bonsai/bim/module/profile/prop.py index afe21b1446..9fa4f5e360 100644 --- a/src/bonsai/bonsai/bim/module/profile/prop.py +++ b/src/bonsai/bonsai/bim/module/profile/prop.py @@ -81,14 +81,24 @@ def generate_thumbnail_for_active_profile(): if not props.profiles: bpy.ops.bim.load_profiles() - profile_id = props.profiles[props.active_profile_index].ifc_definition_id + active_profile = tool.Profile.get_active_profile_ui() + assert active_profile + profile_id = active_profile.ifc_definition_id profile = ifc_file.by_id(profile_id) # generate image size = 128 img = Image.new("RGBA", (size, size)) draw = ImageDraw.Draw(img) - tool.Profile.draw_image_for_ifc_profile(draw, profile, size) + + try: + tool.Profile.draw_image_for_ifc_profile(draw, profile, size) + except RuntimeError as e: + print(f"Failed to generate preview image for profile '{profile}': '{e}'.") + ProfileData.failed_previews.add(profile_id) + return + + ProfileData.failed_previews.discard(profile_id) pixels = [item for sublist in img.getdata() for item in sublist] # save generated image to preview collection diff --git a/src/bonsai/bonsai/bim/module/profile/ui.py b/src/bonsai/bonsai/bim/module/profile/ui.py index 56c5aefe96..23eecc0037 100644 --- a/src/bonsai/bonsai/bim/module/profile/ui.py +++ b/src/bonsai/bonsai/bim/module/profile/ui.py @@ -43,19 +43,22 @@ class BIM_PT_profiles(Panel): self.props = context.scene.BIMProfileProperties active_profile = None - if self.props.is_editing and self.props.profiles and self.props.active_profile_index < len(self.props.profiles): + if self.props.is_editing and (active_profile := tool.Profile.get_active_profile_ui()): preview_collection = ProfileData.preview_collection box = self.layout.box() - active_profile = self.props.profiles[self.props.active_profile_index] profile_id = active_profile.ifc_definition_id - profile_id_str = str(profile_id) - if profile_id_str in preview_collection: - preview_image = preview_collection[profile_id_str] - else: - preview_image = preview_collection.new(profile_id_str) - generate_thumbnail_for_active_profile() - box.template_icon(icon_value=preview_image.icon_id, scale=5) + if profile_id in ProfileData.failed_previews: + box.label(text="Failed to load preview (invalid profile).", icon="ERROR") + else: + profile_id_str = str(profile_id) + if profile_id_str in preview_collection: + preview_image = preview_collection[profile_id_str] + else: + preview_image = preview_collection.new(profile_id_str) + generate_thumbnail_for_active_profile() + + box.template_icon(icon_value=preview_image.icon_id, scale=5) row = self.layout.row(align=True) row.label(text=f"{ProfileData.data['total_profiles']} Named Profiles", icon="ITALIC") diff --git a/src/bonsai/bonsai/tool/profile.py b/src/bonsai/bonsai/tool/profile.py index cc7e91f0b3..ae1d9a45de 100644 --- a/src/bonsai/bonsai/tool/profile.py +++ b/src/bonsai/bonsai/tool/profile.py @@ -40,7 +40,11 @@ class Profile(bonsai.core.tool.Profile): settings = ifcopenshell.geom.settings() settings.set("dimensionality", ifcopenshell.ifcopenshell_wrapper.CURVES_SURFACES_AND_SOLIDS) shape = ifcopenshell.geom.create_shape(settings, profile) + verts = shape.verts + if not verts: + raise RuntimeError("Profile shape has no vertices, it probably is invalid.") + edges = shape.edges grouped_verts = [[verts[i], verts[i + 1]] for i in range(0, len(verts), 3)]