diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-12-09 13:03:28 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-12-09 13:03:28 +0300 |
commit | f5fbe860fe1962673de7a7d479287e418152faff (patch) | |
tree | cc95d0956f896f930107c1bb72b4a239bfcc319a /object_collection_manager | |
parent | ec6873e90f2d1e2765f85b58dfa6addeb2a592dd (diff) |
Cleanup: trailing space
Diffstat (limited to 'object_collection_manager')
-rw-r--r-- | object_collection_manager/__init__.py | 20 | ||||
-rw-r--r-- | object_collection_manager/internals.py | 28 | ||||
-rw-r--r-- | object_collection_manager/operators.py | 612 | ||||
-rw-r--r-- | object_collection_manager/ui.py | 206 |
4 files changed, 433 insertions, 433 deletions
diff --git a/object_collection_manager/__init__.py b/object_collection_manager/__init__.py index 75142a35..687f4fc7 100644 --- a/object_collection_manager/__init__.py +++ b/object_collection_manager/__init__.py @@ -33,7 +33,7 @@ bl_info = { if "bpy" in locals(): import importlib - + importlib.reload(internals) importlib.reload(operators) importlib.reload(ui) @@ -78,16 +78,16 @@ classes = ( def register(): for cls in classes: bpy.utils.register_class(cls) - + bpy.types.Scene.CMListCollection = CollectionProperty(type=internals.CMListCollection) bpy.types.Scene.CMListIndex = IntProperty(update=ui.update_selection) - + bpy.types.Scene.show_exclude = BoolProperty(default=True, name="Exclude from View Layer") bpy.types.Scene.show_selectable = BoolProperty(default=True, name="Selectable") bpy.types.Scene.show_hideviewport = BoolProperty(default=True, name="Hide in Viewport") bpy.types.Scene.show_disableviewport = BoolProperty(default=False, name="Disable in Viewports") bpy.types.Scene.show_render = BoolProperty(default=False, name="Disable in Renders") - + bpy.types.Scene.CM_Phantom_Mode = BoolProperty(default=False) @@ -96,26 +96,26 @@ def register(): km = wm.keyconfigs.addon.keymaps.new(name='Object Mode') kmi = km.keymap_items.new('view3d.collection_manager', 'M', 'PRESS') addon_keymaps.append((km, kmi)) - + def unregister(): for cls in classes: bpy.utils.unregister_class(cls) - + del bpy.types.Scene.CMListCollection del bpy.types.Scene.CMListIndex - + del bpy.types.Scene.show_exclude del bpy.types.Scene.show_selectable del bpy.types.Scene.show_hideviewport del bpy.types.Scene.show_disableviewport del bpy.types.Scene.show_render - + del bpy.types.Scene.CM_Phantom_Mode - + # remove keymaps when add-on is deactivated for km, kmi in addon_keymaps: km.keymap_items.remove(kmi) addon_keymaps.clear() - + if __name__ == "__main__": register() diff --git a/object_collection_manager/internals.py b/object_collection_manager/internals.py index e898de1c..8b440ce8 100644 --- a/object_collection_manager/internals.py +++ b/object_collection_manager/internals.py @@ -18,12 +18,12 @@ def update_col_name(self, context): if self.name == '': self.name = self.last_name return - + if self.last_name != '': layer_collections[self.last_name]["ptr"].collection.name = self.name - + update_property_group(context) - + self.last_name = self.name class CMListCollection(PropertyGroup): @@ -38,9 +38,9 @@ def update_collection_tree(context): layer_collections.clear() max_lvl = 0 row_index = 0 - + init_laycol_list = context.view_layer.layer_collection.children - + master_laycol = {"id": 0, "name": context.view_layer.layer_collection.name, "lvl": -1, @@ -52,13 +52,13 @@ def update_collection_tree(context): "children": [], "ptr": context.view_layer.layer_collection } - + get_all_collections(context, init_laycol_list, master_laycol, collection_tree, visible=True) def get_all_collections(context, collections, parent, tree, level=0, visible=False): global row_index - + for item in collections: laycol = {"id": len(layer_collections) +1, "name": item.name, @@ -71,21 +71,21 @@ def get_all_collections(context, collections, parent, tree, level=0, visible=Fal "children": [], "ptr": item } - + row_index += 1 - + layer_collections[item.name] = laycol tree.append(laycol) - + if len(item.children) > 0: global max_lvl max_lvl += 1 laycol["has_children"] = True - + if item.name in expanded and laycol["visible"]: laycol["expanded"] = True get_all_collections(context, item.children, laycol, laycol["children"], level+1, visible=True) - + else: get_all_collections(context, item.children, laycol, laycol["children"], level+1) @@ -98,10 +98,10 @@ def update_property_group(context): def create_property_group(context, tree): global in_filter - + for laycol in tree: new_cm_listitem = context.scene.CMListCollection.add() new_cm_listitem.name = laycol["name"] - + if laycol["has_children"]: create_property_group(context, laycol["children"]) diff --git a/object_collection_manager/operators.py b/object_collection_manager/operators.py index 84396e7e..85a5a822 100644 --- a/object_collection_manager/operators.py +++ b/object_collection_manager/operators.py @@ -25,7 +25,7 @@ class ExpandAllOperator(bpy.types.Operator): bl_label = "Expand All Items" bl_idname = "view3d.expand_all_items" bl_options = {'REGISTER', 'UNDO'} - + def execute(self, context): if len(expanded) > 0: expanded.clear() @@ -33,10 +33,10 @@ class ExpandAllOperator(bpy.types.Operator): for laycol in layer_collections.values(): if laycol["ptr"].children: expanded.append(laycol["name"]) - + # update tree view update_property_group(context) - + return {'FINISHED'} @@ -45,16 +45,16 @@ class ExpandSublevelOperator(bpy.types.Operator): bl_label = "Expand Sublevel Items" bl_idname = "view3d.expand_sublevel" bl_options = {'REGISTER', 'UNDO'} - + expand: BoolProperty() name: StringProperty() index: IntProperty() - + def invoke(self, context, event): if event.shift: # expand/collapse all subcollections expand = None - + # check whether to expand or collapse if self.name in expanded: expanded.remove(self.name) @@ -62,7 +62,7 @@ class ExpandSublevelOperator(bpy.types.Operator): else: expanded.append(self.name) expand = True - + # do expanding/collapsing def loop(laycol): for item in laycol.children: @@ -72,24 +72,24 @@ class ExpandSublevelOperator(bpy.types.Operator): else: if item.name in expanded: expanded.remove(item.name) - + if len(item.children) > 0: loop(item) - + loop(layer_collections[self.name]["ptr"]) - + else: # expand/collapse collection if self.expand: expanded.append(self.name) else: expanded.remove(self.name) - - + + # set selected row to the collection you're expanding/collapsing and update tree view context.scene.CMListIndex = self.index update_property_group(context) - + return {'FINISHED'} @@ -98,42 +98,42 @@ class CMSetCollectionOperator(bpy.types.Operator): bl_label = "Set Object Collection" bl_idname = "view3d.set_collection" bl_options = {'REGISTER', 'UNDO'} - + collection_index: IntProperty() collection_name: StringProperty() - + def invoke(self, context, event): collection = layer_collections[self.collection_name]["ptr"].collection - + if event.shift: # add object to collection - + # check if in collection in_collection = True - + for obj in context.selected_objects: if obj.name not in collection.objects: in_collection = False - + if not in_collection: # add to collection bpy.ops.object.link_to_collection(collection_index=self.collection_index) - + else: # check and disallow removing from all collections for obj in context.selected_objects: if len(obj.users_collection) == 1: send_report("Error removing 1 or more objects from this collection.\nObjects would be left without a collection") - + return {'FINISHED'} - + # remove from collection bpy.ops.collection.objects_remove(collection=collection.name) - + else: # move object to collection bpy.ops.object.move_to_collection(collection_index=self.collection_index) - + return {'FINISHED'} @@ -142,68 +142,68 @@ class CMExcludeOperator(bpy.types.Operator): bl_label = "Exclude Collection from View Layer" bl_idname = "view3d.exclude_collection" bl_options = {'REGISTER', 'UNDO'} - + name: StringProperty() - + def invoke(self, context, event): global rto_history - + view_layer = context.view_layer.name laycol_ptr = layer_collections[self.name]["ptr"] - + if not view_layer in rto_history["exclude"]: rto_history["exclude"][view_layer] = {"target": "", "history": []} - + rto_history["exclude"][view_layer]["target"] = self.name exclude_history = rto_history["exclude"][view_layer]["history"] - + if event.shift: # isolate/de-isolate exclusion of collections - + # get active layer collections active_layer_collections = [x for x in layer_collections.values() \ if x["ptr"].exclude == False] - + # check if collection isolated if len(active_layer_collections) == 1 and active_layer_collections[0]["name"] == self.name: if len(exclude_history) > 1: # restore previous state for x, item in enumerate(layer_collections.values()): item["ptr"].exclude = exclude_history[x] - + else: # enable all collections for item in layer_collections.values(): item["ptr"].exclude = False - + # reset exclude history del rto_history["exclude"][view_layer] - + else: # isolate collection - + # reset exclude history exclude_history.clear() - + # save state keep_history = -1 for item in layer_collections.values(): exclude_history.append(item["ptr"].exclude) - + if item["ptr"].exclude == False: keep_history += 1 - + if not keep_history: del rto_history["exclude"][view_layer] - - + + # isolate collection for item in layer_collections.values(): if item["name"] != laycol_ptr.name: item["ptr"].exclude = True - + laycol_ptr.exclude = False - + # exclude all children laycol_iter_list = [laycol_ptr.children] while len(laycol_iter_list) > 0: @@ -213,29 +213,29 @@ class CMExcludeOperator(bpy.types.Operator): layer_collection.exclude = True if len(layer_collection.children) > 0: new_laycol_iter_list.append(layer_collection.children) - + laycol_iter_list = new_laycol_iter_list - - + + elif event.ctrl: # toggle children - + # reset exclude history del rto_history["exclude"][view_layer] - + # toggle exclusion of collection (this propagates to children) laycol_ptr.exclude = not laycol_ptr.exclude - + else: # toggle exclusion - + # reset exclude history del rto_history["exclude"][view_layer] - - + + # get current child exclusion state child_exclusion = [] - + laycol_iter_list = [laycol_ptr.children] while len(laycol_iter_list) > 0: new_laycol_iter_list = [] @@ -244,23 +244,23 @@ class CMExcludeOperator(bpy.types.Operator): child_exclusion.append([layer_collection, layer_collection.exclude]) if len(layer_collection.children) > 0: new_laycol_iter_list.append(layer_collection.children) - + laycol_iter_list = new_laycol_iter_list - - + + # 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] - - + + # reset exclude all history if view_layer in rto_history["exclude_all"]: del rto_history["exclude_all"][view_layer] - + return {'FINISHED'} @@ -269,51 +269,51 @@ class CMUnExcludeAllOperator(bpy.types.Operator): bl_label = "Toggle Excluded Status Of All Collections" bl_idname = "view3d.un_exclude_all_collections" bl_options = {'REGISTER', 'UNDO'} - + def invoke(self, context, event): global rto_history - + view_layer = context.view_layer.name - + if not view_layer in rto_history["exclude_all"]: rto_history["exclude_all"][view_layer] = [] - + exclude_all_history = rto_history["exclude_all"][view_layer] - + if len(exclude_all_history) == 0: exclude_all_history.clear() keep_history = False - + if event.shift: for item in layer_collections.values(): keep_history = True exclude_all_history.append(item["ptr"].exclude) - + for x, item in enumerate(layer_collections.values()): item["ptr"].exclude = not exclude_all_history[x] - + print([not i for i in exclude_all_history]) - + else: for item in reversed(list(layer_collections.values())): if item["ptr"].exclude: keep_history = True - + exclude_all_history.append(item["ptr"].exclude) - + item["ptr"].exclude = False - + exclude_all_history.reverse() - + if not keep_history: del rto_history["exclude_all"][view_layer] - + else: for x, item in enumerate(layer_collections.values()): item["ptr"].exclude = exclude_all_history[x] - + del rto_history["exclude_all"][view_layer] - + return {'FINISHED'} @@ -322,89 +322,89 @@ class CMRestrictSelectOperator(bpy.types.Operator): bl_label = "Disable Selection of Collection" bl_idname = "view3d.restrict_select_collection" bl_options = {'REGISTER', 'UNDO'} - + name: StringProperty() - + def invoke(self, context, event): global rto_history - + view_layer = context.view_layer.name laycol_ptr = layer_collections[self.name]["ptr"] - + if not view_layer in rto_history["select"]: rto_history["select"][view_layer] = {"target": "", "history": []} - + rto_history["select"][view_layer]["target"] = self.name select_history = rto_history["select"][view_layer]["history"] - + if event.shift: # isolate/de-isolate selectability of collections - + # get active collections active_layer_collections = [x for x in layer_collections.values() \ if x["ptr"].collection.hide_select == False] - + layerchain = [] laycol = layer_collections[self.name] - + # get chain of parents up to top level collection while laycol["id"] != 0: layerchain.append(laycol) laycol = laycol["parent"] - + # check if reversed layerchain matches active collections if layerchain[::-1] == active_layer_collections: if len(select_history) > 1: # restore previous state for x, item in enumerate(layer_collections.values()): item["ptr"].collection.hide_select = select_history[x] - + else: # make all collections selectable for item in layer_collections.values(): item["ptr"].collection.hide_select = False - + # reset select history del rto_history["select"][view_layer] - + else: # reset select history select_history.clear() - + # save state keep_history = -1 for item in layer_collections.values(): select_history.append(item["ptr"].collection.hide_select) - + if item["ptr"].collection.hide_select == False: keep_history += 1 - + if not keep_history: del rto_history["select"][view_layer] - + # make all collections unselectable for item in layer_collections.values(): item["ptr"].collection.hide_select = True - + # allow selection of active collection plus parents laycol_ptr.collection.hide_select = False - + laycol = layer_collections[self.name] while laycol["id"] != 0: laycol["ptr"].collection.hide_select = False laycol = laycol["parent"] - - + + elif event.ctrl: # toggle children - + # reset select history del rto_history["select"][view_layer] - + # toggle selectability of collection state = not laycol_ptr.collection.hide_select laycol_ptr.collection.hide_select = state - + # pass state to children laycol_iter_list = [laycol_ptr.children] while len(laycol_iter_list) > 0: @@ -414,21 +414,21 @@ class CMRestrictSelectOperator(bpy.types.Operator): layer_collection.collection.hide_select = state if len(layer_collection.children) > 0: new_laycol_iter_list.append(layer_collection.children) - + laycol_iter_list = new_laycol_iter_list - + else: # reset select history del rto_history["select"][view_layer] - + # toggle selectability of collection laycol_ptr.collection.hide_select = not laycol_ptr.collection.hide_select - - + + # reset select all history if view_layer in rto_history["select_all"]: del rto_history["select_all"][view_layer] - + return {'FINISHED'} @@ -437,43 +437,43 @@ class CMUnRestrictSelectAllOperator(bpy.types.Operator): bl_label = "Toggle Selectable Status Of All Collections" bl_idname = "view3d.un_restrict_select_all_collections" bl_options = {'REGISTER', 'UNDO'} - + def invoke(self, context, event): global rto_history - + view_layer = context.view_layer.name if not view_layer in rto_history["select_all"]: rto_history["select_all"][view_layer] = [] select_all_history = rto_history["select_all"][view_layer] - + if len(select_all_history) == 0: select_all_history.clear() keep_history = False - + for item in layer_collections.values(): if event.shift: keep_history = True select_all_history.append(item["ptr"].collection.hide_select) item["ptr"].collection.hide_select = not item["ptr"].collection.hide_select - + else: if item["ptr"].collection.hide_select: keep_history = True - + select_all_history.append(item["ptr"].collection.hide_select) item["ptr"].collection.hide_select = False - + if not keep_history: del rto_history["select_all"][view_layer] - + else: for x, item in enumerate(layer_collections.values()): item["ptr"].collection.hide_select = select_all_history[x] - + del rto_history["select_all"][view_layer] - + return {'FINISHED'} @@ -482,88 +482,88 @@ class CMHideOperator(bpy.types.Operator): bl_label = "Hide Collection" bl_idname = "view3d.hide_collection" bl_options = {'REGISTER', 'UNDO'} - + name: StringProperty() - + def invoke(self, context, event): global rto_history - + view_layer = context.view_layer.name laycol_ptr = layer_collections[self.name]["ptr"] - + if not view_layer in rto_history["hide"]: rto_history["hide"][view_layer] = {"target": "", "history": []} - + rto_history["hide"][view_layer]["target"] = self.name hide_history = rto_history["hide"][view_layer]["history"] - + if event.shift: # isolate/de-isolate view of collections - + # get active collections active_layer_collections = [x for x in layer_collections.values() \ if x["ptr"].hide_viewport == False] - + layerchain = [] laycol = layer_collections[self.name] - + # get chain of parents up to top level collection while laycol["id"] != 0: layerchain.append(laycol) laycol = laycol["parent"] - + # check if reversed layerchain matches active collections if layerchain[::-1] == active_layer_collections: if len(hide_history) > 1: # restore previous state for x, item in enumerate(layer_collections.values()): item["ptr"].hide_viewport = hide_history[x] - + else: # show all collections for laycol in layer_collections.values(): laycol["ptr"].hide_viewport = False - + # reset hide history del rto_history["hide"][view_layer] - + else: # reset hide history hide_history.clear() - + # save state keep_history = -1 for item in layer_collections.values(): hide_history.append(item["ptr"].hide_viewport) - + if item["ptr"].hide_viewport == False: keep_history += 1 - + if not keep_history: del rto_history["hide"][view_layer] - + # hide all collections for laycol in layer_collections.values(): laycol["ptr"].hide_viewport = True - + # show active collection plus parents laycol_ptr.hide_viewport = False - + laycol = layer_collections[self.name] while laycol["id"] != 0: laycol["ptr"].hide_viewport = False laycol = laycol["parent"] - + elif event.ctrl: # toggle children - + # reset hide history del rto_history["hide"][view_layer] - + # toggle view of collection state = not laycol_ptr.hide_viewport laycol_ptr.hide_viewport = state - + # pass state to children laycol_iter_list = [laycol_ptr.children] while len(laycol_iter_list) > 0: @@ -573,21 +573,21 @@ class CMHideOperator(bpy.types.Operator): layer_collection.hide_viewport = state if len(layer_collection.children) > 0: new_laycol_iter_list.append(layer_collection.children) - + laycol_iter_list = new_laycol_iter_list - + else: # reset hide history del rto_history["hide"][view_layer] - + # toggle view of collection laycol_ptr.hide_viewport = not laycol_ptr.hide_viewport - - + + # reset hide all history if view_layer in rto_history["hide_all"]: del rto_history["hide_all"][view_layer] - + return {'FINISHED'} @@ -596,43 +596,43 @@ class CMUnHideAllOperator(bpy.types.Operator): bl_label = "Toggle Hidden Status Of All Collections" bl_idname = "view3d.un_hide_all_collections" bl_options = {'REGISTER', 'UNDO'} - + def invoke(self, context, event): global rto_history - + view_layer = context.view_layer.name if not view_layer in rto_history["hide_all"]: rto_history["hide_all"][view_layer] = [] hide_all_history = rto_history["hide_all"][view_layer] - + if len(hide_all_history) == 0: hide_all_history.clear() keep_history = False - + for item in layer_collections.values(): if event.shift: keep_history = True hide_all_history.append(item["ptr"].hide_viewport) item["ptr"].hide_viewport = not item["ptr"].hide_viewport - + else: if item["ptr"].hide_viewport: keep_history = True - + hide_all_history.append(item["ptr"].hide_viewport) item["ptr"].hide_viewport = False - + if not keep_history: del rto_history["hide_all"][view_layer] - + else: for x, item in enumerate(layer_collections.values()): item["ptr"].hide_viewport = hide_all_history[x] - + del rto_history["hide_all"][view_layer] - + return {'FINISHED'} @@ -641,88 +641,88 @@ class CMDisableViewportOperator(bpy.types.Operator): bl_label = "Disable Collection in Viewport" bl_idname = "view3d.disable_viewport_collection" bl_options = {'REGISTER', 'UNDO'} - + name: StringProperty() - + def invoke(self, context, event): global rto_history - + view_layer = context.view_layer.name laycol_ptr = layer_collections[self.name]["ptr"] - + if not view_layer in rto_history["disable"]: rto_history["disable"][view_layer] = {"target": "", "history": []} - + rto_history["disable"][view_layer]["target"] = self.name disable_history = rto_history["disable"][view_layer]["history"] - + if event.shift: # isolate/de-isolate disablement of collections in viewport - + # get active collections active_layer_collections = [x for x in layer_collections.values() \ if x["ptr"].collection.hide_viewport == False] - + layerchain = [] laycol = layer_collections[self.name] - + # get chain of parents up to top level collection while laycol["id"] != 0: layerchain.append(laycol) laycol = laycol["parent"] - + # check if reversed layerchain matches active collections if layerchain[::-1] == active_layer_collections: if len(disable_history) > 1: # restore previous state for x, item in enumerate(layer_collections.values()): item["ptr"].collection.hide_viewport = disable_history[x] - + else: # enable all collections in viewport for laycol in layer_collections.values(): laycol["ptr"].collection.hide_viewport = False - + # reset disable history del rto_history["disable"][view_layer] - + else: # reset disable history disable_history.clear() - + # save state keep_history = -1 for item in layer_collections.values(): disable_history.append(item["ptr"].collection.hide_viewport) - + if item["ptr"].collection.hide_viewport == False: keep_history += 1 - + if not keep_history: del rto_history["disable"][view_layer] - + # disable all collections in viewport for laycol in layer_collections.values(): laycol["ptr"].collection.hide_viewport = True - + # enable active collection plus parents in viewport laycol_ptr.collection.hide_viewport = False - + laycol = layer_collections[self.name] while laycol["id"] != 0: laycol["ptr"].collection.hide_viewport = False laycol = laycol["parent"] - + elif event.ctrl: # toggle children - + # reset disable history del rto_history["disable"][view_layer] - + # toggle view of collection state = not laycol_ptr.collection.hide_viewport laycol_ptr.collection.hide_viewport = state - + # pass state to children laycol_iter_list = [laycol_ptr.children] while len(laycol_iter_list) > 0: @@ -732,21 +732,21 @@ class CMDisableViewportOperator(bpy.types.Operator): layer_collection.collection.hide_viewport = state if len(layer_collection.children) > 0: new_laycol_iter_list.append(layer_collection.children) - + laycol_iter_list = new_laycol_iter_list - + else: # reset disable history del rto_history["disable"][view_layer] - + # toggle disable of collection in viewport laycol_ptr.collection.hide_viewport = not laycol_ptr.collection.hide_viewport - - + + # reset disable all history if view_layer in rto_history["disable_all"]: del rto_history["disable_all"][view_layer] - + return {'FINISHED'} @@ -755,44 +755,44 @@ class CMUnDisableViewportAllOperator(bpy.types.Operator): bl_label = "Toggle Viewport Display of All Collections" bl_idname = "view3d.un_disable_viewport_all_collections" bl_options = {'REGISTER', 'UNDO'} - + def invoke(self, context, event): global rto_history - + view_layer = context.view_layer.name if not view_layer in rto_history["disable_all"]: rto_history["disable_all"][view_layer] = [] disable_all_history = rto_history["disable_all"][view_layer] - + if len(disable_all_history) == 0: disable_all_history.clear() keep_history = False - + for item in layer_collections.values(): if event.shift: keep_history = True disable_all_history.append(item["ptr"].collection.hide_viewport) item["ptr"].collection.hide_viewport = not \ item["ptr"].collection.hide_viewport - + else: if item["ptr"].collection.hide_viewport: keep_history = True - + disable_all_history.append(item["ptr"].collection.hide_viewport) item["ptr"].collection.hide_viewport = False - + if not keep_history: del rto_history["disable_all"][view_layer] - + else: for x, item in enumerate(layer_collections.values()): item["ptr"].collection.hide_viewport = disable_all_history[x] - + del rto_history["disable_all"][view_layer] - + return {'FINISHED'} @@ -801,88 +801,88 @@ class CMDisableRenderOperator(bpy.types.Operator): bl_label = "Disable Collection in Render" bl_idname = "view3d.disable_render_collection" bl_options = {'REGISTER', 'UNDO'} - + name: StringProperty() - + def invoke(self, context, event): global rto_history - + view_layer = context.view_layer.name laycol_ptr = layer_collections[self.name]["ptr"] - + if not view_layer in rto_history["render"]: rto_history["render"][view_layer] = {"target": "", "history": []} rto_history["render"][view_layer]["target"] = self.name render_history = rto_history["render"][view_layer]["history"] - + if event.shift: # isolate/de-isolate render of collections - + # get active collections active_layer_collections = [x for x in layer_collections.values() \ if x["ptr"].collection.hide_render == False] - + layerchain = [] laycol = layer_collections[self.name] - + # get chain of parents up to top level collection while laycol["id"] != 0: layerchain.append(laycol) laycol = laycol["parent"] - + # check if reversed layerchain matches active collections if layerchain[::-1] == active_layer_collections: if len(render_history) > 1: # restore previous state for x, item in enumerate(layer_collections.values()): item["ptr"].collection.hide_render = render_history[x] - + else: # allow render of all collections for laycol in layer_collections.values(): laycol["ptr"].collection.hide_render = False - + # reset render history del rto_history["render"][view_layer] - + else: # reset render history render_history.clear() - + # save state keep_history = -1 for item in layer_collections.values(): render_history.append(item["ptr"].collection.hide_render) - + if item["ptr"].collection.hide_render == False: keep_history += 1 - + if not keep_history: del rto_history["render"][view_layer] - + # disallow render of all collections for laycol in layer_collections.values(): laycol["ptr"].collection.hide_render = True - + # allow render of active collection plus parents laycol_ptr.collection.hide_render = False - + laycol = layer_collections[self.name] while laycol["id"] != 0: laycol["ptr"].collection.hide_render = False laycol = laycol["parent"] - + elif event.ctrl: # toggle children - + # reset render history del rto_history["render"][view_layer] - + # toggle view of collection state = not laycol_ptr.collection.hide_render laycol_ptr.collection.hide_render = state - + # pass state to children laycol_iter_list = [laycol_ptr.children] while len(laycol_iter_list) > 0: @@ -892,21 +892,21 @@ class CMDisableRenderOperator(bpy.types.Operator): layer_collection.collection.hide_render = state if len(layer_collection.children) > 0: new_laycol_iter_list.append(layer_collection.children) - + laycol_iter_list = new_laycol_iter_list - + else: # reset render history del rto_history["render"][view_layer] - + # toggle renderability of collection laycol_ptr.collection.hide_render = not laycol_ptr.collection.hide_render - - + + # reset render all history if view_layer in rto_history["render_all"]: del rto_history["render_all"][view_layer] - + return {'FINISHED'} @@ -915,44 +915,44 @@ class CMUnDisableRenderAllOperator(bpy.types.Operator): bl_label = "Toggle Render Status of All Collections" bl_idname = "view3d.un_disable_render_all_collections" bl_options = {'REGISTER', 'UNDO'} - + def invoke(self, context, event): global rto_history - + view_layer = context.view_layer.name if not view_layer in rto_history["render_all"]: rto_history["render_all"][view_layer] = [] render_all_history = rto_history["render_all"][view_layer] - + if len(render_all_history) == 0: render_all_history.clear() keep_history = False - + for item in layer_collections.values(): if event.shift: keep_history = True render_all_history.append(item["ptr"].collection.hide_render) item["ptr"].collection.hide_render = not \ item["ptr"].collection.hide_render - + else: if item["ptr"].collection.hide_render: keep_history = True - + render_all_history.append(item["ptr"].collection.hide_render) item["ptr"].collection.hide_render = False - + if not keep_history: del rto_history["render_all"][view_layer] - + else: for x, item in enumerate(layer_collections.values()): item["ptr"].collection.hide_render = render_all_history[x] - + del rto_history["render_all"][view_layer] - + return {'FINISHED'} @@ -961,95 +961,95 @@ class CMRemoveCollectionOperator(bpy.types.Operator): bl_label = "Remove Collection" bl_idname = "view3d.remove_collection" bl_options = {'UNDO'} - + collection_name: StringProperty() - + def execute(self, context): global rto_history - + laycol = layer_collections[self.collection_name] collection = laycol["ptr"].collection laycol_parent = laycol["parent"] - + # save state and remove all hiding properties of parent collection orig_parent_hide_select = False orig_parent_exclude = False orig_parent_hide_viewport = False - + if laycol_parent["ptr"].collection.hide_select: orig_parent_hide_select = True - + if laycol_parent["ptr"].exclude: orig_parent_exclude = True - + if laycol_parent["ptr"].hide_viewport: orig_parent_hide_viewport = True - + laycol_parent["ptr"].collection.hide_select = False laycol_parent["ptr"].exclude = False laycol_parent["ptr"].hide_viewport = False - - + + # remove all hiding properties of this collection collection.hide_select = False laycol["ptr"].exclude = False laycol["ptr"].hide_viewport = False - - + + # shift all objects in this collection to the parent collection if collection.objects: orig_selected_objs = context.selected_objects orig_active_obj = context.active_object - + # select all objects in collection bpy.ops.object.select_same_collection(collection=collection.name) context.view_layer.objects.active = context.selected_objects[0] - + # remove any objects already in parent collection from selection for obj in context.selected_objects: if obj in laycol["parent"]["ptr"].collection.objects.values(): obj.select_set(False) - + # link selected objects to parent collection bpy.ops.object.link_to_collection(collection_index=laycol_parent["id"]) - + # remove objects from collection bpy.ops.collection.objects_remove(collection=collection.name) - + # reset selection original values bpy.ops.object.select_all(action='DESELECT') - + for obj in orig_selected_objs: obj.select_set(True) context.view_layer.objects.active = orig_active_obj - - + + # shift all child collections to the parent collection if collection.children: for subcollection in collection.children: laycol_parent["ptr"].collection.children.link(subcollection) - + # reset hiding properties of parent collection laycol_parent["ptr"].collection.hide_select = orig_parent_hide_select laycol_parent["ptr"].exclude = orig_parent_exclude laycol_parent["ptr"].hide_viewport = orig_parent_hide_viewport - - + + # remove collection and update tree view bpy.data.collections.remove(collection) - - + + update_property_group(context) - + if len(context.scene.CMListCollection) == context.scene.CMListIndex: context.scene.CMListIndex = len(context.scene.CMListCollection) - 1 update_property_group(context) - - + + # reset history for rto in rto_history.values(): rto.clear() - + return {'FINISHED'} rename = [False] @@ -1058,66 +1058,66 @@ class CMNewCollectionOperator(bpy.types.Operator): bl_label = "Add New Collection" bl_idname = "view3d.add_collection" bl_options = {'UNDO'} - + child: BoolProperty() - + def execute(self, context): global rto_history - + new_collection = bpy.data.collections.new('Collection') scn = context.scene - + # if there are collections if len(scn.CMListCollection) > 0: # get selected collection laycol = layer_collections[scn.CMListCollection[scn.CMListIndex].name] - + # add new collection if self.child: laycol["ptr"].collection.children.link(new_collection) expanded.append(laycol["name"]) - + # update tree view property update_property_group(context) - + scn.CMListIndex = layer_collections[new_collection.name]["row_index"] - + else: laycol["parent"]["ptr"].collection.children.link(new_collection) - + # update tree view property update_property_group(context) - + scn.CMListIndex = layer_collections[new_collection.name]["row_index"] - + # if no collections add top level collection and select it else: scn.collection.children.link(new_collection) - + # update tree view property update_property_group(context) - + scn.CMListIndex = 0 - + global rename rename[0] = True - + # reset history for rto in rto_history.values(): rto.clear() - + return {'FINISHED'} - + phantom_history = {"view_layer": "", "initial_state": {}, - + "exclude_history": [], "select_history": [], "hide_history": [], "disable_history": [], "render_history": [], - + "exclude_all_history": [], "select_all_history": [], "hide_all_history": [], @@ -1129,22 +1129,22 @@ class CMPhantomModeOperator(bpy.types.Operator): '''Toggle Phantom Mode''' bl_label = "Toggle Phantom Mode" bl_idname = "view3d.toggle_phantom_mode" - + def execute(self, context): global phantom_history global rto_history - + scn = context.scene view_layer = context.view_layer.name - + # enter Phantom Mode if not scn.CM_Phantom_Mode: - + scn.CM_Phantom_Mode = True - + # save current visibility state phantom_history["view_layer"] = view_layer - + laycol_iter_list = [context.view_layer.layer_collection.children] while len(laycol_iter_list) > 0: new_laycol_iter_list = [] @@ -1157,18 +1157,18 @@ class CMPhantomModeOperator(bpy.types.Operator): "disable": layer_collection.collection.hide_viewport, "render": layer_collection.collection.hide_render, } - + if len(layer_collection.children) > 0: new_laycol_iter_list.append(layer_collection.children) - + laycol_iter_list = new_laycol_iter_list - - + + # save current rto history for rto, history, in rto_history.items(): phantom_history[rto+"_history"] = history.get(view_layer, {}).copy() - - + + # return to normal mode else: laycol_iter_list = [context.view_layer.layer_collection.children] @@ -1177,34 +1177,34 @@ class CMPhantomModeOperator(bpy.types.Operator): for laycol_iter in laycol_iter_list: for layer_collection in laycol_iter: phantom_laycol = phantom_history["initial_state"][layer_collection.name] - + layer_collection.exclude = \ phantom_laycol["exclude"] - + layer_collection.collection.hide_select = \ phantom_laycol["select"] - + layer_collection.hide_viewport = \ phantom_laycol["hide"] - + layer_collection.collection.hide_viewport = \ phantom_laycol["disable"] - + layer_collection.collection.hide_render = \ phantom_laycol["render"] - - + + if len(layer_collection.children) > 0: new_laycol_iter_list.append(layer_collection.children) - + laycol_iter_list = new_laycol_iter_list - - + + # restore previous rto history for rto, history, in rto_history.items(): history[view_layer] = phantom_history[rto+"_history"].copy() - + scn.CM_Phantom_Mode = False - - + + return {'FINISHED'} diff --git a/object_collection_manager/ui.py b/object_collection_manager/ui.py index 4c0e4597..b48f2535 100644 --- a/object_collection_manager/ui.py +++ b/object_collection_manager/ui.py @@ -18,28 +18,28 @@ from .operators import ( class CollectionManager(Operator): bl_label = "Collection Manager" bl_idname = "view3d.collection_manager" - + last_view_layer = "" - + def draw(self, context): layout = self.layout scn = context.scene view_layer = context.view_layer.name - + if view_layer != self.last_view_layer: update_collection_tree(context) self.last_view_layer = view_layer - + title_row = layout.split(factor=0.5) main = title_row.row() view = title_row.row(align=True) view.alignment = 'RIGHT' - + main.label(text="Collection Manager") - + view.prop(context.view_layer, "use", text="") view.separator() - + window = context.window scene = window.scene view.template_search( @@ -47,89 +47,89 @@ class CollectionManager(Operator): scene, "view_layers", new="scene.view_layer_add", unlink="scene.view_layer_remove") - + 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' - + sec1 = toggle_row.row() sec1.alignment = 'LEFT' sec1.enabled = False - + if len(expanded) > 0: text = "Collapse All Items" else: text = "Expand All Items" - + sec1.operator("view3d.expand_all_items", text=text) - + for laycol in collection_tree: if laycol["has_children"]: sec1.enabled = True break - + sec2 = toggle_row.row() sec2.alignment = 'RIGHT' - + if scn.show_exclude: exclude_all_history = rto_history["exclude_all"].get(view_layer, []) depress = True if len(exclude_all_history) else False - + sec2.operator("view3d.un_exclude_all_collections", text="", icon='CHECKBOX_HLT', depress=depress) - + if scn.show_selectable: select_all_history = rto_history["select_all"].get(view_layer, []) depress = True if len(select_all_history) else False - + sec2.operator("view3d.un_restrict_select_all_collections", text="", icon='RESTRICT_SELECT_OFF', depress=depress) - + if scn.show_hideviewport: hide_all_history = rto_history["hide_all"].get(view_layer, []) depress = True if len(hide_all_history) else False - + sec2.operator("view3d.un_hide_all_collections", text="", icon='HIDE_OFF', depress=depress) - + if scn.show_disableviewport: disable_all_history = rto_history["disable_all"].get(view_layer, []) depress = True if len(disable_all_history) else False - + sec2.operator("view3d.un_disable_viewport_all_collections", text="", icon='RESTRICT_VIEW_OFF', depress=depress) - + if scn.show_render: render_all_history = rto_history["render_all"].get(view_layer, []) depress = True if len(render_all_history) else False - + sec2.operator("view3d.un_disable_render_all_collections", text="", icon='RESTRICT_RENDER_OFF', depress=depress) - + layout.row().template_list("CM_UL_items", "", context.scene, "CMListCollection", context.scene, "CMListIndex", rows=15, sort_lock=True) - + addcollec_row = layout.row() addcollec_row.operator("view3d.add_collection", text="Add Collection", icon='COLLECTION_NEW').child = False - + addcollec_row.operator("view3d.add_collection", text="Add SubCollection", icon='COLLECTION_NEW').child = True - + phantom_row = layout.row() toggle_text = "Disable " if scn.CM_Phantom_Mode else "Enable " phantom_row.operator("view3d.toggle_phantom_mode", text=toggle_text+"Phantom Mode") - + if scn.CM_Phantom_Mode: view.enabled = False addcollec_row.enabled = False - - + + def execute(self, context): wm = context.window_manager lvl = 0 - + #expanded.clear() - + #excludeall_history.clear() #restrictselectall_history.clear() #hideall_history.clear() @@ -137,14 +137,14 @@ class CollectionManager(Operator): #disablerenderall_history.clear() update_property_group(context) - + lvl = get_max_lvl() - + if lvl > 25: lvl = 25 self.view_layer = context.view_layer.name - + # sync selection in ui list with active layer collection try: active_laycol_name = context.view_layer.active_layer_collection.name @@ -152,21 +152,21 @@ class CollectionManager(Operator): context.scene.CMListIndex = active_laycol_row_index except: context.scene.CMListIndex = 0 - + if context.scene.CM_Phantom_Mode: if set(layer_collections.keys()) != set(phantom_history["initial_state"].keys()): context.scene.CM_Phantom_Mode = False - + if context.view_layer.name != phantom_history["view_layer"]: context.scene.CM_Phantom_Mode = False - + return wm.invoke_popup(self, width=(400+(lvl*20))) def update_selection(self, context): selected_item = context.scene.CMListCollection[context.scene.CMListIndex] layer_collection = layer_collections[selected_item.name]["ptr"] - + context.view_layer.active_layer_collection = layer_collection @@ -186,7 +186,7 @@ def filter_items_by_name_insensitive(pattern, bitflag, items, propname="name", f if flags is None: flags = [0] * len(items) - + # Make pattern case-insensitive pattern = pattern.lower() @@ -195,43 +195,43 @@ def filter_items_by_name_insensitive(pattern, bitflag, items, propname="name", f for i, item in enumerate(items): name = getattr(item, propname, None) - + # Make name case-insensitive name = name.lower() - + # This is similar to a logical xor if bool(name and fnmatch.fnmatch(name, pattern)) is not bool(reverse): flags[i] |= bitflag - + return flags class CM_UL_items(UIList): last_filter_value = "" - + filter_by_selected: BoolProperty( name="Filter By Selected", default=False, description="Filter collections by selected items" ) - + def draw_item(self, context, layout, data, item, icon, active_data,active_propname, index): self.use_filter_show = True - + scn = context.scene view_layer = context.view_layer.name laycol = layer_collections[item.name] collection = laycol["ptr"].collection - + split = layout.split(factor=0.96) row = split.row(align=True) row.alignment = 'LEFT' - + # indent child items if laycol["lvl"] > 0: for x in range(laycol["lvl"]): row.label(icon='BLANK1') - + # add expander if collection has children to make UIList act like tree view if laycol["has_children"]: if laycol["expanded"]: @@ -239,156 +239,156 @@ class CM_UL_items(UIList): prop.expand = False prop.name = item.name prop.index = index - + else: prop = row.operator("view3d.expand_sublevel", text="", icon='DISCLOSURE_TRI_RIGHT', emboss=False) prop.expand = True prop.name = item.name prop.index = index - + else: row.label(icon='BLANK1') - - + + row.label(icon='GROUP') - + name_row = row.row() - + #if rename[0] and index == scn.CMListIndex: #name_row.activate_init = True #rename[0] = False - + name_row.prop(item, "name", text="", expand=True) - + # used as a separator (actual separator not wide enough) row.label() - + # add set_collection op row_setcol = row.row() row_setcol.operator_context = 'INVOKE_DEFAULT' - + icon = 'MESH_CUBE' - + if len(context.selected_objects) > 0 and context.active_object: if context.active_object.name in collection.objects: icon = 'SNAP_VOLUME' else: row_setcol.enabled = False - - + + prop = row_setcol.operator("view3d.set_collection", text="", icon=icon, emboss=False) prop.collection_index = laycol["id"] prop.collection_name = item.name - - + + if scn.show_exclude: exclude_history_base = rto_history["exclude"].get(view_layer, {}) exclude_target = exclude_history_base.get("target", "") exclude_history = exclude_history_base.get("history", []) - + depress = True if len(exclude_history) and exclude_target == item.name else False emboss = True if len(exclude_history) and exclude_target == item.name else False icon = 'CHECKBOX_DEHLT' if laycol["ptr"].exclude else 'CHECKBOX_HLT' - + row.operator("view3d.exclude_collection", text="", icon=icon, emboss=emboss, depress=depress).name = item.name - + if scn.show_selectable: select_history_base = rto_history["select"].get(view_layer, {}) select_target = select_history_base.get("target", "") select_history = select_history_base.get("history", []) - + depress = True if len(select_history) and select_target == item.name else False emboss = True if len(select_history) and select_target == item.name else False icon = 'RESTRICT_SELECT_ON' if laycol["ptr"].collection.hide_select else 'RESTRICT_SELECT_OFF' - + row.operator("view3d.restrict_select_collection", text="", icon=icon, emboss=emboss, depress=depress).name = item.name - + if scn.show_hideviewport: hide_history_base = rto_history["hide"].get(view_layer, {}) hide_target = hide_history_base.get("target", "") hide_history = hide_history_base.get("history", []) - + depress = True if len(hide_history) and hide_target == item.name else False emboss = True if len(hide_history) and hide_target == item.name else False icon = 'HIDE_ON' if laycol["ptr"].hide_viewport else 'HIDE_OFF' - + row.operator("view3d.hide_collection", text="", icon=icon, emboss=emboss, depress=depress).name = item.name - + if scn.show_disableviewport: disable_history_base = rto_history["disable"].get(view_layer, {}) disable_target = disable_history_base.get("target", "") disable_history = disable_history_base.get("history", []) - + depress = True if len(disable_history) and disable_target == item.name else False emboss = True if len(disable_history) and disable_target == item.name else False icon = 'RESTRICT_VIEW_ON' if laycol["ptr"].collection.hide_viewport else 'RESTRICT_VIEW_OFF' - + row.operator("view3d.disable_viewport_collection", text="", icon=icon, emboss=emboss, depress=depress).name = item.name - + if scn.show_render: render_history_base = rto_history["render"].get(view_layer, {}) render_target = render_history_base.get("target", "") render_history = render_history_base.get("history", []) - + depress = True if len(render_history) and render_target == item.name else False emboss = True if len(render_history) and render_target == item.name else False icon = 'RESTRICT_RENDER_ON' if laycol["ptr"].collection.hide_render else 'RESTRICT_RENDER_OFF' - + row.operator("view3d.disable_render_collection", text="", icon=icon, emboss=emboss, depress=depress).name = item.name - - + + rm_op = split.row() rm_op.alignment = 'RIGHT' rm_op.operator("view3d.remove_collection", text="", icon='X', emboss=False).collection_name = item.name - + if scn.CM_Phantom_Mode: name_row.enabled = False row_setcol.enabled = False rm_op.enabled = False - - + + def draw_filter(self, context, layout): row = layout.row() subrow = row.row(align=True) subrow.prop(self, "filter_name", text="") - + icon = 'ZOOM_OUT' if self.use_filter_invert else 'ZOOM_IN' subrow.prop(self, "use_filter_invert", text="", icon=icon) - + subrow = row.row(align=True) subrow.prop(self, "filter_by_selected", text="", icon='SNAP_VOLUME') - + def filter_items(self, context, data, propname): flt_flags = [] flt_neworder = [] - + list_items = getattr(data, propname) - + if self.filter_name: flt_flags = filter_items_by_name_insensitive(self.filter_name, self.bitflag_filter_item, list_items) - + elif self.filter_by_selected: flt_flags = [0] * len(list_items) - + for idx, item in enumerate(list_items): collection = layer_collections[item.name]["ptr"].collection - + # check if any of the selected objects are in the collection if not set(context.selected_objects).isdisjoint(collection.objects): flt_flags[idx] |= self.bitflag_filter_item - + else: # display as treeview flt_flags = [self.bitflag_filter_item] * len(list_items) - + for idx, item in enumerate(list_items): if not layer_collections[item.name]["visible"]: flt_flags[idx] = 0 - + return flt_flags, flt_neworder - - + + def invoke(self, context, event): pass @@ -398,13 +398,13 @@ class CMRestrictionTogglesPanel(Panel): bl_idname = "COLLECTIONMANAGER_PT_restriction_toggles" bl_space_type = 'VIEW_3D' bl_region_type = 'HEADER' - + def draw(self, context): - + layout = self.layout - + row = layout.row() - + row.prop(context.scene, "show_exclude", icon='CHECKBOX_HLT', icon_only=True) row.prop(context.scene, "show_selectable", icon='RESTRICT_SELECT_OFF', icon_only=True) row.prop(context.scene, "show_hideviewport", icon='HIDE_OFF', icon_only=True) |