mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
Fix deep magick bug where copying elements without having one of them active didn't actually copy them in IFC too
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@ classes = (
|
||||
operator.CopyRepresentation,
|
||||
operator.EditObjectPlacement,
|
||||
operator.GetRepresentationIfcParameters,
|
||||
operator.OverrideDelete,
|
||||
operator.OverrideDuplicateMove,
|
||||
operator.RemoveRepresentation,
|
||||
operator.SwitchRepresentation,
|
||||
operator.UpdateParametricRepresentation,
|
||||
|
||||
@@ -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"}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user