diff --git a/src/blenderbim/blenderbim/bim/module/geometry/operator.py b/src/blenderbim/blenderbim/bim/module/geometry/operator.py index 7a03fd084e..4d8c9da684 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/operator.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/operator.py @@ -453,4 +453,50 @@ class OverrideDuplicateMove(bpy.types.Operator): blenderbim.core.root.copy_class(tool.Ifc, tool.Collector, tool.Geometry, tool.Root, obj=new_obj) bpy.ops.transform.translate("INVOKE_DEFAULT") blenderbim.bim.handler.purge_module_data() + + +class OverrideDuplicateMoveLinked(bpy.types.Operator): + bl_idname = "object.duplicate_move_linked" + bl_label = "Duplicate Linked" + + @classmethod + def poll(cls, context): + return len(context.selected_objects) > 0 + + def execute(self, context): + # Deep magick from the dawn of time + if IfcStore.get_file(): + IfcStore.execute_ifc_operator(self, context) + if self.new_active_obj: + context.view_layer.objects.active = self.new_active_obj + return {"FINISHED"} + + new_active_obj = None + for obj in context.selected_objects: + new_obj = obj.copy() + if obj == context.active_object: + new_active_obj = new_obj + for collection in obj.users_collection: + collection.objects.link(new_obj) + obj.select_set(False) + new_obj.select_set(True) + if new_active_obj: + context.view_layer.objects.active = new_active_obj + bpy.ops.transform.translate("INVOKE_DEFAULT") + return {"FINISHED"} + + def _execute(self, context): + self.new_active_obj = None + for obj in context.selected_objects: + new_obj = obj.copy() + if obj == context.active_object: + self.new_active_obj = new_obj + for collection in obj.users_collection: + collection.objects.link(new_obj) + obj.select_set(False) + new_obj.select_set(True) + # This is the only difference + blenderbim.core.root.copy_class(tool.Ifc, tool.Collector, tool.Geometry, tool.Root, obj=new_obj) + bpy.ops.transform.translate("INVOKE_DEFAULT") + blenderbim.bim.handler.purge_module_data() return {"FINISHED"} diff --git a/src/blenderbim/test/bim/feature/geometry.feature b/src/blenderbim/test/bim/feature/geometry.feature index 0385379a49..1f8abe30eb 100644 --- a/src/blenderbim/test/bim/feature/geometry.feature +++ b/src/blenderbim/test/bim/feature/geometry.feature @@ -244,3 +244,30 @@ Scenario: Override duplicate move - copying a profiled extrusion When I press "object.duplicate_move" Then the object "IfcWall/Cube.001" exists Then the object "IfcWall/Cube.001" has a "SweptSolid" representation of "Model/Body/MODEL_VIEW" + +Scenario: Override duplicate move linked - without active IFC data + Given an empty Blender session + And I add a cube + And I add an empty + And the object "Cube" is selected + And additionally the object "Empty" is selected + When I press "object.duplicate_move_linked" + Then the object "Cube" exists + And the object "Cube.001" exists + +Scenario: Override duplicate move linked - with active IFC data + Given an empty IFC project + And I add a cube + And the object "Cube" is selected + And I set "scene.BIMRootProperties.ifc_class" to "IfcWall" + And I press "bim.assign_class" + And the object "IfcWall/Cube" is selected + And additionally the object "IfcBuildingStorey/My Storey" is selected + When I press "object.duplicate_move_linked" + Then the object "IfcWall/Cube" exists + And the object "IfcWall/Cube" is an "IfcWall" + And the object "IfcWall/Cube.001" exists + And the object "IfcWall/Cube.001" is an "IfcWall" + And the object "IfcWall/Cube.001" has a "Tessellation" representation of "Model/Body/MODEL_VIEW" + And the object "IfcBuildingStorey/My Storey.001" exists + And the object "IfcBuildingStorey/My Storey.001" is an "IfcBuildingStorey"