From b752048baf64fb04d33c855216c206e862f76d5d Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sun, 24 Sep 2023 15:45:11 +1000 Subject: [PATCH] We now support separating IFC meshes. --- src/blenderbim/blenderbim/bim/import_ifc.py | 2 +- .../bim/module/geometry/__init__.py | 4 +++ .../bim/module/geometry/operator.py | 33 +++++++++++++++++++ .../blenderbim/bim/module/geometry/ui.py | 15 +++++++++ 4 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/blenderbim/blenderbim/bim/import_ifc.py b/src/blenderbim/blenderbim/bim/import_ifc.py index fe3df02658..762a482382 100644 --- a/src/blenderbim/blenderbim/bim/import_ifc.py +++ b/src/blenderbim/blenderbim/bim/import_ifc.py @@ -1939,7 +1939,7 @@ class IfcImporter: def setup_arrays(self): for element in self.file.by_type("IfcElement"): pset_data = ifcopenshell.util.element.get_pset(element, "BBIM_Array") - if pset_data or not pset_data.get("Data", None): # skip array children + if not pset_data or not pset_data.get("Data", None): # skip array children continue for i in range(len(json.loads(pset_data["Data"]))): tool.Blender.Modifier.Array.set_children_lock_state(element, i, True) diff --git a/src/blenderbim/blenderbim/bim/module/geometry/__init__.py b/src/blenderbim/blenderbim/bim/module/geometry/__init__.py index c6f2a1e1c9..29503856bc 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/__init__.py @@ -32,6 +32,7 @@ classes = ( operator.OverrideDuplicateMoveLinkedMacro, operator.OverrideDuplicateMoveMacro, operator.OverrideJoin, + operator.OverrideMeshSeparate, operator.OverrideModeSetEdit, operator.OverrideModeSetObject, operator.OverrideOriginSet, @@ -53,6 +54,7 @@ classes = ( ui.BIM_PT_mesh, ui.BIM_PT_workarounds, ui.BIM_MT_object_set_origin, + ui.BIM_MT_separate, ) @@ -73,6 +75,7 @@ def register(): bpy.types.VIEW3D_MT_object.append(ui.object_menu) bpy.types.OUTLINER_MT_object.append(ui.outliner_menu) bpy.types.VIEW3D_MT_object_context_menu.append(ui.object_menu) + bpy.types.VIEW3D_MT_edit_mesh.append(ui.edit_mesh_menu) wm = bpy.context.window_manager if wm.keyconfigs.addon: km = wm.keyconfigs.addon.keymaps.new(name="Object Mode", space_type="EMPTY") @@ -116,6 +119,7 @@ def unregister(): bpy.types.OBJECT_PT_transform.remove(ui.BIM_PT_transform) bpy.types.OUTLINER_MT_object.remove(ui.outliner_menu) bpy.types.VIEW3D_MT_object_context_menu.remove(ui.outliner_menu) + bpy.types.VIEW3D_MT_edit_mesh.remove(ui.edit_mesh_menu) del bpy.types.Scene.BIMGeometryProperties del bpy.types.Object.BIMGeometryProperties wm = bpy.context.window_manager diff --git a/src/blenderbim/blenderbim/bim/module/geometry/operator.py b/src/blenderbim/blenderbim/bim/module/geometry/operator.py index a2a01392f5..cd0d147e94 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/operator.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/operator.py @@ -57,6 +57,39 @@ class EditObjectPlacement(bpy.types.Operator, Operator): core.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=obj) +class OverrideMeshSeparate(bpy.types.Operator, Operator): + bl_idname = "bim.override_mesh_separate" + bl_label = "IFC Mesh Separate" + bl_options = {"REGISTER", "UNDO"} + obj: bpy.props.StringProperty() + type: bpy.props.StringProperty() + + def _execute(self, context): + obj = context.active_object + + # You cannot separate meshes if the representation is mapped. + relating_type = tool.Root.get_element_type(tool.Ifc.get_entity(obj)) + if relating_type and tool.Root.does_type_have_representations(relating_type): + # We toggle edit mode to ensure that once representations are + # unmapped, our Blender mesh only has a single user. + tool.Blender.toggle_edit_mode(context) + bpy.ops.bim.unassign_type(related_object=obj.name) + tool.Blender.toggle_edit_mode(context) + + selected_objects = context.selected_objects + bpy.ops.mesh.separate(type=self.type) + bpy.ops.object.mode_set(mode="OBJECT", toggle=False) + new_objs = [obj] + for new_obj in context.selected_objects: + if new_obj == obj: + continue + # This is not very efficient, it needlessly copies the representations first. + blenderbim.core.root.copy_class(tool.Ifc, tool.Collector, tool.Geometry, tool.Root, obj=new_obj) + new_objs.append(new_obj) + for new_obj in new_objs: + bpy.ops.bim.update_representation(obj=new_obj.name) + + class OverrideOriginSet(bpy.types.Operator, Operator): bl_idname = "bim.override_origin_set" bl_label = "IFC Origin Set" diff --git a/src/blenderbim/blenderbim/bim/module/geometry/ui.py b/src/blenderbim/blenderbim/bim/module/geometry/ui.py index 92a8167443..a91cf340ee 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/ui.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/ui.py @@ -32,6 +32,21 @@ def object_menu(self, context): self.layout.menu("BIM_MT_object_set_origin", icon="PLUGIN") +def edit_mesh_menu(self, context): + self.layout.separator() + self.layout.menu("BIM_MT_separate", icon="PLUGIN") + + +class BIM_MT_separate(Menu): + bl_idname = "BIM_MT_separate" + bl_label = "IFC Separate" + + def draw(self, context): + self.layout.operator("bim.override_mesh_separate", icon="PLUGIN", text="IFC Selection").type = "SELECTED" + self.layout.operator("bim.override_mesh_separate", icon="PLUGIN", text="IFC By Material").type = "MATERIAL" + self.layout.operator("bim.override_mesh_separate", icon="PLUGIN", text="IFC By Loose Parts").type = "LOOSE" + + class BIM_MT_object_set_origin(Menu): bl_idname = "BIM_MT_object_set_origin" bl_label = "IFC Set Origin"