Keyframe snapping when scaling
Closed, ResolvedPublic

Description

Setting "Auto Snap" to "Nearest Frame" currently behaves in such a way that it both limits movement of keyframes to whole frames (not subframes) and merges two keyframes when they're both occupying the same frame.

However when selecting keyframes in the dopesheet and scaling them down it only limits the movement of the keyframes to whole frames but doesn't merge keyframes when they're both occupying the same frame.

When wanting to fix this and make sure it behaves in the same way then of course the question arises: "How does the code know which keyframe is more important, which one should it keep and which one should it throw away?"

My suggestion would be to simply split the difference. Check the values for all the competing keyframes in a single frame and go with an average. Given the "Auto Snap" current behavior in Blender this feels intuitive from the user's point of view. Assuming it will auto snap to the nearest frame only to find out in the graph editor that it created a tangled mess of keyframes occupying the same frames is in no way user friendly behavior.

If the user would not want any snapping they always have the option of turning it off, that's never been a problem.

I'm including a simple Blend file that has two cubes with simple Z-location animation. The keyframes for one of them have been scaled to 66% (with Auto Snap set to "Nearest Frame") and in the Graph Editor you should see how the keyframes have been snapped to whole frames but not merged together. You can scale down the keyframes of the original cube in order to replicate the function.

Details

Type
Bug

Hi @Hjalti Hjálmarsson (hjalti) , nice to see suggestions in this area.
Could you confirm if I understood your proposal right?

Let's take this curve as an example:

If we activate the Snap for the Nearest Frame and scale in Dope Sheet to very small values (close to zero), currently we get something like this:

But if I understood your suggestion, the idea would be that it would look like this:

Am I right?

Exactly!

(sorry for the late reply, didn't see the notification)

But only if "AutoMerge Keyframes" is toggled on ...that's something I totally forgot to mention in my original post.

Joshua Leung (aligorith) triaged this task as Normal priority.Feb 8 2018, 7:48 AM

I've taken a look at what the code is currently doing. Basically, it makes several assumptions (based on the grabbing/translating keyframes case):

  1. You're only moving a few keyframes at once (and mostly not a whole set of consecutive points that may end up overlapping after the transform)
  2. You're more interested in the ones that you're currently moving (i.e. the selected ones) than the ones not moving, so it only keeps the selected ones if they come in conflict with anything

Obviously, these don't really work in this case :)


In light of this, we'll probably need to specifically handle the post-scaling case separately using a new method. The existing method isn't that easy to shoehorn any of the desired behaviours into it.

In the meantime, I could try making the "overlapping data" check less strict (i.e. using the same 0.01 threshold used when playing back animation, as opposed to FLT_EPSILON), which will make it delete a whole lot more points (probably leaving only the first one).

BTW, it occurred me while typing this that there are probably some cases where we wouldn't want to average keyframes (as they may end up falling on invalid values). But, there are some fairly easy ways to solve for that, so those won't be a problem.

Joshua Leung (aligorith) closed this task as Resolved.Feb 22 2018, 3:16 PM
Joshua Leung (aligorith) claimed this task.

Closing. The previous commits should implement the desired functionality now. (But somehow, I ended up quoting the wrong task number when making the commits)