diff --git a/src/bonsai/bonsai/bim/module/root/operator.py b/src/bonsai/bonsai/bim/module/root/operator.py index eb51f33d9f..8f36cb95ad 100644 --- a/src/bonsai/bonsai/bim/module/root/operator.py +++ b/src/bonsai/bonsai/bim/module/root/operator.py @@ -377,16 +377,18 @@ class AddElement(bpy.types.Operator, tool.Ifc.Operator): if representation_template == "EMTPY" or not ifc_context: pass - elif representation_template == "OBJ" and not props.representation_obj: - pass - elif representation_template == "OBJ": + elif representation_template == "OBJ" and props.representation_obj: obj.matrix_world = props.representation_obj.matrix_world builder = ifcopenshell.util.shape_builder.ShapeBuilder(tool.Ifc.get()) unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get()) - verts = [v.co / unit_scale for v in props.representation_obj.data.vertices] - faces = [p.vertices[:] for p in props.representation_obj.data.polygons] - item = builder.mesh(verts, faces) - representation = builder.get_representation(ifc_context, [item]) + items = [] + meshes = tool.Geometry.split_by_loose_parts(props.representation_obj) + for mesh in meshes: + verts = [v.co / unit_scale for v in mesh.vertices] + faces = [p.vertices[:] for p in mesh.polygons] + items.append(builder.mesh(verts, faces)) + bpy.data.meshes.remove(mesh) + representation = builder.get_representation(ifc_context, items) ifcopenshell.api.geometry.assign_representation(tool.Ifc.get(), element, representation) bonsai.core.geometry.switch_representation( tool.Ifc, diff --git a/src/bonsai/bonsai/tool/geometry.py b/src/bonsai/bonsai/tool/geometry.py index f83d123c62..0125950e6f 100644 --- a/src/bonsai/bonsai/tool/geometry.py +++ b/src/bonsai/bonsai/tool/geometry.py @@ -47,7 +47,7 @@ from collections import defaultdict from math import radians, pi from mathutils import Vector, Matrix from bonsai.bim.ifc import IfcStore -from typing import Union, Iterable, Optional, Literal, Iterator +from typing import Union, Iterable, Optional, Literal, Iterator, List from typing_extensions import TypeIs @@ -1562,3 +1562,23 @@ class Geometry(bonsai.core.tool.Geometry): ifcopenshell.util.element.remove_deep2(tool.Ifc.get(), item) obj.data.BIMMeshProperties.ifc_definition_id = new_item.id() cls.reload_representation(bpy.context.scene.BIMGeometryProperties.representation_obj) + + @classmethod + def split_by_loose_parts(cls, obj: bpy.types.Object) -> List[bpy.types.Mesh]: + dup_obj = obj.copy() + dup_obj.data = obj.data.copy() + bpy.context.scene.collection.objects.link(dup_obj) + + tool.Blender.select_and_activate_single_object(bpy.context, dup_obj) + + bpy.ops.object.mode_set(mode="EDIT") + bpy.ops.mesh.select_all(action="SELECT") + bpy.ops.mesh.separate(type="LOOSE") + bpy.ops.object.mode_set(mode="OBJECT") + + results = [] + for obj in bpy.context.selected_objects: + results.append(obj.data) + bpy.data.objects.remove(obj) + + return results