diff --git a/src/bonsai/bonsai/bim/module/style/data.py b/src/bonsai/bonsai/bim/module/style/data.py index 4bb888108a..afcc7eba8d 100644 --- a/src/bonsai/bonsai/bim/module/style/data.py +++ b/src/bonsai/bonsai/bim/module/style/data.py @@ -36,24 +36,12 @@ class StylesData: @classmethod def load(cls): cls.data = { - "styles_to_blender_material_names": cls.styles_to_blender_material_names(), "style_types": cls.style_types(), "total_styles": cls.total_styles(), "reflectance_methods": cls.reflectance_methods(), } cls.is_loaded = True - @classmethod - def styles_to_blender_material_names(cls) -> list[Union[str, None]]: - ifc_file = tool.Ifc.get() - props = bpy.context.scene.BIMStylesProperties - materials: list[Union[str, None]] = [] - for style in props.styles: - material = tool.Ifc.get_object(ifc_file.by_id(style.ifc_definition_id)) - # Material will be None if it's not IfcSurfaceStyle. - materials.append(material.name if material is not None else None) - return materials - @classmethod def reflectance_methods(cls): declaration = tool.Ifc.schema().declaration_by_name("IfcReflectanceMethodEnum") diff --git a/src/bonsai/bonsai/bim/module/style/operator.py b/src/bonsai/bonsai/bim/module/style/operator.py index f5f64143a5..24ccc963c4 100644 --- a/src/bonsai/bonsai/bim/module/style/operator.py +++ b/src/bonsai/bonsai/bim/module/style/operator.py @@ -141,6 +141,13 @@ class UnlinkStyle(bpy.types.Operator, tool.Ifc.Operator): core.remove_style(tool.Ifc, tool.Style, style) else: material_copy.use_fake_user = True + # Need to reload Styles UI since it's item is now pointing to wrong Blender material. + if ( + tool.Style.is_editing_styles() + and (style_type := tool.Style.get_active_style_type()) + and style_type == style.is_a() + ): + tool.Style.import_presentation_styles(style_type) # Ensure there won't be any style sync on project save: # bim.update_representation would create new IfcSurfaceStyle diff --git a/src/bonsai/bonsai/bim/module/style/prop.py b/src/bonsai/bonsai/bim/module/style/prop.py index 2a702b8532..b764989b06 100644 --- a/src/bonsai/bonsai/bim/module/style/prop.py +++ b/src/bonsai/bonsai/bim/module/style/prop.py @@ -69,6 +69,13 @@ class Style(PropertyGroup): diffuse_colour: bpy.props.FloatVectorProperty( name="Diffuse Colour", subtype="COLOR", default=(1, 1, 1), min=0.0, max=1.0, size=3 ) + blender_material: PointerProperty( + description=( + "Needed for UI to have style->blender material link that won't break on undo. " + "Can be None if it's not a surface style" + ), + type=bpy.types.Material, + ) STYLE_TYPES = [ diff --git a/src/bonsai/bonsai/bim/module/style/ui.py b/src/bonsai/bonsai/bim/module/style/ui.py index 2230d0fe89..9db28461be 100644 --- a/src/bonsai/bonsai/bim/module/style/ui.py +++ b/src/bonsai/bonsai/bim/module/style/ui.py @@ -52,7 +52,7 @@ class BIM_PT_styles(Panel): row.operator("bim.load_styles", text="", icon="IMPORT").style_type = style_type return - active_style = self.props.styles and self.props.active_style_index < len(self.props.styles) + active_style = bool(self.props.styles and self.props.active_style_index < len(self.props.styles)) row = self.layout.row(align=True) row.label(text="{} {}s".format(len(self.props.styles), self.props.style_type), icon="SHADING_RENDERED") row.operator("bim.disable_editing_styles", text="", icon="CANCEL") @@ -95,9 +95,7 @@ class BIM_PT_styles(Panel): # style ui tools if active_style: row = self.layout.row(align=True) - material_name = StylesData.data["styles_to_blender_material_names"][self.props.active_style_index] - if material_name: # The user may have unlinked the style, so the material may not exist - material = bpy.data.materials[material_name] + if material := style.blender_material: row.prop(material.BIMStyleProperties, "active_style_type", icon="SHADING_RENDERED", text="") op = row.operator("bim.update_current_style", icon="FILE_REFRESH", text="") op.style_id = style.ifc_definition_id @@ -268,9 +266,8 @@ class BIM_UL_styles(UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): if item: row = layout.row(align=True) - material_name: Union[str, None] = StylesData.data["styles_to_blender_material_names"][index] material_icon = 0 - if material_name and (material := bpy.data.materials.get(material_name)): + if material := item.blender_material: preview = material.preview_ensure() material_icon = preview.icon_id row.prop(item, "name", text="", emboss=False, icon_value=material_icon) diff --git a/src/bonsai/bonsai/tool/style.py b/src/bonsai/bonsai/tool/style.py index d4beeff489..1482ece764 100644 --- a/src/bonsai/bonsai/tool/style.py +++ b/src/bonsai/bonsai/tool/style.py @@ -521,6 +521,7 @@ class Style(bonsai.core.tool.Style): for style in styles: new = props.styles.add() new.ifc_definition_id = style.id() + new.blender_material = tool.Ifc.get_object(style) new["name"] = style.Name or "Unnamed" # Avoid writing to IFC through callback. new.ifc_class = style.is_a() for surface_style in getattr(style, "Styles", []) or []: