18 Commits

Author SHA1 Message Date
3ebf0184ee Few more readme details 2025-01-13 17:34:55 -06:00
23ffed939a Rename project to Yet Another Pose Library (for now) 2025-01-13 16:03:46 -06:00
21f2278990 Use words_separated instead of mixedCase for common functions 2025-01-13 15:50:03 -06:00
cb3999de33 Correct tooltip text 2025-01-02 23:21:46 -06:00
5f0a4c93c2 Merge pull request 'Use Object.pose_library instead of Object.dspl.pose_library' (#14) from pose-library-prop into develop
Reviewed-on: #14
2025-01-02 21:38:24 -06:00
efd8acd9a9 Filter for Pose Libraries only 2025-01-02 21:37:09 -06:00
e9d33b7f87 Unify calls to armature and pose library 2025-01-02 21:37:09 -06:00
d008e4750c Use Object.pose_library instead of Object.dspl.pose_library 2025-01-02 21:37:09 -06:00
b2fc121a88 Enable "new" menu by default 2025-01-02 21:35:55 -06:00
a4abb41c73 Merge pull request 'Credits and readme update' (#16) from credits into develop
Reviewed-on: #16
2025-01-02 21:31:37 -06:00
8f936ec085 Credits and readme update 2025-01-02 21:30:58 -06:00
edeaa12f5e Merge pull request 'Remove dsplvars' (#13) from cleanup into develop
Reviewed-on: #13
2024-12-28 04:16:24 -06:00
b6bfb2db00 Remove dsplvars 2024-12-28 04:13:34 -06:00
fecc9d6be5 Merge pull request 'Clean up old button handler' (#12) from cleanup into develop
Reviewed-on: #12
2024-12-28 03:54:31 -06:00
4930b15046 Clean up old button handler 2024-12-28 03:53:50 -06:00
7c9bd136d8 Merge pull request 'Fix rename invoke' (#11) from quick-rename into develop
Reviewed-on: #11
2024-12-28 03:52:17 -06:00
6b1f215517 Fix rename invoke 2024-12-28 03:50:32 -06:00
0d2d51ac74 Merge pull request 'Remove menu handler and refactor add/replace menu' (#8) from add-replace-menu into develop
Reviewed-on: #8
2024-12-28 01:42:03 -06:00
6 changed files with 331 additions and 368 deletions

View File

@ -1,6 +1,63 @@
# Damn Simple Pose Library # Yet Another Pose Library
In Blender 3.x, a new Asset-based Pose system was introduced. For Blender 3.5 - 4.3 (4.1 recommended).
That's fine and dandy, however because of that, the old Pose Library was deprecated and gutted out real quick-like. Too quick.
This brings it back as best as it can. During the Blender 3.x releases, a new Asset-based Pose system was introduced. That's fine and dandy, but it was not (and still is not as of Jan 2025) ready to replace the old Action-based Pose Library system. The former Pose Library was quickly deprecated and removed, leaving legacy users high and dry.
This addon brings the Legacy Pose Library back as best as it can in a modern panel, and tries to stick as close to the old system as possible. Most, if not all existing Pose Libraries should work without any modifications. Little new is introduced outside of UI enhancements and handling for new data.
These excellent addons also address this removal in their own ways, check them out:
- [Sakura Poselib](https://github.com/kafuji/Sakura_Poselib)
- [gret](https://github.com/greisane/gret?tab=readme-ov-file#animation-actions-panel)
- [Amarillo's Pose Library](https://github.com/AmarilloArts/Amarillos-Pose-Library)
## Old Features
- The Pose Library list panel is ported from Armature Data Properties to a Sidebar (N) panel.
- Operators and data property [that were removed in 3.5](https://projects.blender.org/blender/blender/issues/93406) are ported from C to Python:
- `yapl.apply_pose`
- `yapl.browse_poses`
- `yapl.create_pose_library`
- `yapl.convert_pose_library`
- `yapl.add_pose`
- `yapl.move_pose`
- `yapl.remove_pose`
- `yapl.rename_pose`
- `yapl.unlink_pose_library`
- `Object.pose_library`
## New Features
- New panel interface for interacting with pose libraries, inspired by [gret's Actions Panel feature](https://github.com/greisane/gret?tab=readme-ov-file#animation-actions-panel).
- Hover over buttons for tooltips
- Operator to protect potentially-orphaned pose data (read Considerations)
- `yapl.protect_orphan_pose_library`
## Installation
1. [Download the repository as a zip](https://git.bkspl.me/breakingspell/YetAnotherPoseLibrary/archive/develop.zip), or otherwise clone the repository.
2. Install as an Add-on in Blender via Install -> Zip, and enable.
3. Optionally configure the suffix strings to fit your workflow, and whether the orhpan checker should run at startup.
## Usage
1. Open Sidebar (`N`), and choose the `Pose` tab.
2. Select an Armature Object, or an Object parented to an Armature.
3. Select existing Pose Library from drop-down, or create a new library.
### 3D View Hotkeys:
- `Shift + L` - Add/Replace Pose
- `Alt + L` - Browse Poses with Arrow Keys
### New Panel Controls
- `Single click` - Apply Pose
- `Shift + Click` - Rename Pose
- `Alt + Click` - Remove Pose
- `Ctrl + Click ` - Select Pose
- Choose `Edit` for fast Move/Rename/Removal
## Considerations
- Opening older scenes will cause existing Pose Libraries to unlink from their former targets and fall into orphan state. They can be re-linked and will retain their link when saved afterwards, but would otherwise disappear if saved without linking or protecting the datablock.
- This is due to the core DNA type `poselib` having been removed, so objects will drop the data. [There is no way to prevent this](https://developer.blender.org/docs/features/core/rna/#internals) as Python ID properties cannot be present at program runtime, only once the add-on is initialized.
- To mitgate, an operator is provided to protect orphaned pose libraries: `yapl.protect_orphan_pose_library`.
- This add-on was made much easier by the `pose_markers` property being retained for converting old pose libraries to the new asset system. If they decide to remove that property as well, there will be a need to improvise an index-based lookup.

View File

@ -2,11 +2,11 @@ import bpy
from . import gui, operators, common, keymaps from . import gui, operators, common, keymaps
bl_info = \ bl_info = \
{ {
"name": "Damn Simple Pose Library", "name": "Yet Another Pose Library",
"author": "jackie", "author": "breakingspell",
"version": (4, 1, 0), "version": (0, 1, 0),
"blender": (3, 5, 0), "blender": (3, 6, 0),
"description": "woah", "description": "Re-implement 3.x legacy Pose Library",
"category": "Object Data", "category": "Object Data",
} }
@ -22,63 +22,40 @@ if _need_reload:
operators = importlib.reload(operators) operators = importlib.reload(operators)
class dsplObj(bpy.types.PropertyGroup): class yaplSettings(bpy.types.PropertyGroup):
pose_library: bpy.props.PointerProperty(
name="Active Pose Library", description="",
override={'LIBRARY_OVERRIDABLE'}, type=bpy.types.Action)
# update = common.poselib_update)
# , update = anim_layers.layer_name_update
class dsplVars(bpy.types.PropertyGroup):
pose_index: bpy.props.IntProperty(
name="Pose Index", description="", override={'LIBRARY_OVERRIDABLE'})
pose_new_name: bpy.props.StringProperty(
name="Pose Name", description="New name for pose",
default="Pose", override={'LIBRARY_OVERRIDABLE'})
numero: bpy.props.IntProperty(
name='Numero', default=666, override={'LIBRARY_OVERRIDABLE'})
class dsplSettings(bpy.types.PropertyGroup):
new_menu: bpy.props.BoolProperty( new_menu: bpy.props.BoolProperty(
name="New Menu", description="Toggle New Menu", default=False) name="New Menu", description="Toggle New Menu", default=True)
edit_mode: bpy.props.BoolProperty( edit_mode: bpy.props.BoolProperty(
name="Edit Mode", description="Toggle Edit Mode", default=False) name="Edit Mode", description="Toggle Edit Mode", default=False)
classes = (dsplObj, dsplVars, dsplSettings) classes = yaplSettings
def pose_libraries_poll(self, action):
if getattr(action, "pose_markers", None):
return True
def register(): def register():
from bpy.utils import register_class from bpy.utils import register_class
for cls in classes: register_class(yaplSettings)
register_class(cls)
# bpy.types.Armature.pose_library = bpy.props.PointerProperty( bpy.types.Object.pose_library = bpy.props.PointerProperty(
# type=dsplObj, override={'LIBRARY_OVERRIDABLE'}) name="Active Pose Library", description="",
type=bpy.types.Action, override={'LIBRARY_OVERRIDABLE'},
poll=pose_libraries_poll)
# bpy.types.Object.pose_library = bpy.props.PointerProperty( bpy.types.Scene.yaplSettings = bpy.props.PointerProperty(
# type=bpy.types.Action, options={'LIBRARY_EDITABLE'}, override={'LIBRARY_OVERRIDABLE'}) type=yaplSettings, override={'LIBRARY_OVERRIDABLE'})
bpy.types.Object.dspl = bpy.props.PointerProperty(
type=dsplObj, override={'LIBRARY_OVERRIDABLE'})
bpy.types.Object.dsplvars = bpy.props.PointerProperty(
type=dsplVars, override={'LIBRARY_OVERRIDABLE'})
bpy.types.Scene.dsplSettings = bpy.props.PointerProperty(
type=dsplSettings, override={'LIBRARY_OVERRIDABLE'})
gui.register() gui.register()
operators.register() operators.register()
keymaps.register() keymaps.register()
def unregister() -> None: def unregister():
from bpy.utils import unregister_class from bpy.utils import unregister_class
for cls in classes: unregister_class(yaplSettings)
unregister_class(cls)
del bpy.types.Object.dspl del bpy.types.Scene.yaplSettings
del bpy.types.Object.dsplvars del bpy.types.Object.pose_library
del bpy.types.Scene.dsplSettings
keymaps.unregister() keymaps.unregister()
operators.unregister() operators.unregister()

177
common.py
View File

@ -2,51 +2,31 @@ import bpy
import mathutils import mathutils
def getArmatureObject(context): def get_armature_data(context):
obj = context.active_object try:
if obj: arm_object = context.active_object
if obj.type == "ARMATURE": if arm_object and arm_object.type == "ARMATURE":
return obj return arm_object, getattr(arm_object, "pose_library", None)
elif obj.parent is not None and obj.parent.type == "ARMATURE": elif arm_object and arm_object.parent and arm_object.parent.type == "ARMATURE":
return obj.parent return arm_object.parent, getattr(arm_object.parent, "pose_library", None)
else: else:
return None return None, None
except:
return None, None
def getLegacyPoseLibrary(context): def get_armature_action(context):
arm = getArmatureObject(context)
return getattr(arm, "pose_library", None)
def getArmatureAction(context):
arm = getArmatureObject(context)
return getattr(arm.animation_data, "action", None)
def getDsplAction(context):
arm = getArmatureObject(context)
return getattr(arm.dspl, "pose_library", None)
def getPoseLib(context):
arm = getArmatureObject(context)
pose_library_dspl = getDsplAction(context)
pose_library_action = getArmatureAction(context)
pose_library_legacy = getLegacyPoseLibrary(context)
if pose_library_dspl:
return pose_library_dspl
elif pose_library_action and not pose_library_dspl:
return pose_library_action
elif pose_library_legacy and not pose_library_dspl:
return pose_library_legacy
else:
return None
def searchPoseMarker(context, posename, type):
try: try:
pose_library = getPoseLib(context) arm_object, pose_library = get_armature_data(context)
if getattr(arm_object.animation_data.action, "pose_markers", None):
return getattr(arm_object.animation_data, "action", None)
except:
pass
def search_pose_marker(context, posename, type):
try:
arm_object, pose_library = get_armature_data(context)
if type == "marker": if type == "marker":
return pose_library.pose_markers.get(posename, None) return pose_library.pose_markers.get(posename, None)
if type == "frame": if type == "frame":
@ -57,13 +37,12 @@ def searchPoseMarker(context, posename, type):
pass pass
def findFcurve(context, bone_name, transform, index_int): def find_fcurve(context, bone_name, transform, index_int):
arm_object = getArmatureObject(context) arm_object, pose_library = get_armature_data(context)
action_object = getPoseLib(context) pose_markers = pose_library.pose_markers
pose_markers = action_object.pose_markers
active_frame = pose_markers.active.frame active_frame = pose_markers.active.frame
fcurve_object = action_object.fcurves.find( fcurve_object = pose_library.fcurves.find(
'pose.bones["'+bone_name+'"].'+transform+'', index=index_int) 'pose.bones["'+bone_name+'"].'+transform+'', index=index_int)
if hasattr(fcurve_object, 'evaluate'): if hasattr(fcurve_object, 'evaluate'):
return fcurve_object.evaluate(active_frame) return fcurve_object.evaluate(active_frame)
@ -71,33 +50,31 @@ def findFcurve(context, bone_name, transform, index_int):
return None return None
def createFcurve(context, bone_name, transform, index_int): def create_fcurve(context, bone_name, transform, index_int):
arm_object = getArmatureObject(context) arm_object, pose_library = get_armature_data(context)
action_object = getPoseLib(context) pose_markers = pose_library.pose_markers
pose_markers = action_object.pose_markers
try: try:
action_object.fcurves.new( pose_library.fcurves.new(
'pose.bones["'+bone_name+'"].'+transform+'', index=index_int, action_group=bone_name) 'pose.bones["'+bone_name+'"].'+transform+'', index=index_int, action_group=bone_name)
return return
except: except:
pass pass
def createKeyframe(context, bone_name, transform, index_int, new_marker, loc): def create_keyframe(context, bone_name, transform, index_int, new_marker, loc):
arm_object = getArmatureObject(context) arm_object, pose_library = get_armature_data(context)
action_object = getPoseLib(context) pose_markers = pose_library.pose_markers
pose_markers = action_object.pose_markers
try: try:
action_object.fcurves.find( pose_library.fcurves.find(
'pose.bones["'+bone_name+'"].'+transform+'', index=index_int).keyframe_points.insert(new_marker, loc) 'pose.bones["'+bone_name+'"].'+transform+'', index=index_int).keyframe_points.insert(new_marker, loc)
return return
except: except:
pass pass
def setKeyframesFromBones(context, arm_object, new_marker): def set_keyframes_from_bones(context, arm_object, new_marker):
none_selected = True none_selected = True
for bone in arm_object.pose.bones: for bone in arm_object.pose.bones:
if bone.bone.select: if bone.bone.select:
@ -116,53 +93,53 @@ def setKeyframesFromBones(context, arm_object, new_marker):
elif bone.rotation_mode == "QUATERNION": elif bone.rotation_mode == "QUATERNION":
rot_mode = "rotation_quaternion" rot_mode = "rotation_quaternion"
else: else:
self.report({'WARNING'}, "DSPL: Unsupported bone: " + bone.name + ": " + bone.rotation_mode) self.report({'WARNING'}, "YAPL: Unsupported bone: " + bone.name + ": " + bone.rotation_mode)
rot_mode = None rot_mode = None
loc_x = bone.location[0] loc_x = bone.location[0]
loc_y = bone.location[1] loc_y = bone.location[1]
loc_z = bone.location[2] loc_z = bone.location[2]
createFcurve(context, bone_name, "location", 0) create_fcurve(context, bone_name, "location", 0)
createFcurve(context, bone_name, "location", 1) create_fcurve(context, bone_name, "location", 1)
createFcurve(context, bone_name, "location", 2) create_fcurve(context, bone_name, "location", 2)
createKeyframe(context, bone_name, "location", 0, new_marker, loc_x) create_keyframe(context, bone_name, "location", 0, new_marker, loc_x)
createKeyframe(context, bone_name, "location", 1, new_marker, loc_y) create_keyframe(context, bone_name, "location", 1, new_marker, loc_y)
createKeyframe(context, bone_name, "location", 2, new_marker, loc_z) create_keyframe(context, bone_name, "location", 2, new_marker, loc_z)
if rot_mode == "rotation_quaternion": if rot_mode == "rotation_quaternion":
rot_w = bone.rotation_quaternion[0] rot_w = bone.rotation_quaternion[0]
rot_x = bone.rotation_quaternion[1] rot_x = bone.rotation_quaternion[1]
rot_y = bone.rotation_quaternion[2] rot_y = bone.rotation_quaternion[2]
rot_z = bone.rotation_quaternion[3] rot_z = bone.rotation_quaternion[3]
createFcurve(context, bone_name, rot_mode, 0) create_fcurve(context, bone_name, rot_mode, 0)
createFcurve(context, bone_name, rot_mode, 1) create_fcurve(context, bone_name, rot_mode, 1)
createFcurve(context, bone_name, rot_mode, 2) create_fcurve(context, bone_name, rot_mode, 2)
createFcurve(context, bone_name, rot_mode, 3) create_fcurve(context, bone_name, rot_mode, 3)
createKeyframe(context, bone_name, rot_mode, 0, new_marker, rot_w) create_keyframe(context, bone_name, rot_mode, 0, new_marker, rot_w)
createKeyframe(context, bone_name, rot_mode, 1, new_marker, rot_x) create_keyframe(context, bone_name, rot_mode, 1, new_marker, rot_x)
createKeyframe(context, bone_name, rot_mode, 2, new_marker, rot_y) create_keyframe(context, bone_name, rot_mode, 2, new_marker, rot_y)
createKeyframe(context, bone_name, rot_mode, 3, new_marker, rot_z) create_keyframe(context, bone_name, rot_mode, 3, new_marker, rot_z)
elif rot_mode == "rotation_euler": elif rot_mode == "rotation_euler":
rot_x = bone.rotation_euler[0] rot_x = bone.rotation_euler[0]
rot_y = bone.rotation_euler[1] rot_y = bone.rotation_euler[1]
rot_z = bone.rotation_euler[2] rot_z = bone.rotation_euler[2]
createFcurve(context, bone_name, rot_mode, 0) create_fcurve(context, bone_name, rot_mode, 0)
createFcurve(context, bone_name, rot_mode, 1) create_fcurve(context, bone_name, rot_mode, 1)
createFcurve(context, bone_name, rot_mode, 2) create_fcurve(context, bone_name, rot_mode, 2)
createKeyframe(context, bone_name, rot_mode, 0, new_marker, rot_x) create_keyframe(context, bone_name, rot_mode, 0, new_marker, rot_x)
createKeyframe(context, bone_name, rot_mode, 1, new_marker, rot_y) create_keyframe(context, bone_name, rot_mode, 1, new_marker, rot_y)
createKeyframe(context, bone_name, rot_mode, 2, new_marker, rot_z) create_keyframe(context, bone_name, rot_mode, 2, new_marker, rot_z)
scl_x = bone.scale[0] scl_x = bone.scale[0]
scl_y = bone.scale[1] scl_y = bone.scale[1]
scl_z = bone.scale[2] scl_z = bone.scale[2]
createFcurve(context, bone_name, "scale", 0) create_fcurve(context, bone_name, "scale", 0)
createFcurve(context, bone_name, "scale", 1) create_fcurve(context, bone_name, "scale", 1)
createFcurve(context, bone_name, "scale", 2) create_fcurve(context, bone_name, "scale", 2)
createKeyframe(context, bone_name, "scale", 0, new_marker, scl_x) create_keyframe(context, bone_name, "scale", 0, new_marker, scl_x)
createKeyframe(context, bone_name, "scale", 1, new_marker, scl_y) create_keyframe(context, bone_name, "scale", 1, new_marker, scl_y)
createKeyframe(context, bone_name, "scale", 2, new_marker, scl_z) create_keyframe(context, bone_name, "scale", 2, new_marker, scl_z)
def setBonesfromKeyframes(context, arm_object, active_marker): def set_bones_from_keyframes(context, arm_object, active_marker):
none_selected = True none_selected = True
for bone in arm_object.pose.bones: for bone in arm_object.pose.bones:
if bone.bone.select: if bone.bone.select:
@ -181,24 +158,24 @@ def setBonesfromKeyframes(context, arm_object, active_marker):
elif bone.rotation_mode == "QUATERNION": elif bone.rotation_mode == "QUATERNION":
rot_mode = "rotation_quaternion" rot_mode = "rotation_quaternion"
else: else:
self.report({'WARNING'}, "DSPL: Unsupported bone: " + bone.name + ": " + bone.rotation_mode) self.report({'WARNING'}, "YAPL: Unsupported bone: " + bone.name + ": " + bone.rotation_mode)
rot_mode = None rot_mode = None
loc_x = findFcurve(context, bone_name, "location", 0) or 0.0 loc_x = find_fcurve(context, bone_name, "location", 0) or 0.0
loc_y = findFcurve(context, bone_name, "location", 1) or 0.0 loc_y = find_fcurve(context, bone_name, "location", 1) or 0.0
loc_z = findFcurve(context, bone_name, "location", 2) or 0.0 loc_z = find_fcurve(context, bone_name, "location", 2) or 0.0
if rot_mode == "rotation_quaternion": if rot_mode == "rotation_quaternion":
rot_w = findFcurve(context, bone_name, rot_mode, 0) or 1.0 rot_w = find_fcurve(context, bone_name, rot_mode, 0) or 1.0
rot_x = findFcurve(context, bone_name, rot_mode, 1) or 0.0 rot_x = find_fcurve(context, bone_name, rot_mode, 1) or 0.0
rot_y = findFcurve(context, bone_name, rot_mode, 2) or 0.0 rot_y = find_fcurve(context, bone_name, rot_mode, 2) or 0.0
rot_z = findFcurve(context, bone_name, rot_mode, 3) or 0.0 rot_z = find_fcurve(context, bone_name, rot_mode, 3) or 0.0
elif rot_mode == "rotation_euler": elif rot_mode == "rotation_euler":
rot_x = findFcurve(context, bone_name, rot_mode, 0) or 0.0 rot_x = find_fcurve(context, bone_name, rot_mode, 0) or 0.0
rot_y = findFcurve(context, bone_name, rot_mode, 1) or 0.0 rot_y = find_fcurve(context, bone_name, rot_mode, 1) or 0.0
rot_z = findFcurve(context, bone_name, rot_mode, 2) or 0.0 rot_z = find_fcurve(context, bone_name, rot_mode, 2) or 0.0
scl_x = findFcurve(context, bone_name, "scale", 0) or 1.0 scl_x = find_fcurve(context, bone_name, "scale", 0) or 1.0
scl_y = findFcurve(context, bone_name, "scale", 1) or 1.0 scl_y = find_fcurve(context, bone_name, "scale", 1) or 1.0
scl_z = findFcurve(context, bone_name, "scale", 2) or 1.0 scl_z = find_fcurve(context, bone_name, "scale", 2) or 1.0
bone.location = mathutils.Vector((loc_x, loc_y, loc_z)) bone.location = mathutils.Vector((loc_x, loc_y, loc_z))
if bone.rotation_mode == "XYZ": if bone.rotation_mode == "XYZ":

129
gui.py
View File

@ -2,9 +2,9 @@ import bpy
from .common import * from .common import *
class DATA_PT_DSPLPanel(bpy.types.Panel): class DATA_PT_YaplPanel(bpy.types.Panel):
bl_label = "Damn Simple Pose Library" bl_label = "Yet Another Pose Library"
bl_id = "DATA_PT_DSPLPanel" bl_id = "DATA_PT_YaplPanel"
bl_space_type = 'VIEW_3D' bl_space_type = 'VIEW_3D'
bl_region_type = 'UI' bl_region_type = 'UI'
bl_category = 'Pose' bl_category = 'Pose'
@ -14,13 +14,14 @@ class DATA_PT_DSPLPanel(bpy.types.Panel):
return len(bpy.context.selected_objects) return len(bpy.context.selected_objects)
def draw(self, context): def draw(self, context):
dspl_panel_layout = self.layout yapl_panel_layout = self.layout
dsplsettings = bpy.context.scene.dsplSettings yaplsettings = bpy.context.scene.yaplSettings
# Detect Armature object and parent # Detect Armature object and parent
armature_layout = dspl_panel_layout.column(align=True) armature_layout = yapl_panel_layout.column(align=True)
active_obj = context.active_object active_obj = context.active_object
arm_object = getArmatureObject(context) arm_object, pose_library = get_armature_data(context)
pose_library_action = get_armature_action(context)
if arm_object: if arm_object:
if arm_object == active_obj: if arm_object == active_obj:
@ -29,119 +30,113 @@ class DATA_PT_DSPLPanel(bpy.types.Panel):
armature_layout.label(text=arm_object.name + " (Parent)") armature_layout.label(text=arm_object.name + " (Parent)")
# Attach or create pose library # Attach or create pose library
pose_library_dspl = getDsplAction(context) if pose_library or pose_library_action:
pose_library_action = getArmatureAction(context) if pose_library and not pose_library_action:
if pose_library_dspl or pose_library_action:
if pose_library_dspl and not pose_library_action:
active_pose_library = pose_library_dspl
armature_layout.template_ID( armature_layout.template_ID(
arm_object.dspl, "pose_library", new="dspl.create_pose_library", unlink="dspl.unlink_pose_library") arm_object, "pose_library", new="yapl.create_pose_library", unlink="yapl.unlink_pose_library")
elif pose_library_action and not pose_library_dspl: elif pose_library_action and not pose_library:
active_pose_library = pose_library_action
armature_layout.template_ID( armature_layout.template_ID(
arm_object.animation_data, "action", new="dspl.create_pose_library") arm_object.animation_data, "action", new="yapl.create_pose_library")
armature_layout.label( armature_layout.label(
text="Legacy Pose Library detected.") text="Pose Library detected as Action")
armature_layout.label( armature_layout.label(
text="You may convert to avoid problems") text="You should convert to avoid problems")
armature_layout.operator( armature_layout.operator(
"dspl.convert_pose_library", icon='PLUGIN', text="Convert to DSPL") "yapl.convert_pose_library", icon='PLUGIN', text="Convert to Pose Library")
elif pose_library_action and pose_library_dspl: elif pose_library and pose_library_action:
armature_layout.template_ID( armature_layout.template_ID(
arm_object.dspl, "pose_library", new="dspl.create_pose_library") arm_object, "pose_library", new="yapl.create_pose_library")
armature_layout.label(text="Double pose configuration!!") armature_layout.label(text="Pose Library is opened as Action")
armature_layout.label(text="You should not proceed") armature_layout.label(text="Keyframes will affect pose")
armature_layout.operator( armature_layout.operator(
"dspl.convert_pose_library", icon='PLUGIN', text="Convert to DSPL") "yapl.convert_pose_library", icon='PLUGIN', text="Unlink from Action")
active_pose_library = pose_library_dspl
# List poses in pose library # List poses in pose library
if active_pose_library: if pose_library:
pose_box_layout = dspl_panel_layout.column() pose_box_layout = yapl_panel_layout.column()
# Menu switcher # Menu switcher
pose_box_menu_switcher_layout = pose_box_layout.row() pose_box_menu_switcher_layout = pose_box_layout.row()
pose_box_menu_switcher_layout.prop( pose_box_menu_switcher_layout.prop(
dsplsettings, "new_menu", icon='PMARKER_ACT', text="New Menu", toggle=True) yaplsettings, "new_menu", icon='PMARKER_ACT', text="New Menu", toggle=True)
# Quick controls # Quick controls
quick_pose_controls_layout = pose_box_layout.column() quick_pose_controls_layout = pose_box_layout.column()
quick_pose_controls_layout.menu( quick_pose_controls_layout.menu(
OBJECT_MT_AddPoseMenu.bl_idname, icon='ADD', text="New Pose") OBJECT_MT_AddPoseMenu.bl_idname, icon='ADD', text="New Pose")
if active_pose_library.pose_markers.active: if pose_library.pose_markers.active:
quick_apply_layout = quick_pose_controls_layout.split( quick_apply_layout = quick_pose_controls_layout.split(
align=True) align=True)
quick_apply_layout.operator( quick_apply_layout.operator(
"dspl.browse_poses", icon='CON_ARMATURE', text="Browse") "yapl.browse_poses", icon='CON_ARMATURE', text="Browse")
if dsplsettings.new_menu == False: if yaplsettings.new_menu == False:
quick_apply_layout.operator( quick_apply_layout.operator(
"dspl.apply_pose", icon='ARMATURE_DATA', text="Apply Pose").posename = active_pose_library.pose_markers.active.name "yapl.apply_pose", icon='ARMATURE_DATA', text="Apply Pose").posename = pose_library.pose_markers.active.name
else: else:
quick_apply_layout.prop(dsplsettings, quick_apply_layout.prop(yaplsettings,
"edit_mode", icon='GREASEPENCIL', text="Edit", toggle=True) "edit_mode", icon='GREASEPENCIL', text="Edit", toggle=True)
# New menu # New menu
if dsplsettings.new_menu == True: if yaplsettings.new_menu == True:
pose_button_layout = pose_box_layout.row() pose_button_layout = pose_box_layout.row()
pose_button_entries_layout = pose_button_layout.column(align=True) pose_button_entries_layout = pose_button_layout.column(align=True)
for pm in active_pose_library.pose_markers: for pm in pose_library.pose_markers:
row = pose_button_entries_layout.row(align=True) row = pose_button_entries_layout.row(align=True)
# Selected indicator # Selected indicator
selected = pm.frame == active_pose_library.pose_markers.active.frame selected = pm.frame == pose_library.pose_markers.active.frame
if dsplsettings.edit_mode == False: if yaplsettings.edit_mode == False:
row.label(text="", icon='PMARKER_ACT' if selected else 'PMARKER_SEL') row.label(text="", icon='PMARKER_ACT' if selected else 'PMARKER_SEL')
# Pose operator buttons # Pose operator buttons
if dsplsettings.edit_mode == True: if yaplsettings.edit_mode == True:
row.operator('dspl.rename_pose', text=pm.name).posename = pm.name row.operator('yapl.rename_pose', text=pm.name).posename = pm.name
else: else:
row.operator('dspl.apply_pose', text=pm.name).posename = pm.name row.operator('yapl.apply_pose', text=pm.name).posename = pm.name
if dsplsettings.edit_mode == True: if yaplsettings.edit_mode == True:
movebuttondown = row.operator("dspl.move_pose", icon='TRIA_DOWN', text="") movebuttondown = row.operator("yapl.move_pose", icon='TRIA_DOWN', text="")
movebuttondown.direction = "DOWN" movebuttondown.direction = "DOWN"
movebuttondown.posename = pm.name movebuttondown.posename = pm.name
movebuttonup = row.operator("dspl.move_pose", icon='TRIA_UP', text="") movebuttonup = row.operator("yapl.move_pose", icon='TRIA_UP', text="")
movebuttonup.direction = "UP" movebuttonup.direction = "UP"
movebuttonup.posename = pm.name movebuttonup.posename = pm.name
row.operator("dspl.remove_pose", icon='REMOVE', text="").posename = pm.name row.operator("yapl.remove_pose", icon='REMOVE', text="").posename = pm.name
# Old menu # Old menu
elif dsplsettings.new_menu == False: elif yaplsettings.new_menu == False:
pose_list_layout = pose_box_layout.column() pose_list_layout = pose_box_layout.column()
# Pose list # Pose list
pose_list_entries_layout = pose_list_layout.row() pose_list_entries_layout = pose_list_layout.row()
pose_list_entries_layout.template_list("UI_UL_list","pose_markers", pose_list_entries_layout.template_list("UI_UL_list","pose_markers",
active_pose_library, "pose_markers", pose_library, "pose_markers",
active_pose_library.pose_markers, "active_index", rows=4) pose_library.pose_markers, "active_index", rows=4)
# Pose operators # Pose operators
pose_ops_layout = pose_list_entries_layout.column(align=True) pose_ops_layout = pose_list_entries_layout.column(align=True)
pose_ops_layout.operator( pose_ops_layout.operator(
"wm.call_menu", icon='ADD', text="").name = "OBJECT_MT_AddPoseMenu" "wm.call_menu", icon='ADD', text="").name = "OBJECT_MT_AddPoseMenu"
if active_pose_library.pose_markers.active: if pose_library.pose_markers.active:
pose_ops_layout.operator( pose_ops_layout.operator(
"dspl.remove_pose", icon='REMOVE', text="") "yapl.remove_pose", icon='REMOVE', text="")
pose_ops_layout.operator( pose_ops_layout.operator(
"dspl.apply_pose", icon='ARMATURE_DATA', text="" "yapl.apply_pose", icon='ARMATURE_DATA', text=""
).posename = active_pose_library.pose_markers.active.name ).posename = pose_library.pose_markers.active.name
pose_ops_layout.operator( pose_ops_layout.operator(
"dspl.move_pose", icon='TRIA_UP', text="").direction = "UP" "yapl.move_pose", icon='TRIA_UP', text="").direction = "UP"
pose_ops_layout.operator( pose_ops_layout.operator(
"dspl.move_pose", icon='TRIA_DOWN', text="").direction = "DOWN" "yapl.move_pose", icon='TRIA_DOWN', text="").direction = "DOWN"
else: else:
armature_layout.label( armature_layout.label(
text="No Action or Pose Library detected") text="No Action or Pose Library detected")
armature_layout.template_ID( armature_layout.template_ID(
arm_object.dspl, "pose_library", new="dspl.create_pose_library") arm_object, "pose_library", new="yapl.create_pose_library")
else: else:
armature_layout.label(text="No armature or parent selected") armature_layout.label(text="No armature or parent selected")
@ -152,14 +147,13 @@ class OBJECT_MT_AddPoseMenu(bpy.types.Menu):
bl_label = "Add Pose" bl_label = "Add Pose"
def draw(self, context): def draw(self, context):
arm_object = getArmatureObject(context) arm_object, pose_library = get_armature_data(context)
action_object = getPoseLib(context)
dspl_add_menu_layout = self.layout yapl_add_menu_layout = self.layout
dspl_add_menu_layout.operator( yapl_add_menu_layout.operator(
"dspl.add_pose", icon='ADD', text="Add New Pose").posename = arm_object.dsplvars.pose_new_name "yapl.add_pose", icon='ADD', text="Add New Pose")
if len(action_object.pose_markers): if len(pose_library.pose_markers):
dspl_add_menu_layout.menu( yapl_add_menu_layout.menu(
"OBJECT_MT_ReplacePoseMenu", text="Replace Existing Pose", icon="DECORATE_OVERRIDE") "OBJECT_MT_ReplacePoseMenu", text="Replace Existing Pose", icon="DECORATE_OVERRIDE")
@ -168,18 +162,17 @@ class OBJECT_MT_ReplacePoseMenu(bpy.types.Menu):
bl_label = "Add Pose" bl_label = "Add Pose"
def draw(self, context): def draw(self, context):
arm_object = getArmatureObject(context) arm_object, pose_library = get_armature_data(context)
action_object = getPoseLib(context)
dspl_replace_menu_layout = self.layout yapl_replace_menu_layout = self.layout
for pm in action_object.pose_markers: for pm in pose_library.pose_markers:
op = dspl_replace_menu_layout.operator("dspl.add_pose", text=pm.name, icon="PMARKER") op = yapl_replace_menu_layout.operator("yapl.add_pose", text=pm.name, icon="PMARKER")
op.replace = True op.replace = True
op.posename = pm.name op.posename = pm.name
classes = ( classes = (
DATA_PT_DSPLPanel, DATA_PT_YaplPanel,
OBJECT_MT_AddPoseMenu, OBJECT_MT_AddPoseMenu,
OBJECT_MT_ReplacePoseMenu, OBJECT_MT_ReplacePoseMenu,
) )

View File

@ -15,7 +15,7 @@ def register_keymaps():
# Browse Poses # Browse Poses
km = wm.keyconfigs.addon.keymaps.new(name='Pose', space_type='EMPTY') km = wm.keyconfigs.addon.keymaps.new(name='Pose', space_type='EMPTY')
kmi = km.keymap_items.new('dspl.browse_poses', 'L', 'PRESS', alt=True) kmi = km.keymap_items.new('yapl.browse_poses', 'L', 'PRESS', alt=True)
addon_keymaps.append((km, kmi)) addon_keymaps.append((km, kmi))
def unregister_keymaps(): def unregister_keymaps():

View File

@ -6,89 +6,55 @@ from .common import *
# Operator to create a new pose library # Operator to create a new pose library
class DSPL_OT_CreatePoseLibrary(bpy.types.Operator): class YAPL_OT_CreatePoseLibrary(bpy.types.Operator):
bl_idname = "dspl.create_pose_library" bl_idname = "yapl.create_pose_library"
bl_label = "Create Pose Library" bl_label = "Create Pose Library"
bl_description = "Create Pose Library" bl_description = "Create Pose Library"
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
def execute(self, context): def execute(self, context):
arm_object = getArmatureObject(context) arm_object, pose_library = get_armature_data(context)
arm_object.dspl.pose_library = bpy.data.actions.new( arm_object.pose_library = bpy.data.actions.new(
name=arm_object.name + "_PoseLib") name=arm_object.name + "_PoseLib")
arm_object.dspl.pose_library.use_fake_user = True arm_object.pose_library.use_fake_user = True
return {'FINISHED'} return {'FINISHED'}
# Operator to convert a pose library to dspl property # Operator to convert an action to pose library
class DSPL_OT_ConvertPoseLibrary(bpy.types.Operator): class YAPL_OT_ConvertPoseLibrary(bpy.types.Operator):
bl_idname = "dspl.convert_pose_library" bl_idname = "yapl.convert_pose_library"
bl_label = "Convert Pose Library" bl_label = "Convert Pose Library"
bl_description = "Convert Pose Library" bl_description = "Convert Pose Library"
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
def execute(self, context): def execute(self, context):
arm_object = getArmatureObject(context) arm_object, pose_library = get_armature_data(context)
arm_object.dspl.pose_library = arm_object.animation_data.action if pose_library is None:
arm_object.pose_library = arm_object.animation_data.action
arm_object.animation_data.action = None arm_object.animation_data.action = None
return {'FINISHED'} return {'FINISHED'}
# Operator to manage the big menu buttons
class DSPL_OT_MenuButtonHandler(bpy.types.Operator):
bl_idname = "dspl.menu_button_handler"
bl_label = "Button Handler"
bl_description = "Button Handler"
bl_options = {'REGISTER', 'UNDO'}
posename: bpy.props.StringProperty()
def execute(self, context):
bpy.ops.wm.call_menu(name=self.menuID)
return {'FINISHED'}
def invoke(self, context, event):
if event.ctrl:
# Select
action_object = getPoseLib(context)
action_object.pose_markers.active_index = searchPoseMarker(context, posename=self.posename, type="index")
return {'FINISHED'}
elif event.alt:
# Remove
bpy.ops.dspl.remove_pose(posename = self.posename)
return {'FINISHED'}
elif event.shift:
# Rename
bpy.ops.dspl.rename_pose(posename = self.posename)
return {'FINISHED'}
else:
return self.execute(context)
# Operator to add keyframes and marker to pose library # Operator to add keyframes and marker to pose library
class DSPL_OT_AddPose(bpy.types.Operator): class YAPL_OT_AddPose(bpy.types.Operator):
bl_idname = "dspl.add_pose" bl_idname = "yapl.add_pose"
bl_label = "Add Pose" bl_label = "Add Pose"
bl_description = "Add Pose" bl_description = "Add Pose"
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
posename: bpy.props.StringProperty() posename: bpy.props.StringProperty(default="Pose")
replace: bpy.props.BoolProperty(name="Replace", description="Replace existing pose", default=False, options={'SKIP_SAVE'}) replace: bpy.props.BoolProperty(name="Replace", description="Replace existing pose", default=False, options={'SKIP_SAVE', 'HIDDEN'})
def execute(self, context): def execute(self, context):
arm_object, pose_library = get_armature_data(context)
if self.replace == False: if self.replace == False:
arm_object = getArmatureObject(context) pose_markers = pose_library.pose_markers
action_object = getPoseLib(context)
pose_markers = action_object.pose_markers
new_name = self.posename new_name = self.posename
counter = 1 counter = 1
@ -114,17 +80,15 @@ class DSPL_OT_AddPose(bpy.types.Operator):
pose_markers.new(name=pose_name) pose_markers.new(name=pose_name)
pose_markers[pose_name].frame = new_marker pose_markers[pose_name].frame = new_marker
setKeyframesFromBones(context, arm_object, new_marker) set_keyframes_from_bones(context, arm_object, new_marker)
action_object.pose_markers.active = pose_markers[pose_name] pose_library.pose_markers.active = pose_markers[pose_name]
bpy.context.area.tag_redraw() bpy.context.area.tag_redraw()
self.report({'INFO'}, "DSPL: Added " + pose_markers[new_name].name + " to frame " + str(pose_markers[new_name].frame)) self.report({'INFO'}, "YAPL: Added " + pose_markers[new_name].name + " to frame " + str(pose_markers[new_name].frame))
else: else:
arm_object = getArmatureObject(context) pose_markers = pose_library.pose_markers
action_object = getPoseLib(context)
pose_markers = action_object.pose_markers
active_marker = pose_markers.active active_marker = pose_markers.active
new_name = self.posename new_name = self.posename
counter = 1 counter = 1
@ -141,9 +105,9 @@ class DSPL_OT_AddPose(bpy.types.Operator):
new_marker = target_frame new_marker = target_frame
setKeyframesFromBones(context, arm_object, new_marker) set_keyframes_from_bones(context, arm_object, new_marker)
self.report({'INFO'}, "DSPL: Replaced " + pose_markers[new_name].name + " on frame " + str(pose_markers[new_name].frame)) self.report({'INFO'}, "YAPL: Replaced " + pose_markers[new_name].name + " on frame " + str(pose_markers[new_name].frame))
return {'FINISHED'} return {'FINISHED'}
@ -151,8 +115,8 @@ class DSPL_OT_AddPose(bpy.types.Operator):
# Operator to remove keyframes and marker # Operator to remove keyframes and marker
class DSPL_OT_RemovePose(bpy.types.Operator): class YAPL_OT_RemovePose(bpy.types.Operator):
bl_idname = "dspl.remove_pose" bl_idname = "yapl.remove_pose"
bl_label = "Remove Pose" bl_label = "Remove Pose"
bl_description = "Remove Pose" bl_description = "Remove Pose"
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
@ -160,18 +124,17 @@ class DSPL_OT_RemovePose(bpy.types.Operator):
posename: bpy.props.StringProperty() posename: bpy.props.StringProperty()
def execute(self, context): def execute(self, context):
arm_object = getArmatureObject(context) arm_object, pose_library = get_armature_data(context)
action_object = getPoseLib(context) pose_markers = pose_library.pose_markers
pose_markers = action_object.pose_markers
if self.posename: if self.posename:
action_object.pose_markers.active_index = searchPoseMarker(context, posename=self.posename, type="index") pose_library.pose_markers.active_index = search_pose_marker(context, posename=self.posename, type="index")
active_index = action_object.pose_markers.active_index active_index = pose_library.pose_markers.active_index
else: else:
active_index = pose_markers.active_index active_index = pose_markers.active_index
active_marker = pose_markers.active active_marker = pose_markers.active
active_frame = active_marker.frame active_frame = active_marker.frame
fcurves = action_object.fcurves fcurves = pose_library.fcurves
for fcu in fcurves: for fcu in fcurves:
for kf in fcu.keyframe_points.values(): for kf in fcu.keyframe_points.values():
if kf.co.x == active_frame: if kf.co.x == active_frame:
@ -189,10 +152,10 @@ class DSPL_OT_RemovePose(bpy.types.Operator):
pose_markers.remove(marker=active_marker) pose_markers.remove(marker=active_marker)
action_object.pose_markers.active = next_marker pose_library.pose_markers.active = next_marker
action_object.pose_markers.active_index = next_index pose_library.pose_markers.active_index = next_index
self.report({'INFO'}, "DSPL: Removed " + self.posename) self.report({'INFO'}, "YAPL: Removed " + self.posename)
return {'FINISHED'} return {'FINISHED'}
@ -200,8 +163,8 @@ class DSPL_OT_RemovePose(bpy.types.Operator):
# Operator to rename the current pose # Operator to rename the current pose
class DSPL_OT_RenamePose(bpy.types.Operator): class YAPL_OT_RenamePose(bpy.types.Operator):
bl_idname = "dspl.rename_pose" bl_idname = "yapl.rename_pose"
bl_label = "Rename Pose" bl_label = "Rename Pose"
bl_description = "Rename Pose" bl_description = "Rename Pose"
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
@ -210,20 +173,21 @@ class DSPL_OT_RenamePose(bpy.types.Operator):
pose_new_name: bpy.props.StringProperty() pose_new_name: bpy.props.StringProperty()
def execute(self, context): def execute(self, context):
arm_object, pose_library = get_armature_data(context)
arm_object = getArmatureObject(context) pose_markers = pose_library.pose_markers
action_object = getPoseLib(context)
pose_markers = action_object.pose_markers
active_marker = pose_markers.active active_marker = pose_markers.active
if self.posename: if self.posename:
target_marker = searchPoseMarker(context, posename=self.posename, type="marker") target_marker = search_pose_marker(context, posename=self.posename, type="marker")
else: else:
target_marker = active_marker target_marker = active_marker
if self.pose_new_name: if self.pose_new_name:
target_marker.name = self.pose_new_name target_marker.name = self.pose_new_name
context.area.tag_redraw() context.area.tag_redraw()
self.report({'INFO'}, "YAPL: Renamed " + self.posename + " to " + self.pose_new_name + " on frame " + str(active_marker.frame))
return {'FINISHED'} return {'FINISHED'}
else: else:
return {'FINISHED'} return {'FINISHED'}
@ -237,8 +201,8 @@ class DSPL_OT_RenamePose(bpy.types.Operator):
# Operator to reorder pose markers # Operator to reorder pose markers
class DSPL_OT_MovePose(bpy.types.Operator): class YAPL_OT_MovePose(bpy.types.Operator):
bl_idname = "dspl.move_pose" bl_idname = "yapl.move_pose"
bl_label = "Move Pose" bl_label = "Move Pose"
bl_description = "Move pose" bl_description = "Move pose"
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
@ -247,18 +211,15 @@ class DSPL_OT_MovePose(bpy.types.Operator):
posename: bpy.props.StringProperty(name="Pose Name", default="", options={'SKIP_SAVE'}) posename: bpy.props.StringProperty(name="Pose Name", default="", options={'SKIP_SAVE'})
def execute(self, context): def execute(self, context):
arm_object = getArmatureObject(context) arm_object, pose_library = get_armature_data(context)
action_object = getPoseLib(context) pose_markers = pose_library.pose_markers
pose_lib = getPoseLib(context)
pose_markers = action_object.pose_markers
if self.posename: if self.posename:
active_index = searchPoseMarker(context, posename=self.posename, type="index") active_index = search_pose_marker(context, posename=self.posename, type="index")
active_marker = searchPoseMarker(context, posename=self.posename, type="marker") active_marker = search_pose_marker(context, posename=self.posename, type="marker")
active_frame = active_marker.frame active_frame = active_marker.frame
active_posename = active_marker.name active_posename = active_marker.name
else: else:
arm_object = getArmatureObject(context)
active_marker = pose_markers.active active_marker = pose_markers.active
active_index = pose_markers.active_index active_index = pose_markers.active_index
@ -270,21 +231,19 @@ class DSPL_OT_MovePose(bpy.types.Operator):
swap_index = active_index + move_dir swap_index = active_index + move_dir
if swap_index < 0: if swap_index < 0:
# swap_index = len(pose_lib.pose_markers) - 1
return {'FINISHED'} return {'FINISHED'}
elif swap_index >= len(pose_lib.pose_markers): elif swap_index >= len(pose_library.pose_markers):
# swap_index = 0
return {'FINISHED'} return {'FINISHED'}
swap_marker = pose_markers[swap_index] swap_marker = pose_markers[swap_index]
tmp_marker_name = swap_marker.name tmp_marker_name = swap_marker.name
tmp_marker_frame = swap_marker.frame tmp_marker_frame = swap_marker.frame
action_object.pose_markers[swap_index].name = active_marker.name pose_library.pose_markers[swap_index].name = active_marker.name
action_object.pose_markers[swap_index].frame = active_marker.frame pose_library.pose_markers[swap_index].frame = active_marker.frame
action_object.pose_markers[active_index].name = tmp_marker_name pose_library.pose_markers[active_index].name = tmp_marker_name
action_object.pose_markers[active_index].frame = tmp_marker_frame pose_library.pose_markers[active_index].frame = tmp_marker_frame
action_object.pose_markers.active_index = swap_index pose_library.pose_markers.active_index = swap_index
return {'FINISHED'} return {'FINISHED'}
@ -292,50 +251,49 @@ class DSPL_OT_MovePose(bpy.types.Operator):
# Operator to apply a pose from active marker # Operator to apply a pose from active marker
class DSPL_OT_ApplyPose(bpy.types.Operator): class YAPL_OT_ApplyPose(bpy.types.Operator):
bl_idname = "dspl.apply_pose" bl_idname = "yapl.apply_pose"
bl_label = "Apply Pose" bl_label = "Apply Pose"
bl_description = "Apply Pose (Ctrl+Click to select, Alt+Click to remove)" bl_description = "Apply Pose (Ctrl+Click to select, Shift+Click to rename, Alt+Click to remove)"
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
posename: bpy.props.StringProperty() posename: bpy.props.StringProperty()
def execute(self, context): def execute(self, context):
arm_object = getArmatureObject(context) arm_object, pose_library = get_armature_data(context)
action_object = getPoseLib(context) pose_markers = pose_library.pose_markers
pose_markers = action_object.pose_markers
if self.posename: if self.posename:
active_marker = searchPoseMarker(context, posename=self.posename, type="marker") active_marker = search_pose_marker(context, posename=self.posename, type="marker")
active_frame = active_marker.frame active_frame = active_marker.frame
active_posename = active_marker.name active_posename = active_marker.name
action_object.pose_markers.active_index = searchPoseMarker(context, posename=self.posename, type="index") pose_library.pose_markers.active_index = search_pose_marker(context, posename=self.posename, type="index")
else: else:
active_index = pose_markers.active_index active_index = pose_markers.active_index
active_marker = pose_markers.active active_marker = pose_markers.active
active_frame = active_marker.frame active_frame = active_marker.frame
active_posename = active_marker.name active_posename = active_marker.name
setBonesfromKeyframes(context, arm_object, active_marker) set_bones_from_keyframes(context, arm_object, active_marker)
self.report({'INFO'}, "DSPL: Applied " + active_posename) self.report({'INFO'}, "YAPL: Applied " + active_posename)
return {'FINISHED'} return {'FINISHED'}
def invoke(self, context, event): def invoke(self, context, event):
if event.ctrl: if event.ctrl:
# Select # Select
action_object = getPoseLib(context) arm_object, pose_library = get_armature_data(context)
action_object.pose_markers.active_index = searchPoseMarker(context, posename=self.posename, type="index") pose_library.pose_markers.active_index = search_pose_marker(context, posename=self.posename, type="index")
return {'FINISHED'} return {'FINISHED'}
elif event.alt: elif event.alt:
# Remove # Remove
bpy.ops.dspl.remove_pose(posename = self.posename) bpy.ops.yapl.remove_pose(posename = self.posename)
return {'FINISHED'} return {'FINISHED'}
elif event.shift: elif event.shift:
# Rename # Rename
bpy.ops.dspl.rename_pose(posename = self.posename) bpy.ops.yapl.rename_pose('INVOKE_DEFAULT', posename = self.posename)
return {'FINISHED'} return {'FINISHED'}
else: else:
return self.execute(context) return self.execute(context)
@ -344,8 +302,8 @@ class DSPL_OT_ApplyPose(bpy.types.Operator):
# Operator to preview up and down pose list # Operator to preview up and down pose list
class DSPL_OT_BrowsePoses(bpy.types.Operator): class YAPL_OT_BrowsePoses(bpy.types.Operator):
bl_idname = "dspl.browse_poses" bl_idname = "yapl.browse_poses"
bl_label = "Browse Poses" bl_label = "Browse Poses"
bl_description = "Browse Poses" bl_description = "Browse Poses"
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
@ -357,7 +315,7 @@ class DSPL_OT_BrowsePoses(bpy.types.Operator):
font_dpi = 72 font_dpi = 72
blf.position(font_id, 15, 30, 0) blf.position(font_id, 15, 30, 0)
mod_var = self.pose_lib.pose_markers.active.name mod_var = self.pose_library.pose_markers.active.name
blf.color(font_id, 1.0, 1.0, 1.0, 1.0) blf.color(font_id, 1.0, 1.0, 1.0, 1.0)
blf.size(font_id, font_size) blf.size(font_id, font_size)
blf.draw(font_id, "Previewing pose: " + mod_var) blf.draw(font_id, "Previewing pose: " + mod_var)
@ -368,17 +326,17 @@ class DSPL_OT_BrowsePoses(bpy.types.Operator):
if event.value == 'PRESS': if event.value == 'PRESS':
if event.type in {'LEFT_ARROW', 'UP_ARROW'}: if event.type in {'LEFT_ARROW', 'UP_ARROW'}:
if self.pose_lib.pose_markers.active_index <= 0: if self.pose_library.pose_markers.active_index <= 0:
self.pose_lib.pose_markers.active_index = len(self.pose_lib.pose_markers) - 1 self.pose_library.pose_markers.active_index = len(self.pose_library.pose_markers) - 1
else: else:
self.pose_lib.pose_markers.active_index = self.pose_lib.pose_markers.active_index - 1 self.pose_library.pose_markers.active_index = self.pose_library.pose_markers.active_index - 1
bpy.ops.dspl.apply_pose() bpy.ops.yapl.apply_pose()
elif event.type in {'RIGHT_ARROW', 'DOWN_ARROW'}: elif event.type in {'RIGHT_ARROW', 'DOWN_ARROW'}:
if self.pose_lib.pose_markers.active_index + 1 >= len(self.pose_lib.pose_markers): if self.pose_library.pose_markers.active_index + 1 >= len(self.pose_library.pose_markers):
self.pose_lib.pose_markers.active_index = 0 self.pose_library.pose_markers.active_index = 0
else: else:
self.pose_lib.pose_markers.active_index = self.pose_lib.pose_markers.active_index + 1 self.pose_library.pose_markers.active_index = self.pose_library.pose_markers.active_index + 1
bpy.ops.dspl.apply_pose() bpy.ops.yapl.apply_pose()
if event.type in {'LEFTMOUSE', 'RET', 'NUMPAD_ENTER'}: if event.type in {'LEFTMOUSE', 'RET', 'NUMPAD_ENTER'}:
bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW') bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
@ -386,7 +344,7 @@ class DSPL_OT_BrowsePoses(bpy.types.Operator):
elif event.type in {'RIGHTMOUSE', 'ESC'}: elif event.type in {'RIGHTMOUSE', 'ESC'}:
self.arm_object.pose.backup_restore() self.arm_object.pose.backup_restore()
self.pose_lib.pose_markers.active_index = self.backup_index self.pose_library.pose_markers.active_index = self.backup_index
bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW') bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
return {'CANCELLED'} return {'CANCELLED'}
@ -396,19 +354,18 @@ class DSPL_OT_BrowsePoses(bpy.types.Operator):
def invoke(self, context, event): def invoke(self, context, event):
bpy.context.area.tag_redraw() bpy.context.area.tag_redraw()
self.arm_object = getArmatureObject(context) self.arm_object, self.pose_library = get_armature_data(context)
self.pose_lib = getPoseLib(context)
if self.pose_library is None:
if self.pose_lib is None: self.report({'WARNING'}, "YAPL: Pose Library not active")
self.report({'WARNING'}, "DSPL: Pose Library not active")
return {'CANCELLED'} return {'CANCELLED'}
self.arm_object.pose.backup_create(self.pose_lib) self.arm_object.pose.backup_create(self.pose_library)
self.backup_index = self.pose_lib.pose_markers.active_index self.backup_index = self.pose_library.pose_markers.active_index
bpy.ops.dspl.apply_pose() bpy.ops.yapl.apply_pose()
if context.area.type == 'VIEW_3D': if context.area.type == 'VIEW_3D':
self.report({'INFO'}, "DSPL: Browsing Poses") self.report({'INFO'}, "YAPL: Browsing Poses")
args = (self, context) args = (self, context)
self._handle = bpy.types.SpaceView3D.draw_handler_add(self.draw_callback_px, args, 'WINDOW', 'POST_PIXEL') self._handle = bpy.types.SpaceView3D.draw_handler_add(self.draw_callback_px, args, 'WINDOW', 'POST_PIXEL')
context.window_manager.modal_handler_add(self) context.window_manager.modal_handler_add(self)
@ -419,18 +376,22 @@ class DSPL_OT_BrowsePoses(bpy.types.Operator):
# Operator to unlink a pose library and mark for removal # Operator to unlink a pose library and mark for removal
class DSPL_OT_UnlinkPoseLibrary(bpy.types.Operator): class YAPL_OT_UnlinkPoseLibrary(bpy.types.Operator):
bl_idname = "dspl.unlink_pose_library" bl_idname = "yapl.unlink_pose_library"
bl_label = "Unlink Pose Library" bl_label = "Unlink Pose Library"
bl_description = "Unlink Pose Library" bl_description = "Unlink Pose Library"
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
def execute(self, context): def execute(self, context):
arm_object = getArmatureObject(context) arm_object, pose_library = get_armature_data(context)
pose_library = getPoseLib(context)
arm_object.dspl.pose_library.name = "del_" + arm_object.dspl.pose_library.name try:
arm_object.dspl.pose_library = None arm_object.pose_library = None
# arm_object.pose_library.use_fake_user = False
# if not arm_object.pose_library.name.startswith("del_"):
# arm_object.pose_library.name = "del_{}".format(arm_object.pose_library.name)
except:
pass
return {'FINISHED'} return {'FINISHED'}
@ -438,8 +399,8 @@ class DSPL_OT_UnlinkPoseLibrary(bpy.types.Operator):
# Operator to protect orphaned legacy pose libraries # Operator to protect orphaned legacy pose libraries
class DSPL_OT_ProtectOrphanPoseLibrary(bpy.types.Operator): class YAPL_OT_ProtectOrphanPoseLibrary(bpy.types.Operator):
bl_idname = "dspl.protect_orphan_pose_library" bl_idname = "yapl.protect_orphan_pose_library"
bl_label = "Protect Orphaned Pose Libraries" bl_label = "Protect Orphaned Pose Libraries"
bl_description = "Protect Orphaned Pose Libraries" bl_description = "Protect Orphaned Pose Libraries"
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
@ -475,25 +436,23 @@ class DSPL_OT_ProtectOrphanPoseLibrary(bpy.types.Operator):
if orphaned_act: if orphaned_act:
for act in orphaned_act: for act in orphaned_act:
if "_loc" in act.name or "PoseLib" in act.name: if "_loc" in act.name or "PoseLib" in act.name:
self.report({'INFO'}, "DSPL: Protecting orphaned action: " + act.name) self.report({'INFO'}, "YAPL: Protecting orphaned action: " + act.name)
act.use_fake_user = True act.use_fake_user = True
return {'FINISHED'} return {'FINISHED'}
classes = ( classes = (
DSPL_OT_CreatePoseLibrary, YAPL_OT_CreatePoseLibrary,
DSPL_OT_ConvertPoseLibrary, YAPL_OT_ConvertPoseLibrary,
DSPL_OT_CallPopupMenu, YAPL_OT_AddPose,
DSPL_OT_MenuButtonHandler, YAPL_OT_RemovePose,
DSPL_OT_AddPose, YAPL_OT_RenamePose,
DSPL_OT_RemovePose, YAPL_OT_MovePose,
DSPL_OT_RenamePose, YAPL_OT_ApplyPose,
DSPL_OT_MovePose, YAPL_OT_BrowsePoses,
DSPL_OT_ApplyPose, YAPL_OT_UnlinkPoseLibrary,
DSPL_OT_BrowsePoses, YAPL_OT_ProtectOrphanPoseLibrary
DSPL_OT_UnlinkPoseLibrary,
DSPL_OT_ProtectOrphanPoseLibrary
) )
register, unregister = bpy.utils.register_classes_factory(classes) register, unregister = bpy.utils.register_classes_factory(classes)