Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add time remapping support to Core Animation rendering engine #2286

Merged
merged 6 commits into from Jan 12, 2024

Conversation

calda
Copy link
Member

@calda calda commented Jan 9, 2024

This PR adds support for time remapping to the Core Animation rendering engine. Fixes #1648.

Time remapping is a function that changes how time progresses for a layer. It's an arbitrarily complex function from the current "global time" of the overall animation to the "local time" in the layer that should be displayed.

For example, if you have a layer that animates from 0 to 10, you could have that animation play over range 50 to 100 in the overall animation. That would be a function like local_time = (global_time - 50) / 5. Time remapping functions can be arbitrarily complex and non-linear, and can even loop / go backwards.

All of the keyframes a Lottie animation are expressed in "local time" for the layer, and we cannot convert these local times to global times. To apply this "global time to local time" time mapping for the layer, we have to manually interpolate the keyframes at each individual global frame, and then apply that time remapping at each frame.

This PR adds a new Keyframes.manuallyInterpolatedWithTimeRemapping codepath that is used for any layer that is a child of some PreCompLayer with a timeRemapping function.

Without time remapping With time remapping
2024-01-09 14 29 39 2024-01-09 14 28 08
Without time remapping With time remapping
2024-01-09 14 29 56 2024-01-09 14 30 34

Copy link

emerge-tools bot commented Jan 9, 2024

1 build increased size

Name Version Download Change Install Change
⚠️ SizeTest
com.airbnb.lottie.sizetest.iOS
1.0 (1) 777.4 kB ⬆️ 25.2 kB (3.35%) 2.3 MB ⬆️ 71.3 kB (3.21%)

SizeTest 1.0 (1)
com.airbnb.lottie.sizetest.iOS

⚖️ Compare build
⏱️ Analyze build performance

⚠️ Install size change increased by >= 2%
Total install size change: ⬆️ 71.3 kB (3.21%)
Total download size change: ⬆️ 25.2 kB (3.35%)

Largest size changes

Item Install Size Change
Lottie.CALayer.defaultAnimation(for,keyframes,value,context) ⬆️ 21.8 kB
📝 Lottie.Keyframes.manuallyInterpolatedWithTimeRemapping(context) ⬆️ 7.7 kB
📝 CoreGraphics._NativeDictionary._copyOrMoveAndResize(capacity,move... ⬆️ 6.7 kB
📝 CoreGraphics._NativeDictionary.copy ⬆️ 4.3 kB
Lottie.CALayer.path(keyframes,value) ⬆️ 3.6 kB

Image of diff


🛸 Powered by Emerge Tools

@@ -10,7 +10,7 @@ extension CALayer {
/// Constructs a `CAKeyframeAnimation` that reflects the given keyframes,
/// and adds it to this `CALayer`.
@nonobjc
func addAnimation<KeyframeValue, ValueRepresentation>(
func addAnimation<KeyframeValue: AnyInterpolatable, ValueRepresentation>(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keyframes.manuallyInterpolatedWithTimeRemapping requires the keyframe values to be Interpolatable, which adds this additional requirement here. This PR adds an Interpolatable conformance to any existing type that is used with this method but didn't already have a conformance.

/// this can be prohibitively expensive.
func validateReasonableNumberOfTimeRemappingLayers() throws {
try layerContext.compatibilityAssert(
numberOfLayersWithTimeRemapping < 500,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pr_2286.json animation I added is very large (3500+ layers with time remapping). This causes the main thread to hang for quite a while while setting up all of those layers.

All of the other animations I've tested locally have less than ~250 layers with time remapping, and I don't notice any perceptible thread hanging. For now we can just set a cap on the size of animations that we let use this new codepath. Those animations will continue falling back to the main thread rendering engine like they do today.

{
try context.logCompatibilityIssue("""
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
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This previous implementation attempted to invert the time remapping keyframes. This happened to work in some simple cases, but didn't work in general.

Supports Core Animation engine
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

woohoo! 🥳 🎉

@calda calda force-pushed the cal--time-remapping-core-animation branch from 7fdf3d3 to e31cfd0 Compare January 11, 2024 22:56
Copy link
Contributor

@miguel-jimenez-0529 miguel-jimenez-0529 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

context: context)
}

/// Otherwise continue using the previous codepath that doesn't support complex time remapping.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the wording previous here makes sense in a PR but could be confusing after we merge the code. Someone may not know the else block was the previous codepath.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea

/// An `Interpolatable` container that animates using "hold" keyframes.
/// The keyframes do not animate, and instead always display the value from the most recent keyframe.
/// This is necessary when passing non-interpolatable values to a method that requires an `Interpolatable` conformance.
struct Hold<T>: Interpolatable {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we move this to its own file?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll move it to the file with the Interpolatable protocol and main interpolation implementations

@calda calda enabled auto-merge (squash) January 12, 2024 03:52
@calda calda merged commit 7cae3aa into master Jan 12, 2024
14 checks passed
@calda calda deleted the cal--time-remapping-core-animation branch January 12, 2024 04:11
cgrindel-self-hosted-renovate bot added a commit to cgrindel/rules_swift_package_manager that referenced this pull request Jan 23, 2024
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [airbnb/lottie-spm](https://togithub.com/airbnb/lottie-spm) | minor |
`from: "4.3.4"` -> `from: "4.4.0"` |

---

### Release Notes

<details>
<summary>airbnb/lottie-spm (airbnb/lottie-spm)</summary>

###
[`v4.4.0`](https://togithub.com/airbnb/lottie-spm/releases/tag/4.4.0)

[Compare
Source](https://togithub.com/airbnb/lottie-spm/compare/4.3.4...4.4.0)

#### New features

- Add privacy manifest
([airbnb/lottie-ios#2252)
- Codesign Lottie.xcframework
([airbnb/lottie-ios#2259)
- Add time remapping support to Core Animation rendering engine
([airbnb/lottie-ios#2286)
- Add official visionOS support to lottie-ios repo
([airbnb/lottie-ios#2287)
- lottie-spm now supports visionOS
([airbnb/lottie-spm#12)
- Adopt policy on minimum supported Swift / Xcode version, update
minimum versions to Swift 5.7 / Xcode 14.1
([airbnb/lottie-ios#2260)

#### Bug fixes

- Update LottieView to display placeholder using `overlay` instead of
`ZStack`
([airbnb/lottie-ios#2289)
- Fix issue where Core Animation rendering engine couldn't display last
frame of animation when paused
([airbnb/lottie-ios#2254)
- Do not create `DotLottieImageProvider` instance if there's no image
files
([airbnb/lottie-ios#2271)
- Mark DotLottieCache as Sendable
([airbnb/lottie-ios#2245)
- Fix issue where AnimationKeypath in SolidLayer could be incorrect
([airbnb/lottie-ios#2278)
- Fix issue where Repeater could be displayed incorrectly
([airbnb/lottie-ios#2276)
- Include dSYMs in xcframework build
([airbnb/lottie-ios#2284)
- Fix parsing issue, add support for DotLottieConfiguration in SwiftUI
LottieView
([airbnb/lottie-ios#2277)
- Fix issue where DotLottieImageProvider didn't handle base64 images
([airbnb/lottie-ios#2283)
- Fix issue where manually interpolated keyframes could animate
incorrectly
([airbnb/lottie-ios#2285)

**Full Changelog**:
airbnb/lottie-ios@4.3.4...4.4.0

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config help](https://togithub.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Renovate
Bot](https://togithub.com/renovatebot/renovate).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNi4xMDAuMCIsInVwZGF0ZWRJblZlciI6IjM2LjEwMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->

Co-authored-by: Self-hosted Renovate Bot <361546+cgrindel-self-hosted-renovate[bot]@users.noreply.github.enterprise.com>
iago849 pushed a commit to atteamapps/lottie-ios that referenced this pull request Feb 8, 2024
cgrindel-self-hosted-renovate bot added a commit to cgrindel/rules_swift_package_manager that referenced this pull request Feb 22, 2024
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [airbnb/lottie-spm](https://togithub.com/airbnb/lottie-spm) | patch |
`from: "4.4.0"` -> `from: "4.4.1"` |

---

### Release Notes

<details>
<summary>airbnb/lottie-spm (airbnb/lottie-spm)</summary>

###
[`v4.4.1`](https://togithub.com/airbnb/lottie-spm/releases/tag/4.4.1)

[Compare
Source](https://togithub.com/airbnb/lottie-spm/compare/4.4.0...4.4.1)

##### Bug fixes in 4.4.1

- Replace os check with canImport so classes are available on visionOS
([airbnb/lottie-ios#2294)
- Omit privacy manifest from source files in podspec
([airbnb/lottie-ios#2307)
- Fix crash in Main Thread rendering engine path interpolation
implementation
([airbnb/lottie-ios#2305)
- Fix warning from invalid character in Cocoapods resource bundle
identifier
([airbnb/lottie-ios#2317)
- Fix infinite loop when setting `LottieAnimationView.viewportFrame`
([airbnb/lottie-ios#2316)

##### New features in 4.4.0

- Add privacy manifest
([airbnb/lottie-ios#2252)
- Codesign Lottie.xcframework
([airbnb/lottie-ios#2259)
- Add time remapping support to Core Animation rendering engine
([airbnb/lottie-ios#2286)
- Add official visionOS support to lottie-ios repo
([airbnb/lottie-ios#2287)
- lottie-spm now supports visionOS
([airbnb/lottie-spm#12)
- Adopt policy on minimum supported Swift / Xcode version, update
minimum versions to Swift 5.7 / Xcode 14.1
([airbnb/lottie-ios#2260)

**Full Changelog**:
airbnb/lottie-ios@4.4.0...4.4.1

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config help](https://togithub.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Renovate
Bot](https://togithub.com/renovatebot/renovate).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNi4xMDAuMCIsInVwZGF0ZWRJblZlciI6IjM2LjEwMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->

Co-authored-by: Self-hosted Renovate Bot <361546+cgrindel-self-hosted-renovate[bot]@users.noreply.github.enterprise.com>
cgrindel-self-hosted-renovate bot added a commit to cgrindel/rules_swift_package_manager that referenced this pull request Apr 8, 2024
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [airbnb/lottie-spm](https://togithub.com/airbnb/lottie-spm) | patch |
`from: "4.4.1"` -> `from: "4.4.2"` |

---

### Release Notes

<details>
<summary>airbnb/lottie-spm (airbnb/lottie-spm)</summary>

###
[`v4.4.2`](https://togithub.com/airbnb/lottie-spm/releases/tag/4.4.2)

[Compare
Source](https://togithub.com/airbnb/lottie-spm/compare/4.4.1...4.4.2)

##### Changes in 4.4.2

- Update minimum deployment target to iOS 13.0 / macOS 10.15
([airbnb/lottie-ios#2322)
- Add privacy manifest to lottie-spm repo
([airbnb/lottie-spm#23)
- Add visionOS support to Cocoapods podspec
([airbnb/lottie-ios#2348)
- Fix incorrect usage of `State(initialValue:)` in `LottieView`
([airbnb/lottie-ios#2357)
- Use correct version number when building XCFramework bundle
([airbnb/lottie-ios#2341)

##### New features in 4.4.0

- Add privacy manifest
([airbnb/lottie-ios#2252)
- Codesign Lottie.xcframework
([airbnb/lottie-ios#2259)
- Add time remapping support to Core Animation rendering engine
([airbnb/lottie-ios#2286)
- Add official visionOS support to lottie-ios repo
([airbnb/lottie-ios#2287)
- lottie-spm now supports visionOS
([airbnb/lottie-spm#12)
- Adopt policy on minimum supported Swift / Xcode version, update
minimum versions to Swift 5.7 / Xcode 14.1
([airbnb/lottie-ios#2260)

**Full Changelog**:
airbnb/lottie-ios@4.4.1...4.4.2

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config help](https://togithub.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Renovate
Bot](https://togithub.com/renovatebot/renovate).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNi4xMDkuNCIsInVwZGF0ZWRJblZlciI6IjM2LjEwOS40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->

Co-authored-by: Self-hosted Renovate Bot <361546+cgrindel-self-hosted-renovate[bot]@users.noreply.github.enterprise.com>
cgrindel-self-hosted-renovate bot added a commit to cgrindel/rules_swift_package_manager that referenced this pull request Apr 16, 2024
)

This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [airbnb/lottie-spm](https://togithub.com/airbnb/lottie-spm) | patch |
`from: "4.4.2"` -> `from: "4.4.3"` |

---

### Release Notes

<details>
<summary>airbnb/lottie-spm (airbnb/lottie-spm)</summary>

###
[`v4.4.3`](https://togithub.com/airbnb/lottie-spm/releases/tag/4.4.3)

[Compare
Source](https://togithub.com/airbnb/lottie-spm/compare/4.4.2...4.4.3)

##### Bug fixes in 4.4.3

- Fix issue where animation size could be incorrect after loading async
animation
([airbnb/lottie-ios#2379)
- Update NSPrivacyAccessedAPITypeReasons in privacy manifest
([airbnb/lottie-ios#2380)
- Include animation duration when computing cost/complexity of Core
Animation time remapping
([airbnb/lottie-ios#2381)

##### New features in 4.4.0

- Add privacy manifest
([airbnb/lottie-ios#2252)
- Codesign Lottie.xcframework
([airbnb/lottie-ios#2259)
- Add time remapping support to Core Animation rendering engine
([airbnb/lottie-ios#2286)
- Add official visionOS support to lottie-ios repo
([airbnb/lottie-ios#2287)
- lottie-spm now supports visionOS
([airbnb/lottie-spm#12)
- Adopt policy on minimum supported Swift / Xcode version, update
minimum versions to Swift 5.7 / Xcode 14.1
([airbnb/lottie-ios#2260)

**Full Changelog**:
airbnb/lottie-ios@4.4.2...4.4.3

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config help](https://togithub.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Renovate
Bot](https://togithub.com/renovatebot/renovate).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNi4xMDkuNCIsInVwZGF0ZWRJblZlciI6IjM2LjEwOS40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->

Co-authored-by: Self-hosted Renovate Bot <361546+cgrindel-self-hosted-renovate[bot]@users.noreply.github.enterprise.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

The Core Animation rendering engine partially supports time remapping keyframes
2 participants