Fix #7587. See #7550. Bug where you couldn't load or edit arrayed voids.

Reuse tool.Geometry.duplicate_ifc_objects because that's where all
duplication logic should stay instead of half reimplementing it every
time which introduces subtle bugs.
This commit is contained in:
Dion Moult
2026-01-24 23:03:18 +11:00
parent cf52607528
commit 0d8c4c7795
3 changed files with 22 additions and 15 deletions
+2 -1
View File
@@ -1223,7 +1223,8 @@ class Blender(bonsai.core.tool.Blender):
@classmethod
def constrain_children_to_parent(cls, parent_element: ifcopenshell.entity_instance) -> None:
parent_obj = tool.Ifc.get_object(parent_element)
if not (parent_obj := tool.Ifc.get_object(parent_element)):
return # Filtered out, arrayed void, etc
assert isinstance(parent_obj, bpy.types.Object)
children = cls.get_all_children_objects(parent_element)
for child in children:
+8
View File
@@ -2106,6 +2106,14 @@ class Geometry(bonsai.core.tool.Geometry):
active_object: Optional[bpy.types.Object] = None,
linked: bool = False,
) -> tuple[dict[ifcopenshell.entity_instance, list[ifcopenshell.entity_instance]], Union[bpy.types.Object, None]]:
"""Duplicate IFC objects
Duplication is surprisingly complicated because you might only select
part of a group of related items.
TODO: write some tests and figure out how to make this function
actually understandable.
"""
# Handle arrays
objects_to_duplicate = set(objects_to_duplicate)
arrays_to_duplicate, array_children = cls.process_arrays_for_duplication(objects_to_duplicate)
+12 -14
View File
@@ -1063,8 +1063,7 @@ class Model(bonsai.core.tool.Model):
removed_children = set(array["children"])
for removed_child in removed_children:
element = tool.Ifc.get().by_guid(removed_child)
obj = tool.Ifc.get_object(element)
if obj:
if obj := tool.Ifc.get_object(element):
tool.Geometry.delete_ifc_object(obj)
array["children"].clear()
@@ -1087,19 +1086,18 @@ class Model(bonsai.core.tool.Model):
offset = base_offset * i
for obj in obj_stack:
# get currently proccesed array element and it's object
if child_i >= total_existing_children:
child_obj = tool.Spatial.duplicate_object_and_data(obj)
child_element = tool.Spatial.run_root_copy_class(obj=child_obj)
else:
try:
global_id = array["children"][child_i]
try:
child_element = tool.Ifc.get().by_guid(global_id)
child_obj = tool.Ifc.get_object(child_element)
assert child_obj
except:
child_obj = tool.Spatial.duplicate_object_and_data(obj)
child_element = tool.Spatial.run_root_copy_class(obj=child_obj)
child_element = tool.Ifc.get().by_guid(global_id)
child_obj = tool.Ifc.get_object(child_element)
assert child_obj
except:
old_to_new, _ = tool.Geometry.duplicate_ifc_objects([obj])
# TODO Is this correct to assume one child? I really
# don't understand the linked aggregates and array
# behaviour.
child_element = list(old_to_new.values())[0][0]
child_obj = tool.Ifc.get_object(child_element)
# add child pset
child_pset = tool.Pset.get_element_pset(child_element, "BBIM_Array")