Maniphest T96488

Removing all keyframes in for loop fails
Closed, Archived

Assigned To
None
Authored By
Andrej (andrej730)
Mar 15 2022, 9:45 AM
Tags
  • BF Blender
  • Python API
Subscribers
Andrej (andrej730)
butaixianran (butaixianran)
Campbell Barton (campbellbarton)
Colin Basnett (cmbasnett)
p (phil123456)

Description

Blender Version
The issue occurs at Blender 3.1 (as for today).

Short description of error
Removing all keyframes in for loop fails with exception RuntimeError: Error: Keyframe not in F-Curve

Exact steps for others to reproduce the error

  1. Open file
  2. Run script

Event Timeline

Andrej (andrej730) created this task.Mar 15 2022, 9:45 AM
Andrej (andrej730) updated the task description.
Andrej (andrej730) updated the task description.
Richard Antalik (ISS) renamed this task from Bug when removing fcurve keyframe_points values to Removing all keyframes in for loop fails.Mar 16 2022, 12:25 AM
Richard Antalik (ISS) changed the task status from Needs Triage to Confirmed.
Richard Antalik (ISS) updated the task description.
Richard Antalik (ISS) added a project: Python API.
butaixianran (butaixianran) added a subscriber: butaixianran (butaixianran).May 6 2022, 6:06 PM

Same issues here, and searched in google lead to this page.

here is more information:

I am running code like this:

python
                            for kfp in fcurve.keyframe_points:
                                if kfp.co.x >= startFrame and kfp.co.x <= endFrame:
                                    print("kfp.co.x: " + str(kfp.co.x))
                                    fcurve.keyframe_points.remove(kfp)

There are 2 problems about the running result, to me, looks like 2 bugs, not one.

For example, if I have camera keyframes at frame number: 1, 30, 31, 60, 61, 90,91, 120
And the start and end frame number is: 1~250

Then, the loop above, will only print keyframe at: 1.0, 31.0, 61.0, 91.0.

Get it? If there are 2 keyframes, one next the other, the first keyframe is never handled.

And since the last keyframe is at frame 120 and there is no next keyframe at frame number 121, it gives me the error:
RuntimeError: Error: Keyframe not in F-Curve

So, since it alway leaves half keyframes un-removed, I have to run that script about 5~6 times to remove all the keyframe in a range.

btw, this issue can be confirmed in Blender 3.0 too.

p (phil123456) added a subscriber: p (phil123456).May 30 2022, 1:28 PM

so the workaround is to use a loop that checks the length of the array until it is empty I guess

Colin Basnett (cmbasnett) added a subscriber: Colin Basnett (cmbasnett).Jun 23 2022, 8:13 PM

This is not a valid bug. This is a common programming problem where you cannot remove items from a list from within a loop using a forward iterator because the iterator is invalidated after the first removal. There are a number of ways to fix this, but the easiest way is to just reversing the iteration order (e.g., reversed(fc.keyframe_points.values())).

Campbell Barton (campbellbarton) closed this task as Archived.Aug 5 2022, 7:13 AM
Campbell Barton (campbellbarton) added a subscriber: Campbell Barton (campbellbarton).

Removing the key frame point will re-allocate the array, you'll need to access points from fcurve.keyframe_points after removing the first item.

Andrej (andrej730) added a comment.Aug 14 2022, 8:06 AM
In T96488#1379206, @Colin Basnett (cmbasnett) wrote:

This is not a valid bug. This is a common programming problem where you cannot remove items from a list from within a loop using a forward iterator because the iterator is invalidated after the first removal. There are a number of ways to fix this, but the easiest way is to just reversing the iteration order (e.g., reversed(fc.keyframe_points.values())).

Agree that it's just a common programming problem, good point.