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")