diff --git a/object_collection_manager/__init__.py b/object_collection_manager/__init__.py index ef46feed517a9c051d240fc3fcc6abdaa0739e87..9e4a8d60de068f1830aa7bb696a6b39decdcc738 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,6,1), + "version": (2,7,1), "blender": (2, 80, 0), "location": "View3D - Object Mode (Shortcut - M)", "warning": '', # used for warning icon and text in addons panel @@ -86,6 +86,7 @@ addon_keymaps = [] classes = ( internals.CMListCollection, internals.CMSendReport, + operators.SetActiveCollection, operators.ExpandAllOperator, operators.ExpandSublevelOperator, operators.CMExcludeOperator, diff --git a/object_collection_manager/operators.py b/object_collection_manager/operators.py index 45993f1ff6a0d2c1fbd6123232c1fee848c1a896..efb9e40bb3f26396eb447b3a3f433f8c60e43507 100644 --- a/object_collection_manager/operators.py +++ b/object_collection_manager/operators.py @@ -65,6 +65,29 @@ from .operator_utils import ( clear_swap, ) +class SetActiveCollection(Operator): + '''Set the active collection''' + bl_label = "Set Active Collection" + bl_idname = "view3d.set_active_collection" + bl_options = {'REGISTER', 'UNDO'} + + collection_index: IntProperty() + collection_name: StringProperty() + + def execute(self, context): + if self.collection_index == 0: + cm = context.scene.collection_manager + cm.cm_list_index = -1 + layer_collection = context.view_layer.layer_collection + + else: + laycol = layer_collections[self.collection_name] + layer_collection = laycol["ptr"] + + context.view_layer.active_layer_collection = layer_collection + + return {'FINISHED'} + class ExpandAllOperator(Operator): '''Expand/Collapse all collections''' @@ -197,8 +220,12 @@ class CMSetCollectionOperator(Operator): collection_name: StringProperty() def invoke(self, context, event): - laycol = layer_collections[self.collection_name] - target_collection = laycol["ptr"].collection + if self.collection_index == 0: + target_collection = context.view_layer.layer_collection.collection + + else: + laycol = layer_collections[self.collection_name] + target_collection = laycol["ptr"].collection selected_objects = get_move_selection() active_object = get_move_active() @@ -223,7 +250,8 @@ class CMSetCollectionOperator(Operator): target_collection.objects.link(obj) else: - errors = False + warnings = False + master_warning = False # remove from collections for obj in selected_objects: @@ -231,14 +259,34 @@ class CMSetCollectionOperator(Operator): # disallow removing if only one if len(obj.users_collection) == 1: - errors = True - continue + warnings = True + master_laycol = context.view_layer.layer_collection + master_collection = master_laycol.collection + + if obj.name not in master_collection.objects: + master_collection.objects.link(obj) + + else: + master_warning = True + continue + # remove from collection target_collection.objects.unlink(obj) - if errors: - send_report("Error removing 1 or more objects from this collection.\nObjects would be left without a collection") + if warnings: + if master_warning: + send_report( + "Error removing 1 or more objects from the Scene Collection.\n" + "Objects would be left without a collection." + ) + self.report({"WARNING"}, + "Error removing 1 or more objects from the Scene Collection." + " Objects would be left without a collection." + ) + + else: + self.report({"INFO"}, "1 or more objects moved to Scene Collection.") else: @@ -249,7 +297,7 @@ class CMSetCollectionOperator(Operator): # remove from all other collections for collection in obj.users_collection: - if collection.name != target_collection.name: + if collection != target_collection: collection.objects.unlink(obj) # update the active object if needed @@ -864,21 +912,30 @@ class CMNewCollectionOperator(Operator): # if there are collections if len(cm.cm_list_collection) > 0: - # get selected collection - laycol = layer_collections[cm.cm_list_collection[cm.cm_list_index].name] + if not cm.cm_list_index == -1: + # get selected collection + laycol = layer_collections[cm.cm_list_collection[cm.cm_list_index].name] - # add new collection - if self.child: - laycol["ptr"].collection.children.link(new_collection) - expanded.add(laycol["name"]) + # add new collection + if self.child: + laycol["ptr"].collection.children.link(new_collection) + expanded.add(laycol["name"]) - # update tree view property - update_property_group(context) + # update tree view property + update_property_group(context) - cm.cm_list_index = layer_collections[new_collection.name]["row_index"] + cm.cm_list_index = layer_collections[new_collection.name]["row_index"] + + else: + laycol["parent"]["ptr"].collection.children.link(new_collection) + + # update tree view property + update_property_group(context) + + cm.cm_list_index = layer_collections[new_collection.name]["row_index"] else: - laycol["parent"]["ptr"].collection.children.link(new_collection) + context.scene.collection.children.link(new_collection) # update tree view property update_property_group(context) diff --git a/object_collection_manager/ui.py b/object_collection_manager/ui.py index fd1c362f220fb8c1b3fe5c5a49f90d78f0766bcc..e20c5c124ead4f7a2f80470f7e8c83664b947848 100644 --- a/object_collection_manager/ui.py +++ b/object_collection_manager/ui.py @@ -26,7 +26,10 @@ from bpy.types import ( UIList, ) -from bpy.props import BoolProperty +from bpy.props import ( + BoolProperty, + StringProperty, +) from .internals import ( collection_tree, @@ -62,6 +65,12 @@ class CollectionManager(Operator): window_open = False + master_collection: StringProperty( + default='Scene Collection', + name="", + description="Scene Collection" + ) + def __init__(self): self.window_open = True @@ -99,15 +108,10 @@ class CollectionManager(Operator): layout.row().separator() layout.row().separator() - filter_row = layout.row() - filter_row.alignment = 'RIGHT' - - filter_row.popover(panel="COLLECTIONMANAGER_PT_restriction_toggles", text="", icon='FILTER') - - toggle_row = layout.split(factor=0.3) - toggle_row.alignment = 'LEFT' + button_row = layout.split(factor=0.3) + button_row.alignment = 'LEFT' - sec1 = toggle_row.row() + sec1 = button_row.row() sec1.alignment = 'LEFT' sec1.enabled = False @@ -124,12 +128,63 @@ class CollectionManager(Operator): break if context.preferences.addons[__package__].preferences.enable_qcd: - renum = toggle_row.row() + renum = button_row.row() renum.alignment = 'LEFT' renum.operator("view3d.renumerate_qcd_slots") - sec2 = toggle_row.row() - sec2.alignment = 'RIGHT' + filter_sec = button_row.row() + filter_sec.alignment = 'RIGHT' + + filter_sec.popover(panel="COLLECTIONMANAGER_PT_restriction_toggles", + text="", icon='FILTER') + + mc_box = layout.box() + master_collection_row = mc_box.row(align=True) + + highlight = False + if (context.view_layer.active_layer_collection == + context.view_layer.layer_collection): + highlight = True + + prop = master_collection_row.operator("view3d.set_active_collection", + text='', icon='GROUP', depress=highlight) + prop.collection_index = 0 + prop.collection_name = 'Master Collection' + + master_collection_row.separator() + + name_row = master_collection_row.row() + name_row.prop(self, "master_collection", text='') + name_row.enabled = False + + master_collection_row.separator() + + global_rto_row = master_collection_row.row() + global_rto_row.alignment = 'RIGHT' + + row_setcol = global_rto_row.row() + row_setcol.alignment = 'LEFT' + row_setcol.operator_context = 'INVOKE_DEFAULT' + selected_objects = get_move_selection() + active_object = get_move_active() + collection = context.view_layer.layer_collection.collection + + icon = 'MESH_CUBE' + + if selected_objects: + if active_object and active_object.name in collection.objects: + icon = 'SNAP_VOLUME' + + elif not set(selected_objects).isdisjoint(collection.objects): + icon = 'STICKY_UVS_LOC' + + else: + row_setcol.enabled = False + + prop = row_setcol.operator("view3d.set_collection", text="", + icon=icon, emboss=False) + prop.collection_index = 0 + prop.collection_name = 'Master Collection' copy_icon = 'COPYDOWN' swap_icon = 'ARROW_LEFTRIGHT' @@ -152,7 +207,7 @@ class CollectionManager(Operator): if buffers[0] and buffers[1]: icon = copy_swap_icon - sec2.operator("view3d.un_exclude_all_collections", text="", icon=icon, depress=depress) + global_rto_row.operator("view3d.un_exclude_all_collections", text="", icon=icon, depress=depress) if cm.show_selectable: select_all_history = rto_history["select_all"].get(view_layer.name, []) @@ -171,7 +226,7 @@ class CollectionManager(Operator): if buffers[0] and buffers[1]: icon = copy_swap_icon - sec2.operator("view3d.un_restrict_select_all_collections", text="", icon=icon, depress=depress) + global_rto_row.operator("view3d.un_restrict_select_all_collections", text="", icon=icon, depress=depress) if cm.show_hide_viewport: hide_all_history = rto_history["hide_all"].get(view_layer.name, []) @@ -190,7 +245,7 @@ class CollectionManager(Operator): if buffers[0] and buffers[1]: icon = copy_swap_icon - sec2.operator("view3d.un_hide_all_collections", text="", icon=icon, depress=depress) + global_rto_row.operator("view3d.un_hide_all_collections", text="", icon=icon, depress=depress) if cm.show_disable_viewport: disable_all_history = rto_history["disable_all"].get(view_layer.name, []) @@ -209,7 +264,7 @@ class CollectionManager(Operator): if buffers[0] and buffers[1]: icon = copy_swap_icon - sec2.operator("view3d.un_disable_viewport_all_collections", text="", icon=icon, depress=depress) + global_rto_row.operator("view3d.un_disable_viewport_all_collections", text="", icon=icon, depress=depress) if cm.show_render: render_all_history = rto_history["render_all"].get(view_layer.name, []) @@ -228,7 +283,7 @@ class CollectionManager(Operator): if buffers[0] and buffers[1]: icon = copy_swap_icon - sec2.operator("view3d.un_disable_render_all_collections", text="", icon=icon, depress=depress) + global_rto_row.operator("view3d.un_disable_render_all_collections", text="", icon=icon, depress=depress) layout.row().template_list("CM_UL_items", "", cm, "cm_list_collection", @@ -271,7 +326,7 @@ class CollectionManager(Operator): active_laycol_row_index = layer_collections[active_laycol_name]["row_index"] cm.cm_list_index = active_laycol_row_index - except KeyError: # Master Collection isn't supported + except KeyError: # Master Collection is special and not part of regular collections cm.cm_list_index = -1 # check if history/buffer state still correct