diff --git a/src/blenderbim/blenderbim/bim/helper.py b/src/blenderbim/blenderbim/bim/helper.py index ccbd176f9f..277ff83e4d 100644 --- a/src/blenderbim/blenderbim/bim/helper.py +++ b/src/blenderbim/blenderbim/bim/helper.py @@ -23,6 +23,7 @@ import math import zipfile import ifcopenshell import ifcopenshell.util.attribute +import ifcopenshell.util.element from ifcopenshell.util.doc import get_attribute_doc, get_predefined_type_doc, get_property_doc from mathutils import geometry from mathutils import Vector @@ -207,6 +208,10 @@ def get_obj_ifc_definition_id(context, obj, obj_type): return bpy.data.objects.get(obj).BIMObjectProperties.ifc_definition_id elif obj_type == "Material": return bpy.data.materials.get(obj).BIMObjectProperties.ifc_definition_id + elif obj_type == "MaterialSet": + return ifcopenshell.util.element.get_material( + tool.Ifc.get_entity(bpy.data.objects.get(obj)), should_skip_usage=True + ).id() elif obj_type == "Task": return context.scene.BIMTaskTreeProperties.tasks[ context.scene.BIMWorkScheduleProperties.active_task_index diff --git a/src/blenderbim/blenderbim/bim/module/pset/__init__.py b/src/blenderbim/blenderbim/bim/module/pset/__init__.py index 4cf97e2ba0..fa51c8453e 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/pset/__init__.py @@ -41,6 +41,7 @@ classes = ( prop.IfcProperty, prop.PsetProperties, prop.MaterialPsetProperties, + prop.MaterialSetPsetProperties, prop.TaskPsetProperties, prop.ResourcePsetProperties, prop.ProfilePsetProperties, @@ -51,6 +52,7 @@ classes = ( ui.BIM_PT_object_psets, ui.BIM_PT_object_qtos, ui.BIM_PT_material_psets, + ui.BIM_PT_material_set_psets, ui.BIM_PT_task_qtos, ui.BIM_PT_resource_qtos, ui.BIM_PT_resource_psets, @@ -65,6 +67,7 @@ classes = ( def register(): bpy.types.Object.PsetProperties = bpy.props.PointerProperty(type=prop.PsetProperties) + bpy.types.Object.MaterialSetPsetProperties = bpy.props.PointerProperty(type=prop.MaterialSetPsetProperties) bpy.types.Material.PsetProperties = bpy.props.PointerProperty(type=prop.MaterialPsetProperties) bpy.types.Scene.TaskPsetProperties = bpy.props.PointerProperty(type=prop.TaskPsetProperties) bpy.types.Scene.ResourcePsetProperties = bpy.props.PointerProperty(type=prop.ResourcePsetProperties) diff --git a/src/blenderbim/blenderbim/bim/module/pset/data.py b/src/blenderbim/blenderbim/bim/module/pset/data.py index aa4c81fe6a..23e2d371c2 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/data.py +++ b/src/blenderbim/blenderbim/bim/module/pset/data.py @@ -29,6 +29,7 @@ def refresh(): ObjectPsetsData.is_loaded = False ObjectQtosData.is_loaded = False MaterialPsetsData.is_loaded = False + MaterialSetPsetsData.is_loaded = False TaskQtosData.is_loaded = False ResourceQtosData.is_loaded = False ResourcePsetsData.is_loaded = False @@ -98,6 +99,22 @@ class MaterialPsetsData(Data): cls.is_loaded = True +class MaterialSetPsetsData(Data): + data = {} + is_loaded = False + + @classmethod + def load(cls): + psets = {} + element = tool.Ifc.get_entity(bpy.context.active_object) + if element: + material = ifcopenshell.util.element.get_material(element, should_skip_usage=True) + if material and "Set" in material.is_a(): + psets = cls.psetqtos(material) + cls.data = {"psets": psets} + cls.is_loaded = True + + class TaskQtosData(Data): data = {} is_loaded = False diff --git a/src/blenderbim/blenderbim/bim/module/pset/operator.py b/src/blenderbim/blenderbim/bim/module/pset/operator.py index dd17f9483d..7823b27616 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/operator.py +++ b/src/blenderbim/blenderbim/bim/module/pset/operator.py @@ -47,6 +47,8 @@ def get_pset_props(context, obj, obj_type): return bpy.data.objects.get(obj).PsetProperties elif obj_type == "Material": return bpy.data.materials.get(obj).PsetProperties + elif obj_type == "MaterialSet": + return bpy.data.objects.get(obj).MaterialSetPsetProperties elif obj_type == "Task": return context.scene.TaskPsetProperties elif obj_type == "Resource": diff --git a/src/blenderbim/blenderbim/bim/module/pset/prop.py b/src/blenderbim/blenderbim/bim/module/pset/prop.py index 083ba585a9..8d512a2716 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/prop.py +++ b/src/blenderbim/blenderbim/bim/module/pset/prop.py @@ -82,6 +82,21 @@ def get_material_pset_names(self, context): return psetnames[ifc_class] +def get_material_set_pset_names(self, context): + global psetnames + element = tool.Ifc.get_entity(context.active_object) + if not element: + return [] + material = ifcopenshell.util.element.get_material(element, should_skip_usage=True) + if not material or "Set" not in material.is_a(): + return [] + ifc_class = material.is_a() + if ifc_class not in psetnames: + psets = blenderbim.bim.schema.ifc.psetqto.get_applicable(ifc_class, pset_only=True) + psetnames[ifc_class] = blender_formatted_enum_from_psets(psets) + return psetnames[ifc_class] + + def get_task_qto_names(self, context): global qtonames ifc_class = "IfcTask" @@ -182,6 +197,13 @@ class MaterialPsetProperties(PropertyGroup): pset_name: EnumProperty(items=get_material_pset_names, name="Pset Name") +class MaterialSetPsetProperties(PropertyGroup): + active_pset_id: IntProperty(name="Active Pset ID") + active_pset_name: StringProperty(name="Pset Name") + properties: CollectionProperty(name="Properties", type=IfcProperty) + pset_name: EnumProperty(items=get_material_set_pset_names, name="Pset Name") + + class TaskPsetProperties(PropertyGroup): active_pset_id: IntProperty(name="Active Pset ID") active_pset_name: StringProperty(name="Pset Name") diff --git a/src/blenderbim/blenderbim/bim/module/pset/ui.py b/src/blenderbim/blenderbim/bim/module/pset/ui.py index c36b7ac3e9..fb81f823dc 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/ui.py +++ b/src/blenderbim/blenderbim/bim/module/pset/ui.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU General Public License # along with BlenderBIM Add-on. If not, see . +import blenderbim.tool as tool from bpy.types import Panel from blenderbim.bim.ifc import IfcStore from blenderbim.bim.helper import prop_with_search @@ -23,6 +24,7 @@ from blenderbim.bim.module.pset.data import ( ObjectPsetsData, ObjectQtosData, MaterialPsetsData, + MaterialSetPsetsData, TaskQtosData, ResourceQtosData, ResourcePsetsData, @@ -75,6 +77,8 @@ def get_active_pset_obj_name(context, obj_type): return context.active_object.name elif obj_type == "Material": return context.active_object.active_material.name + elif obj_type == "MaterialSet": + return context.active_object.name return "" @@ -270,6 +274,40 @@ class BIM_PT_material_psets(Panel): draw_psetqto_ui(context, pset["id"], pset, props, self.layout, "Material") +class BIM_PT_material_set_psets(Panel): + bl_label = "IFC Material Set Property Sets" + bl_idname = "BIM_PT_material_set_psets" + bl_options = {"DEFAULT_CLOSED"} + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "object" + bl_parent_id = "BIM_PT_object_material" + + @classmethod + def poll(cls, context): + if not context.active_object: + return False + if not tool.Ifc.get() or tool.Ifc.get().schema == "IFC2X3": + return False # We don't support material psets in IFC2X3 because they suck + if not tool.Ifc.get_entity(context.active_object): + return False + return True + + def draw(self, context): + if not MaterialSetPsetsData.is_loaded: + MaterialSetPsetsData.load() + + props = context.active_object.MaterialSetPsetProperties + row = self.layout.row(align=True) + prop_with_search(row, props, "pset_name", text="") + op = row.operator("bim.add_pset", icon="ADD", text="") + op.obj = context.active_object.name + op.obj_type = "MaterialSet" + + for pset in MaterialSetPsetsData.data["psets"]: + draw_psetqto_ui(context, pset["id"], pset, props, self.layout, "MaterialSet") + + class BIM_PT_task_qtos(Panel): bl_label = "IFC Task Quantity Sets" bl_idname = "BIM_PT_task_qtos"