From 1d1bb1a707554ce51696d85d2feb9718e34a0220 Mon Sep 17 00:00:00 2001 From: Ryan Inch Date: Tue, 11 Aug 2020 00:02:52 -0400 Subject: Collection Manager: Object selection. Task: T69577 Adds the ability to select all object in a QCD slot. Alt+LMB deselects everything and selects all objects in the QCD slot. Alt+Shift+LMB adds/removes objects in the QCD slot to/from the selection. Added a selection operator for use in the Collection Manager popup. (currently unused) --- object_collection_manager/__init__.py | 3 +- object_collection_manager/operator_utils.py | 48 ++++++++++++++++++++------ object_collection_manager/operators.py | 53 +++++++++++++++++++++++++++++ object_collection_manager/qcd_operators.py | 24 ++++++++++--- 4 files changed, 112 insertions(+), 16 deletions(-) diff --git a/object_collection_manager/__init__.py b/object_collection_manager/__init__.py index 09cb1c2c..49bd0de9 100644 --- a/object_collection_manager/__init__.py +++ b/object_collection_manager/__init__.py @@ -22,7 +22,7 @@ bl_info = { "name": "Collection Manager", "description": "Manage collections and their objects", "author": "Ryan Inch", - "version": (2, 12, 5), + "version": (2, 13, 0), "blender": (2, 80, 0), "location": "View3D - Object Mode (Shortcut - M)", "warning": '', # used for warning icon and text in addons panel @@ -111,6 +111,7 @@ classes = ( operators.CMNewCollectionOperator, operators.CMRemoveCollectionOperator, operators.CMRemoveEmptyCollectionsOperator, + operators.CMSelectCollectionObjectsOperator, operators.CMSetCollectionOperator, operators.CMPhantomModeOperator, operators.CMApplyPhantomModeOperator, diff --git a/object_collection_manager/operator_utils.py b/object_collection_manager/operator_utils.py index d86a534f..ed7fce09 100644 --- a/object_collection_manager/operator_utils.py +++ b/object_collection_manager/operator_utils.py @@ -28,6 +28,7 @@ from .internals import ( copy_buffer, swap_buffer, update_property_group, + get_move_selection, ) rto_path = { @@ -57,20 +58,21 @@ def set_rto(layer_collection, rto, value): setattr(collection, rto_path[rto].split(".")[1], value) -def apply_to_children(laycol, apply_function): - laycol_iter_list = [laycol.children] +def apply_to_children(parent, apply_function): + # works for both Collections & LayerCollections + child_lists = [parent.children] - while len(laycol_iter_list) > 0: - new_laycol_iter_list = [] + while child_lists: + new_child_lists = [] - for laycol_iter in laycol_iter_list: - for layer_collection in laycol_iter: - apply_function(layer_collection) + for child_list in child_lists: + for child in child_list: + apply_function(child) - if len(layer_collection.children) > 0: - new_laycol_iter_list.append(layer_collection.children) + if child.children: + new_child_lists.append(child.children) - laycol_iter_list = new_laycol_iter_list + child_lists = new_child_lists def isolate_rto(cls, self, view_layer, rto, *, children=False): @@ -371,3 +373,29 @@ def remove_collection(laycol, collection, context): laycol = laycol["parent"] cm.cm_list_index = laycol["row_index"] + + +def select_collection_objects(collection_index, collection_name, replace, nested): + if collection_index == 0: + target_collection = bpy.context.view_layer.layer_collection.collection + + else: + laycol = layer_collections[collection_name] + target_collection = laycol["ptr"].collection + + if replace: + bpy.ops.object.select_all(action='DESELECT') + + selection_state = get_move_selection().isdisjoint(target_collection.objects) + + def select_objects(collection): + for obj in collection.objects: + try: + obj.select_set(selection_state) + except RuntimeError: + pass + + select_objects(target_collection) + + if nested: + apply_to_children(target_collection, select_objects) diff --git a/object_collection_manager/operators.py b/object_collection_manager/operators.py index 46e83023..7509d3f2 100644 --- a/object_collection_manager/operators.py +++ b/object_collection_manager/operators.py @@ -65,6 +65,7 @@ from .operator_utils import ( clear_swap, link_child_collections_to_parent, remove_collection, + select_collection_objects, ) class SetActiveCollection(Operator): @@ -215,6 +216,58 @@ class ExpandSublevelOperator(Operator): return {'FINISHED'} +class CMSelectCollectionObjectsOperator(Operator): + bl_label = "Select All Objects in the Collection" + bl_description = ( + " * LMB - Select all objects in collection.\n" + " * Shift+LMB - Add/Remove collection objects from selection.\n" + " * Ctrl+LMB - Isolate nested selection.\n" + " * Ctrl+Shift+LMB - Add/Remove nested from selection" + ) + bl_idname = "view3d.select_collection_objects" + bl_options = {'REGISTER', 'UNDO'} + + collection_index: IntProperty() + collection_name: StringProperty() + + def invoke(self, context, event): + modifiers = get_modifiers(event) + + if modifiers == {"shift"}: + select_collection_objects( + collection_index=self.collection_index, + collection_name=self.collection_name, + replace=False, + nested=False + ) + + elif modifiers == {"ctrl"}: + select_collection_objects( + collection_index=self.collection_index, + collection_name=self.collection_name, + replace=True, + nested=True + ) + + elif modifiers == {"ctrl", "shift"}: + select_collection_objects( + collection_index=self.collection_index, + collection_name=self.collection_name, + replace=False, + nested=True + ) + + else: + select_collection_objects( + collection_index=self.collection_index, + collection_name=self.collection_name, + replace=True, + nested=False + ) + + return {'FINISHED'} + + class CMSetCollectionOperator(Operator): bl_label = "Set Object Collection" bl_description = ( diff --git a/object_collection_manager/qcd_operators.py b/object_collection_manager/qcd_operators.py index 4f5f555a..4ffec562 100644 --- a/object_collection_manager/qcd_operators.py +++ b/object_collection_manager/qcd_operators.py @@ -45,6 +45,7 @@ from .internals import ( from .operator_utils import ( apply_to_children, + select_collection_objects, ) @@ -157,19 +158,32 @@ class ViewMoveQCDSlot(Operator): if modifiers == {"shift"}: bpy.ops.view3d.view_qcd_slot(slot=self.slot, toggle=True) - return {'FINISHED'} - elif modifiers == {"ctrl"}: bpy.ops.view3d.move_to_qcd_slot(slot=self.slot, toggle=False) - return {'FINISHED'} elif modifiers == {"ctrl", "shift"}: bpy.ops.view3d.move_to_qcd_slot(slot=self.slot, toggle=True) - return {'FINISHED'} + + elif modifiers == {"alt"}: + select_collection_objects( + collection_index=None, + collection_name=qcd_slots.get_name(self.slot), + replace=True, + nested=False + ) + + elif modifiers == {"alt", "shift"}: + select_collection_objects( + collection_index=None, + collection_name=qcd_slots.get_name(self.slot), + replace=False, + nested=False + ) else: bpy.ops.view3d.view_qcd_slot(slot=self.slot, toggle=False) - return {'FINISHED'} + + return {'FINISHED'} class ViewQCDSlot(Operator): '''View objects in QCD slot''' -- cgit v1.2.3