0
$\begingroup$

I have two identical armatures:

A - armature with some pose, no animation, B - armature with animation.

I know, that to fix for example arm position along all animation I can select all frames in Graph Editor for specific bone and axis and then use moving along Y axis for adjusting. It works fine.

Now I would like to use exactly the same approach to change all values in my first animation frame to match A armature pose, of course in an automatic way. How can I do that?

EDIT:

Ok, I think I have to explain it in more details.

First of all, armature A only have one pose and no frames at all.

Let's say we have bone named "Root". It's X Rotation is equal to 1 for armature A and 2 for armature B (we consider first frame).

In Graph Editor for armature B I'm selecting a curve which is responsible for this bone and axis. I'm also selecting all keyframes on this curve. I'm using G+Y shortcut to move a curve down to achieve value 1 for it (as in armature A). This way I have the same value in both, but the rest of my animation will follow. I'm adding or subtracting a constant to all my frames. This way I can for example change arm position for all my keyframes respectively (this is an idle animation).

Now I need to do this operation for every single curve in Graph Editor. What I'm trying to achieve is to change my idle animation to play the same move but in different base position defined by A armature.

The first frame of my animation should change to the pose of armature A. The rest of my keyframes should follow, in this case value 1 (2-1) should be subtracted from X rotation value of every single keyframe.

$\endgroup$
1
  • $\begingroup$ Ah your edit clears up your goal tremendously, you want a form of "relative to A" transformation of each bone-for-bone, each axis-by-axis ... an offset to Armature A. This is somewhat similar to a question I asked yesterday, blender.stackexchange.com/questions/281062/… , but now you want to do "for all bones and axis", which probably implies a python script. $\endgroup$
    – james_t
    Dec 11, 2022 at 21:32

1 Answer 1

0
$\begingroup$

Ok, finally I found a solution. I needed to write the following script.

In general this idea is not perfect, but with Smooth Keys functionality and a little bit of manual tweaking it allows me to do what I described above.

import bpy

OBJ_POSE = ''
OBJ_ANIM = ''

OBJ_POSE_CURVES = bpy.data.objects[OBJ_POSE].animation_data.action.fcurves
OBJ_ANIM_CURVES = bpy.data.objects[OBJ_ANIM].animation_data.action.fcurves

def get_bone_name(curve):
    return curve.data_path.split('"')[1]

def get_operation_name(curve):
    return curve.data_path.split('.')[-1]

def update_keyframes(curve_pose_idx, curve_anim_idx, num_of_axes):
    for i in range(0, num_of_axes):
        offset = OBJ_POSE_CURVES[curve_pose_idx + i].keyframe_points[0].co[1] - OBJ_ANIM_CURVES[curve_anim_idx + i].keyframe_points[0].co[1]
        for keyframe in OBJ_ANIM_CURVES[curve_anim_idx + i].keyframe_points:
            keyframe.co[1] += offset

curve_anim_idx = 0
while curve_anim_idx < len(OBJ_ANIM_CURVES):
    curve_anim = OBJ_ANIM_CURVES[curve_anim_idx]
    # WXYZ for rotation, XYZ for translation and scale
    num_of_axes = 4 if get_operation_name(curve_anim) == 'rotation_quaternion' else 3
    for curve_pose_idx, curve_pose in enumerate(OBJ_POSE_CURVES):
        if get_bone_name(curve_pose) == get_bone_name(curve_anim) and get_operation_name(curve_pose) == get_operation_name(curve_anim):
            update_keyframes(curve_pose_idx, curve_anim_idx, num_of_axes)
            break
    curve_anim_idx += num_of_axes
```
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .