From 40e30eaa367c531cf4f380bbda7577d89970637f Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Mon, 9 Nov 2020 19:15:23 +1100 Subject: [PATCH] Support exporting more metadata labels like names and descriptions for profile sets --- .../blenderbim/bim/__init__.py | 6 ++- .../blenderbim/bim/export_ifc.py | 30 ++++++++++--- .../blenderbim/bim/operator.py | 38 ++++++++++++++++ src/ifcblenderexport/blenderbim/bim/prop.py | 42 ++++++++++------- src/ifcblenderexport/blenderbim/bim/ui.py | 45 ++++++++++++++----- 5 files changed, 128 insertions(+), 33 deletions(-) diff --git a/src/ifcblenderexport/blenderbim/bim/__init__.py b/src/ifcblenderexport/blenderbim/bim/__init__.py index 780f55086d..ad955586dc 100644 --- a/src/ifcblenderexport/blenderbim/bim/__init__.py +++ b/src/ifcblenderexport/blenderbim/bim/__init__.py @@ -74,6 +74,9 @@ if bpy is not None: operator.AddMaterialConstituent, operator.RemoveMaterialConstituent, operator.MoveMaterialConstituent, + operator.AddMaterialProfile, + operator.RemoveMaterialProfile, + operator.MoveMaterialProfile, operator.AddConstraint, operator.RemoveConstraint, operator.AssignConstraint, @@ -215,8 +218,10 @@ if bpy is not None: operator.GetRepresentationIfcParameters, operator.UpdateIfcRepresentation, prop.StrProperty, + prop.Attribute, prop.MaterialLayer, prop.MaterialConstituent, + prop.MaterialProfile, prop.MaterialSet, prop.Variable, prop.Role, @@ -244,7 +249,6 @@ if bpy is not None: prop.BcfTopicDocumentReference, prop.BcfTopicRelatedTopic, prop.Subcontext, - prop.Attribute, prop.BIMProperties, prop.BIMDebugProperties, prop.BCFProperties, diff --git a/src/ifcblenderexport/blenderbim/bim/export_ifc.py b/src/ifcblenderexport/blenderbim/bim/export_ifc.py index 98a6d8d94a..37afa66bf1 100644 --- a/src/ifcblenderexport/blenderbim/bim/export_ifc.py +++ b/src/ifcblenderexport/blenderbim/bim/export_ifc.py @@ -434,7 +434,7 @@ class IfcParser: 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 + self.rel_associates_material_profile_set[self.product_index] = obj.BIMObjectProperties.material_set return product @@ -2047,13 +2047,11 @@ class IfcExporter: material_type = material["material_type"][0:-3] self.cast_attributes(material_type, material["attributes"]) material["attributes"]["Material"] = material["ifc"] - if material_type == "IfcMaterialProfile": - material["attributes"]["Profile"] = self.create_material_profile(material) material["part_ifc"] = self.file.create_entity(material_type, **material["attributes"]) - def create_material_profile(self, material): - ifc_class = material["raw"].BIMMaterialProperties.profile_def - attributes = {a.name: a.string_value for a in material["raw"].BIMMaterialProperties.profile_attributes} + def create_material_profile_def(self, profile): + ifc_class = profile.profile + attributes = {a.name: a.string_value for a in profile.profile_attributes} self.cast_attributes(ifc_class, attributes) return self.file.create_entity(ifc_class, **attributes) @@ -3147,7 +3145,7 @@ class IfcExporter: elif set_type == "layer": materials = self.create_material_layers(material_set.material_layers) elif set_type == "profile": - materials = [] # TODO + materials = self.create_material_profiles(material_set.material_profiles) if not materials: continue @@ -3215,6 +3213,24 @@ class IfcExporter: ) return results + def create_material_profiles(self, profiles): + results = [] + for profile in profiles: + results.append( + self.file.create_entity( + "IfcMaterialProfile", + **{ + "Name": profile.name or None, + "Description": profile.description or None, + "Material": self.ifc_parser.materials[profile.material.name]["ifc"], + "Profile": self.create_material_profile_def(profile), + "Priority": profile.priority, + "Category": profile.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/operator.py b/src/ifcblenderexport/blenderbim/bim/operator.py index 9eaf01843e..31de9faebc 100644 --- a/src/ifcblenderexport/blenderbim/bim/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/operator.py @@ -4195,6 +4195,44 @@ class MoveMaterialConstituent(bpy.types.Operator): return {"FINISHED"} +class AddMaterialProfile(bpy.types.Operator): + bl_idname = "bim.add_material_profile" + bl_label = "Add Material Profile" + + def execute(self, context): + new = bpy.context.active_object.BIMObjectProperties.material_set.material_profiles.add() + new.material = bpy.data.materials[0] + new.name = "Material Profile" + return {"FINISHED"} + + +class RemoveMaterialProfile(bpy.types.Operator): + bl_idname = "bim.remove_material_profile" + bl_label = "Remove Material Profile" + index: bpy.props.IntProperty() + + def execute(self, context): + bpy.context.active_object.BIMObjectProperties.material_set.material_profiles.remove(self.index) + return {"FINISHED"} + + +class MoveMaterialProfile(bpy.types.Operator): + bl_idname = "bim.move_material_profile" + bl_label = "Move Material Profile" + direction: bpy.props.StringProperty() + + def execute(self, context): + props = bpy.context.active_object.BIMObjectProperties.material_set + index = props.active_material_profile_index + if self.direction == "UP" and index - 1 >= 0: + props.material_profiles.move(index, index - 1) + props.active_material_profile_index = index - 1 + elif self.direction == "DOWN" and index + 1 < len(props.material_profiles): + props.material_profiles.move(index, index + 1) + props.active_material_profile_index = index + 1 + return {"FINISHED"} + + class SelectScheduleFile(bpy.types.Operator): bl_idname = "bim.select_schedule_file" bl_label = "Select Documentation IFC File" diff --git a/src/ifcblenderexport/blenderbim/bim/prop.py b/src/ifcblenderexport/blenderbim/bim/prop.py index 904c7c9162..6e08108be5 100644 --- a/src/ifcblenderexport/blenderbim/bim/prop.py +++ b/src/ifcblenderexport/blenderbim/bim/prop.py @@ -484,10 +484,12 @@ def getApplicableMaterialAttributes(self, context): def refreshProfileAttributes(self, context): - while len(context.active_object.active_material.BIMMaterialProperties.profile_attributes) > 0: - context.active_object.active_material.BIMMaterialProperties.profile_attributes.remove(0) - for attribute in schema.ifc.IfcParameterizedProfileDef[self.profile_def]["attributes"]: - profile_attribute = context.active_object.active_material.BIMMaterialProperties.profile_attributes.add() + props = context.active_object.BIMObjectProperties + profile = props.material_set.material_profiles[props.material_set.active_material_profile_index] + while len(profile.profile_attributes) > 0: + profile.profile_attributes.remove(0) + for attribute in schema.ifc.IfcParameterizedProfileDef[profile.profile]["attributes"]: + profile_attribute = profile.profile_attributes.add() profile_attribute.name = attribute["name"] @@ -541,6 +543,15 @@ class Variable(PropertyGroup): prop_key: StringProperty(name="Property Key") +class Attribute(PropertyGroup): + name: StringProperty(name="Name") + data_type: StringProperty(name="Data Type") + string_value: StringProperty(name="Value") + bool_value: BoolProperty(name="Value") + int_value: IntProperty(name="Value") + float_value: FloatProperty(name="Value") + + class Subcontext(PropertyGroup): name: StringProperty(name="Name") context: StringProperty(name="Context") @@ -584,6 +595,16 @@ class MaterialConstituent(PropertyGroup): category: StringProperty(name="Category") +class MaterialProfile(PropertyGroup): + name: StringProperty(name="Name") + description: StringProperty(name="Description") + material: PointerProperty(name="Material", type=bpy.types.Material) + profile: EnumProperty(items=getProfileDef, name="Parameterized Profile Def", update=refreshProfileAttributes) + profile_attributes: CollectionProperty(name="Profile Attributes", type=Attribute) + priority: IntProperty(name="Priority") + category: StringProperty(name="Category") + + class MaterialSet(PropertyGroup): name: StringProperty(name="Name") description: StringProperty(name="Description") @@ -591,6 +612,8 @@ class MaterialSet(PropertyGroup): material_layers: CollectionProperty(name="Material Layers", type=MaterialLayer) active_material_constituent_index: IntProperty(name="Active Material Constituent Index") material_constituents: CollectionProperty(name="Material Constituents", type=MaterialConstituent) + active_material_profile_index: IntProperty(name="Active Material Profile Index") + material_profiles: CollectionProperty(name="Material Profiles", type=MaterialProfile) class Drawing(PropertyGroup): @@ -1605,15 +1628,6 @@ class BIMLibrary(PropertyGroup): description: StringProperty(name="Description") -class Attribute(PropertyGroup): - name: StringProperty(name="Name") - data_type: StringProperty(name="Data Type") - string_value: StringProperty(name="Value") - bool_value: BoolProperty(name="Value") - int_value: IntProperty(name="Value") - float_value: FloatProperty(name="Value") - - class IfcParameter(PropertyGroup): name: StringProperty(name="Name") step_id: IntProperty(name="STEP ID") @@ -1683,8 +1697,6 @@ class BIMMaterialProperties(PropertyGroup): psets: CollectionProperty(name="Psets", type=PsetQto) attributes: CollectionProperty(name="Attributes", type=Attribute) applicable_attributes: EnumProperty(items=getApplicableMaterialAttributes, name="Attribute Names") - profile_def: EnumProperty(items=getProfileDef, name="Parameterized Profile Def", update=refreshProfileAttributes) - profile_attributes: CollectionProperty(name="Profile Attributes", type=Attribute) class SweptSolid(PropertyGroup): diff --git a/src/ifcblenderexport/blenderbim/bim/ui.py b/src/ifcblenderexport/blenderbim/bim/ui.py index 5eb3b5c123..692369405f 100644 --- a/src/ifcblenderexport/blenderbim/bim/ui.py +++ b/src/ifcblenderexport/blenderbim/bim/ui.py @@ -194,6 +194,41 @@ class BIM_PT_object_material(Panel): row.prop(material, "fraction") row = layout.row() row.prop(material, "category") + elif props.material_type == "IfcMaterialProfileSet": + row.template_list( + "MATERIAL_UL_matslots", + "", + set_props, + "material_profiles", + set_props, + "active_material_profile_index", + ) + col = row.column(align=True) + col.operator("bim.add_material_profile", icon="ADD", text="") + col.operator( + "bim.remove_material_profile", icon="REMOVE", text="" + ).index = set_props.active_material_profile_index + col.operator("bim.move_material_profile", icon="TRIA_UP", text="").direction = "UP" + col.operator("bim.move_material_profile", icon="TRIA_DOWN", text="").direction = "DOWN" + + if set_props.active_material_profile_index < len(set_props.material_profiles): + material = set_props.material_profiles[set_props.active_material_profile_index] + row = layout.row() + row.prop(material, "material") + row = layout.row() + row.prop(material, "name") + row = layout.row() + row.prop(material, "description") + row = layout.row() + row.prop(material, "priority") + row = layout.row() + row.prop(material, "category") + row = layout.row() + row.prop(material, "profile") + for index, attribute in enumerate(material.profile_attributes): + row = layout.row(align=True) + row.prop(attribute, "name", text="") + row.prop(attribute, "string_value", text="") class BIM_PT_object_psets(Panel): @@ -834,16 +869,6 @@ class BIM_PT_material(Panel): row = layout.row() row.prop(props, "psets", text="") - if context.active_object.BIMObjectProperties.material_type == "IfcMaterialProfileSet": - layout.label(text="Profile Definition:") - row = layout.row() - row.prop(props, "profile_def") - - for index, attribute in enumerate(props.profile_attributes): - row = layout.row(align=True) - row.prop(attribute, "name", text="") - row.prop(attribute, "string_value", text="") - class BIM_PT_gis(Panel): bl_label = "IFC Georeferencing"