mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-18 22:33:33 +00:00
Fix bug where deleting the drawing object could lead to orphaned relationships
This commit is contained in:
@@ -28,6 +28,7 @@ import ifcopenshell.api
|
|||||||
import blenderbim.core.geometry as core
|
import blenderbim.core.geometry as core
|
||||||
import blenderbim.core.style
|
import blenderbim.core.style
|
||||||
import blenderbim.core.root
|
import blenderbim.core.root
|
||||||
|
import blenderbim.core.drawing
|
||||||
import blenderbim.tool as tool
|
import blenderbim.tool as tool
|
||||||
import blenderbim.bim.handler
|
import blenderbim.bim.handler
|
||||||
from mathutils import Vector
|
from mathutils import Vector
|
||||||
@@ -357,6 +358,8 @@ class OverrideDeleteTrait:
|
|||||||
element = tool.Ifc.get_entity(obj)
|
element = tool.Ifc.get_entity(obj)
|
||||||
if not element:
|
if not element:
|
||||||
return
|
return
|
||||||
|
if element.is_a("IfcAnnotation") and element.ObjectType == "DRAWING":
|
||||||
|
return blenderbim.core.drawing.remove_drawing(tool.Ifc, tool.Drawing, drawing=element)
|
||||||
IfcStore.delete_element(element)
|
IfcStore.delete_element(element)
|
||||||
if obj.users_collection and obj.users_collection[0].name == obj.name:
|
if obj.users_collection and obj.users_collection[0].name == obj.name:
|
||||||
parent = ifcopenshell.util.element.get_aggregate(element)
|
parent = ifcopenshell.util.element.get_aggregate(element)
|
||||||
@@ -425,7 +428,11 @@ class OverrideDelete(bpy.types.Operator, OverrideDeleteTrait):
|
|||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
for obj in context.selected_objects:
|
for obj in context.selected_objects:
|
||||||
self.delete_ifc_object(obj)
|
self.delete_ifc_object(obj)
|
||||||
bpy.data.objects.remove(obj)
|
try:
|
||||||
|
obj.name
|
||||||
|
bpy.data.objects.remove(obj)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
# Required otherwise gizmos are still visible
|
# Required otherwise gizmos are still visible
|
||||||
context.view_layer.objects.active = None
|
context.view_layer.objects.active = None
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|||||||
@@ -191,13 +191,13 @@ def duplicate_drawing(ifc, drawing_tool, drawing=None, should_duplicate_annotati
|
|||||||
|
|
||||||
|
|
||||||
def remove_drawing(ifc, drawing_tool, drawing=None):
|
def remove_drawing(ifc, drawing_tool, drawing=None):
|
||||||
|
collection = drawing_tool.get_drawing_collection(drawing)
|
||||||
|
if collection:
|
||||||
|
drawing_tool.delete_collection(collection)
|
||||||
group = drawing_tool.get_drawing_group(drawing)
|
group = drawing_tool.get_drawing_group(drawing)
|
||||||
if group:
|
if group:
|
||||||
drawing_tool.delete_drawing_elements(drawing_tool.get_group_elements(group))
|
drawing_tool.delete_drawing_elements(drawing_tool.get_group_elements(group))
|
||||||
ifc.run("group.remove_group", group=group)
|
ifc.run("group.remove_group", group=group)
|
||||||
collection = drawing_tool.get_drawing_collection(drawing)
|
|
||||||
if collection:
|
|
||||||
drawing_tool.delete_collection(collection)
|
|
||||||
for reference in drawing_tool.get_drawing_references(drawing):
|
for reference in drawing_tool.get_drawing_references(drawing):
|
||||||
reference_obj = ifc.get_object(reference)
|
reference_obj = ifc.get_object(reference)
|
||||||
if reference_obj:
|
if reference_obj:
|
||||||
|
|||||||
@@ -47,3 +47,29 @@ Scenario: Create drawing after deleting a duplicated object
|
|||||||
And I press "object.delete(use_global=False)"
|
And I press "object.delete(use_global=False)"
|
||||||
When I press "bim.create_drawing"
|
When I press "bim.create_drawing"
|
||||||
Then nothing happens
|
Then nothing happens
|
||||||
|
|
||||||
|
Scenario: Remove drawing
|
||||||
|
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 variable "wall1" is "IfcStore.get_file().by_type('IfcWall')[-1].id()"
|
||||||
|
And I press "bim.add_drawing"
|
||||||
|
And the variable "drawing" is "IfcStore.get_file().by_type('IfcAnnotation')[0].id()"
|
||||||
|
And the collection "IfcGroup/PLAN_VIEW" exists
|
||||||
|
When I press "bim.remove_drawing(drawing={drawing})"
|
||||||
|
Then the collection "IfcGroup/PLAN_VIEW" does not exist
|
||||||
|
|
||||||
|
Scenario: Remove drawing - via object deletion
|
||||||
|
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 variable "wall1" is "IfcStore.get_file().by_type('IfcWall')[-1].id()"
|
||||||
|
And I press "bim.add_drawing"
|
||||||
|
And the variable "drawing" is "IfcStore.get_file().by_type('IfcAnnotation')[0].id()"
|
||||||
|
And the object "IfcAnnotation/PLAN_VIEW" is selected
|
||||||
|
When I press "bim.override_object_delete"
|
||||||
|
Then the collection "IfcGroup/PLAN_VIEW" does not exist
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ Scenario: Override delete - without active IFC data
|
|||||||
Given an empty Blender session
|
Given an empty Blender session
|
||||||
And I add a cube
|
And I add a cube
|
||||||
And the object "Cube" is selected
|
And the object "Cube" is selected
|
||||||
When I press "object.delete"
|
When I press "bim.override_object_delete"
|
||||||
Then the object "Cube" does not exist
|
Then the object "Cube" does not exist
|
||||||
|
|
||||||
Scenario: Override delete - with active IFC data
|
Scenario: Override delete - with active IFC data
|
||||||
@@ -272,7 +272,7 @@ Scenario: Override delete - with active IFC data
|
|||||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
|
||||||
And I press "bim.assign_class"
|
And I press "bim.assign_class"
|
||||||
And the object "IfcWall/Cube" is selected
|
And the object "IfcWall/Cube" is selected
|
||||||
When I press "object.delete"
|
When I press "bim.override_object_delete"
|
||||||
Then the object "IfcWall/Cube" does not exist
|
Then the object "IfcWall/Cube" does not exist
|
||||||
|
|
||||||
Scenario: Override outliner delete
|
Scenario: Override outliner delete
|
||||||
|
|||||||
@@ -301,6 +301,16 @@ def the_object_name_exists(name) -> bpy.types.Object:
|
|||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
@given(parsers.parse('the collection "{name}" exists'))
|
||||||
|
@when(parsers.parse('the collection "{name}" exists'))
|
||||||
|
@then(parsers.parse('the collection "{name}" exists'))
|
||||||
|
def the_collection_name_exists(name) -> bpy.types.Collection:
|
||||||
|
obj = bpy.data.collections.get(name)
|
||||||
|
if not obj:
|
||||||
|
assert False, f'The collection "{name}" does not exist'
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
@then(parsers.parse('the object "{name1}" and "{name2}" are different elements'))
|
@then(parsers.parse('the object "{name1}" and "{name2}" are different elements'))
|
||||||
def the_object_name1_and_name2_are_different_elements(name1, name2):
|
def the_object_name1_and_name2_are_different_elements(name1, name2):
|
||||||
ifc = an_ifc_file_exists()
|
ifc = an_ifc_file_exists()
|
||||||
@@ -585,7 +595,13 @@ def the_collection_name1_is_in_the_collection_name2(name1, name2):
|
|||||||
@then(parsers.parse('the object "{name}" does not exist'))
|
@then(parsers.parse('the object "{name}" does not exist'))
|
||||||
def the_object_name_does_not_exist(name):
|
def the_object_name_does_not_exist(name):
|
||||||
obj = bpy.data.objects.get(name)
|
obj = bpy.data.objects.get(name)
|
||||||
assert obj is None or len(obj.users_collection) == 0, "Object exists"
|
assert obj is None or len(obj.users_collection) == 0, f"Object {name} exists"
|
||||||
|
|
||||||
|
|
||||||
|
@then(parsers.parse('the collection "{name}" does not exist'))
|
||||||
|
def the_collection_name_does_not_exist(name):
|
||||||
|
obj = bpy.data.collections.get(name)
|
||||||
|
assert obj is None, f"Collection {name} exists"
|
||||||
|
|
||||||
|
|
||||||
@then(parsers.parse('objects starting with "{name}" do not exist'))
|
@then(parsers.parse('objects starting with "{name}" do not exist'))
|
||||||
|
|||||||
Reference in New Issue
Block a user