So I need to cycle through a selected bone's keyframes to do some action at each keyframe. It must be independent of the scene frame range as keyframes can be outside of it, and I also must not create keyframes at frames that weren't keyed in the first place which jumping to the playback start/end would do in my case).
I guessed the brute solution would be to bpy.ops.screen.keyframe_jump(next=False)
till there's nothing to get to the very first keyframe, and then do if forward again to do the actual keyframe actions.
But I suspected a smarter way would be to get a list of the bone's keyed frames and cycles through them according to that list.
So I manage to get the following code to get the armature's keyframe list, and remove all duplicates.
import bpy
from bpy.types import (Context, Operator, )
def get_keyed_frames():
KEYED_FRAMES_ARRAY = []
fcurves = bpy.context.active_object.animation_data.action.fcurves
for curve in fcurves:
keyframePoints = curve.keyframe_points
for keyframe in keyframePoints:
# if dev_mode == True:
# print('TOTAL FRAMES ARE: {}'.format(keyframe.co[0]))
KEYED_FRAMES_ARRAY.append(keyframe.co[0])
KEYED_FRAMES_ARRAY = list(dict.fromkeys(KEYED_FRAMES_ARRAY))
return KEYED_FRAMES_ARRAY
print(get_keyed_frames())
But I couldn't make this work on a specific bone, so currently it picks up all the armature's keyed frames. Is there an active_bone
or even selected
bone equivalent to bpy.context.active_object.animation_data.action.fcurves
?
Or maybe a better/smarter way to cycle through each keyed frame of a bone.