In Blender, how can I copy an animation from one bone to another using the built in python tools?

582 Views Asked by At

I wanted to have all translation animations on a "root" bone, and all rotation animations on a child "hips" bone, but I accidentally put all the animations on the hips bone and now I cannot use root motion in the game engine!

Preferably I would not redo all the animations by hand, as I have nearly a hundred.

I tried several variations on this pseudo-code, hoping that the animation would have moved to the other bone. I keep getting errors about missing fields/methods, but it's difficult to figure out what fields I have access to in python since it's not statically typed.

import bpy

# Get the root bone and the hips bone for future reference
root = bpy.data.objects["Armature"].data.bones["_rootJoint"] # Root bone with no animation called "_rootJoint"
hips = bpy.data.objects["Armature"].data.bones["CG_02"] # Hips bone that was supposed to have only rotation animations called "CG_02"

# I wish to select the actions to perform this operation on
# OR iterate through all NLA actions...???
for action in bpy.context.selected_objects:
    for point in action.fcurves.keyframe_points:
        # if this point is on the hips object:
            # for each keyframe on tracks 0, 1, and 2 (the location tracks):
                # Copy that keyframe from hips to root
                # Then remove it from hips
    
1

There are 1 best solutions below

0
Mechanic On

I think it could be something like this (it's for 2.7x)

import bpy

ROOT_BONE = "_rootJoint" # Root bone with no animation called "_rootJoint"
HIPS_BONE = "CG_02" # Hips bone that was supposed to have only rotation animations called "CG_02"
    
for action in bpy.data.actions: # all actions in the file
    for fcurve in action.fcurves:
        # just rename channel, if it's a location
        _path = fcurve.data_path
        if "location" in _path:
            _new_path = _path.replace(HIPS_BONE, ROOT_BONE)
            print(f"{_path} -> {_new_path}")
            fcurve.data_path = _new_path