I want to access the keyframes for a specific bone in animation_data.action, just so I can reset them to a default value. My main problem is I dont know how to just access a specific bone.
The general purpose of this is to automatically reset the hand positions of bvh animation loaded onto a manuelbastionilab model. The bvh animation loads it in fine, but because there isnt really any hand data, it sets the animation to a default splayed out position. And because it assigns it to the wrong bones, it comes in with a crooked little finger. So I just want a simple python script to reset any animations I load in to a good default.
I think I should be able to get to the animation data for the keyframes with
myaction = bpy.context.active_object.animation_data.action
But I dont know what comes next, I dont know how to access the fcurves for a specific bone like a joint / bone in my little finger called pinky02_L
This seems incredibly basic but Ive spent ages googling it and failed miserably.
I suspect I might have problems with setting the data too ! I am using quaternions and so I want to access say the z rotation quaternion. So how do I access the z rot channel, I think its some array offset for the fcurve or something ? So once I have found the fcurve for pinky02l (pinky02lfcurve = ?), is it something like curve = pinky02lfcurve[6] to access the z rotation channel ? Or have I got it all horribly wrong ?
keyframePoints = curve.keyframe_points
for keyframe in keyframePoints:
And Once I have a keyframe how do I set it to a value like :
keyframe.value = math.radians(8.0)
. Is it that simple ? I bet its not!
Any answers to any parts of this would be great ! p.s. thank you to batFinger and Scott Milner for answering my question about it setting it to the wrong degrees the other day.
So from the post lemon refers too I if I am understanding it correctly if I use:
for curve in pinky02lfcurve
if curve.data_path.endswith('rotation_quaternion')
if curve.array_index == 2 # or is it 3 for z with quaternions ?
keyframePoints = curve.keyframe_points
for keyframe in keyframePoints:
keyframe.co[1] = math.radians(8.0)
Ok so re writing to take into account batFingers post I think the following should do what I want !
myaction = bpy.context.active_object.animation_data.action
fcurves = myaction.fcurves
rot = Euler(0,0,8)
myquat = rot.to_quaternion()
pinkyb = bpy.data.objects['MyArmature'].pose.bones['pinky02_L']
dpath = pinkyb.path_from_id("rotation_quaternion")
fc = fcurves.find(dpath, index=0)
keyframePoints = fc.keyframe_points
for keyframe in keyframePoints:
keyframe.co[1] = myquat.w
fc = fcurves.find(dpath, index=1)
keyframePoints = fc.keyframe_points
for keyframe in keyframePoints:
keyframe.co[1] = myquat.x
fc = fcurves.find(dpath, index=2)
keyframePoints = fc.keyframe_points
for keyframe in keyframePoints:
keyframe.co[1] = myquat.y
fc = fcurves.find(dpath, index=3)
keyframePoints = fc.keyframe_points
for keyframe in keyframePoints:
keyframe.co[1] = myquat.z
So I hope this should be good apart from the curve control points which are still at their original positions I think. Though I also still need to work out what angle I actually want to set it too ! Thanks again batFinger and lemon.