Hi - I’m struggling with converting my keyframes to linear. I’ve done a lot of Googling, but none of the presented solutions have worked so far for me. I provided an extract of the relevant script below. Note that the “collection” is a collection with curve objects only.
The first part of the code works. I can create keyframes for all my objects but they default to Bezier. Now, I found a snippet (2nd part) that should convert the keyframes to manual. But, I think the issue is that with my keyframe insert method it doesn’t put this in the animation_data block?? (I verified that the created curve after the script indeed lists animation_data as ‘none’)
for ob in collection.all_objects:
for t in range(Sim_Duration+20):
if t==ob["start_time"]:
ob.data.bevel_factor_end = 0
ob.data.keyframe_insert(data_path="bevel_factor_end", index=-1,frame=t)
if t==ob["end_time"]:
ob.data.bevel_factor_end = 1
ob.data.keyframe_insert(data_path="bevel_factor_end", index=-1,frame=t)
fcurves = ob.animation_data.action.fcurves # here I get the error that a nonetype object has no attribute action
for fcurve in fcurves:
for kf in fcurve.keyframe_points:
kf.interpolation = 'CONSTANT'
type or paste code here
I also tried a different approach by explicitly creating fcurves via animation_data. Trouble here is that the data_path doesn’t seem to be recognised and it just creates a new property (?) for each curve and then appends an index:
for ob in collection.all_objects:
ob.animation_data_create()
ob.animation_data.action = bpy.data.actions.new(name="Growth")
fcu=ob.animation_data.action.fcurves.new(data_path='bevel_factor_end')
fcu.keyframe_points.add(2)
for t in range(Sim_Duration+20):
if t==ob["start_time"]:
#ob.data.bevel_factor_end = 0
#ob.data.keyframe_insert(data_path="bevel_factor_end", index=-1,frame=t)
fcu.keyframe_points[0].co = t,0
if t==ob["end_time"]:
#ob.data.bevel_factor_end = 1
#ob.data.keyframe_insert(data_path="bevel_factor_end", index=-1,frame=t)
fcu.keyframe_points[1].co = t,1
Forgot to say that when I then add the 2nd piece of code, the interpolation is set correctly! It’s just that the keyframes don’t tie in with the actual variable/property that I want to animate!.
So, this is the “full” code that leads to what I want: change of interpolation to constant for all the keyframes:
for ob in collection.all_objects:
ob.animation_data_create()
ob.animation_data.action = bpy.data.actions.new(name="Growth")
fcu=ob.animation_data.action.fcurves.new(data_path='bevel_factor_end', index=-1)
fcu.keyframe_points.add(2)
for t in range(Sim_Duration+20):
if t==ob["start_time"]:
#ob.data.bevel_factor_end = 0
#ob.data.keyframe_insert(data_path="bevel_factor_end", index=-1,frame=t)
fcu.keyframe_points[0].co = t,0
if t==ob["end_time"]:
#ob.data.bevel_factor_end = 1
#ob.data.keyframe_insert(data_path="bevel_factor_end", index=-1,frame=t)
fcu.keyframe_points[1].co = t,1
fcurves = ob.animation_data.action.fcurves
for fcurve in fcurves:
for kf in fcurve.keyframe_points:
kf.interpolation = 'CONSTANT'
type or paste code here
By the way, the above code does work with other properties like ‘scale’… it’s just that it doesn’t seem to recognize bevel_factor_end as a built in propery?
OK - so, seems I was wrong (happy to admit!) I managed to make it work. I’ll leave some code later on. But one of the issues was just stupidity on my part; one of the curves I had didn’t have any keyframes set (conditions not met) and hence I got an error message about action not being available.