diff --git a/src/bonsai/bonsai/bim/module/spatial/operator.py b/src/bonsai/bonsai/bim/module/spatial/operator.py index f0c117528b..f8620e2d53 100644 --- a/src/bonsai/bonsai/bim/module/spatial/operator.py +++ b/src/bonsai/bonsai/bim/module/spatial/operator.py @@ -159,7 +159,18 @@ class SelectContainer(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.select_container" bl_label = "Select Container" bl_options = {"REGISTER", "UNDO"} + bl_description = "SHIFT + Click to add container to selection\nALT + Click to remove container from selection" container: bpy.props.IntProperty() + selection_mode: bpy.props.EnumProperty(items=[["ADD"] * 3, ["REMOVE"] * 3, ["SINGLE" * 3]]) + + def invoke(self, context, event): + if event.shift: + self.selection_mode = "ADD" + elif event.alt: + self.selection_mode = "REMOVE" + else: + self.selection_mode = "SINGLE" + return self.execute(context) def _execute(self, context): if self.container: @@ -169,7 +180,12 @@ class SelectContainer(bpy.types.Operator, tool.Ifc.Operator): else: return if container: - core.select_container(tool.Ifc, tool.Spatial, container=container) + core.select_container( + tool.Ifc, + tool.Spatial, + container=container, + selection_mode=self.selection_mode, + ) class SelectSimilarContainer(bpy.types.Operator, tool.Ifc.Operator): diff --git a/src/bonsai/bonsai/core/spatial.py b/src/bonsai/bonsai/core/spatial.py index bd1ba68d3a..8765493d4c 100644 --- a/src/bonsai/bonsai/core/spatial.py +++ b/src/bonsai/bonsai/core/spatial.py @@ -101,8 +101,10 @@ def copy_to_container( return result_objs -def select_container(ifc: tool.Ifc, spatial: tool.Spatial, container: ifcopenshell.entity_instance) -> None: - spatial.set_active_object(ifc.get_object(container)) +def select_container( + ifc: tool.Ifc, spatial: tool.Spatial, container: ifcopenshell.entity_instance, selection_mode: str = "ADD" +) -> None: + spatial.set_active_object(ifc.get_object(container), selection_mode=selection_mode) def select_similar_container(ifc: tool.Ifc, spatial: tool.Spatial, obj: bpy.types.Object) -> None: diff --git a/src/bonsai/bonsai/tool/blender.py b/src/bonsai/bonsai/tool/blender.py index 1bca5a3548..d3d3f04dc3 100644 --- a/src/bonsai/bonsai/tool/blender.py +++ b/src/bonsai/bonsai/tool/blender.py @@ -515,12 +515,22 @@ class Blender(bonsai.core.tool.Blender): active_object.select_set(True) @classmethod - def select_object(cls, obj: bpy.types.Object): + def set_object_selection(cls, obj: bpy.types.Object, state: bool = True): try: - obj.select_set(True) + obj.select_set(state) except RuntimeError: # Trying to select a hidden object throws an error pass + @classmethod + def select_object(cls, obj: bpy.types.Object): + cls.set_object_selection(obj, True) + + @classmethod + def deselect_object(cls, obj: bpy.types.Object, ensure_active_object: bool = True): + cls.set_object_selection(obj, False) + if ensure_active_object and bpy.context.view_layer.objects.active == obj and bpy.context.selected_objects: + cls.set_active_object(bpy.context.selected_objects[-1]) + @classmethod def set_objects_selection( cls, diff --git a/src/bonsai/bonsai/tool/spatial.py b/src/bonsai/bonsai/tool/spatial.py index 258d494224..b9c7e5e3ce 100644 --- a/src/bonsai/bonsai/tool/spatial.py +++ b/src/bonsai/bonsai/tool/spatial.py @@ -131,8 +131,13 @@ class Spatial(bonsai.core.tool.Spatial): tool.Blender.select_object(obj) @classmethod - def set_active_object(cls, obj: bpy.types.Object) -> None: - tool.Blender.set_active_object(obj) + def set_active_object(cls, obj: bpy.types.Object, selection_mode: str = "ADD") -> None: + if selection_mode == "ADD": + tool.Blender.set_active_object(obj) + elif selection_mode == "REMOVE": + tool.Blender.deselect_object(obj) + else: + tool.Blender.select_and_activate_single_object(bpy.context, obj) @classmethod def set_relative_object_matrix(