Reliable way to select active action in Dopesheet via code?

Hi folks,

i’m working on an import script for basic animations and i’m encountering a somewhat annoying problem right now.

I want to loop through a set of animations and create a new action using a naming like “Animation_0” then make this action “active” so that every keyframe I will create from the binary animation data will be assigned to that action.

The general adding of keyframes etc and just creating the actions itself is no problem but I have a hard time selecting the correct action by code. I have tried the following, but it doesn’t work reliable at all…


for i in range(number_of_animations):
    bpy.context.area.type = 'DOPESHEET_EDITOR'
    bpy.context.space_data.mode = 'ACTION'

    bpy.data.actions.new('Animation_' + str(i))
        
    x = bpy.context.area.spaces.active
    x.action = bpy.data.actions.get('Animation_' + str(i))
        
    bpy.context.scene.frame_current = 0
        
    for j in range(number_of_frames):
        bpy.context.scene.frame_current = j
        #add keyframe here...

This however doesn’t work reliable at all. I often end up with Blender just creating 1 new action at the end of the loop and adding the keyframes there instead of adding it to the created actions.

Is there any way to really just simply select the currect action by code? :S

You don’t have to change the editor type and select an action in order to create actions and set FCurve points directly on them.

for i in range(len(anims)):
    action = bpy.data.actions.new("Animation_{}".format(i))
    fcu = action.fcurves.new("location", index=0) # co.x
    fcu.keyframe_points.add(5)
    for j, k in enumerate(fcu.keyframe_points): # 3 demo keyframes
        k.co = (j*50, j % 2) # (time, value)
    fcu.update()

You can use / assign these actions later.

If you want to use keyframe_insert() because you set rotation matrices or similar, then it needs to be assign in the script I guess…

You can reference the just created action like shown above however, bpy.data..new() returns actual references unlike bpy.ops.