diff --git a/src/bonsai/bonsai/bim/module/geometry/operator.py b/src/bonsai/bonsai/bim/module/geometry/operator.py index f41a7c7edc..4bdef85702 100644 --- a/src/bonsai/bonsai/bim/module/geometry/operator.py +++ b/src/bonsai/bonsai/bim/module/geometry/operator.py @@ -1070,11 +1070,20 @@ class OverrideDuplicateMove(bpy.types.Operator): tool.Root.reload_item_decorator() @staticmethod - def process_arrays(self, context): + def process_arrays( + self, context: bpy.types.Context + ) -> tuple[dict[bpy.types.Object, Any], set[ifcopenshell.entity_instance]]: + """ "Process arrays for currently selected objects. + + :return: A tuple of two elements:\n + - dictionary of objects and their array data. Those objects are safe to duplicate and regenerate arrays using the data.\n + - set of array children objects. Those objects can be ignored during duplication, they will be recreated automatically + when arrays are regenerated for objects from the dictionary. + """ selected_objects = set(context.selected_objects) array_parents = set() - arrays_to_create = dict() - array_children = set() # will be ignored during the duplication + arrays_to_create: dict[bpy.types.Object, Any] = dict() + array_children: set[ifcopenshell.entity_instance] = set() # will be ignored during the duplication for obj in context.selected_objects: element = tool.Ifc.get_entity(obj) diff --git a/src/bonsai/bonsai/core/pset.py b/src/bonsai/bonsai/core/pset.py index 5a059f4833..477f023cc2 100644 --- a/src/bonsai/bonsai/core/pset.py +++ b/src/bonsai/bonsai/core/pset.py @@ -65,7 +65,7 @@ def add_pset( def enable_pset_editing( pset_tool: tool.Pset, - pset: ifcopenshell.entity_instance, + pset: Union[ifcopenshell.entity_instance, None], pset_name: str, pset_type: tool.Pset.PSET_TYPE, obj_name: str, diff --git a/src/bonsai/bonsai/tool/model.py b/src/bonsai/bonsai/tool/model.py index 19e0660c69..2291d6862e 100644 --- a/src/bonsai/bonsai/tool/model.py +++ b/src/bonsai/bonsai/tool/model.py @@ -675,13 +675,14 @@ class Model(bonsai.core.tool.Model): # remove constraints obj = tool.Ifc.get_object(element) + assert isinstance(obj, bpy.types.Object) if not array_pset_data: # skip array parents constraint = next((c for c in obj.constraints if c.type == "CHILD_OF"), None) if constraint: matrix = obj.matrix_world.copy() obj.constraints.remove(constraint) - # keep the matrix before the constraint - # otherwise object will jump to some previous position + # Keep the matrix before removing the constraint, + # otherwise object will jump to some previous position. obj.matrix_world = matrix tool.Blender.lock_transform(obj, False) diff --git a/src/ifcopenshell-python/ifcopenshell/api/pset/edit_pset.py b/src/ifcopenshell-python/ifcopenshell/api/pset/edit_pset.py index eddc927d1a..d93bb9ebb9 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/pset/edit_pset.py +++ b/src/ifcopenshell-python/ifcopenshell/api/pset/edit_pset.py @@ -410,7 +410,12 @@ class Usecase: raise TypeError(f"'{self.settings['pset']}' is not a valid pset") - def get_primary_measure_type(self, name, old_value=None, new_value=None): + def get_primary_measure_type( + self, + name: str, + old_value: Optional[ifcopenshell.entity_instance] = None, + new_value: Optional[Union[ifcopenshell.entity_instance, str, float, bool, int]] = None, + ) -> Union[str, None]: if old_value: return old_value.is_a() if self.pset_template: @@ -418,7 +423,7 @@ class Usecase: if prop_template.Name != name: continue return prop_template.PrimaryMeasureType or "IfcLabel" - if new_value and hasattr(new_value, "is_a"): + if isinstance(new_value, ifcopenshell.entity_instance): return new_value.is_a() elif new_value is not None: if isinstance(new_value, str):