From 62aef09bc7a7c99c974c5fba166751e51f257878 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Fri, 4 Oct 2024 11:15:19 +0500 Subject: [PATCH] Fix UI issue when material styles were not reflecting active material #5447 It was reflecting active material but it was only updated when ifc UI data was refreshed (usually after some IFC operators), now it should be always up to date. --- src/bonsai/bonsai/bim/module/material/data.py | 34 +++++++++++-------- src/bonsai/bonsai/bim/module/material/ui.py | 23 ++++++------- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/material/data.py b/src/bonsai/bonsai/bim/module/material/data.py index cd5f804bc0..b85cd95cb6 100644 --- a/src/bonsai/bonsai/bim/module/material/data.py +++ b/src/bonsai/bonsai/bim/module/material/data.py @@ -24,6 +24,7 @@ import ifcopenshell.util.doc import ifcopenshell.util.schema import bonsai.tool as tool from bonsai.bim.module.drawing.helper import format_distance +from typing import Any def refresh(): @@ -43,7 +44,7 @@ class MaterialsData: cls.data["profiles"] = cls.profiles() cls.data["styles"] = cls.styles() cls.data["contexts"] = cls.contexts() - cls.data["active_styles"] = cls.active_styles() + cls.data["material_styles_data"] = cls.material_styles_data() @classmethod def total_materials(cls): @@ -99,23 +100,28 @@ class MaterialsData: ] @classmethod - def active_styles(cls): + def material_styles_data(cls) -> dict[int, list[dict[str, Any]]]: props = bpy.context.scene.BIMMaterialProperties - results = [] - if not props.materials or props.active_material_index >= len(props.materials): - return results + material_styles_data: dict[int, list[dict[str, Any]]] = {} - material = props.materials[props.active_material_index].ifc_definition_id - if not material: - return results + for material_item in props.materials: + if not (material_id := material_item.ifc_definition_id): # Category. + continue - material = tool.Ifc.get_entity_by_id(material) + material = tool.Ifc.get_entity_by_id(material_id) + # NOTE: it's possible that data will be refreshed during material removal + # (when it will try to fetch active material type and will reach for material_types) + # and props.materials[i].ifc_definition_id will contain already removed id + if not material or not material.is_a("IfcMaterial"): + results = [] + else: + results = cls.get_styles_data(material) + material_styles_data[material_id] = results + return material_styles_data - # NOTE: it's possible that data will be refreshed during material removal - # (when it will try to fetch active material type and will reach for material_types) - # and props.materials[i].ifc_definition_id will contain already removed id - if not material or not material.is_a("IfcMaterial"): - return results + @classmethod + def get_styles_data(cls, material: ifcopenshell.entity_instance) -> list[dict[str, Any]]: + results: list[dict[str, Any]] = [] for definition in material.HasRepresentation: for representation in definition.Representations: diff --git a/src/bonsai/bonsai/bim/module/material/ui.py b/src/bonsai/bonsai/bim/module/material/ui.py index 607b7e1086..3b474010f1 100644 --- a/src/bonsai/bonsai/bim/module/material/ui.py +++ b/src/bonsai/bonsai/bim/module/material/ui.py @@ -88,18 +88,17 @@ class BIM_PT_materials(Panel): self.layout.template_list("BIM_UL_materials", "", self.props, "materials", self.props, "active_material_index") - # TODO: data.py is not updated on changing active_material_index - # so the active material styles go out of sync with the active material - for style in MaterialsData.data["active_styles"]: - row = self.layout.row(align=True) - row.label(text="", icon="SHADING_RENDERED") - row.label(text=style["context_type"]) - row.label(text=style["context_identifier"]) - row.label(text=style["target_view"]) - row.label(text=style["name"]) - op = row.operator("bim.unassign_material_style", text="", icon="X") - op.style = style["id"] - op.context = style["context_id"] + if material_id: + for style in MaterialsData.data["material_styles_data"][material_id]: + row = self.layout.row(align=True) + row.label(text="", icon="SHADING_RENDERED") + row.label(text=style["context_type"]) + row.label(text=style["context_identifier"]) + row.label(text=style["target_view"]) + row.label(text=style["name"]) + op = row.operator("bim.unassign_material_style", text="", icon="X") + op.style = style["id"] + op.context = style["context_id"] def draw_editing_ui(self): if not self.props.active_material_id: