From a9defb94d0217f1c443cb21f29646ca78fb5ef74 Mon Sep 17 00:00:00 2001 From: Ryan Schultz Date: Sun, 8 Dec 2024 20:01:49 -0600 Subject: [PATCH] Improved UI for BIM_PT_object_material also can run `bim.select_by_material` by clicking on material name --- src/bonsai/bonsai/bim/module/material/ui.py | 114 ++++++++++++++------ 1 file changed, 80 insertions(+), 34 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/material/ui.py b/src/bonsai/bonsai/bim/module/material/ui.py index 0ac0cdd54d..e3d2b75ee9 100644 --- a/src/bonsai/bonsai/bim/module/material/ui.py +++ b/src/bonsai/bonsai/bim/module/material/ui.py @@ -207,9 +207,14 @@ class BIM_PT_object_material(Panel): prop_with_search(self.layout, self.props, "material", text="") def draw_read_only_single_ui(self): - row = self.layout.row(align=True) + material_id = ObjectMaterialData.data["material_id"] + layout = self.layout + box = layout.box() + row = box.row() row.label(text="Name") - row.label(text=ObjectMaterialData.data["material_name"]) + op = row.operator("bim.select_by_material", text=ObjectMaterialData.data["material_name"], icon="NONE", emboss=False) + op.material = material_id + def draw_set_ui(self): if self.props.is_editing: @@ -225,6 +230,9 @@ class BIM_PT_object_material(Panel): row.label(text="No Profiles Available") row.operator("bim.add_profile_def", icon="ADD", text="") else: + layout = self.layout + layout.separator() + layout.separator() row = self.layout.row(align=True) if ObjectMaterialData.data["set_item_name"] == "profile": prop_with_search(row, self.mprops, "profiles", icon="ITALIC", text="") @@ -233,12 +241,12 @@ class BIM_PT_object_material(Panel): setattr(op, f"{ObjectMaterialData.data['set_item_name']}_set", ObjectMaterialData.data["set"]["id"]) total_items = len(ObjectMaterialData.data["set_items"]) - row = self.layout.row(align=True) - layer_set_direction = self.props.material_set_usage_attributes["LayerSetDirection"].enum_value - if layer_set_direction == "AXIS3": - row.label(text="----- Top -----") - else: - row.label(text="----- Exterior -----") + + layout = self.layout + box = layout.box() + active_object = bpy.context.active_object + self.layerset_bounds (box, active_object, location="Top_Exterior") + for index, set_item in enumerate(ObjectMaterialData.data["set_items"]): if ( len(self.props.material_set_item_profile_attributes) @@ -248,12 +256,9 @@ class BIM_PT_object_material(Panel): elif self.props.active_material_set_item_id == set_item["id"]: self.draw_editable_set_item_ui(set_item) else: - self.draw_read_only_set_item_ui(set_item, index, is_first=index == 0, is_last=index == total_items - 1) - row = self.layout.row(align=True) - if layer_set_direction == "AXIS3": - row.label(text="----- Bottom -----") - else: - row.label(text="----- Interior -----") + self.draw_read_only_set_item_ui(box, set_item, index, is_first=index == 0, is_last=index == total_items - 1) + + self.layerset_bounds (box, active_object, location="Bottom_Interior") def draw_editable_set_item_profile_ui(self, set_item): box = self.layout.box() @@ -279,13 +284,13 @@ class BIM_PT_object_material(Panel): row = box.row() prop_with_search(row, self.mprops, "profiles", icon="ITALIC", text="Profile") - def draw_read_only_set_item_ui(self, set_item, index, is_first=False, is_last=False): + def draw_read_only_set_item_ui(self, box, set_item, index, is_first=False, is_last=False): if ObjectMaterialData.data["material_class"] == "IfcMaterialList": - row = self.layout.row(align=True) + row = box.row(align=True) row.label(text="IfcMaterial", icon="LAYER_ACTIVE") row.label(text=set_item["name"], icon="MATERIAL") else: - row = self.layout.row(align=True) + row = box.row(align=True) row.label(text=set_item["name"], icon=set_item["icon"]) row.label(text=set_item["material"], icon="MATERIAL") @@ -322,29 +327,19 @@ class BIM_PT_object_material(Panel): def draw_read_only_set_ui(self): if ObjectMaterialData.data["material_class"] != "IfcMaterialList": row = self.layout.row(align=True) - row.label(text="Name") - row.label(text=ObjectMaterialData.data["set"]["name"]) + set_name = ObjectMaterialData.data["set"]["name"] + row.label(text=f" Name: {set_name}") if ObjectMaterialData.data["set"]["description"]: + set_description = ObjectMaterialData.data["set"]["description"] row = self.layout.row(align=True) - row.label(text="Description") - row.label(text=ObjectMaterialData.data["set"]["description"]) + row.label(text=f" Description: {set_description}") if ObjectMaterialData.data["material_class"] == "IfcMaterialProfileSetUsage": if ObjectMaterialData.data["set_usage"].get("cardinal_point"): + cardinal_point = ObjectMaterialData.data["set_usage"]["cardinal_point"] row = self.layout.row(align=True) - row.label(text="CardinalPoint") - row.label(text=ObjectMaterialData.data["set_usage"]["cardinal_point"]) - - for set_item in ObjectMaterialData.data["set_items"]: - if ObjectMaterialData.data["material_class"] == "IfcMaterialList": - row = self.layout.row(align=True) - row.label(text="IfcMaterial", icon="LAYER_ACTIVE") - row.label(text=set_item["name"], icon="MATERIAL") - else: - row = self.layout.row(align=True) - row.label(text=set_item["name"], icon=set_item["icon"]) - row.label(text=set_item["material"], icon="MATERIAL") + row.label(text=f" Cardinal Point: {cardinal_point}") if ObjectMaterialData.data["total_thickness"]: total_thickness = ObjectMaterialData.data["total_thickness"] @@ -358,9 +353,60 @@ class BIM_PT_object_material(Panel): total_thickness, precision=precision, suppress_zero_inches=True, in_unit_length=True ) row = self.layout.row(align=True) - row.label(text=f"Total Thickness: {formatted_thickness}") + row.label(text=f" Total Thickness: {formatted_thickness}") + + + layout = self.layout + box = layout.box() + active_object = bpy.context.active_object + self.layerset_bounds (box, active_object, location="Top_Exterior") + + + for set_item in ObjectMaterialData.data["set_items"]: + material_name = set_item["material"] + material_id = self.get_material_id_from_name(material_name) + if ObjectMaterialData.data["material_class"] == "IfcMaterialList": + row = box.row() + row.label(text="IfcMaterial", icon="LAYER_ACTIVE") + op = row.operator("bim.select_by_material", text=material_name, emboss=False) + op.material = material_id + else: + row = box.row() + row.label(text=set_item["name"], icon=set_item["icon"]) + op = row.operator("bim.select_by_material", text=material_name, emboss=False) + op.material = material_id + + self.layerset_bounds (box, active_object, location="Bottom_Interior") + + + + + def get_material_id_from_name(self, material_name): + for index, set_item in enumerate(ObjectMaterialData.data["materials"]): + if material_name == ObjectMaterialData.data["materials"][index][1]: + material_id = int(ObjectMaterialData.data["materials"][index][0]) + return material_id + + + def layerset_bounds (self, box, obj, location="Top_Exterior"): + element = tool.Ifc.get_entity(obj) + has_layersetdirection = hasattr(element.HasAssociations[0].RelatingMaterial, "LayerSetDirection") + if has_layersetdirection: + layer_set_direction = element.HasAssociations[0].RelatingMaterial.LayerSetDirection + if location == "Top_Exterior": + if layer_set_direction == "AXIS3": + box.label(text="----- Top -----") + else: + box.label(text="----- Exterior -----") + if location == "Bottom_Interior": + if layer_set_direction == "AXIS2": + box.label(text="----- Bottom -----") + else: + box.label(text="----- Interior -----") + + class BIM_UL_materials(UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname): mprops = context.scene.BIMMaterialProperties