diff --git a/object_collection_manager/__init__.py b/object_collection_manager/__init__.py index 246e6bd7697678df6e2ba494d411e65ae238b1fd..bbfdd0b1c8b0984b6cc4db78736067461533f598 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, 20, 0), + "version": (2, 21, 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/cm_init.py b/object_collection_manager/cm_init.py index 54d616ce0150cd2fe21adea162026527fc0a9922..61ff75e7fcaf8c4f887dc417afac5c19a3da84ba 100644 --- a/object_collection_manager/cm_init.py +++ b/object_collection_manager/cm_init.py @@ -77,6 +77,7 @@ addon_disable_objects_hotkey_keymaps = [] classes = ( internals.CMListCollection, internals.CMSendReport, + internals.CMUISeparatorButton, operators.SetActiveCollection, operators.ExpandAllOperator, operators.ExpandSublevelOperator, diff --git a/object_collection_manager/internals.py b/object_collection_manager/internals.py index eb80ae409b99ff07216e197c3c03eddc11f0dbd3..706bc89dea369102a312ed49a49ca137a16f696b 100644 --- a/object_collection_manager/internals.py +++ b/object_collection_manager/internals.py @@ -794,3 +794,30 @@ def send_report(message): bpy.ops.view3d.cm_send_report(ctx, 'INVOKE_DEFAULT', message=message) bpy.app.timers.register(report) + + +class CMUISeparatorButton(Operator): + bl_label = "UI Separator Button" + bl_idname = "view3d.cm_ui_separator_button" + + def execute(self, context): + return {'CANCELED'} + +def add_vertical_separator_line(row): + # add buffer before to account for scaling + separator = row.row() + separator.scale_x = 0.1 + separator.label() + + # add separator line + separator = row.row() + separator.scale_x = 0.2 + separator.enabled = False + separator.operator("view3d.cm_ui_separator_button", + text="", + icon='BLANK1', + ) + # add buffer after to account for scaling + separator = row.row() + separator.scale_x = 0.1 + separator.label() diff --git a/object_collection_manager/ui.py b/object_collection_manager/ui.py index d5740e8649bf884cbfc14b11247006a339df6aca..a81c18aebb20094dc11e506760db88e8872277db 100644 --- a/object_collection_manager/ui.py +++ b/object_collection_manager/ui.py @@ -44,6 +44,7 @@ from .internals import ( get_move_selection, get_move_active, update_qcd_header, + add_vertical_separator_line, ) preview_collections = {} @@ -75,6 +76,7 @@ class CollectionManager(Operator): cm = context.scene.collection_manager prefs = context.preferences.addons[__package__].preferences view_layer = context.view_layer + collection = context.view_layer.layer_collection.collection if view_layer.name != cls.last_view_layer: if prefs.enable_qcd: @@ -163,16 +165,52 @@ class CollectionManager(Operator): master_collection_row.separator() # name - name_row = master_collection_row.row() - name_row.prop(self, "master_collection", text='') - name_row.enabled = False + name_row = master_collection_row.row(align=True) + name_field = name_row.row(align=True) + name_field.prop(self, "master_collection", text='') + name_field.enabled = False + + # set selection + setsel = name_row.row(align=True) + icon = 'DOT' + + if any((laycol["ptr"].exclude, + collection.hide_select, + collection.hide_viewport, + laycol["ptr"].hide_viewport, + not collection.objects,)): + # objects cannot be selected + setsel.active = False + + else: + for obj in collection.objects: + if obj.select_get() == False: + # some objects remain unselected + icon = 'LAYER_USED' + break + + if icon != 'LAYER_USED': + # all objects are selected + icon = 'LAYER_ACTIVE' + + prop = setsel.operator("view3d.select_collection_objects", + text="", + icon=icon, + depress=bool(icon == 'LAYER_ACTIVE') + ) + prop.is_master_collection = True + prop.collection_name = 'Master Collection' - master_collection_row.separator() # global rtos global_rto_row = master_collection_row.row() global_rto_row.alignment = 'RIGHT' + # used as a separator (actual separator not wide enough) + global_rto_row.label() + + + # set collection row_setcol = global_rto_row.row() row_setcol.alignment = 'LEFT' row_setcol.operator_context = 'INVOKE_DEFAULT' @@ -184,7 +222,10 @@ class CollectionManager(Operator): collection = context.view_layer.layer_collection.collection - icon = 'MESH_CUBE' + icon = 'GRID' + + if collection.objects: + icon = 'MESH_CUBE' if selected_objects: if active_object and active_object.name in collection.objects: @@ -194,13 +235,33 @@ class CollectionManager(Operator): icon = 'STICKY_UVS_LOC' else: - row_setcol.enabled = False + row_setcol.active = False + + + # add vertical separator line + separator = row_setcol.row() + separator.scale_x = 0.2 + separator.enabled = False + separator.operator("view3d.cm_ui_separator_button", + text="", + icon='BLANK1', + ) + # add operator prop = row_setcol.operator("view3d.set_collection", text="", icon=icon, emboss=False) prop.is_master_collection = True prop.collection_name = 'Master Collection' + # add vertical separator line + separator = row_setcol.row() + separator.scale_x = 0.2 + separator.enabled = False + separator.operator("view3d.cm_ui_separator_button", + text="", + icon='BLANK1', + ) + copy_icon = 'COPYDOWN' swap_icon = 'ARROW_LEFTRIGHT' copy_swap_icon = 'SELECT_INTERSECT' @@ -534,7 +595,8 @@ class CM_UL_items(UIList): QCD.scale_x = 0.4 QCD.prop(item, "qcd_slot_idx", text="") - c_name = row.row() + # collection name + c_name = row.row(align=True) #if rename[0] and index == cm.cm_list_index: #c_name.activate_init = True @@ -542,16 +604,54 @@ class CM_UL_items(UIList): c_name.prop(item, "name", text="", expand=True) + # set selection + setsel = c_name.row(align=True) + icon = 'DOT' + + if any((laycol["ptr"].exclude, + collection.hide_select, + collection.hide_viewport, + laycol["ptr"].hide_viewport, + not collection.objects,)): + # objects cannot be selected + setsel.active = False + + else: + for obj in collection.objects: + if obj.select_get() == False: + # some objects remain unselected + icon = 'LAYER_USED' + break + + if icon != 'LAYER_USED': + # all objects are selected + icon = 'LAYER_ACTIVE' + + prop = setsel.operator("view3d.select_collection_objects", + text="", + icon=icon, + depress=bool(icon == 'LAYER_ACTIVE') + ) + prop.is_master_collection = False + prop.collection_name = item.name + # used as a separator (actual separator not wide enough) row.label() row = s2 if cm.align_local_ops else s1 + + add_vertical_separator_line(row) + + # add set_collection op set_obj_col = row.row() set_obj_col.operator_context = 'INVOKE_DEFAULT' - icon = 'MESH_CUBE' + icon = 'GRID' + + if collection.objects: + icon = 'MESH_CUBE' if selected_objects: if active_object and active_object.name in collection.objects: @@ -569,6 +669,8 @@ class CM_UL_items(UIList): prop.is_master_collection = False prop.collection_name = item.name + add_vertical_separator_line(row) + if cm.show_exclude: exclude_history_base = internals.rto_history["exclude"].get(view_layer.name, {})