# How to change an FCurve value in Python

Someone asked for the functionality to change multiple fcurves at once (f.e. Loc X, Loc Y, Loc Z).

Now I managed to get all selected Fcurves in an array but I can't find any way to change their values. There is the bpy.types.FCurve.evaluate() method which only reads the given value at a frame.

How could I change it(optionally at a specific frame)?

EDIT: Found a workaround and posted it as solution.

An fcurve is made up of splines connecting key frame points. FCurve.keyframe_points a set of points (x, y) analogous to (frame, value).

import bpy
context = bpy.context
# use action on active object

obj = context.object
action = obj.animation_data.action

# location fcurves
fcurves = [fc for fc in action.fcurves if fc.data_path == "location"]

# set value of all fcurves to value at frame
edit_frame = 1
edit_value = (10.0, 0.0, -1.0)

for fc in fcurves:
axis = fc.array_index
# remove keyframe points already at edit_frame
[fc.keyframe_points.remove(p) for p in fc.keyframe_points
if abs(p.co.x - edit_frame) < 0.0001]
# insert a keyframe
fc.keyframe_points.insert(edit_frame, edit_value[axis])


Note this wont work for baked fcurves, which have sampled points. The value of fcurve.evaluate(frame) will evaluate curve after applying any fcurve modifiers.

• Thanks a lot for this! I thought about replacing the keyframe points too but it somehow seemed to be too much of an improvisation for me. I guess this will work fine though. – johnmcdon321 Jul 30 '17 at 15:27

Alright, I managed this little workaround that will change the property of the object associated with the selected FCurve and make a new keyframe for it.

Thanks to batFINGER, I'll also take a deeper look into this keyframe point method.

This would be my solution:

def fcurve_change(value,frames):
ob = bpy.context.active_object
sel_fcrvs = [fc for fc in ob.animation_data.action.fcurves if fc.select]

for fc in sel_fcrvs:
for fr in frames:
ob.keyframe_delete(fc.data_path,fc.array_index,fr)
getattr(bpy.context.active_object, fc.data_path)[fc.array_index] = value
ob.keyframe_insert(fc.data_path,fc.array_index,fr)