2
$\begingroup$

I'm trying to import models from a video game into Blender. The tools I have to dump the models gives me a rigged-but-unanimated FBX as the main model, and a second file in a custom format that contains all the animations. I want to use a script to parse the animation file and create one Action for each animation. However, I'm unable to figure out how from the docs and from tinkering around.

This code works, but inserts the keyframes directly onto the timeline, which isn't what I want:

mybone.rotation_quaternion = some_quaternion_from_file
mybone.keyframe_insert("rotation_quaternion", 1)

Looking at the docs for the keyframe_insert function, it looks like the datapath should be "bones[MyBone].rotation_quaternion", but this doesn't work:

newAction = bpy.data.actions.new("testanim")
bpy.data.objects["Armature"].animation_data.action = newAction
mybone.rotation_quaternion = some_quaternion_from_file
newAction.keyframe_insert("bones[MyBone].rotation_quaternion", 1)

This results in the error "property bones[MyBone].rotation_quaternion not found". I've verified that MyBone exists, and I don't know what exactly it wants for the datapath of keyframe_insert.

What am I doing wrong here? How can I get this to work? I've never used the scripting side of Blender before so I don't really know what I'm doing here.

$\endgroup$
3
  • $\begingroup$ Please change it to 'pose.bones["MyBone"].rotation_quaternion'. $\endgroup$ Commented Sep 11 at 23:04
  • $\begingroup$ @tetii No change. TypeError: bpy_struct.keyframe_insert() property "pose.bones["MyBone"].location" not found $\endgroup$ Commented Sep 12 at 1:40
  • $\begingroup$ Sorry, I mistook it for Object.keyframe_insert. I've never used Action.keyframe_insert and don't know the data path for it. What do you mean by "but inserts the keyframes directly onto the timeline, which isn't what I want"? Do you mean you want to create only fcurves or temporary keyframes? $\endgroup$ Commented Sep 12 at 3:55

1 Answer 1

1
$\begingroup$

As tetii pointed out in the comments, you should be adding the keyframes to the bone not to the action. The keyframes are stored in the action if the action is already assigned to the armature whose bone is getting keyframed.

I modified the script and attached it below. The comments should provide more insight.

import bpy

# Inputs:
#   - Armature to assign the action to
#   - Bone whose rotation will be keyframed
#   - The desired rotation
arm_obj = bpy.data.objects["Armature"]
mybone = arm_obj.pose.bones["MyBone"]
some_quaternion_from_file = (0.0, 0.0, 0.0, 1.0)

# Create the action.
newAction = bpy.data.actions.new("testanim")
# Create the animation data for the armature if it doesn't exist.
# This is necessary for assigning the action.
if arm_obj.animation_data == None:
    arm_obj.animation_data_create()
# Assign the action to the armature.
arm_obj.animation_data.action = newAction

# Set the bone rotation.
mybone.rotation_quaternion = some_quaternion_from_file
# Keyframe the bone's rotation at the specified frame
mybone.keyframe_insert(data_path='rotation_quaternion', frame=1)
$\endgroup$
2
  • $\begingroup$ Dang, I can't believe it was that simple. I thought for sure I'd tried that and it didn't work, but plugging that into my script and it works just fine. Thanks so much! $\endgroup$ Commented Sep 12 at 20:22
  • $\begingroup$ You're welcome! $\endgroup$ Commented Sep 13 at 10:34

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.