diff --git a/src/bonsai/bonsai/tool/blender.py b/src/bonsai/bonsai/tool/blender.py index 24cd5071fa..56e78d5c4f 100644 --- a/src/bonsai/bonsai/tool/blender.py +++ b/src/bonsai/bonsai/tool/blender.py @@ -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: diff --git a/src/bonsai/bonsai/tool/geometry.py b/src/bonsai/bonsai/tool/geometry.py index e2955d3d28..e10b2de832 100644 --- a/src/bonsai/bonsai/tool/geometry.py +++ b/src/bonsai/bonsai/tool/geometry.py @@ -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) diff --git a/src/bonsai/bonsai/tool/model.py b/src/bonsai/bonsai/tool/model.py index 28506bd8db..b8af52705c 100644 --- a/src/bonsai/bonsai/tool/model.py +++ b/src/bonsai/bonsai/tool/model.py @@ -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")