From c086104573d5a6374e22d686037be7263dcc89d8 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sat, 14 Aug 2021 20:02:31 +1000 Subject: [PATCH] Fix #1640. A Blender material is now always applied even if indirectly applied through a set or usage. --- .../bim/module/material/operator.py | 40 ------------------- .../blenderbim/bim/module/model/handler.py | 17 ++++++-- .../blenderbim/bim/module/model/product.py | 28 +++++++++++++ 3 files changed, 42 insertions(+), 43 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/material/operator.py b/src/blenderbim/blenderbim/bim/module/material/operator.py index dbc1d0c1a5..0d071dedbc 100644 --- a/src/blenderbim/blenderbim/bim/module/material/operator.py +++ b/src/blenderbim/blenderbim/bim/module/material/operator.py @@ -120,28 +120,8 @@ class AssignMaterial(bpy.types.Operator): ) Data.load(IfcStore.get_file()) Data.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id) - self.set_default_material(obj, element) return {"FINISHED"} - def set_default_material(self, obj, element): - if not obj.data: - return - - element_material = ifcopenshell.util.element.get_material(element) - material = [m for m in self.file.traverse(element_material) if m.is_a("IfcMaterial")] - if not material: - return - - object_material_ids = [ - om.BIMObjectProperties.ifc_definition_id - for om in obj.data.materials - if om is not None and om.BIMObjectProperties.ifc_definition_id - ] - - if material[0].id() in object_material_ids: - return - obj.data.materials.append(IfcStore.get_element(material[0].id())) - class UnassignMaterial(bpy.types.Operator): bl_idname = "bim.unassign_material" @@ -549,28 +529,8 @@ class EditAssignedMaterial(bpy.types.Operator): elif material_set.is_a("IfcMaterialProfileSet"): Data.load_profiles() bpy.ops.bim.disable_editing_assigned_material(obj=obj.name) - self.set_default_material(obj, self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)) return {"FINISHED"} - def set_default_material(self, obj, element): - if not obj.data: - return - - element_material = ifcopenshell.util.element.get_material(element) - material = [m for m in self.file.traverse(element_material) if m.is_a("IfcMaterial")] - if not material: - return - - object_material_ids = [ - om.BIMObjectProperties.ifc_definition_id - for om in obj.data.materials - if om is not None and om.BIMObjectProperties.ifc_definition_id - ] - - if material[0].id() in object_material_ids: - return - obj.data.materials.append(IfcStore.get_element(material[0].id())) - class EnableEditingMaterialSetItem(bpy.types.Operator): bl_idname = "bim.enable_editing_material_set_item" diff --git a/src/blenderbim/blenderbim/bim/module/model/handler.py b/src/blenderbim/blenderbim/bim/module/model/handler.py index 49a8100f5c..bde632c0b3 100644 --- a/src/blenderbim/blenderbim/bim/module/model/handler.py +++ b/src/blenderbim/blenderbim/bim/module/model/handler.py @@ -8,9 +8,7 @@ from bpy.app.handlers import persistent @persistent def load_post(*args): - ifcopenshell.api.add_pre_listener( - "attribute.edit_attributes", "BlenderBIM.Root.SyncName", root.sync_name - ) + ifcopenshell.api.add_pre_listener("attribute.edit_attributes", "BlenderBIM.Root.SyncName", root.sync_name) ifcopenshell.api.add_post_listener( "geometry.add_representation", "BlenderBIM.Product.GenerateBox", product.generate_box @@ -20,6 +18,19 @@ def load_post(*args): "sequence.edit_task_time", "BlenderBIM.Task.CalculateQuantities", task.calculate_quantities ) + for usecase in [ + "material.assign_material", + "material.edit_constituent", + "material.edit_layer", + "material.edit_profile", + "material.add_constituent", + "material.add_layer", + "material.add_profile", + ]: + ifcopenshell.api.add_post_listener( + usecase, "BlenderBIM.Product.EnsureMaterialAssigned", product.ensure_material_assigned + ) + ifcopenshell.api.add_post_listener( "material.edit_profile_usage", "BlenderBIM.Product.RegenerateProfileUsage", diff --git a/src/blenderbim/blenderbim/bim/module/model/product.py b/src/blenderbim/blenderbim/bim/module/model/product.py index 3d230403a7..55e99c7045 100644 --- a/src/blenderbim/blenderbim/bim/module/model/product.py +++ b/src/blenderbim/blenderbim/bim/module/model/product.py @@ -241,3 +241,31 @@ def regenerate_profile_usage(usecase_path, ifc_file, settings): bpy.ops.bim.switch_representation( obj=obj.name, ifc_definition_id=representation.id(), should_reload=True, should_switch_all_meshes=True ) + + +def ensure_material_assigned(usecase_path, ifc_file, settings): + elements = [] + for rel in ifc_file.by_type("IfcRelAssociatesMaterial"): + if rel.RelatingMaterial == settings["material"] or [ + e for e in ifc_file.traverse(rel.RelatingMaterial) if e == settings["material"] + ]: + elements.extend(rel.RelatedObjects) + + for element in elements: + obj = IfcStore.get_element(element.GlobalId) + if not obj: + continue + + element_material = ifcopenshell.util.element.get_material(element) + material = [m for m in ifc_file.traverse(element_material) if m.is_a("IfcMaterial")] + + object_material_ids = [ + om.BIMObjectProperties.ifc_definition_id + for om in obj.data.materials + if om is not None and om.BIMObjectProperties.ifc_definition_id + ] + + if material[0].id() in object_material_ids: + continue + + obj.data.materials.append(IfcStore.get_element(material[0].id()))