1
$\begingroup$

I am writing a script to offset some animations of subsequent objects from an array.

The idea is that I will take the 'old' keyframe data, add some number to it, then insert the 'new' keyframe with the updated data.

import bpy

active_obj = bpy.context.active_object

tracks = active_obj.animation_data.nla_tracks 

for track in tracks:
    for strip in track.strips:
        action = strip.action

        for fcu in action.fcurves:
            data_path = fcu.data_path  # Name of parameter
            for keyframe in fcu.keyframe_points:
                old_keyframe = keyframe.co
                new_keyframe = (old_keyframe.x + 2, old_keyframe.y + 2)
                
                fcu.keyframe_delete(data_path, 0, old_keyframe.x)

When I run this code, I get the error: Traceback (most recent call last): File "X:\path\to\file\offset.py", line 17, in <module> TypeError: bpy_struct.keyframe_insert() property "location" not found.

My scene is just a single cube that goes from Location Z=9 to Location Z=1 over 30 frames, but I can provide the blend file if you need that.

I'm unsure why it is trying to run keyframe_insert() when I am not referencing it at all in my script..

Also, I am using Blender 2.93

Documentation for keyframe_delete()

$\endgroup$
2
  • 1
    $\begingroup$ The keyframe_insert and keyframe_delete are methods on blender object properties s that can be animated, . for example the location property of the "Cube". An fcurve has neither a location property (the error message), nor can it be animated. Suggest if you wish to shift the z location keyframe, search for datapath and array index and set that fcurves value with keyframe.co.y += 2 (The x part of a keyframe is the frame) $\endgroup$
    – batFINGER
    Commented Jul 27, 2021 at 17:38
  • $\begingroup$ Ah, so you are saying that I should adjust the actual keyframe values instead of deleting and creating new ones? That makes a lot of sense here. Cheers man $\endgroup$
    – Rug
    Commented Jul 27, 2021 at 17:46

1 Answer 1

3
$\begingroup$

Using foreach_get and foreach_set

The keyframe_insert and keyframe_delete are methods on blender object properties that can be animated, . for example the location property of the "Cube". On the default file with no animations, adding a keyframe to cube using cube.keyframe_insert("location", 0, 1) creates an action, creates an fcurve, inserts the keyframe, returns a boolean, True if successful.

An fcurve has neither a location property (the error message), nor can it be animated. (It is the animation) Suggest if you wish to shift the z location keyframe, search for datapath and array index and set that fcurves value with keyframe.co.y += 2 (The x part of a keyframe is the frame)

Note: if the action is in the NLA then shifting the x (frame) can be done by setting the strip start. Adding to the value y, can be done via adding a simple action that is simply a constant

Another thing to consider is the keyframe handles.

Here is a test script to shift all keyframes in an fcurve.

import bpy
import numpy as np

def fcurve_shift(fcurve, shift=(0, 0), shift_handles=True):
    props = ("co", "handle_left", "handle_right") if shift_handles else ("co",) 
    for prop in props:
        kfps = np.empty(len(fcurve.keyframe_points) << 1)
        fcurve.keyframe_points.foreach_get(prop, kfps)
        kfps = kfps.reshape((2, -1)) + shift
        fcurve.keyframe_points.foreach_set(prop, kfps.ravel())
        

# test call

action = bpy.data.actions["CubeAction"]
for fc in action.fcurves:
    fcurve_shift(fc, (2, 2))

Copying specific frames from one action to another ( python )

How to obtain max and min of f-curve in python

$\endgroup$
2
  • $\begingroup$ This looks really promising, thank you. Can you explain why you are bitshifting in the line np.empty(len(fcurve.keyframe_points)? That confuses me a bit. But this is way better than my loops haha. $\endgroup$
    – Rug
    Commented Jul 28, 2021 at 12:59
  • 1
    $\begingroup$ Basically just doubling for x and y. The foreach methods require a flat list. See blender.stackexchange.com/a/214510/15543 image has 4 r, g, b, a.. bit shifting is a squeak quicker than multiplying. $\endgroup$
    – batFINGER
    Commented Jul 28, 2021 at 13:05

You must log in to answer this question.

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