lottie-ios icon indicating copy to clipboard operation
lottie-ios copied to clipboard

The Core Animation rendering engine partially supports time remapping keyframes

Open smolskyaleksey opened this issue 2 years ago • 11 comments

version 3.4.0 master branch

Lottie/AnimationView.swift:1003: Assertion failed: Encountered Core Animation compatibility issues while setting up animation: [Puke Splash_PRECOMP_02] The Core Animation rendering engine partially supports time remapping keyframes, but this is somewhat experimental and has some known issues. Since it doesn't work in all cases, we have to fall back to using the main thread engine when using RenderingEngineOption.automatic. [Puke Splash_PRECOMP_02] The Core Animation rendering engine partially supports time remapping keyframes, but this is somewhat experimental and has some known issues. Since it doesn't work in all cases, we have to fall back to using the main thread engine when using RenderingEngineOption.automatic.

This animation cannot be rendered correctly by the Core Animation engine. To resolve this issue, you can use RenderingEngineOption.automatic, which automatically falls back to the Main Thread rendering engine when necessary, or just use RenderingEngineOption.mainThread.

smolskyaleksey avatar Jul 11 '22 23:07 smolskyaleksey

The Core Animation rendering engine has a partial implementation of time remapping that works in some circumstances, but doesn't always work correctly. For now I'd suggest using LottieConfiguration(renderingEngine: .automatic), which will automatically fall back to using the main thread rendering engine for animations that use time remapping.

If you specifically want or need to use the Core Animation rendering engine for this animation, you can suppress this assertion by disabling the LottieLogger (either via LottieLogger.shared = .printToConsole or AnimationView(animation: myAnimation, logger: .printToConsole)).

calda avatar Jul 11 '22 23:07 calda

Ok, thx, but the performance is still worse than 2.5.3 version. Do you have any idea why?

smolskyaleksey avatar Jul 11 '22 23:07 smolskyaleksey

When using which rendering engine?

calda avatar Jul 11 '22 23:07 calda

When using which rendering engine?

Yes. Any rendering engine worse than 2.5.3

smolskyaleksey avatar Jul 12 '22 08:07 smolskyaleksey

Can you share your animation json?

calda avatar Jul 12 '22 13:07 calda

Can you share your animation json?

gemmic.zip

smolskyaleksey avatar Jul 12 '22 14:07 smolskyaleksey

Performance of these animations seems great when using the Core Animation engine (0% CPU utilization, and a high framerate), is there a specific issue you were encountering?

calda avatar Jul 12 '22 16:07 calda

Performance of these animations seems great when using the Core Animation engine (0% CPU utilization, and a high framerate), is there a specific issue you were encountering?

When you add all of this to vertical collectionView, one per cell and try to scroll up/down fps rate will be decrease

smolskyaleksey avatar Jul 13 '22 06:07 smolskyaleksey

Hey @calda , our designers like to use time remapping, so this is something I'd be interested in getting support for and would be willing to work on if feasible.

Do you have more info on what the outstanding issues here are?

pejato avatar Oct 20 '22 15:10 pejato

We have an implementation of time remapping that sort of works, but only in simple cases.

Time remapping in Core Animation is complicated for a few reasons:

Every animation has keyframes with timing curves, which Core Animation uses to determine the current value of the property animated at any given time. You can think of these as an arbitrary function that takes the layer's current time value and outputs the value of the property at that time.

Time remapping is also a set of keyframes with timing curves. Time remapping is basically a function that takes a layer's current time value and outputs the remapped time value for its child layer.

To render this correctly, the time remapping of the parent has to be applied to the child every frame. The Core Animation engine doesn't currently operate on individual frames -- it only operates on the set of defined keyframes, and lets Core Animation itself interpolate the individual frames. But if we only apply the time remapping to the keyframes that we create, then the output is incorrect in complex cases. To fix this we would need to manually interpolate the keyframes so we know the value at each frame, and then apply the time remapping to each of those frames.

Another obstacle is the direction in which we have to apply the time remapping. Time remapping is specifically a function from the parent's "local time" to the child's "local time". An example of this -- say you want the child's animation to go twice as fast. When the parent layer is at frame 10, the child's frame is at time 20.

Because of the architecture of the Core Animation engine, I think we have to answer this question in reverse. In the same example of making the child's animation go twice as fast, when computing a value of the child layer at frame 20 we have to know that we should actually be using the value originally intended to be used at frame 10. This requires taking the inverse of the time remapping function, which I don't know how to do correctly (particularly when accounting for the timing curves).

calda avatar Oct 20 '22 16:10 calda

Thanks for the informative reply Cal, it's very helpful 😄 Going to do a more thorough reading of Lottie's CA rendering code this weekend.

This requires taking the inverse of the time remapping function, which I don't know how to do correctly

I'm not sure this is even possible if the time remapping function isn't invertible, which is a possibility, e.g. if we reverse and replay some frames like the second animation here, right?

pejato avatar Oct 21 '22 13:10 pejato

Fixed in https://github.com/airbnb/lottie-ios/pull/2286!

calda avatar Jan 09 '24 23:01 calda