diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000..e34796ec5f --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,2 @@ +[tool.black] +line-length = 120 \ No newline at end of file diff --git a/src/ifcblenderexport/blenderbim/bim/__init__.py b/src/ifcblenderexport/blenderbim/bim/__init__.py index 1296a667b1..96b8bf7bbd 100644 --- a/src/ifcblenderexport/blenderbim/bim/__init__.py +++ b/src/ifcblenderexport/blenderbim/bim/__init__.py @@ -68,6 +68,9 @@ if bpy is not None: operator.RemoveQto, operator.AddMaterialPset, operator.RemoveMaterialPset, + operator.AddMaterialLayer, + operator.RemoveMaterialLayer, + operator.MoveMaterialLayer, operator.AddConstraint, operator.RemoveConstraint, operator.AssignConstraint, @@ -205,6 +208,7 @@ if bpy is not None: operator.GetRepresentationIfcParameters, operator.UpdateIfcRepresentation, prop.StrProperty, + prop.MaterialLayer, prop.Variable, prop.Role, prop.Address, @@ -280,6 +284,7 @@ if bpy is not None: ui.BIM_PT_mesh, ui.BIM_PT_presentation, ui.BIM_PT_object, + ui.BIM_PT_object_material, ui.BIM_PT_object_psets, ui.BIM_PT_object_qto, ui.BIM_PT_representations, diff --git a/src/ifcblenderexport/blenderbim/bim/operator.py b/src/ifcblenderexport/blenderbim/bim/operator.py index 0355a5fddf..c4d60a6711 100644 --- a/src/ifcblenderexport/blenderbim/bim/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/operator.py @@ -4096,6 +4096,44 @@ class RemoveSchedule(bpy.types.Operator): return {"FINISHED"} +class AddMaterialLayer(bpy.types.Operator): + bl_idname = "bim.add_material_layer" + bl_label = "Add Material Layer" + + def execute(self, context): + new = bpy.context.active_object.BIMObjectProperties.material_layers.add() + new.material = bpy.data.materials[0] + new.name = "Material Layer" + return {"FINISHED"} + + +class RemoveMaterialLayer(bpy.types.Operator): + bl_idname = "bim.remove_material_layer" + bl_label = "Remove Material Layer" + index: bpy.props.IntProperty() + + def execute(self, context): + bpy.context.active_object.BIMObjectProperties.material_layers.remove(self.index) + return {"FINISHED"} + + +class MoveMaterialLayer(bpy.types.Operator): + bl_idname = "bim.move_material_layer" + bl_label = "Move Material Layer" + direction: bpy.props.StringProperty() + + def execute(self, context): + props = bpy.context.active_object.BIMObjectProperties + index = props.active_material_layer_index + if self.direction == "UP" and index - 1 >= 0: + props.material_layers.move(index, index - 1) + props.active_material_layer_index = index - 1 + elif self.direction == "DOWN" and index + 1 < len(props.material_layers): + props.material_layers.move(index, index + 1) + props.active_material_layer_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 86f3793401..7b3740b069 100644 --- a/src/ifcblenderexport/blenderbim/bim/prop.py +++ b/src/ifcblenderexport/blenderbim/bim/prop.py @@ -567,6 +567,34 @@ class Subcontext(PropertyGroup): target_view: StringProperty(name="Target View") +class MaterialLayer(PropertyGroup): + name: StringProperty(name="Name") + material: PointerProperty(name="Material", type=bpy.types.Material) + layer_thickness: FloatProperty(name="Layer Thickness") + is_ventilated: EnumProperty( + items=[ + ("TRUE", "True", "Is an air gap and provides air exchange from the layer to outside air"), + ("FALSE", "False", "Is a solid material layer"), + ("UNKNOWN", "Unknown", "Is an air gap but does not provide air exchange or not known"), + ], + name="Is Ventilated", + default="FALSE", + ) + description: StringProperty(name="Description") + category: EnumProperty( + items=[ + ("LoadBearing", "Load Bearing", ""), + ("Insulation", "Insulation", ""), + ("Finish", "Finish", ""), + ("Custom", "Custom", ""), + ], + name="Category", + default="LoadBearing", + ) + custom_category: StringProperty(name="Custom Category") + priority: IntProperty(name="Priority") + + class Drawing(PropertyGroup): name: StringProperty(name="Name", update=updateDrawingName) camera: PointerProperty(name="Camera", type=bpy.types.Object) @@ -1636,6 +1664,9 @@ class BIMObjectProperties(PropertyGroup): active_constraint_index: IntProperty(name="Active Constraint Index") classifications: CollectionProperty(name="Classifications", type=ClassificationReference) material_type: EnumProperty(items=getMaterialTypes, name="Material Type") + material: PointerProperty(name="Material", type=bpy.types.Material) + material_layers: CollectionProperty(name="Material Layers", type=MaterialLayer) + active_material_layer_index: IntProperty(name="Active Material Layer Index") pset_name: EnumProperty(items=getPsetNames, name="Pset Name") qto_name: EnumProperty(items=getQtoNames, name="Qto Name") has_boundary_condition: BoolProperty(name="Has Boundary Condition") diff --git a/src/ifcblenderexport/blenderbim/bim/ui.py b/src/ifcblenderexport/blenderbim/bim/ui.py index c3536cb59e..7253ce1e6a 100644 --- a/src/ifcblenderexport/blenderbim/bim/ui.py +++ b/src/ifcblenderexport/blenderbim/bim/ui.py @@ -76,9 +76,6 @@ class BIM_PT_object(Panel): row = layout.row() row.prop(props, "relating_structure") - row = layout.row() - row.prop(props, "material_type") - def draw_addresses_ui(self): layout = self.layout layout.label(text="Address:") @@ -107,6 +104,58 @@ class BIM_PT_object(Panel): row.prop(address, "country") +class BIM_PT_object_material(Panel): + bl_label = "IFC Object Material" + bl_idname = "BIM_PT_object_material" + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "object" + + @classmethod + def poll(cls, context): + return context.active_object is not None and hasattr(context.active_object, "BIMObjectProperties") + + def draw(self, context): + if context.active_object is None: + return + layout = self.layout + props = context.active_object.BIMObjectProperties + row = layout.row() + row.prop(props, "material_type") + + if props.material_type == "IfcMaterial": + row = layout.row() + row.prop(props, "material") + elif props.material_type == "IfcMaterialLayerSet": + row = layout.row() + row.template_list( + "MATERIAL_UL_matslots", "", props, "material_layers", props, "active_material_layer_index" + ) + col = row.column(align=True) + col.operator("bim.add_material_layer", icon="ADD", text="") + col.operator("bim.remove_material_layer", icon="REMOVE", text="").index = props.active_material_layer_index + col.operator("bim.move_material_layer", icon="TRIA_UP", text="").direction = "UP" + col.operator("bim.move_material_layer", icon="TRIA_DOWN", text="").direction = "DOWN" + + if props.active_material_layer_index < len(props.material_layers): + material = props.material_layers[props.active_material_layer_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, "category") + if material.category == "Custom": + row = layout.row() + row.prop(material, "custom_category") + row = layout.row() + row.prop(material, "layer_thickness") + row = layout.row() + row.prop(material, "priority") + + class BIM_PT_object_psets(Panel): bl_label = "IFC Object Property Sets" bl_idname = "BIM_PT_object_psets"