diff options
author | Ryan Inch <mythologylover75@gmail.com> | 2021-01-13 06:30:16 +0300 |
---|---|---|
committer | Ryan Inch <mythologylover75@gmail.com> | 2021-01-13 06:30:16 +0300 |
commit | 47820f66c255ce816c29fc50431b39a5148d8353 (patch) | |
tree | e62c44155b67a8ff88cffe4a2d2e983ad3d17f40 | |
parent | 589d13408a60cbec34a8bc3cc798c586043743ae (diff) |
Collection Manager: Add ops for selected objects. Task: T69577
Add operators to isolate/disable the collections of selected objects.
-rw-r--r-- | object_collection_manager/__init__.py | 2 | ||||
-rw-r--r-- | object_collection_manager/internals.py | 4 | ||||
-rw-r--r-- | object_collection_manager/operator_utils.py | 117 | ||||
-rw-r--r-- | object_collection_manager/operators.py | 114 | ||||
-rw-r--r-- | object_collection_manager/qcd_init.py | 14 | ||||
-rw-r--r-- | object_collection_manager/qcd_operators.py | 64 | ||||
-rw-r--r-- | object_collection_manager/ui.py | 6 |
7 files changed, 317 insertions, 4 deletions
diff --git a/object_collection_manager/__init__.py b/object_collection_manager/__init__.py index 4c8901ce..6a93ecd1 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, 18, 5), + "version": (2, 19, 0), "blender": (2, 80, 0), "location": "View3D - Object Mode (Shortcut - M)", "warning": '', # used for warning icon and text in addons panel diff --git a/object_collection_manager/internals.py b/object_collection_manager/internals.py index c95328c8..77e801f6 100644 --- a/object_collection_manager/internals.py +++ b/object_collection_manager/internals.py @@ -638,14 +638,14 @@ def get_move_selection(*, names_only=False): return {obj for obj in bpy.data.objects if obj.name in move_selection} -def get_move_active(): +def get_move_active(*, always=False): global move_active global move_selection if not move_active: move_active = getattr(bpy.context.view_layer.objects.active, "name", None) - if move_active not in get_move_selection(names_only=True): + if not always and move_active not in get_move_selection(names_only=True): move_active = None return bpy.data.objects[move_active] if move_active else None diff --git a/object_collection_manager/operator_utils.py b/object_collection_manager/operator_utils.py index 8b637a57..820ab1bb 100644 --- a/object_collection_manager/operator_utils.py +++ b/object_collection_manager/operator_utils.py @@ -26,6 +26,7 @@ from . import internals from .internals import ( update_property_group, get_move_selection, + get_move_active, ) mode_converter = { @@ -244,6 +245,122 @@ def isolate_rto(cls, self, view_layer, rto, *, children=False): cls.isolated = True +def isolate_sel_objs_collections(view_layer, rto, caller, *, use_active=False): + selected_objects = get_move_selection() + + if use_active: + selected_objects.add(get_move_active(always=True)) + + if not selected_objects: + return "No selected objects" + + off = set_off_on[rto]["off"] + on = set_off_on[rto]["on"] + + if caller == "CM": + history = internals.rto_history[rto+"_all"][view_layer] + + elif caller == "QCD": + history = internals.qcd_history[view_layer] + + + # if not isolated, isolate collections of selected objects + if len(history) == 0: + keep_history = False + + # save history and isolate RTOs + for item in internals.layer_collections.values(): + history.append(get_rto(item["ptr"], rto)) + rto_state = off + + # check if any of the selected objects are in the collection + if not set(selected_objects).isdisjoint(item["ptr"].collection.objects): + rto_state = on + + if history[-1] != rto_state: + keep_history = True + + if rto == "exclude": + set_exclude_state(item["ptr"], rto_state) + + else: + set_rto(item["ptr"], rto, rto_state) + + # activate all parents if needed + if rto_state == on and rto not in ["holdout", "indirect"]: + laycol = item["parent"] + while laycol["id"] != 0: + set_rto(laycol["ptr"], rto, on) + laycol = laycol["parent"] + + + if not keep_history: + history.clear() + + return "Collection already isolated" + + + else: + for x, item in enumerate(internals.layer_collections.values()): + set_rto(item["ptr"], rto, history[x]) + + # clear history + if caller == "CM": + del internals.rto_history[rto+"_all"][view_layer] + + elif caller == "QCD": + del internals.qcd_history[view_layer] + + +def disable_sel_objs_collections(view_layer, rto, caller): + off = set_off_on[rto]["off"] + on = set_off_on[rto]["on"] + selected_objects = get_move_selection() + + if caller == "CM": + history = internals.rto_history[rto+"_all"][view_layer] + + elif caller == "QCD": + history = internals.qcd_history[view_layer] + + + if not selected_objects and not history: + # clear history + if caller == "CM": + del internals.rto_history[rto+"_all"][view_layer] + + elif caller == "QCD": + del internals.qcd_history[view_layer] + + return "No selected objects" + + # if not disabled, disable collections of selected objects + if len(history) == 0: + # save history and disable RTOs + for item in internals.layer_collections.values(): + history.append(get_rto(item["ptr"], rto)) + + # check if any of the selected objects are in the collection + if not set(selected_objects).isdisjoint(item["ptr"].collection.objects): + if rto == "exclude": + set_exclude_state(item["ptr"], off) + + else: + set_rto(item["ptr"], rto, off) + + + else: + for x, item in enumerate(internals.layer_collections.values()): + set_rto(item["ptr"], rto, history[x]) + + # clear history + if caller == "CM": + del internals.rto_history[rto+"_all"][view_layer] + + elif caller == "QCD": + del internals.qcd_history[view_layer] + + def toggle_children(self, view_layer, rto): laycol_ptr = internals.layer_collections[self.name]["ptr"] # clear rto history diff --git a/object_collection_manager/operators.py b/object_collection_manager/operators.py index 94b7518d..45dc4df5 100644 --- a/object_collection_manager/operators.py +++ b/object_collection_manager/operators.py @@ -59,6 +59,8 @@ from .operator_utils import ( remove_collection, select_collection_objects, set_exclude_state, + isolate_sel_objs_collections, + disable_sel_objs_collections, ) from . import ui @@ -441,6 +443,8 @@ class CMUnExcludeAllOperator(Operator): bl_description = ( " * LMB - Enable all/Restore.\n" " * Shift+LMB - Invert.\n" + " * Shift+Ctrl+LMB - Isolate collections w/ selected objects.\n" + " * Shift+Alt+LMB - Disable collections w/ selected objects.\n" " * Ctrl+LMB - Copy/Paste RTOs.\n" " * Ctrl+Alt+LMB - Swap RTOs.\n" " * Alt+LMB - Discard history" @@ -472,6 +476,20 @@ class CMUnExcludeAllOperator(Operator): elif modifiers == {"shift"}: invert_rtos(view_layer, "exclude") + elif modifiers == {"shift", "ctrl"}: + error = isolate_sel_objs_collections(view_layer, "exclude", "CM") + + if error: + self.report({"WARNING"}, error) + return {'CANCELLED'} + + elif modifiers == {"shift", "alt"}: + error = disable_sel_objs_collections(view_layer, "exclude", "CM") + + if error: + self.report({"WARNING"}, error) + return {'CANCELLED'} + else: activate_all_rtos(view_layer, "exclude") @@ -550,6 +568,8 @@ class CMUnRestrictSelectAllOperator(Operator): bl_description = ( " * LMB - Enable all/Restore.\n" " * Shift+LMB - Invert.\n" + " * Shift+Ctrl+LMB - Isolate collections w/ selected objects.\n" + " * Shift+Alt+LMB - Disable collections w/ selected objects.\n" " * Ctrl+LMB - Copy/Paste RTOs.\n" " * Ctrl+Alt+LMB - Swap RTOs.\n" " * Alt+LMB - Discard history" @@ -579,6 +599,20 @@ class CMUnRestrictSelectAllOperator(Operator): elif modifiers == {"shift"}: invert_rtos(view_layer, "select") + elif modifiers == {"shift", "ctrl"}: + error = isolate_sel_objs_collections(view_layer, "select", "CM") + + if error: + self.report({"WARNING"}, error) + return {'CANCELLED'} + + elif modifiers == {"shift", "alt"}: + error = disable_sel_objs_collections(view_layer, "select", "CM") + + if error: + self.report({"WARNING"}, error) + return {'CANCELLED'} + else: activate_all_rtos(view_layer, "select") @@ -649,6 +683,8 @@ class CMUnHideAllOperator(Operator): bl_description = ( " * LMB - Enable all/Restore.\n" " * Shift+LMB - Invert.\n" + " * Shift+Ctrl+LMB - Isolate collections w/ selected objects.\n" + " * Shift+Alt+LMB - Disable collections w/ selected objects.\n" " * Ctrl+LMB - Copy/Paste RTOs.\n" " * Ctrl+Alt+LMB - Swap RTOs.\n" " * Alt+LMB - Discard history" @@ -678,6 +714,20 @@ class CMUnHideAllOperator(Operator): elif modifiers == {"shift"}: invert_rtos(view_layer, "hide") + elif modifiers == {"shift", "ctrl"}: + error = isolate_sel_objs_collections(view_layer, "hide", "CM") + + if error: + self.report({"WARNING"}, error) + return {'CANCELLED'} + + elif modifiers == {"shift", "alt"}: + error = disable_sel_objs_collections(view_layer, "hide", "CM") + + if error: + self.report({"WARNING"}, error) + return {'CANCELLED'} + else: activate_all_rtos(view_layer, "hide") @@ -748,6 +798,8 @@ class CMUnDisableViewportAllOperator(Operator): bl_description = ( " * LMB - Enable all/Restore.\n" " * Shift+LMB - Invert.\n" + " * Shift+Ctrl+LMB - Isolate collections w/ selected objects.\n" + " * Shift+Alt+LMB - Disable collections w/ selected objects.\n" " * Ctrl+LMB - Copy/Paste RTOs.\n" " * Ctrl+Alt+LMB - Swap RTOs.\n" " * Alt+LMB - Discard history" @@ -777,6 +829,20 @@ class CMUnDisableViewportAllOperator(Operator): elif modifiers == {"shift"}: invert_rtos(view_layer, "disable") + elif modifiers == {"shift", "ctrl"}: + error = isolate_sel_objs_collections(view_layer, "disable", "CM") + + if error: + self.report({"WARNING"}, error) + return {'CANCELLED'} + + elif modifiers == {"shift", "alt"}: + error = disable_sel_objs_collections(view_layer, "disable", "CM") + + if error: + self.report({"WARNING"}, error) + return {'CANCELLED'} + else: activate_all_rtos(view_layer, "disable") @@ -848,6 +914,8 @@ class CMUnDisableRenderAllOperator(Operator): bl_description = ( " * LMB - Enable all/Restore.\n" " * Shift+LMB - Invert.\n" + " * Shift+Ctrl+LMB - Isolate collections w/ selected objects.\n" + " * Shift+Alt+LMB - Disable collections w/ selected objects.\n" " * Ctrl+LMB - Copy/Paste RTOs.\n" " * Ctrl+Alt+LMB - Swap RTOs.\n" " * Alt+LMB - Discard history" @@ -877,6 +945,20 @@ class CMUnDisableRenderAllOperator(Operator): elif modifiers == {"shift"}: invert_rtos(view_layer, "render") + elif modifiers == {"shift", "ctrl"}: + error = isolate_sel_objs_collections(view_layer, "render", "CM") + + if error: + self.report({"WARNING"}, error) + return {'CANCELLED'} + + elif modifiers == {"shift", "alt"}: + error = disable_sel_objs_collections(view_layer, "render", "CM") + + if error: + self.report({"WARNING"}, error) + return {'CANCELLED'} + else: activate_all_rtos(view_layer, "render") @@ -947,6 +1029,8 @@ class CMUnHoldoutAllOperator(Operator): bl_description = ( " * LMB - Enable all/Restore.\n" " * Shift+LMB - Invert.\n" + " * Shift+Ctrl+LMB - Isolate collections w/ selected objects.\n" + " * Shift+Alt+LMB - Disable collections w/ selected objects.\n" " * Ctrl+LMB - Copy/Paste RTOs.\n" " * Ctrl+Alt+LMB - Swap RTOs.\n" " * Alt+LMB - Discard history" @@ -976,6 +1060,20 @@ class CMUnHoldoutAllOperator(Operator): elif modifiers == {"shift"}: invert_rtos(view_layer, "holdout") + elif modifiers == {"shift", "ctrl"}: + error = isolate_sel_objs_collections(view_layer, "holdout", "CM") + + if error: + self.report({"WARNING"}, error) + return {'CANCELLED'} + + elif modifiers == {"shift", "alt"}: + error = disable_sel_objs_collections(view_layer, "holdout", "CM") + + if error: + self.report({"WARNING"}, error) + return {'CANCELLED'} + else: activate_all_rtos(view_layer, "holdout") @@ -1047,6 +1145,8 @@ class CMUnIndirectOnlyAllOperator(Operator): bl_description = ( " * LMB - Enable all/Restore.\n" " * Shift+LMB - Invert.\n" + " * Shift+Ctrl+LMB - Isolate collections w/ selected objects.\n" + " * Shift+Alt+LMB - Disable collections w/ selected objects.\n" " * Ctrl+LMB - Copy/Paste RTOs.\n" " * Ctrl+Alt+LMB - Swap RTOs.\n" " * Alt+LMB - Discard history" @@ -1076,6 +1176,20 @@ class CMUnIndirectOnlyAllOperator(Operator): elif modifiers == {"shift"}: invert_rtos(view_layer, "indirect") + elif modifiers == {"shift", "ctrl"}: + error = isolate_sel_objs_collections(view_layer, "indirect", "CM") + + if error: + self.report({"WARNING"}, error) + return {'CANCELLED'} + + elif modifiers == {"shift", "alt"}: + error = disable_sel_objs_collections(view_layer, "indirect", "CM") + + if error: + self.report({"WARNING"}, error) + return {'CANCELLED'} + else: activate_all_rtos(view_layer, "indirect") diff --git a/object_collection_manager/qcd_init.py b/object_collection_manager/qcd_init.py index 41363b7b..dca4d5cf 100644 --- a/object_collection_manager/qcd_init.py +++ b/object_collection_manager/qcd_init.py @@ -50,6 +50,8 @@ qcd_classes = ( qcd_operators.EnableAllQCDSlotsMeta, qcd_operators.EnableAllQCDSlots, qcd_operators.EnableAllQCDSlotsIsolated, + qcd_operators.IsolateSelectedObjectsCollections, + qcd_operators.DisableSelectedObjectsCollections, qcd_operators.DisableAllNonQCDSlots, qcd_operators.DisableAllCollections, qcd_operators.SelectAllQCDObjects, @@ -170,6 +172,14 @@ def register_qcd_view_hotkeys(): addon_qcd_view_hotkey_keymaps.append((km, kmi)) km = wm.keyconfigs.addon.keymaps.new(name=mode) + kmi = km.keymap_items.new('view3d.isolate_selected_objects_collections', 'EQUAL', 'PRESS') + addon_qcd_view_hotkey_keymaps.append((km, kmi)) + + km = wm.keyconfigs.addon.keymaps.new(name=mode) + kmi = km.keymap_items.new('view3d.disable_selected_objects_collections', 'MINUS', 'PRESS') + addon_qcd_view_hotkey_keymaps.append((km, kmi)) + + km = wm.keyconfigs.addon.keymaps.new(name=mode) kmi = km.keymap_items.new('view3d.disable_all_non_qcd_slots', 'PLUS', 'PRESS', shift=True, ctrl=True) addon_qcd_view_hotkey_keymaps.append((km, kmi)) @@ -229,6 +239,10 @@ def register_qcd_view_edit_mode_hotkeys(): addon_qcd_view_edit_mode_hotkey_keymaps.append((km, kmi)) km = wm.keyconfigs.addon.keymaps.new(name=mode) + kmi = km.keymap_items.new('view3d.isolate_selected_objects_collections', 'EQUAL', 'PRESS') + addon_qcd_view_edit_mode_hotkey_keymaps.append((km, kmi)) + + km = wm.keyconfigs.addon.keymaps.new(name=mode) kmi = km.keymap_items.new('view3d.enable_all_qcd_slots_isolated', 'PLUS', 'PRESS', shift=True, alt=True) addon_qcd_view_edit_mode_hotkey_keymaps.append((km, kmi)) diff --git a/object_collection_manager/qcd_operators.py b/object_collection_manager/qcd_operators.py index 6d79ac88..6093257c 100644 --- a/object_collection_manager/qcd_operators.py +++ b/object_collection_manager/qcd_operators.py @@ -48,6 +48,8 @@ from .operator_utils import ( apply_to_children, select_collection_objects, set_exclude_state, + isolate_sel_objs_collections, + disable_sel_objs_collections, ) class LockedObjects(): @@ -134,7 +136,7 @@ class QCDAllBase(): cls.history = None cls.orig_active_collection = None cls.orig_active_object = None - cls.locked = {} + cls.locked = None class EnableAllQCDSlotsMeta(Operator): @@ -308,6 +310,66 @@ class EnableAllQCDSlotsIsolated(Operator): return {'FINISHED'} +class IsolateSelectedObjectsCollections(Operator): + '''Isolate collections (via EC) that contain the selected objects''' + bl_label = "Isolate Selected Objects Collections" + bl_idname = "view3d.isolate_selected_objects_collections" + + def execute(self, context): + qab = QCDAllBase + qab.init(context) + + use_active = bool(context.mode != 'OBJECT') + + # isolate + error = isolate_sel_objs_collections(qab.view_layer, "exclude", "QCD", use_active=use_active) + + if error: + qab.clear() + self.report({"WARNING"}, error) + return {'CANCELLED'} + + qab.finalize() + + internals.qcd_collection_state.clear() + internals.qcd_collection_state.update(internals.generate_state(qcd=True)) + + return {'FINISHED'} + + +class DisableSelectedObjectsCollections(Operator): + '''Disable all collections that contain the selected objects''' + bl_label = "Disable Selected Objects Collections" + bl_idname = "view3d.disable_selected_objects_collections" + + def execute(self, context): + qab = QCDAllBase + qab.init(context) + + if qab.locked.objs: + # clear rto history + del internals.qcd_history[qab.view_layer] + qab.clear() + + self.report({"WARNING"}, "Can only be executed in Object Mode") + return {'CANCELLED'} + + # disable + error = disable_sel_objs_collections(qab.view_layer, "exclude", "QCD") + + if error: + qab.clear() + self.report({"WARNING"}, error) + return {'CANCELLED'} + + qab.finalize() + + internals.qcd_collection_state.clear() + internals.qcd_collection_state.update(internals.generate_state(qcd=True)) + + return {'FINISHED'} + + class DisableAllNonQCDSlots(Operator): '''Toggles between the current state and all non-QCD collections disabled''' bl_label = "Disable All Non QCD Slots" diff --git a/object_collection_manager/ui.py b/object_collection_manager/ui.py index 6e3d018b..b11a08bc 100644 --- a/object_collection_manager/ui.py +++ b/object_collection_manager/ui.py @@ -905,6 +905,12 @@ class EnableAllQCDSlotsMenu(Menu): layout.separator() + layout.operator("view3d.isolate_selected_objects_collections") + if context.mode == 'OBJECT': + layout.operator("view3d.disable_selected_objects_collections") + + layout.separator() + layout.operator("view3d.disable_all_non_qcd_slots") layout.operator("view3d.disable_all_collections") |