diff --git a/src/blenderbim/blenderbim/bim/module/model/product.py b/src/blenderbim/blenderbim/bim/module/model/product.py
index 0f8f4bdeda..76a743105e 100644
--- a/src/blenderbim/blenderbim/bim/module/model/product.py
+++ b/src/blenderbim/blenderbim/bim/module/model/product.py
@@ -108,7 +108,7 @@ class AddTypeInstance(bpy.types.Operator):
]
mesh = bpy.data.meshes.new(name="Instance")
mesh.from_pydata(verts, edges, faces)
- obj = bpy.data.objects.new("Instance", mesh)
+ obj = bpy.data.objects.new(tool.Model.generate_occurrence_name(relating_type, instance_class), mesh)
obj.location = context.scene.cursor.location
collection = context.view_layer.active_layer_collection.collection
collection.objects.link(obj)
diff --git a/src/blenderbim/blenderbim/bim/module/model/profile.py b/src/blenderbim/blenderbim/bim/module/model/profile.py
index fb3ef464fd..1c3e6bbe26 100644
--- a/src/blenderbim/blenderbim/bim/module/model/profile.py
+++ b/src/blenderbim/blenderbim/bim/module/model/profile.py
@@ -138,18 +138,18 @@ class DumbProfileGenerator:
[0, 2, 6, 4],
]
+ ifc_classes = ifcopenshell.util.type.get_applicable_entities(self.relating_type.is_a(), self.file.schema)
+ # Standard cases are deprecated, so let's cull them
+ ifc_class = [c for c in ifc_classes if "StandardCase" not in c][0]
+
mesh = bpy.data.meshes.new(name="Dumb Profile")
mesh.from_pydata(verts, edges, faces)
- obj = bpy.data.objects.new("Profile", mesh)
+ obj = bpy.data.objects.new(tool.Model.generate_occurrence_name(self.relating_type, ifc_class), mesh)
obj.location = self.location
if self.collection_obj and self.collection_obj.BIMObjectProperties.ifc_definition_id:
obj.location[2] = self.collection_obj.location[2]
self.collection.objects.link(obj)
- ifc_classes = ifcopenshell.util.type.get_applicable_entities(self.relating_type.is_a(), self.file.schema)
- # Standard cases are deprecated, so let's cull them
- ifc_class = [c for c in ifc_classes if "StandardCase" not in c][0]
- obj.name = ifc_class[3:]
bpy.ops.bim.assign_class(obj=obj.name, ifc_class=ifc_class, should_add_representation=False)
if self.relating_type.is_a() in ["IfcBeamType", "IfcMemberType"]:
diff --git a/src/blenderbim/blenderbim/bim/module/model/prop.py b/src/blenderbim/blenderbim/bim/module/model/prop.py
index 5852118f9b..378794653f 100644
--- a/src/blenderbim/blenderbim/bim/module/model/prop.py
+++ b/src/blenderbim/blenderbim/bim/module/model/prop.py
@@ -53,3 +53,5 @@ def update_ifc_class(self, context):
class BIMModelProperties(PropertyGroup):
ifc_class: bpy.props.EnumProperty(items=get_ifc_class, name="IFC Class", update=update_ifc_class)
relating_type: bpy.props.EnumProperty(items=get_relating_type, name="Relating Type")
+ occurrence_name_style: bpy.props.EnumProperty(items=[("CLASS", "By Class", ""), ("TYPE", "By Type", ""), ("CUSTOM", "Custom", "")], name="Occurrence Name Style")
+ occurrence_name_function: bpy.props.StringProperty(name="Occurrence Name Function")
diff --git a/src/blenderbim/blenderbim/bim/module/model/slab.py b/src/blenderbim/blenderbim/bim/module/model/slab.py
index 517a7cf0ec..622f447e83 100644
--- a/src/blenderbim/blenderbim/bim/module/model/slab.py
+++ b/src/blenderbim/blenderbim/bim/module/model/slab.py
@@ -278,19 +278,18 @@ class DumbSlabGenerator:
edges = []
faces = [[0, 3, 2, 1]]
+ ifc_classes = ifcopenshell.util.type.get_applicable_entities(self.relating_type.is_a(), self.file.schema)
+ # Standard cases are deprecated, so let's cull them
+ ifc_class = [c for c in ifc_classes if "StandardCase" not in c][0]
+
mesh = bpy.data.meshes.new(name="Dumb Slab")
mesh.from_pydata(verts, edges, faces)
- obj = bpy.data.objects.new("Slab", mesh)
+ obj = bpy.data.objects.new(tool.Model.generate_occurrence_name(self.relating_type, ifc_class), mesh)
modifier = obj.modifiers.new("Slab Depth", "SOLIDIFY")
modifier.use_even_offset = True
modifier.offset = 1
modifier.thickness = self.depth
- ifc_classes = ifcopenshell.util.type.get_applicable_entities(self.relating_type.is_a(), self.file.schema)
- # Standard cases are deprecated, so let's cull them
- ifc_class = [c for c in ifc_classes if "StandardCase" not in c][0]
-
- obj.name = ifc_class[3:]
obj.location = self.location
if self.collection_obj and self.collection_obj.BIMObjectProperties.ifc_definition_id:
obj.location[2] = self.collection_obj.location[2] - self.depth
diff --git a/src/blenderbim/blenderbim/bim/module/model/wall.py b/src/blenderbim/blenderbim/bim/module/model/wall.py
index 513d929a8f..72a2c33c45 100644
--- a/src/blenderbim/blenderbim/bim/module/model/wall.py
+++ b/src/blenderbim/blenderbim/bim/module/model/wall.py
@@ -795,7 +795,7 @@ class DumbWallGenerator:
# Standard cases are deprecated, so let's cull them
ifc_class = [c for c in ifc_classes if "StandardCase" not in c][0]
- obj = bpy.data.objects.new(ifc_class[3:], mesh)
+ obj = bpy.data.objects.new(tool.Model.generate_occurrence_name(self.relating_type, ifc_class), mesh)
obj.location = self.location
obj.rotation_euler[2] = self.rotation
if self.collection_obj and self.collection_obj.BIMObjectProperties.ifc_definition_id:
diff --git a/src/blenderbim/blenderbim/bim/module/owner/operator.py b/src/blenderbim/blenderbim/bim/module/owner/operator.py
index f4aea75214..45b9c7f503 100644
--- a/src/blenderbim/blenderbim/bim/module/owner/operator.py
+++ b/src/blenderbim/blenderbim/bim/module/owner/operator.py
@@ -17,7 +17,6 @@
# along with BlenderBIM Add-on. If not, see .
import bpy
-import ifcopenshell.api
import blenderbim.tool as tool
import blenderbim.core.owner as core
import blenderbim.bim.handler
diff --git a/src/blenderbim/blenderbim/bim/ui.py b/src/blenderbim/blenderbim/bim/ui.py
index 23c49c4775..796ec67806 100644
--- a/src/blenderbim/blenderbim/bim/ui.py
+++ b/src/blenderbim/blenderbim/bim/ui.py
@@ -146,6 +146,12 @@ class BIM_ADDON_preferences(bpy.types.AddonPreferences):
row.prop(self, "should_hide_empty_props")
row = layout.row()
row.prop(self, "should_play_chaching_sound")
+
+ row = layout.row()
+ row.prop(context.scene.BIMModelProperties, "occurrence_name_style")
+ row = layout.row()
+ row.prop(context.scene.BIMModelProperties, "occurrence_name_function")
+
row = layout.row()
row.operator("bim.configure_visibility")
diff --git a/src/blenderbim/blenderbim/core/tool.py b/src/blenderbim/blenderbim/core/tool.py
index f47f870401..ebadfb8186 100644
--- a/src/blenderbim/blenderbim/core/tool.py
+++ b/src/blenderbim/blenderbim/core/tool.py
@@ -233,6 +233,11 @@ class Misc:
def split_objects_with_cutter(cls, objs, cutter): pass
+@interface
+class Model:
+ pass
+
+
@interface
class Patch:
def run_migrate_patch(cls, infile, outfile, schema): pass
diff --git a/src/blenderbim/blenderbim/tool/__init__.py b/src/blenderbim/blenderbim/tool/__init__.py
index 137d4d6102..82b9d537a7 100644
--- a/src/blenderbim/blenderbim/tool/__init__.py
+++ b/src/blenderbim/blenderbim/tool/__init__.py
@@ -30,6 +30,7 @@ from blenderbim.tool.ifc import Ifc
from blenderbim.tool.library import Library
from blenderbim.tool.material import Material
from blenderbim.tool.misc import Misc
+from blenderbim.tool.model import Model
from blenderbim.tool.owner import Owner
from blenderbim.tool.patch import Patch
from blenderbim.tool.pset import Pset
diff --git a/src/blenderbim/blenderbim/tool/model.py b/src/blenderbim/blenderbim/tool/model.py
new file mode 100644
index 0000000000..4e01dc38fb
--- /dev/null
+++ b/src/blenderbim/blenderbim/tool/model.py
@@ -0,0 +1,37 @@
+# BlenderBIM Add-on - OpenBIM Blender Add-on
+# Copyright (C) 2022 Dion Moult
+#
+# This file is part of BlenderBIM Add-on.
+#
+# BlenderBIM Add-on is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# BlenderBIM Add-on is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with BlenderBIM Add-on. If not, see .
+
+import bpy
+import blenderbim.core.tool
+import blenderbim.tool as tool
+
+
+class Model(blenderbim.core.tool.Model):
+ @classmethod
+ def generate_occurrence_name(cls, element_type, ifc_class):
+ props = bpy.context.scene.BIMModelProperties
+ if props.occurrence_name_style == "CLASS":
+ return ifc_class[3:]
+ elif props.occurrence_name_style == "TYPE":
+ return element_type.Name or "Unnamed"
+ elif props.occurrence_name_style == "CUSTOM":
+ try:
+ # Power users gonna power
+ return eval(props.occurrence_name_function) or "Instance"
+ except:
+ return "Instance"
diff --git a/src/blenderbim/test/tool/test_model.py b/src/blenderbim/test/tool/test_model.py
new file mode 100644
index 0000000000..005aa0e3d5
--- /dev/null
+++ b/src/blenderbim/test/tool/test_model.py
@@ -0,0 +1,52 @@
+# BlenderBIM Add-on - OpenBIM Blender Add-on
+# Copyright (C) 2022 Dion Moult
+#
+# This file is part of BlenderBIM Add-on.
+#
+# BlenderBIM Add-on is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# BlenderBIM Add-on is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with BlenderBIM Add-on. If not, see .
+
+import bpy
+import ifcopenshell
+import blenderbim.core.tool
+import blenderbim.tool as tool
+from test.bim.bootstrap import NewFile
+from blenderbim.tool.model import Model as subject
+
+
+class TestImplementsTool(NewFile):
+ def test_run(self):
+ assert isinstance(subject(), blenderbim.core.tool.Model)
+
+
+class TestGenerateOccurrenceName(NewFile):
+ def test_generating_based_on_class(self):
+ ifc = ifcopenshell.file()
+ element_type = ifc.createIfcWallType(Name="Foobar")
+ bpy.context.scene.BIMModelProperties.occurrence_name_style = "CLASS"
+ assert subject.generate_occurrence_name(element_type, "IfcWall") == "Wall"
+
+ def test_generating_based_on_type_name(self):
+ ifc = ifcopenshell.file()
+ element_type = ifc.createIfcWallType()
+ bpy.context.scene.BIMModelProperties.occurrence_name_style = "TYPE"
+ assert subject.generate_occurrence_name(element_type, "IfcWall") == "Unnamed"
+ element_type.Name = "Foobar"
+ assert subject.generate_occurrence_name(element_type, "IfcWall") == "Foobar"
+
+ def test_generating_based_on_a_custom_function(self):
+ ifc = ifcopenshell.file()
+ element_type = ifc.createIfcWallType()
+ bpy.context.scene.BIMModelProperties.occurrence_name_style = "CUSTOM"
+ bpy.context.scene.BIMModelProperties.occurrence_name_function = "\"Foobar\""
+ assert subject.generate_occurrence_name(element_type, "IfcWall") == "Foobar"