diff --git a/src/ifcblenderexport/blenderbim/bim/export_ifc.py b/src/ifcblenderexport/blenderbim/bim/export_ifc.py index 4d157dd290..98a6d8d94a 100644 --- a/src/ifcblenderexport/blenderbim/bim/export_ifc.py +++ b/src/ifcblenderexport/blenderbim/bim/export_ifc.py @@ -427,19 +427,14 @@ class IfcParser: for constraint in obj.BIMObjectProperties.constraints: self.rel_associates_constraint_object.setdefault(constraint.name, []).append(product) - for slot in obj.material_slots: - if slot.material is None or slot.link == "OBJECT": - continue - if obj.BIMObjectProperties.material_type == "IfcMaterialLayerSet": - self.rel_associates_material_layer_set.setdefault(self.product_index, []).append(slot.material.name) - elif obj.BIMObjectProperties.material_type == "IfcMaterialConstituentSet": - self.rel_associates_material_constituent_set.setdefault(self.product_index, []).append( - slot.material.name - ) - elif obj.BIMObjectProperties.material_type == "IfcMaterialProfileSet": - self.rel_associates_material_profile_set.setdefault(self.product_index, []).append(slot.material.name) - else: - self.rel_associates_material.setdefault(slot.material.name, []).append(product) + if obj.BIMObjectProperties.material_type == "IfcMaterial" and obj.BIMObjectProperties.material: + self.rel_associates_material.setdefault(obj.BIMObjectProperties.material.name, []).append(product) + elif obj.BIMObjectProperties.material_type == "IfcMaterialConstituentSet": + self.rel_associates_material_constituent_set[self.product_index] = obj.BIMObjectProperties.material_set + elif obj.BIMObjectProperties.material_type == "IfcMaterialLayerSet": + self.rel_associates_material_layer_set[self.product_index] = obj.BIMObjectProperties.material_set + elif obj.BIMObjectProperties.material_type == "IfcMaterialProfileSet": + pass # TODO return product @@ -1158,7 +1153,7 @@ class IfcParser: continue results[slot.material.name] = { "ifc": None, - "part_ifc": None, + "part_ifc": None, # TODO: check if we deprecate this "raw": slot.material, "material_type": obj.BIMObjectProperties.material_type, "attributes": self.get_material_attributes(slot.material), @@ -3146,17 +3141,27 @@ class IfcExporter: def relate_objects_to_material_sets(self, set_type): if not self.ifc_export_settings.has_representations: return - for product_index, related_materials in getattr( - self.ifc_parser, f"rel_associates_material_{set_type}_set" - ).items(): - material_set = self.file.create_entity( - f"IfcMaterial{set_type.capitalize()}Set", - **{ - f"Material{set_type.capitalize()}s": [ - self.ifc_parser.materials[m]["part_ifc"] for m in related_materials - ] - }, - ) + for product_index, material_set in getattr(self.ifc_parser, f"rel_associates_material_{set_type}_set").items(): + if set_type == "constituent": + materials = self.create_material_constituents(material_set.material_constituents) + elif set_type == "layer": + materials = self.create_material_layers(material_set.material_layers) + elif set_type == "profile": + materials = [] # TODO + if not materials: + continue + + attributes = { + f"Material{set_type.capitalize()}s": materials, + "Description": material_set.description or None, + } + + if set_type == "layer": + attributes["LayerSetName"] = material_set.name or None + else: + attributes["Name"] = material_set.name or None + + material_set = self.file.create_entity(f"IfcMaterial{set_type.capitalize()}Set", **attributes) self.file.createIfcRelAssociatesMaterial( ifcopenshell.guid.new(), self.owner_history, @@ -3166,6 +3171,50 @@ class IfcExporter: material_set, ) + def create_material_layers(self, layers): + results = [] + for layer in layers: + if layer.category == "None": + category = None + elif layer.category == "Custom": + category = layer.custom_category or None + else: + category = layer.category + is_ventilated = layer.is_ventilated == "TRUE" if layer.is_ventilated != "UNKNOWN" else None + results.append( + self.file.create_entity( + "IfcMaterialLayer", + **{ + "Material": self.ifc_parser.materials[layer.material.name]["ifc"] or None, + "LayerThickness": layer.layer_thickness, + "IsVentilated": is_ventilated, + "Name": layer.name or None, + "Description": layer.description or None, + "Category": category, + "Priority": layer.priority, + }, + ) + ) + return results + + def create_material_constituents(self, constituents): + results = [] + # TODO: the correlation for IfcShapeAspect is not yet implemented + for constituent in constituents: + results.append( + self.file.create_entity( + "IfcMaterialConstituent", + **{ + "Name": constituent.name or None, + "Description": constituent.description or None, + "Material": self.ifc_parser.materials[constituent.material.name]["ifc"], + "Fraction": constituent.fraction or None, + "Category": constituent.category or None, + }, + ) + ) + return results + def relate_spaces_to_boundary_elements(self): for (relating_space_index, relationships,) in self.ifc_parser.rel_space_boundaries.items(): for relationship in relationships: diff --git a/src/ifcblenderexport/blenderbim/bim/prop.py b/src/ifcblenderexport/blenderbim/bim/prop.py index 9fbf174ad9..54c3da6005 100644 --- a/src/ifcblenderexport/blenderbim/bim/prop.py +++ b/src/ifcblenderexport/blenderbim/bim/prop.py @@ -563,6 +563,7 @@ class MaterialLayer(PropertyGroup): description: StringProperty(name="Description") category: EnumProperty( items=[ + ("None", "None", ""), ("LoadBearing", "Load Bearing", ""), ("Insulation", "Insulation", ""), ("Finish", "Finish", ""), diff --git a/src/ifcblenderexport/blenderbim/bim/ui.py b/src/ifcblenderexport/blenderbim/bim/ui.py index 40567c42f3..5cb69efbc3 100644 --- a/src/ifcblenderexport/blenderbim/bim/ui.py +++ b/src/ifcblenderexport/blenderbim/bim/ui.py @@ -162,6 +162,8 @@ class BIM_PT_object_material(Panel): row = layout.row() row.prop(material, "layer_thickness") row = layout.row() + row.prop(material, "is_ventilated") + row = layout.row() row.prop(material, "priority") elif props.material_type == "IfcMaterialConstituentSet": row.template_list(