diff options
author | Ryan Inch <mythologylover75@gmail.com> | 2020-03-30 09:34:28 +0300 |
---|---|---|
committer | Ryan Inch <mythologylover75@gmail.com> | 2020-03-30 09:34:28 +0300 |
commit | a32b859fecb1a1d269408d0b9730eb5c7fc52c0f (patch) | |
tree | 81d7374b19aef4f4ecca1a59a8c0fdd4c15ddb0a /object_collection_manager | |
parent | bbd5fd92a3d95389d6489d78cc062539a6f1e0e4 (diff) |
Collection Manager: QCD polishing. Task: T69577
Made QCD internal structure more stable.
Prevented reload scripts from resetting QCD slots.
Fixed QCD being left in an incorrect state on undo/redo.
Fixed a small error on unregister.
Diffstat (limited to 'object_collection_manager')
-rw-r--r-- | object_collection_manager/__init__.py | 7 | ||||
-rw-r--r-- | object_collection_manager/internals.py | 168 | ||||
-rw-r--r-- | object_collection_manager/operators.py | 4 | ||||
-rw-r--r-- | object_collection_manager/persistent_data.py | 23 | ||||
-rw-r--r-- | object_collection_manager/qcd_init.py | 12 | ||||
-rw-r--r-- | object_collection_manager/qcd_move_widget.py | 14 | ||||
-rw-r--r-- | object_collection_manager/qcd_operators.py | 39 | ||||
-rw-r--r-- | object_collection_manager/ui.py | 10 |
8 files changed, 159 insertions, 118 deletions
diff --git a/object_collection_manager/__init__.py b/object_collection_manager/__init__.py index 56450064..de40b9e1 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,4,5), + "version": (2,4,9), "blender": (2, 80, 0), "location": "View3D - Object Mode (Shortcut - M)", "warning": '', # used for warning icon and text in addons panel @@ -126,6 +126,9 @@ def register(): qcd_init.register_qcd() def unregister(): + if bpy.context.preferences.addons[__package__].preferences.enable_qcd: + qcd_init.unregister_qcd() + for cls in classes: bpy.utils.unregister_class(cls) @@ -136,8 +139,6 @@ def unregister(): km.keymap_items.remove(kmi) addon_keymaps.clear() - qcd_init.unregister_qcd() - if __name__ == "__main__": register() diff --git a/object_collection_manager/internals.py b/object_collection_manager/internals.py index 5ebc6025..116eb38c 100644 --- a/object_collection_manager/internals.py +++ b/object_collection_manager/internals.py @@ -18,6 +18,8 @@ # Copyright 2011, Ryan Inch +from . import persistent_data + import bpy from bpy.types import ( @@ -45,21 +47,23 @@ class QCDSlots(): overrides = {} allow_update = True + def __init__(self): + self._slots = persistent_data.slots + self.overrides = persistent_data.overrides + def __iter__(self): return self._slots.items().__iter__() def __repr__(self): return self._slots.__repr__() - def __contains__(self, key): - try: - int(key) - return key in self._slots + def contains(self, *, idx=None, name=None): + if idx: + return idx in self._slots.keys() + if name: + return name in self._slots.values() - except ValueError: - return key in self._slots.values() - - return False + raise def get_data_for_blend(self): return f"{self._slots.__repr__()}\n{self.overrides.__repr__()}" @@ -69,8 +73,14 @@ class QCDSlots(): blend_slots = eval(decoupled_data[0]) blend_overrides = eval(decoupled_data[1]) - self._slots = blend_slots - self.overrides = blend_overrides + self._slots.clear() + self.overrides.clear() + + for k, v in blend_slots.items(): + self._slots[k] = v + + for k, v in blend_overrides.items(): + self.overrides[k] = v def length(self): return len(self._slots) @@ -91,21 +101,64 @@ class QCDSlots(): def add_slot(self, idx, name): self._slots[idx] = name - def update_slot(self, idx, name): - self._slots[idx] = name + if name in self.overrides: + del self.overrides[name] - def del_slot(self, slot): - try: - int(slot) - del self._slots[slot] + def update_slot(self, idx, name): + self.add_slot(idx, name) - except ValueError: - idx = self.get_idx(slot) + def del_slot(self, *, idx=None, name=None): + if idx and not name: del self._slots[idx] + return + + if name and not idx: + slot_idx = self.get_idx(name) + del self._slots[slot_idx] + return - def clear(self): + raise + + def add_override(self, name): + qcd_slots.del_slot(name=name) + qcd_slots.overrides[name] = True + + def clear_slots(self): self._slots.clear() + def update_qcd(self): + for idx, name in list(self._slots.items()): + if not layer_collections.get(name, None): + qcd_slots.del_slot(name=name) + + def auto_numerate(self, *, renumerate=False): + global max_lvl + + if self.length() < 20: + lvl = 0 + num = 1 + while lvl <= max_lvl: + if num > 20: + break + + for laycol in layer_collections.values(): + if num > 20: + break + + if int(laycol["lvl"]) == lvl: + if laycol["name"] in qcd_slots.overrides: + if not renumerate: + num += 1 + continue + + if (not self.contains(idx=str(num)) and + not self.contains(name=laycol["name"])): + self.add_slot(str(num), laycol["name"]) + + num += 1 + + lvl += 1 + qcd_slots = QCDSlots() @@ -140,45 +193,39 @@ def update_qcd_slot(self, context): update_needed = False try: - int(self.qcd_slot) + int(self.qcd_slot_idx) except: - if self.qcd_slot == "": - qcd_slots.del_slot(self.name) - qcd_slots.overrides[self.name] = True + if self.qcd_slot_idx == "": + qcd_slots.add_override(self.name) - if self.name in qcd_slots: + if qcd_slots.contains(name=self.name): qcd_slots.allow_update = False - self.qcd_slot = qcd_slots.get_idx(self.name) + self.qcd_slot_idx = qcd_slots.get_idx(self.name) qcd_slots.allow_update = True if self.name in qcd_slots.overrides: qcd_slots.allow_update = False - self.qcd_slot = "" + self.qcd_slot_idx = "" qcd_slots.allow_update = True return - if self.name in qcd_slots: - qcd_slots.del_slot(self.name) + if qcd_slots.contains(name=self.name): + qcd_slots.del_slot(name=self.name) update_needed = True - if self.qcd_slot in qcd_slots: - qcd_slots.overrides[qcd_slots.get_name(self.qcd_slot)] = True - qcd_slots.del_slot(self.qcd_slot) + if qcd_slots.contains(idx=self.qcd_slot_idx): + qcd_slots.add_override(qcd_slots.get_name(self.qcd_slot_idx)) update_needed = True - if int(self.qcd_slot) > 20: - self.qcd_slot = "20" + if int(self.qcd_slot_idx) > 20: + self.qcd_slot_idx = "20" - if int(self.qcd_slot) < 1: - self.qcd_slot = "1" - - qcd_slots.add_slot(self.qcd_slot, self.name) - - if self.name in qcd_slots.overrides: - del qcd_slots.overrides[self.name] + if int(self.qcd_slot_idx) < 1: + self.qcd_slot_idx = "1" + qcd_slots.add_slot(self.qcd_slot_idx, self.name) if update_needed: update_property_group(context) @@ -187,10 +234,10 @@ def update_qcd_slot(self, context): class CMListCollection(PropertyGroup): name: StringProperty(update=update_col_name) last_name: StringProperty() - qcd_slot: StringProperty(name="QCD Slot", update=update_qcd_slot) + qcd_slot_idx: StringProperty(name="QCD Slot", update=update_qcd_slot) -def update_collection_tree(context, renumerate=False): +def update_collection_tree(context, *, renumerate_qcd=False): global max_lvl global row_index global collection_tree @@ -222,36 +269,9 @@ def update_collection_tree(context, renumerate=False): for laycol in master_laycol["children"]: collection_tree.append(laycol) - # update qcd - for x in range(20): - qcd_slot = qcd_slots.get_name(str(x+1)) - if qcd_slot and not layer_collections.get(qcd_slot, None): - qcd_slots.del_slot(qcd_slot) - - # update autonumeration - if qcd_slots.length() < 20: - lvl = 0 - num = 1 - while lvl <= max_lvl: - if num > 20: - break - - for laycol in layer_collections.values(): - if num > 20: - break - - if int(laycol["lvl"]) == lvl: - if laycol["name"] in qcd_slots.overrides: - if not renumerate: - num += 1 - continue - - if str(num) not in qcd_slots and laycol["name"] not in qcd_slots: - qcd_slots.add_slot(str(num), laycol["name"]) - - num += 1 + qcd_slots.update_qcd() - lvl += 1 + qcd_slots.auto_numerate(renumerate=renumerate_qcd) def get_all_collections(context, collections, parent, tree, level=0, visible=False): @@ -290,13 +310,13 @@ def get_all_collections(context, collections, parent, tree, level=0, visible=Fal get_all_collections(context, item.children, laycol, laycol["children"], level+1) -def update_property_group(context, renumerate=False): +def update_property_group(context, *, renumerate_qcd=False): global collection_tree global qcd_slots qcd_slots.allow_update = False - update_collection_tree(context, renumerate) + update_collection_tree(context, renumerate_qcd=renumerate_qcd) context.scene.collection_manager.cm_list_collection.clear() create_property_group(context, collection_tree) @@ -312,7 +332,7 @@ def create_property_group(context, tree): for laycol in tree: new_cm_listitem = cm.cm_list_collection.add() new_cm_listitem.name = laycol["name"] - new_cm_listitem.qcd_slot = qcd_slots.get_idx(laycol["name"], "") + new_cm_listitem.qcd_slot_idx = qcd_slots.get_idx(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 bf7a77f8..c8c10336 100644 --- a/object_collection_manager/operators.py +++ b/object_collection_manager/operators.py @@ -1905,8 +1905,8 @@ class CMRemoveCollectionOperator(Operator): # update qcd - if self.collection_name in qcd_slots: - qcd_slots.del_slot(self.collection_name) + if qcd_slots.contains(name=self.collection_name): + qcd_slots.del_slot(name=self.collection_name) if self.collection_name in qcd_slots.overrides: del qcd_slots.overrides[self.collection_name] diff --git a/object_collection_manager/persistent_data.py b/object_collection_manager/persistent_data.py new file mode 100644 index 00000000..a3432b7d --- /dev/null +++ b/object_collection_manager/persistent_data.py @@ -0,0 +1,23 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# Copyright 2011, Ryan Inch + +# QCD +slots = {} +overrides = {} diff --git a/object_collection_manager/qcd_init.py b/object_collection_manager/qcd_init.py index 4857719a..87cbcd16 100644 --- a/object_collection_manager/qcd_init.py +++ b/object_collection_manager/qcd_init.py @@ -3,6 +3,7 @@ import bpy import bpy.utils.previews from bpy.app.handlers import persistent +from . import internals from . import preferences from . import qcd_move_widget from . import qcd_operators @@ -27,8 +28,11 @@ def depsgraph_update_post_handler(dummy): qcd_operators.move_selection.clear() qcd_operators.move_active = None - qcd_operators.get_move_selection() - qcd_operators.get_move_active() + +@persistent +def undo_redo_post_handler(dummy): + qcd_operators.move_selection.clear() + qcd_operators.move_active = None @persistent def save_internal_data(dummy): @@ -63,6 +67,8 @@ def register_qcd(): addon_qcd_keymaps.append((km, kmi)) bpy.app.handlers.depsgraph_update_post.append(depsgraph_update_post_handler) + bpy.app.handlers.undo_post.append(undo_redo_post_handler) + bpy.app.handlers.redo_post.append(undo_redo_post_handler) bpy.app.handlers.save_pre.append(save_internal_data) bpy.app.handlers.load_post.append(load_internal_data) @@ -117,6 +123,8 @@ def unregister_qcd(): bpy.utils.unregister_class(cls) bpy.app.handlers.depsgraph_update_post.remove(depsgraph_update_post_handler) + bpy.app.handlers.undo_post.remove(undo_redo_post_handler) + bpy.app.handlers.redo_post.remove(undo_redo_post_handler) bpy.app.handlers.save_pre.remove(save_internal_data) bpy.app.handlers.load_post.remove(load_internal_data) diff --git a/object_collection_manager/qcd_move_widget.py b/object_collection_manager/qcd_move_widget.py index 441c39de..13212146 100644 --- a/object_collection_manager/qcd_move_widget.py +++ b/object_collection_manager/qcd_move_widget.py @@ -653,10 +653,10 @@ def allocate_main_ui(self, context): for num in range(button_group): slot_num = row_num + num - qcd_slot = qcd_slots.get_name(f"{slot_num}") + qcd_slot_name = qcd_slots.get_name(f"{slot_num}") - if qcd_slot: - qcd_laycol = layer_collections[qcd_slot]["ptr"] + if qcd_slot_name: + qcd_laycol = layer_collections[qcd_slot_name]["ptr"] collection_objects = qcd_laycol.collection.objects selected_objects = qcd_operators.get_move_selection() active_object = qcd_operators.get_move_active() @@ -815,16 +815,16 @@ def draw_callback_px(self, context): rounding = 5 if num < 10: - if not f"{num+2}" in qcd_slots: + if not qcd_slots.contains(idx=f"{num+2}"): tr = rounding - if not f"{num}" in qcd_slots: + if not qcd_slots.contains(idx=f"{num}"): tl = rounding else: - if not f"{num+2}" in qcd_slots: + if not qcd_slots.contains(idx=f"{num+2}"): br = rounding - if not f"{num}" in qcd_slots: + if not qcd_slots.contains(idx=f"{num}"): bl = rounding if num in [0,5]: diff --git a/object_collection_manager/qcd_operators.py b/object_collection_manager/qcd_operators.py index 2b45c1de..9bfa2110 100644 --- a/object_collection_manager/qcd_operators.py +++ b/object_collection_manager/qcd_operators.py @@ -47,35 +47,22 @@ def get_move_selection(): global move_selection if not move_selection: - move_selection = bpy.context.selected_objects + move_selection = [obj.name for obj in bpy.context.selected_objects] - return move_selection + return [bpy.data.objects[name] for name in move_selection] def get_move_active(): global move_active global move_selection if not move_active: - move_active = bpy.context.view_layer.objects.active + move_active = getattr(bpy.context.view_layer.objects.active, "name", None) - if move_active not in get_move_selection(): + if move_active not in [obj.name for obj in get_move_selection()]: move_active = None - if move_active: - try: - move_active.name + return bpy.data.objects[move_active] if move_active else None - except: - move_active = None - move_selection = [] - - # update header widget - cm = bpy.context.scene.collection_manager - cm.update_header.clear() - new_update_header = cm.update_header.add() - new_update_header.name = "updated" - - return move_active class MoveToQCDSlot(Operator): '''Move object(s) to QCD slot''' @@ -94,10 +81,11 @@ class MoveToQCDSlot(Operator): selected_objects = get_move_selection() active_object = get_move_active() move_triggered = True - qcd_laycol = qcd_slots.get_name(self.slot) + qcd_laycol = None + slot_name = qcd_slots.get_name(self.slot) - if qcd_laycol: - qcd_laycol = layer_collections[qcd_laycol]["ptr"] + if slot_name: + qcd_laycol = layer_collections[slot_name]["ptr"] else: return {'CANCELLED'} @@ -213,10 +201,11 @@ class ViewQCDSlot(Operator): global layer_collections global rto_history - qcd_laycol = qcd_slots.get_name(self.slot) + qcd_laycol = None + slot_name = qcd_slots.get_name(self.slot) - if qcd_laycol: - qcd_laycol = layer_collections[qcd_laycol]["ptr"] + if slot_name: + qcd_laycol = layer_collections[slot_name]["ptr"] else: return {'CANCELLED'} @@ -297,6 +286,6 @@ class RenumerateQCDSlots(Operator): if event.ctrl: qcd_slots.overrides.clear() - update_property_group(context, renumerate=True) + update_property_group(context, renumerate_qcd=True) return {'FINISHED'} diff --git a/object_collection_manager/ui.py b/object_collection_manager/ui.py index e2f075db..4640c9c2 100644 --- a/object_collection_manager/ui.py +++ b/object_collection_manager/ui.py @@ -343,7 +343,7 @@ class CM_UL_items(UIList): if context.preferences.addons[__package__].preferences.enable_qcd: QCD = row.row() QCD.scale_x = 0.4 - QCD.prop(item, "qcd_slot", text="") + QCD.prop(item, "qcd_slot_idx", text="") name_row = row.row() @@ -483,7 +483,7 @@ class CM_UL_items(UIList): flt_flags = [0] * len(list_items) for idx, item in enumerate(list_items): - if item.qcd_slot: + if item.qcd_slot_idx: flt_flags[idx] |= self.bitflag_filter_item else: # display as treeview @@ -533,10 +533,10 @@ def view3d_header_qcd_slots(self, context): update_collection_tree(context) for x in range(20): - qcd_slot = qcd_slots.get_name(str(x+1)) + qcd_slot_name = qcd_slots.get_name(str(x+1)) - if qcd_slot: - qcd_laycol = layer_collections[qcd_slot]["ptr"] + if qcd_slot_name: + qcd_laycol = layer_collections[qcd_slot_name]["ptr"] collection_objects = qcd_laycol.collection.objects selected_objects = qcd_operators.get_move_selection() active_object = qcd_operators.get_move_active() |