mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-21 14:23:53 +00:00
Fix aggregate duplication to include parts and preserve hierarchy (#7550)
- Auto-include all parts when duplicating aggregates - Preserve nested aggregate relationships during duplication - Select all duplicated objects for immediate moving
This commit is contained in:
@@ -1205,13 +1205,84 @@ class OverrideDuplicateMove(bpy.types.Operator):
|
|||||||
for obj in objects_to_remove:
|
for obj in objects_to_remove:
|
||||||
tool.Blender.deselect_object(obj)
|
tool.Blender.deselect_object(obj)
|
||||||
|
|
||||||
|
# Expand selection to include all parts of selected aggregates
|
||||||
|
objects_to_duplicate = set(context.selected_objects) - objects_to_remove
|
||||||
|
expanded_objects = set(objects_to_duplicate)
|
||||||
|
|
||||||
|
for obj in objects_to_duplicate:
|
||||||
|
element = tool.Ifc.get_entity(obj)
|
||||||
|
if element and element.is_a("IfcElementAssembly"):
|
||||||
|
parts = tool.Aggregate.get_parts_recursively(element)
|
||||||
|
for part in parts:
|
||||||
|
part_obj = tool.Ifc.get_object(part)
|
||||||
|
if part_obj:
|
||||||
|
expanded_objects.add(part_obj)
|
||||||
|
|
||||||
|
# Store parent aggregate relationships
|
||||||
|
parent_aggregates = {}
|
||||||
|
|
||||||
|
for obj in expanded_objects:
|
||||||
|
element = tool.Ifc.get_entity(obj)
|
||||||
|
if element and element.is_a("IfcElementAssembly"):
|
||||||
|
parent_aggregate = ifcopenshell.util.element.get_aggregate(element)
|
||||||
|
if parent_aggregate:
|
||||||
|
parent_aggregates[element] = parent_aggregate
|
||||||
|
|
||||||
old_to_new, new_active_obj = tool.Geometry.duplicate_ifc_objects(
|
old_to_new, new_active_obj = tool.Geometry.duplicate_ifc_objects(
|
||||||
set(context.selected_objects) - objects_to_remove,
|
expanded_objects,
|
||||||
linked=linked,
|
linked=linked,
|
||||||
active_object=context.active_object,
|
active_object=context.active_object,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Restore parent aggregate relationships, but only for parents that were NOT duplicated
|
||||||
|
for old_elem, new_elems in old_to_new.items():
|
||||||
|
if old_elem in parent_aggregates:
|
||||||
|
old_parent = parent_aggregates[old_elem]
|
||||||
|
|
||||||
|
# Check if the parent was also duplicated
|
||||||
|
if old_parent in old_to_new:
|
||||||
|
# The duplication already created the correct nested relationship
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Parent was NOT duplicated, so we need to assign to the original parent
|
||||||
|
for new_elem in new_elems:
|
||||||
|
new_obj = tool.Ifc.get_object(new_elem)
|
||||||
|
parent_obj = tool.Ifc.get_object(old_parent)
|
||||||
|
if new_obj and parent_obj:
|
||||||
|
bonsai.core.aggregate.assign_object(
|
||||||
|
tool.Ifc,
|
||||||
|
tool.Aggregate,
|
||||||
|
tool.Collector,
|
||||||
|
relating_obj=parent_obj,
|
||||||
|
related_obj=new_obj,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Select all duplicated objects and their parts
|
||||||
|
all_objects_to_select = set()
|
||||||
|
for old_elem, new_elems in old_to_new.items():
|
||||||
|
for new_elem in new_elems:
|
||||||
|
new_obj = tool.Ifc.get_object(new_elem)
|
||||||
|
if new_obj:
|
||||||
|
all_objects_to_select.add(new_obj)
|
||||||
|
|
||||||
|
# If it's an aggregate, also select all its parts
|
||||||
|
if new_elem.is_a("IfcElementAssembly"):
|
||||||
|
parts = tool.Aggregate.get_parts_recursively(new_elem)
|
||||||
|
for part in parts:
|
||||||
|
part_obj = tool.Ifc.get_object(part)
|
||||||
|
if part_obj:
|
||||||
|
all_objects_to_select.add(part_obj)
|
||||||
|
|
||||||
|
# Deselect everything first
|
||||||
|
bpy.ops.object.select_all(action='DESELECT')
|
||||||
|
|
||||||
|
# Select all the duplicated objects
|
||||||
|
for obj in all_objects_to_select:
|
||||||
|
obj.select_set(True)
|
||||||
|
|
||||||
if new_active_obj:
|
if new_active_obj:
|
||||||
context.view_layer.objects.active = new_active_obj
|
context.view_layer.objects.active = new_active_obj
|
||||||
|
|
||||||
return old_to_new
|
return old_to_new
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user