[Bf-extensions-cvs] [b752de9e] master: Collection Manager: Add QCD System. Task: T69577

Ryan Inch noreply at git.blender.org
Mon Mar 16 07:57:08 CET 2020


Commit: b752de9e0da4e8ad694de25497275f66168a2df4
Author: Ryan Inch
Date:   Mon Mar 16 02:48:02 2020 -0400
Branches: master
https://developer.blender.org/rBAb752de9e0da4e8ad694de25497275f66168a2df4

Collection Manager: Add QCD System. Task: T69577

Adds a Quick Content Display (QCD) system to the Collection Manager.
This consists of a 3D View Header widget and a floating panel
similar to the layers system in blender 2.7x, along with
hotkeys to view/move objects to QCD slots, and additions to the
main Collection Manager popup to allow you to manage which collections
correspond to which slots.

===================================================================

M	object_collection_manager/__init__.py
A	object_collection_manager/icons/minus.png
M	object_collection_manager/internals.py
M	object_collection_manager/operators.py
A	object_collection_manager/preferences.py
A	object_collection_manager/qcd_move_widget.py
A	object_collection_manager/qcd_operators.py
M	object_collection_manager/ui.py

===================================================================

diff --git a/object_collection_manager/__init__.py b/object_collection_manager/__init__.py
index 4d895df7..37bf9c3a 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": (1,10,0),
+    "version": (2,0,0),
     "blender": (2, 80, 0),
     "location": "View3D - Object Mode (Shortcut - M)",
     "warning": '',  # used for warning icon and text in addons panel
@@ -36,19 +36,30 @@ if "bpy" in locals():
 
     importlib.reload(internals)
     importlib.reload(operators)
+    importlib.reload(preferences)
+    importlib.reload(qcd_move_widget)
+    importlib.reload(qcd_operators)
     importlib.reload(ui)
 
 else:
     from . import internals
     from . import operators
+    from . import preferences
+    from . import qcd_move_widget
+    from . import qcd_operators
     from . import ui
 
+import os
 import bpy
+import bpy.utils.previews
+from bpy.app.handlers import persistent
 from bpy.types import PropertyGroup
 from bpy.props import (
     CollectionProperty,
+    EnumProperty,
     IntProperty,
     BoolProperty,
+    StringProperty,
     PointerProperty,
     )
 
@@ -65,6 +76,10 @@ class CollectionManagerProperties(PropertyGroup):
 
     in_phantom_mode: BoolProperty(default=False)
 
+    update_header: CollectionProperty(type=internals.CMListCollection)
+
+    qcd_slots_blend_data: StringProperty()
+
 
 addon_keymaps = []
 
@@ -87,30 +102,131 @@ classes = (
     operators.CMRemoveCollectionOperator,
     operators.CMSetCollectionOperator,
     operators.CMPhantomModeOperator,
+    preferences.CMPreferences,
+    qcd_move_widget.QCDMoveWidget,
+    qcd_operators.MoveToQCDSlot,
+    qcd_operators.ViewQCDSlot,
+    qcd_operators.ViewMoveQCDSlot,
+    qcd_operators.RenumerateQCDSlots,
     ui.CM_UL_items,
     ui.CollectionManager,
     ui.CMRestrictionTogglesPanel,
     CollectionManagerProperties,
     )
 
+ at persistent
+def depsgraph_update_post_handler(dummy):
+    if qcd_operators.move_triggered:
+        qcd_operators.move_triggered = False
+        return
+
+    qcd_operators.move_selection.clear()
+    qcd_operators.move_active = None
+    qcd_operators.get_move_selection()
+    qcd_operators.get_move_active()
+
+ at persistent
+def save_internal_data(dummy):
+    cm = bpy.context.scene.collection_manager
+
+    cm.qcd_slots_blend_data = internals.qcd_slots.get_data_for_blend()
+
+ at persistent
+def load_internal_data(dummy):
+    cm = bpy.context.scene.collection_manager
+    data = cm.qcd_slots_blend_data
+
+    if not data:
+        return
+
+    internals.qcd_slots.load_blend_data(data)
+
 def register():
     for cls in classes:
         bpy.utils.register_class(cls)
 
+
+    pcoll = bpy.utils.previews.new()
+    icons_dir = os.path.join(os.path.dirname(__file__), "icons")
+    pcoll.load("active_icon_base", os.path.join(icons_dir, "minus.png"), 'IMAGE', True)
+    pcoll.load("active_icon_text", os.path.join(icons_dir, "minus.png"), 'IMAGE', True)
+    pcoll.load("active_icon_text_sel", os.path.join(icons_dir, "minus.png"), 'IMAGE', True)
+    ui.preview_collections["icons"] = pcoll
+
+
     bpy.types.Scene.collection_manager = PointerProperty(type=CollectionManagerProperties)
 
+    bpy.types.VIEW3D_HT_header.append(ui.view3d_header_qcd_slots)
+
     # create the global menu hotkey
     wm = bpy.context.window_manager
     km = wm.keyconfigs.addon.keymaps.new(name='Object Mode')
     kmi = km.keymap_items.new('view3d.collection_manager', 'M', 'PRESS')
     addon_keymaps.append((km, kmi))
 
+    # create qcd hotkeys
+    qcd_hotkeys = [
+        ["ONE", False, "1"],
+        ["TWO", False, "2"],
+        ["THREE", False, "3"],
+        ["FOUR", False, "4"],
+        ["FIVE", False, "5"],
+        ["SIX", False, "6"],
+        ["SEVEN", False, "7"],
+        ["EIGHT", False, "8"],
+        ["NINE", False, "9"],
+        ["ZERO", False, "10"],
+        ["ONE", True, "11"],
+        ["TWO", True, "12"],
+        ["THREE", True, "13"],
+        ["FOUR", True, "14"],
+        ["FIVE", True, "15"],
+        ["SIX", True, "16"],
+        ["SEVEN", True, "17"],
+        ["EIGHT", True, "18"],
+        ["NINE", True, "19"],
+        ["ZERO", True, "20"],
+    ]
+
+    for key in qcd_hotkeys:
+        km = wm.keyconfigs.addon.keymaps.new(name='Object Mode')
+        kmi = km.keymap_items.new('view3d.view_qcd_slot', key[0], 'PRESS', alt=key[1])
+        kmi.properties.slot = key[2]
+        kmi.properties.toggle = False
+        addon_keymaps.append((km, kmi))
+
+        km = wm.keyconfigs.addon.keymaps.new(name='Object Mode')
+        kmi = km.keymap_items.new('view3d.view_qcd_slot', key[0], 'PRESS',shift=True,  alt=key[1])
+        kmi.properties.slot = key[2]
+        kmi.properties.toggle = True
+        addon_keymaps.append((km, kmi))
+
+    km = wm.keyconfigs.addon.keymaps.new(name='Object Mode')
+    kmi = km.keymap_items.new('view3d.qcd_move_widget', 'V', 'PRESS')
+    addon_keymaps.append((km, kmi))
+
+    bpy.app.handlers.depsgraph_update_post.append(depsgraph_update_post_handler)
+    bpy.app.handlers.save_pre.append(save_internal_data)
+    bpy.app.handlers.load_post.append(load_internal_data)
+
 def unregister():
+    bpy.app.handlers.depsgraph_update_post.remove(depsgraph_update_post_handler)
+    bpy.app.handlers.save_pre.remove(save_internal_data)
+    bpy.app.handlers.load_post.remove(load_internal_data)
+
     for cls in classes:
         bpy.utils.unregister_class(cls)
 
+    for pcoll in ui.preview_collections.values():
+        bpy.utils.previews.remove(pcoll)
+    ui.preview_collections.clear()
+    ui.last_icon_theme_text = None
+    ui.last_icon_theme_text_sel = None
+
     del bpy.types.Scene.collection_manager
 
+    bpy.types.VIEW3D_HT_header.remove(ui.view3d_header_qcd_slots)
+
     # remove keymaps when add-on is deactivated
     for km, kmi in addon_keymaps:
         km.keymap_items.remove(kmi)
diff --git a/object_collection_manager/icons/minus.png b/object_collection_manager/icons/minus.png
new file mode 100644
index 00000000..dff25acd
Binary files /dev/null and b/object_collection_manager/icons/minus.png differ
diff --git a/object_collection_manager/internals.py b/object_collection_manager/internals.py
index e7f63884..5ebc6025 100644
--- a/object_collection_manager/internals.py
+++ b/object_collection_manager/internals.py
@@ -25,46 +25,183 @@ from bpy.types import (
     Operator,
 )
 
-from bpy.props import StringProperty
+from bpy.props import (
+    StringProperty,
+    IntProperty,
+)
 
 layer_collections = {}
-
 collection_tree = []
-
 expanded = []
-
-max_lvl = 0
 row_index = 0
 
+max_lvl = 0
 def get_max_lvl():
     return max_lvl
 
+
+class QCDSlots():
+    _slots = {}
+    overrides = {}
+    allow_update = True
+
+    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
+
+        except ValueError:
+            return key in self._slots.values()
+
+        return False
+
+    def get_data_for_blend(self):
+        return f"{self._slots.__repr__()}\n{self.overrides.__repr__()}"
+
+    def load_blend_data(self, data):
+        decoupled_data = data.split("\n")
+        blend_slots = eval(decoupled_data[0])
+        blend_overrides = eval(decoupled_data[1])
+
+        self._slots = blend_slots
+        self.overrides = blend_overrides
+
+    def length(self):
+        return len(self._slots)
+
+    def get_idx(self, name, r_value=None):
+        for k, v in self._slots.items():
+            if v == name:
+                return k
+
+        return r_value
+
+    def get_name(self, idx, r_value=None):
+        if idx in self._slots:
+            return self._slots[idx]
+
+        return r_value
+
+    def add_slot(self, idx, name):
+        self._slots[idx] = name
+
+    def update_slot(self, idx, name):
+        self._slots[idx] = name
+
+    def del_slot(self, slot):
+        try:
+            int(slot)
+            del self._slots[slot]
+
+        except ValueError:
+            idx = self.get_idx(slot)
+            del self._slots[idx]
+
+    def clear(self):
+        self._slots.clear()
+
+qcd_slots = QCDSlots()
+
+
 def update_col_name(self, context):
+    global layer_collections
+    global qcd_slots
+
     if self.name != self.last_name:
         if self.name == '':
             self.name = self.last_name
             return
 
         if self.last_name != '':
+            # update collection name
             layer_collections[self.last_name]["ptr"].collection.name = self.name
 
+            # update qcd_slot
+            idx = qcd_slots.get_idx(self.last_name)
+            if idx:
+                qcd_slots.update_slot(idx, self.name)
+
             update_property_group(context)
 
         self.last_name = self.name
 
+def update_qcd_slot(self, context):
+    global qcd_slots
+
+    if not qcd_slots.allow_update:
+        return
+
+    update_needed = False
+
+    try:
+        int(self.qcd_slot)
+    except:
+
+        if self.qcd_slot == "":
+            qcd_slots.del_slot(self.name)
+            qcd_slots.overrides[self.name] = True
+
+        if self.name in qcd_slots:
+            qcd_slots.allow_update = False
+            self.qcd_slot = 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 = ""
+            qcd_slots.allow_update = True
+
+        return
+
+    if self.name in qcd_slots:
+        qcd_slots.del_slot(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)
+        update_needed = True
+
+    if int(self.qcd_slot) > 20:
+        self.qcd_slot = "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:
+        d

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list