I'm writing a python script that needs to read the pose library associated with a particular armature object. I've figured how to query the pose names (via bpy.data.objects['Armature'].pose_library.pose_markers
), but these objects don't seem to have the actual bone transformations which are of main interest to me. Is there an API to do that, or do I have to find a different way to store poses in Blender (i.e. not the pose library)?
1 Answer
It's an action.
Just as poses are stored when keyframing to an action, a pose library is simply using an action as well.
Run thru example in python console, simple single bone object, LOCROTSCALE added to pose library as "Pose".
The object and its action
>>> C.object
bpy.data.objects['Armature']
>>> C.object.animation_data.action
bpy.data.actions['ArmatureAction']
The action associated with the pose library
>>> C.object.pose_library.id_data
bpy.data.actions['PoseLib']
>>> action = C.object.pose_library.id_data
The frame of that pose marker named "Pose"
>>> C.object.pose_library.pose_markers['Pose'].frame
1
Ok, run thru and evaluate the all the fcurves of this action at frame 1. Note this is evaluating even if a keyframe is not set.
>>> for fc in action.fcurves:
... fc.data_path, fc.array_index, fc.evaluate(1)
...
('pose.bones["Bone"].location', 0, 0.0)
('pose.bones["Bone"].location', 1, 0.0)
('pose.bones["Bone"].location', 2, 0.0)
('pose.bones["Bone"].rotation_quaternion', 0, 1.0)
('pose.bones["Bone"].rotation_quaternion', 1, 0.0)
('pose.bones["Bone"].rotation_quaternion', 2, 0.0)
('pose.bones["Bone"].rotation_quaternion', 3, 0.0)
('pose.bones["Bone"].scale', 0, 1.0)
('pose.bones["Bone"].scale', 1, 1.0)
('pose.bones["Bone"].scale', 2, 1.0)
can look at an fcurves keyframe points, where the coordinates are frame and value. Hence with last fc
from above ob.pose.bones["Bone"].scale.z
(index 2 is z)
>>> for kfp in fc.keyframe_points:
... kfp.co.x, kfp.co.y
...
(1.0, 1.0)
(26.0, 1.0)
has value 1.0 at frame 1.0, the frame of pose marker "Pose".
-
$\begingroup$ Thank you a lot! I've found a similar solution in this blog post: blenderartists.org/t/… which uses 'for group in action.groups: for fc in group.channels' instead of 'for fc in action.fcurves' - what's the difference here? I've also noticed that each of the fcurves has the same number of keyframes as there are saved poses in the library, so do keyframes actually correspond to pose indices? $\endgroup$– lisyarusCommented Jul 12, 2021 at 18:13