Collection Manager: Add QVT. Task: T69577

Add Quick View Toggles for influencing QCD setup,
e.g. enable all slots.
Fix bugs with QCD slot switching.
Fix the active object sometimes getting lost when toggling slots.
This commit is contained in:
Ryan Inch 2020-09-26 03:20:53 -04:00
parent 3d2076556a
commit bf176041da
7 changed files with 627 additions and 57 deletions

View File

@ -22,7 +22,7 @@ bl_info = {
"name": "Collection Manager",
"description": "Manage collections and their objects",
"author": "Ryan Inch",
"version": (2, 14, 3),
"version": (2, 15, 0),
"blender": (2, 80, 0),
"location": "View3D - Object Mode (Shortcut - M)",
"warning": '', # used for warning icon and text in addons panel

View File

@ -39,6 +39,7 @@ move_active = None
layer_collections = {}
collection_tree = []
collection_state = {}
qcd_collection_state = {}
expanded = set()
row_index = 0
max_lvl = 0
@ -60,6 +61,8 @@ rto_history = {
"indirect_all": {},
}
qcd_history = {}
expand_history = {
"target": "",
"history": [],
@ -131,6 +134,13 @@ class QCDSlots():
raise
def object_in_slots(self, obj):
for collection in obj.users_collection:
if self.contains(name=collection.name):
return True
return False
def get_data_for_blend(self):
return f"{self._slots.__repr__()}\n{self.overrides.__repr__()}"
@ -584,8 +594,9 @@ def get_modifiers(event):
return set(modifiers)
def generate_state():
def generate_state(*, qcd=False):
global layer_collections
global qcd_slots
state = {
"name": [],
@ -608,6 +619,9 @@ def generate_state():
state["holdout"].append(laycol["ptr"].holdout)
state["indirect"].append(laycol["ptr"].indirect_only)
if qcd:
state["qcd"] = dict(qcd_slots)
return state

View File

@ -31,6 +31,29 @@ from .internals import (
get_move_selection,
)
mode_converter = {
'EDIT_MESH': 'EDIT',
'EDIT_CURVE': 'EDIT',
'EDIT_SURFACE': 'EDIT',
'EDIT_TEXT': 'EDIT',
'EDIT_ARMATURE': 'EDIT',
'EDIT_METABALL': 'EDIT',
'EDIT_LATTICE': 'EDIT',
'POSE': 'POSE',
'SCULPT': 'SCULPT',
'PAINT_WEIGHT': 'WEIGHT_PAINT',
'PAINT_VERTEX': 'VERTEX_PAINT',
'PAINT_TEXTURE': 'TEXTURE_PAINT',
'PARTICLE': 'PARTICLE_EDIT',
'OBJECT': 'OBJECT',
'PAINT_GPENCIL': 'PAINT_GPENCIL',
'EDIT_GPENCIL': 'EDIT_GPENCIL',
'SCULPT_GPENCIL': 'SCULPT_GPENCIL',
'WEIGHT_GPENCIL': 'WEIGHT_GPENCIL',
'VERTEX_GPENCIL': 'VERTEX_GPENCIL',
}
rto_path = {
"exclude": "exclude",
"select": "collection.hide_select",
@ -469,7 +492,7 @@ def remove_collection(laycol, collection, context):
cm.cm_list_index = laycol["row_index"]
def select_collection_objects(is_master_collection, collection_name, replace, nested):
def select_collection_objects(is_master_collection, collection_name, replace, nested, selection_state=None):
if is_master_collection:
target_collection = bpy.context.view_layer.layer_collection.collection
@ -480,7 +503,8 @@ def select_collection_objects(is_master_collection, collection_name, replace, ne
if replace:
bpy.ops.object.select_all(action='DESELECT')
selection_state = get_move_selection().isdisjoint(target_collection.objects)
if selection_state == None:
selection_state = get_move_selection().isdisjoint(target_collection.objects)
def select_objects(collection):
for obj in collection.objects:
@ -493,3 +517,21 @@ def select_collection_objects(is_master_collection, collection_name, replace, ne
if nested:
apply_to_children(target_collection, select_objects)
def set_exclude_state(target_layer_collection, state):
# get current child exclusion state
child_exclusion = []
def get_child_exclusion(layer_collection):
child_exclusion.append([layer_collection, layer_collection.exclude])
apply_to_children(target_layer_collection, get_child_exclusion)
# set exclusion
target_layer_collection.exclude = state
# set correct state for all children
for laycol in child_exclusion:
laycol[0].exclude = laycol[1]

View File

@ -66,6 +66,7 @@ from .operator_utils import (
link_child_collections_to_parent,
remove_collection,
select_collection_objects,
set_exclude_state,
)
class SetActiveCollection(Operator):
@ -424,23 +425,7 @@ class CMExcludeOperator(Operator):
# reset exclude history
del rto_history["exclude"][view_layer]
# get current child exclusion state
child_exclusion = []
def get_child_exclusion(layer_collection):
child_exclusion.append([layer_collection, layer_collection.exclude])
apply_to_children(laycol_ptr, get_child_exclusion)
# toggle exclusion of collection
laycol_ptr.exclude = not laycol_ptr.exclude
# set correct state for all children
for laycol in child_exclusion:
laycol[0].exclude = laycol[1]
set_exclude_state(laycol_ptr, not laycol_ptr.exclude)
cls.isolated = False

View File

@ -16,10 +16,18 @@ addon_qcd_view_edit_mode_hotkey_keymaps = []
qcd_classes = (
qcd_move_widget.QCDMoveWidget,
qcd_operators.EnableAllQCDSlotsMeta,
qcd_operators.EnableAllQCDSlots,
qcd_operators.EnableAllQCDSlotsIsolated,
qcd_operators.DisableAllNonQCDSlots,
qcd_operators.DisableAllCollections,
qcd_operators.SelectAllQCDObjects,
qcd_operators.DiscardQCDHistory,
qcd_operators.MoveToQCDSlot,
qcd_operators.ViewQCDSlot,
qcd_operators.ViewMoveQCDSlot,
qcd_operators.RenumerateQCDSlots,
ui.EnableAllQCDSlotsMenu,
)
@ -41,6 +49,13 @@ def load_internal_data(dummy):
internals.qcd_slots.load_blend_data(data)
@persistent
def load_pre_handler(dummy):
internals.qcd_collection_state.clear()
for key in list(internals.qcd_history.keys()):
del internals.qcd_history[key]
def register_qcd():
for cls in qcd_classes:
bpy.utils.register_class(cls)
@ -60,6 +75,7 @@ def register_qcd():
bpy.app.handlers.save_pre.append(save_internal_data)
bpy.app.handlers.load_post.append(load_internal_data)
bpy.app.handlers.load_pre.append(load_pre_handler)
prefs = bpy.context.preferences.addons[__package__].preferences
@ -114,6 +130,27 @@ def register_qcd_view_hotkeys():
kmi.properties.toggle = True
addon_qcd_view_hotkey_keymaps.append((km, kmi))
km = wm.keyconfigs.addon.keymaps.new(name=mode)
kmi = km.keymap_items.new('view3d.enable_all_qcd_slots', 'PLUS', 'PRESS', shift=True)
addon_qcd_view_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_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))
km = wm.keyconfigs.addon.keymaps.new(name=mode)
kmi = km.keymap_items.new('view3d.disable_all_collections', 'EQUAL', 'PRESS', alt=True, ctrl=True)
addon_qcd_view_hotkey_keymaps.append((km, kmi))
if mode == 'Object Mode':
km = wm.keyconfigs.addon.keymaps.new(name=mode)
kmi = km.keymap_items.new('view3d.select_all_qcd_objects', 'EQUAL', 'PRESS', alt=True)
addon_qcd_view_hotkey_keymaps.append((km, kmi))
def register_qcd_view_edit_mode_hotkeys():
wm = bpy.context.window_manager
@ -156,6 +193,22 @@ def register_qcd_view_edit_mode_hotkeys():
kmi.properties.toggle = True
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', 'PLUS', 'PRESS', shift=True)
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))
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_edit_mode_hotkey_keymaps.append((km, kmi))
km = wm.keyconfigs.addon.keymaps.new(name=mode)
kmi = km.keymap_items.new('view3d.disable_all_collections', 'EQUAL', 'PRESS', alt=True, ctrl=True)
addon_qcd_view_edit_mode_hotkey_keymaps.append((km, kmi))
km = wm.keyconfigs.addon.keymaps.new(name="Mesh")
kmi = km.keymap_items.new('wm.call_menu', 'ACCENT_GRAVE', 'PRESS')
@ -173,6 +226,7 @@ def unregister_qcd():
bpy.app.handlers.save_pre.remove(save_internal_data)
bpy.app.handlers.load_post.remove(load_internal_data)
bpy.app.handlers.load_pre.remove(load_pre_handler)
for pcoll in ui.preview_collections.values():
bpy.utils.previews.remove(pcoll)

View File

@ -35,8 +35,12 @@ from . import internals
from .internals import (
layer_collections,
rto_history,
qcd_history,
qcd_slots,
qcd_collection_state,
update_collection_tree,
update_property_group,
generate_state,
get_modifiers,
get_move_selection,
get_move_active,
@ -44,10 +48,443 @@ from .internals import (
)
from .operator_utils import (
mode_converter,
apply_to_children,
select_collection_objects,
set_exclude_state,
)
class LockedObjects():
def __init__(self):
self.objs = []
self.mode = ""
def get_locked_objs(context):
# get objects not in object mode
locked = LockedObjects()
if context.mode == 'OBJECT':
return locked
if context.view_layer.objects.active:
active = context.view_layer.objects.active
locked.mode = mode_converter[context.mode]
for obj in context.view_layer.objects:
if obj.mode != 'OBJECT':
if obj.mode not in ['POSE', 'WEIGHT_PAINT'] or obj == active:
if obj.mode == active.mode:
locked.objs.append(obj)
return locked
class QCDAllBase():
meta_op = False
meta_report = None
context = None
view_layer = ""
history = None
orig_active_collection = None
orig_active_object = None
locked = None
@classmethod
def init(cls, context):
cls.context = context
cls.orig_active_collection = context.view_layer.active_layer_collection
cls.view_layer = context.view_layer.name
cls.orig_active_object = context.view_layer.objects.active
if not cls.view_layer in qcd_history:
qcd_history[cls.view_layer] = []
cls.history = qcd_history[cls.view_layer]
cls.locked = get_locked_objs(context)
@classmethod
def apply_history(cls):
for x, item in enumerate(layer_collections.values()):
item["ptr"].exclude = cls.history[x]
# clear rto history
del qcd_history[cls.view_layer]
internals.qcd_collection_state.clear()
cls.history = None
@classmethod
def finalize(cls):
# restore active collection
cls.context.view_layer.active_layer_collection = cls.orig_active_collection
# restore active object if possible
if cls.orig_active_object:
if cls.orig_active_object.name in cls.context.view_layer.objects:
cls.context.view_layer.objects.active = cls.orig_active_object
# restore locked objects back to their original mode
# needed because of exclude child updates
if cls.context.view_layer.objects.active:
if cls.locked.objs:
bpy.ops.object.mode_set(mode=cls.locked.mode)
@classmethod
def clear(cls):
cls.context = None
cls.view_layer = ""
cls.history = None
cls.orig_active_collection = None
cls.orig_active_object = None
cls.locked = {}
class EnableAllQCDSlotsMeta(Operator):
'''QCD All Meta Operator'''
bl_label = "Quick View Toggles"
bl_description = (
" * LMB - Enable all slots/Restore.\n"
" * Alt+LMB - Select all objects in QCD slots.\n"
" * LMB+Hold - Menu"
)
bl_idname = "view3d.enable_all_qcd_slots_meta"
def invoke(self, context, event):
global qcd_slots
global layer_collections
qab = QCDAllBase
modifiers = get_modifiers(event)
qab.meta_op = True
if modifiers == {"alt"}:
bpy.ops.view3d.select_all_qcd_objects()
else:
qab.init(context)
if not qab.history:
bpy.ops.view3d.enable_all_qcd_slots()
else:
qab.apply_history()
qab.finalize()
if qab.meta_report:
self.report({"INFO"}, qab.meta_report)
qab.meta_report = None
qab.meta_op = False
return {'FINISHED'}
class EnableAllQCDSlots(Operator):
'''Toggles between the current state and all enabled'''
bl_label = "Enable All QCD Slots"
bl_idname = "view3d.enable_all_qcd_slots"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
global qcd_slots
global layer_collections
qab = QCDAllBase
# validate qcd slots
if not dict(qcd_slots):
if qab.meta_op:
qab.meta_report = "No QCD slots."
else:
self.report({"INFO"}, "No QCD slots.")
return {'CANCELLED'}
qab.init(context)
if not qab.history:
keep_history = False
for laycol in layer_collections.values():
is_qcd_slot = qcd_slots.contains(name=laycol["name"])
qab.history.append(laycol["ptr"].exclude)
if is_qcd_slot and laycol["ptr"].exclude:
keep_history = True
set_exclude_state(laycol["ptr"], False)
if not keep_history:
# clear rto history
del qcd_history[qab.view_layer]
qab.clear()
if qab.meta_op:
qab.meta_report = "All QCD slots are already enabled."
else:
self.report({"INFO"}, "All QCD slots are already enabled.")
return {'CANCELLED'}
internals.qcd_collection_state.clear()
internals.qcd_collection_state.update(internals.generate_state(qcd=True))
else:
qab.apply_history()
qab.finalize()
return {'FINISHED'}
class EnableAllQCDSlotsIsolated(Operator):
'''Toggles between the current state and all enabled (non-QCD collections disabled)'''
bl_label = "Enable All QCD Slots Isolated"
bl_idname = "view3d.enable_all_qcd_slots_isolated"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
global qcd_slots
global layer_collections
qab = QCDAllBase
# validate qcd slots
if not dict(qcd_slots):
self.report({"INFO"}, "No QCD slots.")
return {'CANCELLED'}
qab.init(context)
if qab.locked.objs and not qcd_slots.object_in_slots(qab.orig_active_object):
# clear rto history
del qcd_history[qab.view_layer]
qab.clear()
self.report({"WARNING"}, "Cannot execute. The active object would be lost.")
return {'CANCELLED'}
if not qab.history:
keep_history = False
for laycol in layer_collections.values():
is_qcd_slot = qcd_slots.contains(name=laycol["name"])
qab.history.append(laycol["ptr"].exclude)
if is_qcd_slot and laycol["ptr"].exclude:
keep_history = True
set_exclude_state(laycol["ptr"], False)
if not is_qcd_slot and not laycol["ptr"].exclude:
keep_history = True
set_exclude_state(laycol["ptr"], True)
if not keep_history:
# clear rto history
del qcd_history[qab.view_layer]
qab.clear()
self.report({"INFO"}, "All QCD slots are already enabled and isolated.")
return {'CANCELLED'}
internals.qcd_collection_state.clear()
internals.qcd_collection_state.update(internals.generate_state(qcd=True))
else:
qab.apply_history()
qab.finalize()
return {'FINISHED'}
class DisableAllNonQCDSlots(Operator):
'''Toggles between the current state and all non-QCD collections disabled'''
bl_label = "Disable All Non QCD Slots"
bl_idname = "view3d.disable_all_non_qcd_slots"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
global qcd_slots
global layer_collections
qab = QCDAllBase
# validate qcd slots
if not dict(qcd_slots):
self.report({"INFO"}, "No QCD slots.")
return {'CANCELLED'}
qab.init(context)
if qab.locked.objs and not qcd_slots.object_in_slots(qab.orig_active_object):
# clear rto history
del qcd_history[qab.view_layer]
qab.clear()
self.report({"WARNING"}, "Cannot execute. The active object would be lost.")
return {'CANCELLED'}
if not qab.history:
keep_history = False
for laycol in layer_collections.values():
is_qcd_slot = qcd_slots.contains(name=laycol["name"])
qab.history.append(laycol["ptr"].exclude)
if not is_qcd_slot and not laycol["ptr"].exclude:
keep_history = True
set_exclude_state(laycol["ptr"], True)
if not keep_history:
# clear rto history
del qcd_history[qab.view_layer]
qab.clear()
self.report({"INFO"}, "All non QCD slots are already disabled.")
return {'CANCELLED'}
internals.qcd_collection_state.clear()
internals.qcd_collection_state.update(internals.generate_state(qcd=True))
else:
qab.apply_history()
qab.finalize()
return {'FINISHED'}
class DisableAllCollections(Operator):
'''Toggles between the current state and all collections disabled'''
bl_label = "Disable All collections"
bl_idname = "view3d.disable_all_collections"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
global qcd_slots
global layer_collections
qab = QCDAllBase
qab.init(context)
if qab.locked.objs:
# clear rto history
del qcd_history[qab.view_layer]
qab.clear()
self.report({"WARNING"}, "Cannot execute. The active object would be lost.")
return {'CANCELLED'}
if not qab.history:
for laycol in layer_collections.values():
qab.history.append(laycol["ptr"].exclude)
if all(qab.history): # no collections are enabled
# clear rto history
del qcd_history[qab.view_layer]
qab.clear()
self.report({"INFO"}, "All collections are already disabled.")
return {'CANCELLED'}
for laycol in layer_collections.values():
laycol["ptr"].exclude = True
internals.qcd_collection_state.clear()
internals.qcd_collection_state.update(internals.generate_state(qcd=True))
else:
qab.apply_history()
qab.finalize()
return {'FINISHED'}
class SelectAllQCDObjects(Operator):
'''Select all objects in QCD slots'''
bl_label = "Select All QCD Objects"
bl_idname = "view3d.select_all_qcd_objects"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
global qcd_slots
global layer_collections
qab = QCDAllBase
if context.mode != 'OBJECT':
return {'CANCELLED'}
if not context.selectable_objects:
if qab.meta_op:
qab.meta_report = "No objects present to select."
else:
self.report({"INFO"}, "No objects present to select.")
return {'CANCELLED'}
orig_selected_objects = context.selected_objects
bpy.ops.object.select_all(action='DESELECT')
for slot, collection_name in qcd_slots:
select_collection_objects(
is_master_collection=False,
collection_name=collection_name,
replace=False,
nested=False,
selection_state=True
)
if context.selected_objects == orig_selected_objects:
for slot, collection_name in qcd_slots:
select_collection_objects(
is_master_collection=False,
collection_name=collection_name,
replace=False,
nested=False,
selection_state=False
)
return {'FINISHED'}
class DiscardQCDHistory(Operator):
'''Discard QCD History'''
bl_label = "Discard History"
bl_idname = "view3d.discard_qcd_history"
def execute(self, context):
global qcd_slots
global layer_collections
qab = QCDAllBase
view_layer = context.view_layer.name
if view_layer in qcd_history:
del qcd_history[view_layer]
qab.clear()
return {'FINISHED'}
class MoveToQCDSlot(Operator):
'''Move object(s) to QCD slot'''
@ -209,46 +646,25 @@ class ViewQCDSlot(Operator):
return {'CANCELLED'}
# get objects not in object mode
locked_active_obj = context.view_layer.objects.active
locked_objs = []
locked_objs_mode = ""
for obj in context.view_layer.objects:
if obj.mode != 'OBJECT':
if obj.mode not in ['POSE', 'WEIGHT_PAINT'] or obj == locked_active_obj:
locked_objs.append(obj)
locked_objs_mode = obj.mode
orig_active_object = context.view_layer.objects.active
locked = get_locked_objs(context)
if self.toggle:
# check if slot can be toggled off.
if not qcd_laycol.exclude:
for obj in qcd_laycol.collection.objects:
if obj.mode != 'OBJECT':
if obj.mode not in ['POSE', 'WEIGHT_PAINT'] or obj == locked_active_obj:
return {'CANCELLED'}
# get current child exclusion state
child_exclusion = []
def get_child_exclusion(layer_collection):
child_exclusion.append([layer_collection, layer_collection.exclude])
apply_to_children(qcd_laycol, get_child_exclusion)
if not set(locked.objs).isdisjoint(qcd_laycol.collection.objects):
return {'CANCELLED'}
# toggle exclusion of qcd_laycol
qcd_laycol.exclude = not qcd_laycol.exclude
# set correct state for all children
for laycol in child_exclusion:
laycol[0].exclude = laycol[1]
set_exclude_state(qcd_laycol, not qcd_laycol.exclude)
else:
# exclude all collections
for laycol in layer_collections.values():
if laycol["name"] != qcd_laycol.name:
# prevent exclusion if locked objects in this collection
if set(locked_objs).isdisjoint(laycol["ptr"].collection.objects):
if set(locked.objs).isdisjoint(laycol["ptr"].collection.objects):
laycol["ptr"].exclude = True
else:
laycol["ptr"].exclude = False
@ -259,21 +675,22 @@ class ViewQCDSlot(Operator):
# exclude all children
def exclude_all_children(layer_collection):
# prevent exclusion if locked objects in this collection
if set(locked_objs).isdisjoint(layer_collection.collection.objects):
if set(locked.objs).isdisjoint(layer_collection.collection.objects):
layer_collection.exclude = True
else:
layer_collection.exclude = False
apply_to_children(qcd_laycol, exclude_all_children)
if orig_active_object:
if orig_active_object.name in context.view_layer.objects:
context.view_layer.objects.active = orig_active_object
# restore locked objects back to their original mode
# needed because of exclude child updates
if locked_objs:
context.view_layer.objects.active = locked_active_obj
if context.view_layer.objects.active:
bpy.ops.object.mode_set(mode=locked_objs_mode)
if context.view_layer.objects.active:
if locked.objs:
bpy.ops.object.mode_set(mode=locked.mode)
# set layer as active layer collection
context.view_layer.active_layer_collection = qcd_laycol

View File

@ -35,10 +35,12 @@ from bpy.props import (
from .internals import (
collection_tree,
collection_state,
qcd_collection_state,
expanded,
get_max_lvl,
layer_collections,
rto_history,
qcd_history,
expand_history,
phantom_history,
copy_buffer,
@ -52,6 +54,10 @@ from .internals import (
update_qcd_header,
)
from .qcd_operators import (
QCDAllBase,
)
preview_collections = {}
last_icon_theme_text = None
@ -842,18 +848,70 @@ class SpecialsMenu(Menu):
prop.without_objects = True
class EnableAllQCDSlotsMenu(Menu):
bl_label = "Global QCD Slot Actions"
bl_idname = "VIEW3D_MT_CM_qcd_enable_all_menu"
def draw(self, context):
layout = self.layout
layout.operator("view3d.enable_all_qcd_slots")
layout.operator("view3d.enable_all_qcd_slots_isolated")
layout.separator()
layout.operator("view3d.disable_all_non_qcd_slots")
layout.operator("view3d.disable_all_collections")
if context.mode == 'OBJECT':
layout.separator()
layout.operator("view3d.select_all_qcd_objects")
layout.separator()
layout.operator("view3d.discard_qcd_history")
def view3d_header_qcd_slots(self, context):
global qcd_collection_state
update_collection_tree(context)
view_layer = context.view_layer
layout = self.layout
idx = 1
split = layout.split()
if qcd_collection_state:
view_layer = context.view_layer
new_state = generate_state(qcd=True)
if (new_state["name"] != qcd_collection_state["name"]
or new_state["exclude"] != qcd_collection_state["exclude"]
or new_state["exclude"] != qcd_collection_state["exclude"]
or new_state["qcd"] != qcd_collection_state["qcd"]):
if view_layer.name in qcd_history:
del qcd_history[view_layer.name]
qcd_collection_state.clear()
QCDAllBase.clear()
main_row = layout.row(align=True)
current_qcd_history = qcd_history.get(context.view_layer.name, [])
main_row.operator_menu_hold("view3d.enable_all_qcd_slots_meta",
text="",
icon='HIDE_OFF',
depress=bool(current_qcd_history),
menu="VIEW3D_MT_CM_qcd_enable_all_menu")
split = main_row.split()
col = split.column(align=True)
row = col.row(align=True)
row.scale_y = 0.5
update_collection_tree(context)
selected_objects = get_move_selection()
active_object = get_move_active()