Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Inch <mythologylover75@gmail.com>2020-03-30 09:34:28 +0300
committerRyan Inch <mythologylover75@gmail.com>2020-03-30 09:34:28 +0300
commita32b859fecb1a1d269408d0b9730eb5c7fc52c0f (patch)
tree81d7374b19aef4f4ecca1a59a8c0fdd4c15ddb0a /object_collection_manager
parentbbd5fd92a3d95389d6489d78cc062539a6f1e0e4 (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__.py7
-rw-r--r--object_collection_manager/internals.py168
-rw-r--r--object_collection_manager/operators.py4
-rw-r--r--object_collection_manager/persistent_data.py23
-rw-r--r--object_collection_manager/qcd_init.py12
-rw-r--r--object_collection_manager/qcd_move_widget.py14
-rw-r--r--object_collection_manager/qcd_operators.py39
-rw-r--r--object_collection_manager/ui.py10
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()