diff --git a/src/blenderbim/blenderbim/bim/__init__.py b/src/blenderbim/blenderbim/bim/__init__.py index 47ed1d2851..6878061ba1 100644 --- a/src/blenderbim/blenderbim/bim/__init__.py +++ b/src/blenderbim/blenderbim/bim/__init__.py @@ -83,7 +83,6 @@ classes = [ operator.SetOverrideColour, operator.SetViewportShadowFromSun, operator.SnapSpacesTogether, - operator.OverrideDelete, prop.StrProperty, prop.Attribute, prop.BIMProperties, @@ -103,7 +102,6 @@ for mod in modules.values(): classes.extend(mod.classes) - def on_register(scene): handler.setDefaultProperties(scene) bpy.app.handlers.depsgraph_update_post.remove(on_register) diff --git a/src/blenderbim/blenderbim/bim/handler.py b/src/blenderbim/blenderbim/bim/handler.py index a2229b786c..0fda547dc4 100644 --- a/src/blenderbim/blenderbim/bim/handler.py +++ b/src/blenderbim/blenderbim/bim/handler.py @@ -107,13 +107,6 @@ def color_callback(obj, data): def active_object_callback(): - obj = bpy.context.active_object - for obj in bpy.context.selected_objects: - if not obj.BIMObjectProperties.ifc_definition_id: - continue - stored_obj = IfcStore.get_element(obj.BIMObjectProperties.ifc_definition_id) - if stored_obj and stored_obj != obj: - bpy.ops.bim.copy_class(obj=obj.name) refresh_ui_data() diff --git a/src/blenderbim/blenderbim/bim/module/geometry/__init__.py b/src/blenderbim/blenderbim/bim/module/geometry/__init__.py index 3b4538333a..b30778b1d7 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/__init__.py @@ -24,6 +24,8 @@ classes = ( operator.CopyRepresentation, operator.EditObjectPlacement, operator.GetRepresentationIfcParameters, + operator.OverrideDelete, + operator.OverrideDuplicateMove, operator.RemoveRepresentation, operator.SwitchRepresentation, operator.UpdateParametricRepresentation, diff --git a/src/blenderbim/blenderbim/bim/module/geometry/operator.py b/src/blenderbim/blenderbim/bim/module/geometry/operator.py index 03ac45928c..a757abc555 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/operator.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/operator.py @@ -431,3 +431,97 @@ class CopyRepresentation(bpy.types.Operator, Operator): if obj.data: bm.to_mesh(obj.data) bpy.ops.bim.add_representation(obj=obj.name) + + +class OverrideDelete(bpy.types.Operator): + bl_idname = "object.delete" + bl_label = "Delete" + + @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(): + return IfcStore.execute_ifc_operator(self, context) + for obj in context.selected_objects: + bpy.data.objects.remove(obj) + return {"FINISHED"} + + def invoke(self, context, event): + return context.window_manager.invoke_confirm(self, event) + + def _execute(self, context): + file = IfcStore.get_file() + for obj in context.selected_objects: + if obj.BIMObjectProperties.ifc_definition_id: + element = file.by_id(obj.BIMObjectProperties.ifc_definition_id) + if element.FillsVoids: + self.remove_filling(element) + if element.is_a("IfcOpeningElement"): + for rel in element.HasFillings: + self.remove_filling(rel.RelatedBuildingElement) + if element.VoidsElements: + self.delete_opening_element(element) + elif element.HasOpenings: + for rel in element.HasOpenings: + self.delete_opening_element(rel.RelatedOpeningElement) + bpy.data.objects.remove(obj) + return {"FINISHED"} + + def delete_opening_element(self, element): + obj = IfcStore.get_element(element.VoidsElements[0].RelatingBuildingElement.id()) + bpy.ops.bim.remove_opening(opening_id=element.id(), obj=obj.name) + + def remove_filling(self, element): + obj = IfcStore.get_element(element.id()) + bpy.ops.bim.remove_filling(obj=obj.name) + + +class OverrideDuplicateMove(bpy.types.Operator): + bl_idname = "object.duplicate_move" + bl_label = "Duplicate Objects" + + @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() + new_obj.data = obj.data.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() + new_obj.data = obj.data.copy() + if obj == context.active_object: + self.new_active_obj = new_obj + # This is the only difference + bpy.ops.bim.copy_class(obj=new_obj.name) + for collection in obj.users_collection: + collection.objects.link(new_obj) + obj.select_set(False) + new_obj.select_set(True) + bpy.ops.transform.translate("INVOKE_DEFAULT") + return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/operator.py b/src/blenderbim/blenderbim/bim/operator.py index 88f2e37e71..f0dcc9a148 100644 --- a/src/blenderbim/blenderbim/bim/operator.py +++ b/src/blenderbim/blenderbim/bim/operator.py @@ -565,48 +565,3 @@ class CopyAttributeToSelection(bpy.types.Operator): a.name() for a in self.schema.declaration_by_name(ifc_class).all_attributes() ] return self.applicable_attributes_cache[ifc_class] - - -class OverrideDelete(bpy.types.Operator): - bl_idname = "object.delete" - bl_label = "Delete" - - @classmethod - def poll(cls, context): - return len(context.selected_objects) > 0 - - def execute(self, context): - if IfcStore.get_file(): - return IfcStore.execute_ifc_operator(self, context) - for obj in context.selected_objects: - bpy.data.objects.remove(obj) - return {"FINISHED"} - - def invoke(self, context, event): - return context.window_manager.invoke_confirm(self, event) - - def _execute(self, context): - file = IfcStore.get_file() - for obj in context.selected_objects: - if obj.BIMObjectProperties.ifc_definition_id: - element = file.by_id(obj.BIMObjectProperties.ifc_definition_id) - if element.FillsVoids: - self.remove_filling(element) - if element.is_a("IfcOpeningElement"): - for rel in element.HasFillings: - self.remove_filling(rel.RelatedBuildingElement) - if element.VoidsElements: - self.delete_opening_element(element) - elif element.HasOpenings: - for rel in element.HasOpenings: - self.delete_opening_element(rel.RelatedOpeningElement) - bpy.data.objects.remove(obj) - return {"FINISHED"} - - def delete_opening_element(self, element): - obj = IfcStore.get_element(element.VoidsElements[0].RelatingBuildingElement.id()) - bpy.ops.bim.remove_opening(opening_id=element.id(), obj=obj.name) - - def remove_filling(self, element): - obj = IfcStore.get_element(element.id()) - bpy.ops.bim.remove_filling(obj=obj.name) diff --git a/src/blenderbim/test/bim/feature/geometry.feature b/src/blenderbim/test/bim/feature/geometry.feature index 3058e205a6..cbd79e4713 100644 --- a/src/blenderbim/test/bim/feature/geometry.feature +++ b/src/blenderbim/test/bim/feature/geometry.feature @@ -24,3 +24,41 @@ Scenario: Copy representation And additionally the object "IfcWall/Cube.001" is selected When I press "bim.copy_representation" Then nothing happens + +Scenario: Override delete - without active IFC data + Given an empty Blender session + And I add a cube + And the object "Cube" is selected + When I press "object.delete" + Then the object "Cube" does not exist + +Scenario: Override delete - 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 + When I press "object.delete" + Then the object "IfcWall/Cube" does not exist + +Scenario: Override duplicate move - without active IFC data + Given an empty Blender session + And I add a cube + And the object "Cube" is selected + When I press "object.duplicate_move" + Then the object "Cube" exists + And the object "Cube.001" exists + +Scenario: Override duplicate move - 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 + When I press "object.duplicate_move" + 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"