From 9a59b8cdae6211f5ae5bb4a0a16a764869cc79f3 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sun, 26 May 2024 11:23:08 +1000 Subject: [PATCH] Material psets now include category-specific psets and docstrings Previously it was not possible to get concrete / steel material psets. Yikes! --- .../blenderbim/bim/module/pset/data.py | 35 ++++++++++++++----- .../blenderbim/bim/module/pset/prop.py | 11 +++--- .../ifcopenshell/util/pset.py | 3 +- .../test/util/test_pset.py | 6 ++++ 4 files changed, 38 insertions(+), 17 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/pset/data.py b/src/blenderbim/blenderbim/bim/module/pset/data.py index dee548eeea..92d0cf112c 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/data.py +++ b/src/blenderbim/blenderbim/bim/module/pset/data.py @@ -61,6 +61,15 @@ class Data: ) return sorted(results, key=lambda v: v["Name"]) + @classmethod + def format_pset_enum(cls, psets): + enum_items = [] + version = tool.Ifc.get_schema() + for pset in psets: + doc = ifcopenshell.util.doc.get_property_set_doc(version, pset.Name) or {} + enum_items.append((pset.Name, pset.Name, doc.get("description", ""))) + return enum_items + class ObjectPsetsData(Data): data = {} @@ -114,15 +123,6 @@ class ObjectPsetsData(Data): ) return cls.format_pset_enum(qtos) - @classmethod - def format_pset_enum(cls, psets): - enum_items = [] - version = tool.Ifc.get_schema() - for pset in psets: - doc = ifcopenshell.util.doc.get_property_set_doc(version, pset.Name) or {} - enum_items.append((pset.Name, pset.Name, doc.get("description", ""))) - return enum_items - class ObjectQtosData(Data): data = {} @@ -165,9 +165,26 @@ class MaterialPsetsData(Data): cls.data = { "ifc_definition_id": ifc_definition_id, "psets": cls.psetqtos(tool.Ifc.get().by_id(ifc_definition_id)), + "pset_name": cls.pset_name(), } cls.is_loaded = True + @classmethod + def pset_name(cls): + props = bpy.context.scene.BIMMaterialProperties + if props.materials and props.active_material_index < len(props.materials): + material = props.materials[props.active_material_index] + if material.ifc_definition_id: + material = tool.Ifc.get().by_id(material.ifc_definition_id) + category = getattr(material, "Category", None) or None + psets = blenderbim.bim.schema.ifc.psetqto.get_applicable("IfcMaterial", category, pset_only=True) + psetnames = cls.format_pset_enum(psets) + assigned_names = ifcopenshell.util.element.get_psets( + material, psets_only=True, should_inherit=False + ).keys() + return [p for p in psetnames if p[0] not in assigned_names] + return [] + class MaterialSetPsetsData(Data): data = {} diff --git a/src/blenderbim/blenderbim/bim/module/pset/prop.py b/src/blenderbim/blenderbim/bim/module/pset/prop.py index c1814dec1f..3834f4337e 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/prop.py +++ b/src/blenderbim/blenderbim/bim/module/pset/prop.py @@ -23,7 +23,7 @@ import ifcopenshell.util.attribute import ifcopenshell.util.element import blenderbim.tool as tool from blenderbim.bim.prop import Attribute, StrProperty -from blenderbim.bim.module.pset.data import AddEditCustomPropertiesData, ObjectPsetsData +from blenderbim.bim.module.pset.data import AddEditCustomPropertiesData, ObjectPsetsData, MaterialPsetsData from blenderbim.bim.ifc import IfcStore from bpy.types import PropertyGroup from bpy.props import ( @@ -89,12 +89,9 @@ def get_object_pset_name(self, context): def get_material_pset_names(self, context): - global psetnames - ifc_class = "IfcMaterial" - 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] + if not MaterialPsetsData.is_loaded: + MaterialPsetsData.load() + return MaterialPsetsData.data["pset_name"] def get_material_set_pset_names(self, context): diff --git a/src/ifcopenshell-python/ifcopenshell/util/pset.py b/src/ifcopenshell-python/ifcopenshell/util/pset.py index 97db6ff4b2..13a6d0c5f8 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/pset.py +++ b/src/ifcopenshell-python/ifcopenshell/util/pset.py @@ -103,7 +103,8 @@ class PsetQto: matched_type = match.group(3) if matched_type and not predefined_type: continue - elif matched_type and predefined_type != match.group(3): + # Case insensitive to handle things like material categories + elif matched_type and predefined_type.lower() != match.group(3).lower(): continue applicable_class = match.group(1) diff --git a/src/ifcopenshell-python/test/util/test_pset.py b/src/ifcopenshell-python/test/util/test_pset.py index 649967b296..2eb5a3da5c 100644 --- a/src/ifcopenshell-python/test/util/test_pset.py +++ b/src/ifcopenshell-python/test/util/test_pset.py @@ -60,3 +60,9 @@ class TestPsetQto: names = self.pset_qto.get_applicable_names("IfcFurnitureType" ) names2 = self.pset_qto.get_applicable_names("IfcFurnitureType", "CUSTOM") assert names == names2 + + def test_getting_applicables_for_a_material_category(self): + names = self.pset_qto.get_applicable_names("IfcMaterial") + assert "Pset_MaterialConcrete" not in names + names = self.pset_qto.get_applicable_names("IfcMaterial", "concrete") + assert "Pset_MaterialConcrete" in names