From 2120653104bfdb9a61a96d3eaffd14c77a69b379 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Tue, 16 Nov 2021 17:52:08 +1100 Subject: [PATCH] Minor fix. --- .../blenderbim/bim/module/type/data.py | 43 ++++++++++++++++--- .../blenderbim/bim/module/type/prop.py | 6 +-- .../blenderbim/bim/module/type/ui.py | 39 ++++++++--------- .../ifcopenshell/util/element.py | 2 + .../test/util/test_element.py | 8 ++++ 5 files changed, 68 insertions(+), 30 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/type/data.py b/src/blenderbim/blenderbim/bim/module/type/data.py index 32533bed93..5398d3e110 100644 --- a/src/blenderbim/blenderbim/bim/module/type/data.py +++ b/src/blenderbim/blenderbim/bim/module/type/data.py @@ -17,6 +17,8 @@ # along with BlenderBIM Add-on. If not, see . import bpy +import ifcopenshell.util.type +import ifcopenshell.util.element import blenderbim.tool as tool @@ -30,24 +32,55 @@ class TypeData: @classmethod def load(cls): + cls.is_loaded = True cls.data = { "relating_type_classes": cls.relating_type_classes(), "relating_types": cls.relating_types(), + "is_product": cls.is_product(), + "total_instances": cls.total_instances(), + "type_name": cls.type_name(), } - cls.is_loaded = True @classmethod def relating_type_classes(cls): results = [] - element = tool.Ifc.get_entity(bpy.context.active_object) + obj = bpy.context.active_object + if not obj: + return + element = tool.Ifc.get_entity(obj) + if not element: + return [] types = ifcopenshell.util.type.get_applicable_types(element.is_a(), schema=tool.Ifc.get_schema()) - applicable_types_enum.extend((t, t, "") for t in types) + results.extend((t, t, "") for t in types) return results @classmethod def relating_types(cls): + relating_type_classes = cls.relating_type_classes() + if not relating_type_classes: + return [] results = [] - elements = tool.Ifc.get().by_type(bpy.context.active_object.BIMTypeProperties.relating_type_class) + relating_type_class = bpy.context.active_object.BIMTypeProperties.relating_type_class + if not relating_type_class and relating_type_classes: + relating_type_class = relating_type_classes[0][0] + elements = tool.Ifc.get().by_type(relating_type_class) elements = [(str(e.id()), e.Name, "") for e in elements] - relating_types_enum.extend(sorted(elements, key=lambda s: s[1])) + results.extend(sorted(elements, key=lambda s: s[1])) return results + + @classmethod + def is_product(cls): + element = tool.Ifc.get_entity(bpy.context.active_object) + return element.is_a("IfcProduct") + + @classmethod + def total_instances(cls): + element = tool.Ifc.get_entity(bpy.context.active_object) + return str(len(ifcopenshell.util.element.get_types(element))) + + @classmethod + def type_name(cls): + element = tool.Ifc.get_entity(bpy.context.active_object) + type = ifcopenshell.util.element.get_type(element) + if type: + return f"{type.is_a()}/{type.Name or 'Unnamed'}" diff --git a/src/blenderbim/blenderbim/bim/module/type/prop.py b/src/blenderbim/blenderbim/bim/module/type/prop.py index 93fa63e2d1..52682dcf66 100644 --- a/src/blenderbim/blenderbim/bim/module/type/prop.py +++ b/src/blenderbim/blenderbim/bim/module/type/prop.py @@ -46,11 +46,11 @@ def get_relating_type(self, context): return TypeData.data["relating_types"] -def update_is_editing_type(self, context): +def update_relating_type_class(self, context): TypeData.is_loaded = False class BIMTypeProperties(PropertyGroup): - is_editing_type: BoolProperty(name="Is Editing Type", update=update_is_editing_type) - relating_type_class: EnumProperty(items=get_relating_type_class, name="Relating Type Class") + is_editing_type: BoolProperty(name="Is Editing Type") + relating_type_class: EnumProperty(items=get_relating_type_class, name="Relating Type Class", update=update_relating_type_class) relating_type: EnumProperty(items=get_relating_type, name="Relating Type") diff --git a/src/blenderbim/blenderbim/bim/module/type/ui.py b/src/blenderbim/blenderbim/bim/module/type/ui.py index 274339e58f..a3d49166f0 100644 --- a/src/blenderbim/blenderbim/bim/module/type/ui.py +++ b/src/blenderbim/blenderbim/bim/module/type/ui.py @@ -16,10 +16,11 @@ # 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 import blenderbim.bim.module.type.prop as type_prop from bpy.types import Panel from blenderbim.bim.ifc import IfcStore -from ifcopenshell.api.type.data import Data +from blenderbim.bim.module.type.data import TypeData class BIM_PT_type(Panel): @@ -33,23 +34,20 @@ class BIM_PT_type(Panel): def poll(cls, context): if not context.active_object: return False - props = context.active_object.BIMObjectProperties - if not props.ifc_definition_id: - return False - if not IfcStore.get_element(props.ifc_definition_id): - return False - if props.ifc_definition_id not in Data.products and props.ifc_definition_id not in Data.types: - Data.load(IfcStore.get_file(), props.ifc_definition_id) - if props.ifc_definition_id not in Data.products and props.ifc_definition_id not in Data.types: - return False - if not Data.products.get(props.ifc_definition_id, None) and not Data.types.get(props.ifc_definition_id, None): + element = tool.Ifc.get_entity(context.active_object) + if not element: return False + if not element.is_a("IfcProduct") and not element.is_a("IfcTypeProduct"): + return True return True def draw(self, context): + if not TypeData.is_loaded: + TypeData.load() + oprops = context.active_object.BIMObjectProperties - if oprops.ifc_definition_id in Data.products: + if TypeData.data["is_product"]: self.draw_product_ui(context) else: self.draw_type_ui(context) @@ -58,7 +56,7 @@ class BIM_PT_type(Panel): props = context.active_object.BIMTypeProperties oprops = context.active_object.BIMObjectProperties row = self.layout.row(align=True) - row.label(text=f"{len(Data.types[oprops.ifc_definition_id])} Typed Objects") + row.label(text=f"{TypeData.data['total_instances']} Typed Objects") row.operator("bim.select_type_objects", icon="RESTRICT_SELECT_OFF", text="") def draw_product_ui(self, context): @@ -69,7 +67,7 @@ class BIM_PT_type(Panel): row = self.layout.row(align=True) row.prop(props, "relating_type_class", text="") - if type_prop.get_object_relating_type(None, context): + if type_prop.get_relating_type(None, context): row.prop(props, "relating_type", text="") row.operator("bim.assign_type", icon="CHECKMARK", text="") else: @@ -77,18 +75,15 @@ class BIM_PT_type(Panel): row.operator("bim.disable_editing_type", icon="CANCEL", text="") else: row = self.layout.row(align=True) - name = "{}/{}".format( - Data.products[oprops.ifc_definition_id]["type"], Data.products[oprops.ifc_definition_id]["Name"] - ) - if name == "None/None": - row.label(text="This object has no type") - row.operator("bim.enable_editing_type", icon="GREASEPENCIL", text="") - else: - row.label(text=name) + if TypeData.data["type_name"]: + row.label(text=TypeData.data["type_name"]) row.operator("bim.select_type", icon="TRACKER", text="") row.operator("bim.select_similar_type", icon="RESTRICT_SELECT_OFF", text="") row.operator("bim.enable_editing_type", icon="GREASEPENCIL", text="") row.operator("bim.unassign_type", icon="X", text="") + else: + row.label(text="This object has no type") + row.operator("bim.enable_editing_type", icon="GREASEPENCIL", text="") def add_object_button(self, context): diff --git a/src/ifcopenshell-python/ifcopenshell/util/element.py b/src/ifcopenshell-python/ifcopenshell/util/element.py index 63b6b79d5c..7faf0fd0ba 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/element.py +++ b/src/ifcopenshell-python/ifcopenshell/util/element.py @@ -81,6 +81,8 @@ def get_type(element): def get_types(type): for rel in getattr(type, "Types", []): return rel.RelatedObjects + for rel in getattr(type, "ObjectTypeOf", []): + return rel.RelatedObjects return [] diff --git a/src/ifcopenshell-python/test/util/test_element.py b/src/ifcopenshell-python/test/util/test_element.py index 855a0e9e59..ca6e4cba05 100644 --- a/src/ifcopenshell-python/test/util/test_element.py +++ b/src/ifcopenshell-python/test/util/test_element.py @@ -144,6 +144,14 @@ class TestGetTypes(test.bootstrap.IFC4): assert subject.get_types(element_type) == (element,) +class TestGetTypesIFC2X3(test.bootstrap.IFC2X3): + def test_getting_the_type_of_a_product(self): + element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") + element_type = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType") + ifcopenshell.api.run("type.assign_type", self.file, related_object=element, relating_type=element_type) + assert subject.get_types(element_type) == (element,) + + class TestGetMaterial(test.bootstrap.IFC4): def test_getting_the_material_of_a_product(self): element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")