From cf28577e2537fd40b002887307cad6508324a1ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Thu, 8 Feb 2018 10:45:57 +0100 Subject: Bone Selection Sets: added copy & paste of individual Selection Sets The copied Selection Set is stored as JSON document on the clipboard, like `{"name": "SelectionSet", "bones": ["Bone", "Bone.001"]}` Using JSON allows the animator to copy/paste selection sets through text- based communication channels (IRC, email, bug reports, etc.) When pasting, a new Selection Set is always made, regardless of whether one with the same name already exists. --- bone_selection_sets.py | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) (limited to 'bone_selection_sets.py') diff --git a/bone_selection_sets.py b/bone_selection_sets.py index a811a068..015bb3f9 100644 --- a/bone_selection_sets.py +++ b/bone_selection_sets.py @@ -68,6 +68,8 @@ class POSE_MT_selection_sets_specials(Menu): layout.operator("pose.selection_set_delete_all", icon='X') layout.operator("pose.selection_set_remove_bones", icon='X') + layout.operator("pose.selection_set_copy", icon='COPYDOWN') + layout.operator("pose.selection_set_paste", icon='PASTEDOWN') class POSE_PT_selection_sets(Panel): @@ -400,6 +402,38 @@ class POSE_OT_selection_set_add_and_assign(PluginOperator): return {'FINISHED'} +class POSE_OT_selection_set_copy(NeedSelSetPluginOperator): + bl_idname = "pose.selection_set_copy" + bl_label = "Copy Selection Set to Clipboard" + bl_description = "Converts the Selection Set to JSON and places it on the clipboard" + bl_options = {'UNDO', 'REGISTER'} + + def execute(self, context): + context.window_manager.clipboard = to_json(context) + self.report({'INFO'}, 'Copied Selection Set to Clipboard') + return {'FINISHED'} + + +class POSE_OT_selection_set_paste(PluginOperator): + bl_idname = "pose.selection_set_paste" + bl_label = "Paste Selection Set from Clipboard" + bl_description = "Adds a new Selection Set from copied JSON on the clipboard" + bl_options = {'UNDO', 'REGISTER'} + + def execute(self, context): + import json + + try: + from_json(context, context.window_manager.clipboard) + except (json.JSONDecodeError, KeyError): + self.report({'ERROR'}, 'The clipboard does not contain a Selection Set') + else: + # Select the pasted Selection Set. + context.object.active_selection_set = len(context.object.selection_sets) - 1 + + return {'FINISHED'} + + # Registry #################################################################### classes = ( @@ -420,6 +454,8 @@ classes = ( POSE_OT_selection_set_select, POSE_OT_selection_set_deselect, POSE_OT_selection_set_add_and_assign, + POSE_OT_selection_set_copy, + POSE_OT_selection_set_paste, ) @@ -427,6 +463,34 @@ def add_sss_button(self, context): self.layout.menu('POSE_MT_selection_sets') +def to_json(context) -> str: + """Convert the active bone selection set of the current rig to JSON.""" + import json + + arm = context.object + active_idx = arm.active_selection_set + sel_set = arm.selection_sets[active_idx] + + return json.dumps({ + 'name': sel_set.name, + 'bones': [bone_id.name for bone_id in sel_set.bone_ids] + }) + + +def from_json(context, as_json: str): + """Add the single bone selection set from JSON to the current rig.""" + import json + + sel_set = json.loads(as_json) + + new_sel_set = context.object.selection_sets.add() + new_sel_set.name = sel_set['name'] + + for bone_name in sel_set['bones']: + bone_id = new_sel_set.bone_ids.add() + bone_id.name = bone_name + + def register(): for cls in classes: bpy.utils.register_class(cls) -- cgit v1.2.3