From 7c89d072e238aadd8a7b340dd877f3d255f7562c Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 8 Dec 2023 15:07:46 +1100 Subject: [PATCH] Fix #4086. Add support for non predefined bSDD pset and qto values. --- .../blenderbim/bim/module/bsdd/operator.py | 23 +++++++++++++------ .../blenderbim/bim/module/bsdd/prop.py | 2 +- .../blenderbim/bim/module/bsdd/ui.py | 14 ++++++----- .../bim/module/classification/operator.py | 21 ++++++++++++++--- .../ifcopenshell/util/element.py | 18 ++++++++++++++- 5 files changed, 60 insertions(+), 18 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/bsdd/operator.py b/src/blenderbim/blenderbim/bim/module/bsdd/operator.py index f69639961b..85299d81ff 100644 --- a/src/blenderbim/blenderbim/bim/module/bsdd/operator.py +++ b/src/blenderbim/blenderbim/bim/module/bsdd/operator.py @@ -34,10 +34,10 @@ class LoadBSDDDomains(bpy.types.Operator): props.domains.clear() client = bsdd.Client() - if props.load_activated_domains: - domains = [d for d in client.Domain() if d["status"] == "Active"] - else: + if props.load_preview_domains: domains = client.Domain() + else: + domains = [d for d in client.Domain() if d["status"] == "Active"] for domain in sorted(domains, key=lambda x: x["name"]): new = props.domains.add() @@ -125,14 +125,23 @@ class GetBSDDClassificationProperties(bpy.types.Operator): possible_values = prop.get("possibleValues", []) or [] possible_values = [v["value"] for v in possible_values] - psets[pset][prop["name"]] = possible_values + psets[pset][prop["name"]] = {"data_type": prop["dataType"], "possible_values": possible_values} + + data_type_map = { + "String": "string", + "Real": "float", + "Boolean": "boolean", + } for pset_name, pset in psets.items(): new = bprops.classification_psets.add() new.name = pset_name - for name, values in pset.items(): + for name, data in pset.items(): new2 = new.properties.add() new2.name = name - new2.enum_items = json.dumps(values) - new2.data_type = "enum" + if data["possible_values"]: + new2.enum_items = json.dumps(data["possible_values"]) + new2.data_type = "enum" + else: + new2.data_type = data_type_map[data["data_type"]] return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/module/bsdd/prop.py b/src/blenderbim/blenderbim/bim/module/bsdd/prop.py index dca20abc6b..6e9fdeab05 100644 --- a/src/blenderbim/blenderbim/bim/module/bsdd/prop.py +++ b/src/blenderbim/blenderbim/bim/module/bsdd/prop.py @@ -63,5 +63,5 @@ class BIMBSDDProperties(PropertyGroup): active_classification_index: IntProperty(name="Active Classification Index") keyword: StringProperty(name="Keyword") should_filter_ifc_class: BoolProperty(name="Filter Active IFC Class", default=True) - load_activated_domains: BoolProperty(name="Load Activated Domains Only", default=True) + load_preview_domains: BoolProperty(name="Load Preview Domains", default=False) classification_psets: CollectionProperty(name="Classification Psets", type=BSDDPset) diff --git a/src/blenderbim/blenderbim/bim/module/bsdd/ui.py b/src/blenderbim/blenderbim/bim/module/bsdd/ui.py index f37986de2a..8bc9e487b4 100644 --- a/src/blenderbim/blenderbim/bim/module/bsdd/ui.py +++ b/src/blenderbim/blenderbim/bim/module/bsdd/ui.py @@ -32,8 +32,10 @@ class BIM_PT_bsdd(Panel): def draw(self, context): props = context.scene.BIMBSDDProperties - row = self.layout.row() - row.prop(props, "load_activated_domains") + row = self.layout.row(align=True) + row.prop(props, "load_preview_domains") + if len(props.domains): + row.operator("bim.load_bsdd_domains", text="", icon="FILE_REFRESH") if props.active_domain: row = self.layout.row() @@ -51,8 +53,6 @@ class BIM_PT_bsdd(Panel): props, "active_domain_index", ) - row = self.layout.row() - row.operator("bim.load_bsdd_domains", text="Reload bSDD Domains") else: row = self.layout.row() row.operator("bim.load_bsdd_domains") @@ -62,8 +62,10 @@ class BIM_UL_bsdd_domains(UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname): if item: row = layout.row(align=True) - row.label(text=f"{item.name} ({item.organization_name_owner})") - row.label(text=item.status) + if item.status != "Active": + row.label(text=f"{item.name} ({item.organization_name_owner}) - {item.status}", icon="ERROR") + else: + row.label(text=f"{item.name} ({item.organization_name_owner})") op = row.operator("bim.set_active_bsdd_domain", text="", icon="RESTRICT_SELECT_OFF") op.name = item.name op.uri = item.namespace_uri diff --git a/src/blenderbim/blenderbim/bim/module/classification/operator.py b/src/blenderbim/blenderbim/bim/module/classification/operator.py index 8ec27ad731..aebff6eb71 100644 --- a/src/blenderbim/blenderbim/bim/module/classification/operator.py +++ b/src/blenderbim/blenderbim/bim/module/classification/operator.py @@ -324,17 +324,32 @@ class AddClassificationReferenceFromBSDD(bpy.types.Operator, tool.Ifc.Operator): reference.Location = bsdd_classification.namespace_uri for classification_pset in bprops.classification_psets: - pset = ifcopenshell.util.element.get_pset(element, classification_pset.name) + is_pset = not classification_pset.name.startswith("Qto_") + + if is_pset: + pset = ifcopenshell.util.element.get_pset(element, classification_pset.name, psets_only=True) + else: + pset = ifcopenshell.util.element.get_pset(element, classification_pset.name, qtos_only=True) + if pset: pset = tool.Ifc.get().by_id(pset["id"]) - else: + elif is_pset: pset = ifcopenshell.api.run( "pset.add_pset", tool.Ifc.get(), product=element, name=classification_pset.name ) + else: + pset = ifcopenshell.api.run( + "pset.add_qto", tool.Ifc.get(), product=element, name=classification_pset.name + ) + properties = {} for prop in classification_pset.properties: properties[prop.name] = prop.get_value() - ifcopenshell.api.run("pset.edit_pset", tool.Ifc.get(), pset=pset, properties=properties) + + if is_pset: + ifcopenshell.api.run("pset.edit_pset", tool.Ifc.get(), pset=pset, properties=properties) + else: + ifcopenshell.api.run("pset.edit_qto", tool.Ifc.get(), qto=pset, properties=properties) class ChangeClassificationLevel(bpy.types.Operator): diff --git a/src/ifcopenshell-python/ifcopenshell/util/element.py b/src/ifcopenshell-python/ifcopenshell/util/element.py index d3547b8cfe..9cb612c609 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/element.py +++ b/src/ifcopenshell-python/ifcopenshell/util/element.py @@ -19,7 +19,7 @@ import ifcopenshell -def get_pset(element, name, prop=None, should_inherit=True, verbose=False): +def get_pset(element, name, prop=None, psets_only=False, qtos_only=False, should_inherit=True, verbose=False): """Retrieve a single property set or single property This is more efficient than ifcopenshell.util.element.get_psets if you know @@ -34,6 +34,10 @@ def get_pset(element, name, prop=None, should_inherit=True, verbose=False): :type name: str :param prop: The name of the property :type prop: str,optional + :param psets_only: Default as False. Set to true if only property sets are needed. + :type psets_only: bool,optional + :param qtos_only: Default as False. Set to true if only quantities are needed. + :type qtos_only: bool,optional :param should_inherit: Default as True. Set to false if you don't want to inherit property sets from the Type. :type should_inherit: bool,optional :return: A dictionary of property names and values, or a single value if a @@ -72,6 +76,18 @@ def get_pset(element, name, prop=None, should_inherit=True, verbose=False): pset = definition break + if pset: + if psets_only and not pset.is_a("IfcPropertySet"): + pset = None + elif qtos_only and not pset.is_a("IfcElementQuantity"): + pset = None + + if type_pset: + if psets_only and not type_pset.is_a("IfcPropertySet"): + type_pset = None + elif qtos_only and not type_pset.is_a("IfcElementQuantity"): + type_pset = None + if not pset and not type_pset: return