Collection Manager: Update Move Operator. Task: T69577
Updates the Collection Manager's Move Operator with improvements developed for QCD.
This commit is contained in:
parent
ba19a9a747
commit
5c9aaca64d
|
@ -22,7 +22,7 @@ bl_info = {
|
|||
"name": "Collection Manager",
|
||||
"description": "Manage collections and their objects",
|
||||
"author": "Ryan Inch",
|
||||
"version": (2,4,12),
|
||||
"version": (2,5,0),
|
||||
"blender": (2, 80, 0),
|
||||
"location": "View3D - Object Mode (Shortcut - M)",
|
||||
"warning": '', # used for warning icon and text in addons panel
|
||||
|
@ -52,6 +52,7 @@ else:
|
|||
from . import preferences
|
||||
|
||||
import bpy
|
||||
from bpy.app.handlers import persistent
|
||||
from bpy.types import PropertyGroup
|
||||
from bpy.props import (
|
||||
CollectionProperty,
|
||||
|
@ -108,7 +109,19 @@ classes = (
|
|||
CollectionManagerProperties,
|
||||
)
|
||||
|
||||
@persistent
|
||||
def depsgraph_update_post_handler(dummy):
|
||||
if internals.move_triggered:
|
||||
internals.move_triggered = False
|
||||
return
|
||||
|
||||
internals.move_selection.clear()
|
||||
internals.move_active = None
|
||||
|
||||
@persistent
|
||||
def undo_redo_post_handler(dummy):
|
||||
internals.move_selection.clear()
|
||||
internals.move_active = None
|
||||
|
||||
def register():
|
||||
for cls in classes:
|
||||
|
@ -122,6 +135,10 @@ def register():
|
|||
kmi = km.keymap_items.new('view3d.collection_manager', 'M', 'PRESS')
|
||||
addon_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)
|
||||
|
||||
if bpy.context.preferences.addons[__package__].preferences.enable_qcd:
|
||||
qcd_init.register_qcd()
|
||||
|
||||
|
@ -132,6 +149,10 @@ def unregister():
|
|||
for cls in classes:
|
||||
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)
|
||||
|
||||
del bpy.types.Scene.collection_manager
|
||||
|
||||
# remove keymaps when add-on is deactivated
|
||||
|
|
|
@ -32,6 +32,10 @@ from bpy.props import (
|
|||
IntProperty,
|
||||
)
|
||||
|
||||
move_triggered = False
|
||||
move_selection = []
|
||||
move_active = None
|
||||
|
||||
layer_collections = {}
|
||||
collection_tree = []
|
||||
collection_state = {}
|
||||
|
@ -186,6 +190,7 @@ def update_col_name(self, context):
|
|||
|
||||
self.last_name = self.name
|
||||
|
||||
|
||||
def update_qcd_slot(self, context):
|
||||
global qcd_slots
|
||||
|
||||
|
@ -357,6 +362,7 @@ def get_modifiers(event):
|
|||
|
||||
return set(modifiers)
|
||||
|
||||
|
||||
def generate_state():
|
||||
global layer_collections
|
||||
|
||||
|
@ -380,6 +386,27 @@ def generate_state():
|
|||
return state
|
||||
|
||||
|
||||
def get_move_selection():
|
||||
global move_selection
|
||||
|
||||
if not move_selection:
|
||||
move_selection = [obj.name for obj in bpy.context.selected_objects]
|
||||
|
||||
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 = getattr(bpy.context.view_layer.objects.active, "name", None)
|
||||
|
||||
if move_active not in [obj.name for obj in get_move_selection()]:
|
||||
move_active = None
|
||||
|
||||
return bpy.data.objects[move_active] if move_active else None
|
||||
|
||||
|
||||
class CMSendReport(Operator):
|
||||
bl_label = "Send Report"
|
||||
|
|
|
@ -32,12 +32,16 @@ from bpy.props import (
|
|||
IntProperty
|
||||
)
|
||||
|
||||
from . import internals
|
||||
|
||||
from .internals import (
|
||||
expanded,
|
||||
layer_collections,
|
||||
qcd_slots,
|
||||
update_property_group,
|
||||
get_modifiers,
|
||||
get_move_selection,
|
||||
get_move_active,
|
||||
send_report,
|
||||
)
|
||||
|
||||
|
@ -187,30 +191,74 @@ class CMSetCollectionOperator(Operator):
|
|||
collection_name: StringProperty()
|
||||
|
||||
def invoke(self, context, event):
|
||||
collection = layer_collections[self.collection_name]["ptr"].collection
|
||||
laycol = layer_collections[self.collection_name]
|
||||
target_collection = laycol["ptr"].collection
|
||||
|
||||
selected_objects = get_move_selection()
|
||||
active_object = get_move_active()
|
||||
|
||||
internals.move_triggered = True
|
||||
|
||||
if not selected_objects:
|
||||
return {'CANCELLED'}
|
||||
|
||||
if event.shift:
|
||||
# add object to collection
|
||||
# add objects to collection
|
||||
|
||||
# make sure there is an active object
|
||||
if not active_object:
|
||||
active_object = selected_objects[0]
|
||||
|
||||
# check if in collection
|
||||
if context.active_object.name not in collection.objects:
|
||||
if not active_object.name in target_collection.objects:
|
||||
# add to collection
|
||||
bpy.ops.object.link_to_collection(collection_index=self.collection_index)
|
||||
for obj in selected_objects:
|
||||
if obj.name not in target_collection.objects:
|
||||
target_collection.objects.link(obj)
|
||||
|
||||
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")
|
||||
errors = False
|
||||
|
||||
return {'FINISHED'}
|
||||
# remove from collections
|
||||
for obj in selected_objects:
|
||||
if obj.name in target_collection.objects:
|
||||
|
||||
# disallow removing if only one
|
||||
if len(obj.users_collection) == 1:
|
||||
errors = True
|
||||
continue
|
||||
|
||||
# remove from collection
|
||||
target_collection.objects.unlink(obj)
|
||||
|
||||
if errors:
|
||||
send_report("Error removing 1 or more objects from this collection.\nObjects would be left without a collection")
|
||||
|
||||
# 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)
|
||||
# move objects to collection
|
||||
for obj in selected_objects:
|
||||
if obj.name not in target_collection.objects:
|
||||
target_collection.objects.link(obj)
|
||||
|
||||
# remove from all other collections
|
||||
for collection in obj.users_collection:
|
||||
if collection.name != target_collection.name:
|
||||
collection.objects.unlink(obj)
|
||||
|
||||
# update the active object if needed
|
||||
if not context.active_object:
|
||||
try:
|
||||
context.view_layer.objects.active = active_object
|
||||
|
||||
except RuntimeError: # object not in visible collection
|
||||
pass
|
||||
|
||||
# update qcd header UI
|
||||
cm = bpy.context.scene.collection_manager
|
||||
cm.update_header.clear()
|
||||
new_update_header = cm.update_header.add()
|
||||
new_update_header.name = "updated"
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
|
|
@ -20,20 +20,6 @@ qcd_classes = (
|
|||
qcd_operators.RenumerateQCDSlots,
|
||||
)
|
||||
|
||||
@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
|
||||
|
||||
@persistent
|
||||
def undo_redo_post_handler(dummy):
|
||||
qcd_operators.move_selection.clear()
|
||||
qcd_operators.move_active = None
|
||||
|
||||
@persistent
|
||||
def save_internal_data(dummy):
|
||||
cm = bpy.context.scene.collection_manager
|
||||
|
@ -66,9 +52,6 @@ def register_qcd():
|
|||
kmi = km.keymap_items.new('view3d.qcd_move_widget', 'V', 'PRESS')
|
||||
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)
|
||||
|
||||
|
@ -122,9 +105,6 @@ def unregister_qcd():
|
|||
for cls in qcd_classes:
|
||||
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)
|
||||
|
||||
|
|
|
@ -30,39 +30,19 @@ from bpy.props import (
|
|||
IntProperty
|
||||
)
|
||||
|
||||
from . import internals
|
||||
|
||||
from .internals import (
|
||||
layer_collections,
|
||||
qcd_slots,
|
||||
update_property_group,
|
||||
get_modifiers,
|
||||
get_move_selection,
|
||||
get_move_active
|
||||
)
|
||||
|
||||
from .operators import rto_history
|
||||
|
||||
move_triggered = False
|
||||
move_selection = []
|
||||
move_active = None
|
||||
|
||||
def get_move_selection():
|
||||
global move_selection
|
||||
|
||||
if not move_selection:
|
||||
move_selection = [obj.name for obj in bpy.context.selected_objects]
|
||||
|
||||
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 = getattr(bpy.context.view_layer.objects.active, "name", None)
|
||||
|
||||
if move_active not in [obj.name for obj in get_move_selection()]:
|
||||
move_active = None
|
||||
|
||||
return bpy.data.objects[move_active] if move_active else None
|
||||
|
||||
|
||||
class MoveToQCDSlot(Operator):
|
||||
'''Move object(s) to QCD slot'''
|
||||
|
@ -76,11 +56,11 @@ class MoveToQCDSlot(Operator):
|
|||
def execute(self, context):
|
||||
global qcd_slots
|
||||
global layer_collections
|
||||
global move_triggered
|
||||
|
||||
selected_objects = get_move_selection()
|
||||
active_object = get_move_active()
|
||||
move_triggered = True
|
||||
internals.move_triggered = True
|
||||
|
||||
qcd_laycol = None
|
||||
slot_name = qcd_slots.get_name(self.slot)
|
||||
|
||||
|
|
|
@ -36,6 +36,8 @@ from .internals import (
|
|||
update_collection_tree,
|
||||
update_property_group,
|
||||
generate_state,
|
||||
get_move_selection,
|
||||
get_move_active
|
||||
)
|
||||
|
||||
from .operators import (
|
||||
|
@ -46,8 +48,6 @@ from .operators import (
|
|||
phantom_history,
|
||||
)
|
||||
|
||||
from . import qcd_operators
|
||||
|
||||
|
||||
preview_collections = {}
|
||||
last_icon_theme_text = None
|
||||
|
@ -353,6 +353,8 @@ class CM_UL_items(UIList):
|
|||
view_layer = context.view_layer
|
||||
laycol = layer_collections[item.name]
|
||||
collection = laycol["ptr"].collection
|
||||
selected_objects = get_move_selection()
|
||||
active_object = get_move_active()
|
||||
|
||||
split = layout.split(factor=0.96)
|
||||
row = split.row(align=True)
|
||||
|
@ -409,9 +411,13 @@ class CM_UL_items(UIList):
|
|||
|
||||
icon = 'MESH_CUBE'
|
||||
|
||||
if len(context.selected_objects) > 0 and context.active_object:
|
||||
if context.active_object.name in collection.objects:
|
||||
if selected_objects:
|
||||
if active_object and active_object.name in collection.objects:
|
||||
icon = 'SNAP_VOLUME'
|
||||
|
||||
elif not set(selected_objects).isdisjoint(collection.objects):
|
||||
icon = 'STICKY_UVS_LOC'
|
||||
|
||||
else:
|
||||
row_setcol.enabled = False
|
||||
|
||||
|
@ -588,8 +594,8 @@ def view3d_header_qcd_slots(self, context):
|
|||
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()
|
||||
selected_objects = get_move_selection()
|
||||
active_object = get_move_active()
|
||||
|
||||
icon_value = 0
|
||||
|
||||
|
|
Loading…
Reference in New Issue