From 10b6253a366a3d5469e3e4b2d9e4713f33390873 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Wed, 28 Jul 2021 19:55:18 +1000 Subject: [PATCH] Fix #1585. Materials are added as a potential if you assign it as an object material too, for convenience. --- src/blenderbim/blenderbim/bim/import_ifc.py | 8 ++- .../bim/module/material/operator.py | 53 ++++++++++++++++--- 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/import_ifc.py b/src/blenderbim/blenderbim/bim/import_ifc.py index 19b7922b49..673c3ba81f 100644 --- a/src/blenderbim/blenderbim/bim/import_ifc.py +++ b/src/blenderbim/blenderbim/bim/import_ifc.py @@ -54,11 +54,11 @@ class MaterialCreator: if not self.mesh or self.mesh.name in self.parsed_meshes: return self.parsed_meshes.add(self.mesh.name) - self.add_default_material_surface_style(element) + self.add_default_material(element) if self.parse_representations(element): self.assign_material_slots_to_faces() - def add_default_material_surface_style(self, element): + def add_default_material(self, element): element_material = ifcopenshell.util.element.get_material(element) if not element_material: return @@ -71,6 +71,10 @@ class MaterialCreator: if surface_style: self.mesh.materials.append(self.styles[surface_style[0].id()]) return + # For authoring convenience, we choose to assign a material, even if it has no surface style. See #1585. + for material in [m for m in self.ifc_importer.file.traverse(element_material) if m.is_a("IfcMaterial")]: + self.mesh.materials.append(self.materials[material.id()]) + return def load_existing_materials(self): for material in bpy.data.materials: diff --git a/src/blenderbim/blenderbim/bim/module/material/operator.py b/src/blenderbim/blenderbim/bim/module/material/operator.py index 3c70e9a5ca..eac898b6e5 100644 --- a/src/blenderbim/blenderbim/bim/module/material/operator.py +++ b/src/blenderbim/blenderbim/bim/module/material/operator.py @@ -1,6 +1,7 @@ import bpy import json import ifcopenshell.api +import ifcopenshell.util.element import ifcopenshell.util.attribute import ifcopenshell.util.representation import blenderbim.bim.helper @@ -54,14 +55,19 @@ class AddMaterial(bpy.types.Operator): self.file = IfcStore.get_file() result = ifcopenshell.api.run("material.add_material", self.file, **{"name": obj.name}) obj.BIMObjectProperties.ifc_definition_id = result.id() + IfcStore.link_element(result, obj) if obj.BIMMaterialProperties.ifc_style_id: context = ifcopenshell.util.representation.get_context(self.file, "Model", "Body", "MODEL_VIEW") if context: - ifcopenshell.api.run("style.assign_material_style", self.file, **{ - "material": result, - "style": self.file.by_id(obj.BIMMaterialProperties.ifc_style_id), - "context": context, - }) + ifcopenshell.api.run( + "style.assign_material_style", + self.file, + **{ + "material": result, + "style": self.file.by_id(obj.BIMMaterialProperties.ifc_style_id), + "context": context, + }, + ) Data.load(IfcStore.get_file()) material_prop_purge() return {"FINISHED"} @@ -103,19 +109,37 @@ class AssignMaterial(bpy.types.Operator): obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object material_type = self.material_type or obj.BIMObjectMaterialProperties.material_type self.file = IfcStore.get_file() + element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id) ifcopenshell.api.run( "material.assign_material", self.file, **{ - "product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id), + "product": element, "type": material_type, "material": self.file.by_id(int(obj.BIMObjectMaterialProperties.material)), }, ) 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): + 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" @@ -523,8 +547,25 @@ 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): + 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"