I’m trying to write an exporter, and I’m having problems figuring out how to loop through all actions in code to be able to export the bone poses. I can get each action from context.blend_data.actions, but this only gives me the individual F-curves. If I want to get the individual bone poses, I can loop through each frame and look at the posebones at each frame. However, I can’t figure out how to do this for each action, only the current action. I’m looking through the API documentation and I can’t find how to do this, the closest I can is each datablock stores its animdata which in turn stores the action, but it’s all read only and I can’t change it. Any ideas, or will I have to resort to manually changing the action and exporting each pose to a different file, as I’ve seen in some other exporters?
I don’t think my intent was clear. Basically, what I’m trying to do is output the bone pose at each frame marker, using the following code:
for i in range(int(start), int(end+1)): bpy.ops.anim.change_frame(frame = i) for posebone in armature.pose.bones: do something to output the pose here
However, this only works on the current action. For example, say I have a run cycle and a walk cycle, and I want to export them both. Right now, I have no way of switching between the run and walk action, so whichever one I have selected in the action editor is the one that gets outputted. I can switch between run and walk and run the script once for each time, creating two files, but I’d like to be able to do it in one call of the script.
However, one thing I realized after I wrote the initial post is that even for one action at a time, my code isn’t working. The pose doesn’t get updated when I change the frame, so it outputs whatever the value of the pose is when the script is run. I know it’s correctly changing the frame because after the script is run, the frame number is set to whatever the end frame should be, and if I going into the console and print the rotation_quaternions for the posebones after running the script, the pose values have changed. For whatever reason though, the posebones remain the same as what they were before the loop was run. Anyone have ideas why this is happening?
for the last question you could try bpy.context.scene.frame_set(frame) instead and see if it works…?
Thanks liero, that fixed that issue
Doesn’t seem like anyone knows how to do this, so I’ll give this one final bump. If it helps any, the tool tip that pops up when I manually switch actions says “Browse action to be linked”, but unlike virtually every other button, it doesn’t give the underlying python command as a subtitle. Searching through the API documentation, I’ve been unable to find any way to link an action.
import bpy for a in bpy.context.screen.areas: if a.type == 'DOPESHEET_EDITOR': x = a.spaces.active z = bpy.data.actions.get('CubeAction') x.action = z
import bpy a = bpy.context.area.type bpy.context.area.type = 'DOPESHEET_EDITOR' x = bpy.context.area.spaces.active x.action = bpy.data.actions.get('CubeAction') bpy.context.area.type = a
I’m kind of going through the same thing only with a camera animated via constraints.
Anyone have ideas why this is happening?
Are you applying the world matrix to the bone? That solved my problem, applying the world_matrix.
Here are a couple new defs I put together to deal with actions if you know their name.
def fetchIfAction (passedName= ""): try: result = bpy.data.actions[passedName] except: result = None return result def fetchFcurveFromAction (passedAction, passedName= ""): try: result = passedAction.fcurves[passedName] except: result = None return result
Thanks everyone for your help, you’ve solved my problem. My final code, for those interested:
original_area_type = bpy.context.area.type for action in bpy.data.actions: a = bpy.context.area a.type = "DOPESHEET_EDITOR" x = bpy.context.area.active_space x.action = action bpy.context.area.type = "VIEW_3D" bpy.ops.object.mode_set(mode="POSE") bpy.ops.pose.select_all(action="SELECT") bpy.ops.pose.transforms_clear() bpy.ops.screen.frame_jump() start = context.scene.frame_current bpy.ops.screen.frame_jump(end=True) end = context.scene.frame_current for frame in range(int(start), int(end+1)): bpy.context.scene.frame_set(frame) for posebone in parent.pose.bones: #DO YOUR EXPORTING HERE bpy.context.area.type = original_area_type
Alright, one final thing. I thought I had it solved, and it was working, but now it seems to have broken, and I have no idea why since I haven’t changed anything. What’s happening is that the x.action = action line isn’t doing anything, x.action is a NoneType and remains so. If I copy that code verbatim from my export file and just run it inside a text file, it works perfectly. So the action never gets changed, and instead of exporting all actions, it only exports the action that the action editor had initially loaded, albeit over and over again for as many actions as there are. I’m baffled by this.
I ma not getting what exactly this coding is all about ?