Skip to content

Commit

Permalink
Expose API to get original value from animation (#1559)
Browse files Browse the repository at this point in the history
Fixes #1547
  • Loading branch information
marcelofabri authored May 5, 2022
1 parent 3fb32ca commit 2037101
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Lottie.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,7 @@
2EAF5B0427A0798700E00531 /* AnimationFontProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EAF59F227A0798700E00531 /* AnimationFontProvider.swift */; };
2EAF5B0527A0798700E00531 /* AnimationFontProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EAF59F227A0798700E00531 /* AnimationFontProvider.swift */; };
2EAF5B0627A0798700E00531 /* AnimationFontProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EAF59F227A0798700E00531 /* AnimationFontProvider.swift */; };
6DB3BDB628243FA5002A276D /* ValueProvidersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DB3BDB528243FA5002A276D /* ValueProvidersTests.swift */; };
A1D5BAAC27C731A500777D06 /* DataURLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1D5BAAB27C731A500777D06 /* DataURLTests.swift */; };
/* End PBXBuildFile section */

Expand Down Expand Up @@ -749,6 +750,7 @@
2EAF59EF27A0798700E00531 /* GradientValueProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradientValueProvider.swift; sourceTree = "<group>"; };
2EAF59F027A0798700E00531 /* PointValueProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PointValueProvider.swift; sourceTree = "<group>"; };
2EAF59F227A0798700E00531 /* AnimationFontProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnimationFontProvider.swift; sourceTree = "<group>"; };
6DB3BDB528243FA5002A276D /* ValueProvidersTests.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = ValueProvidersTests.swift; sourceTree = "<group>"; tabWidth = 2; };
A1D5BAAB27C731A500777D06 /* DataURLTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataURLTests.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -818,6 +820,7 @@
A1D5BAAB27C731A500777D06 /* DataURLTests.swift */,
2E8040BD27A07343006E74CB /* Utils */,
2E044E262820536800FA773B /* AutomaticEngineTests.swift */,
6DB3BDB528243FA5002A276D /* ValueProvidersTests.swift */,
);
path = Tests;
sourceTree = "<group>";
Expand Down Expand Up @@ -1809,6 +1812,7 @@
2EAF59A727A076BC00E00531 /* Bundle+Module.swift in Sources */,
2E8044AE27A07347006E74CB /* Snapshotting+presentationLayer.swift in Sources */,
2E72128527BB32DB0027BC56 /* PerformanceTests.swift in Sources */,
6DB3BDB628243FA5002A276D /* ValueProvidersTests.swift in Sources */,
2E72128327BB329C0027BC56 /* AnimationKeypathTests.swift in Sources */,
2E044E272820536800FA773B /* AutomaticEngineTests.swift in Sources */,
);
Expand Down
7 changes: 7 additions & 0 deletions Sources/Private/CoreAnimation/CoreAnimationLayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,13 @@ extension CoreAnimationLayer: RootAnimationLayer {
return nil
}

func getOriginalValue(for _: AnimationKeypath, atFrame _: AnimationFrameTime?) -> Any? {
LottieLogger.shared.assertionFailure("""
The Core Animation rendering engine doesn't support querying values for individual frames
""")
return nil
}

func layer(for _: AnimationKeypath) -> CALayer? {
LottieLogger.shared.assertionFailure("`AnimationKeypath`s are currently unsupported")
return nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,18 @@ final class MainThreadAnimationLayer: CALayer, RootAnimationLayer {
return nil
}

func getOriginalValue(for keypath: AnimationKeypath, atFrame: AnimationFrameTime?) -> Any? {
for layer in animationLayers {
if
let foundProperties = layer.nodeProperties(for: keypath),
let first = foundProperties.first
{
return first.originalValueProvider.value(frame: atFrame ?? currentFrame)
}
}
return nil
}

func layer(for keypath: AnimationKeypath) -> CALayer? {
for layer in animationLayers {
if let foundLayer = layer.layer(for: keypath) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ class NodeProperty<T>: AnyNodeProperty {

init(provider: AnyValueProvider) {
valueProvider = provider
originalValueProvider = valueProvider
typedContainer = ValueContainer<T>(provider.value(frame: 0) as! T)
typedContainer.setNeedsUpdate()
}

// MARK: Internal

var valueProvider: AnyValueProvider
var originalValueProvider: AnyValueProvider

var valueType: Any.Type { T.self }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ protocol AnyNodeProperty {
/// The value provider for the property
var valueProvider: AnyValueProvider { get }

/// The original value provider for the property
var originalValueProvider: AnyValueProvider { get }

/// The Type of the value provider
var valueType: Any.Type { get }

Expand Down
1 change: 1 addition & 0 deletions Sources/Private/RootAnimationLayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ protocol RootAnimationLayer: CALayer {

func setValueProvider(_ valueProvider: AnyValueProvider, keypath: AnimationKeypath)
func getValue(for keypath: AnimationKeypath, atFrame: AnimationFrameTime?) -> Any?
func getOriginalValue(for keypath: AnimationKeypath, atFrame: AnimationFrameTime?) -> Any?

func layer(for keypath: AnimationKeypath) -> CALayer?
func animatorNodes(for keypath: AnimationKeypath) -> [AnimatorNode]?
Expand Down
10 changes: 10 additions & 0 deletions Sources/Public/Animation/AnimationView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,16 @@ final public class AnimationView: AnimationViewBase {
animationLayer?.getValue(for: keypath, atFrame: atFrame)
}

/// Reads the original value of a property specified by the Keypath.
/// This will ignore any value providers and can be useful when implementing a value providers that makes change to the original value from the animation.
/// Returns nil if no property is found.
///
/// - Parameter for: The keypath used to search for the property.
/// - Parameter atFrame: The Frame Time of the value to query. If nil then the current frame is used.
public func getOriginalValue(for keypath: AnimationKeypath, atFrame: AnimationFrameTime?) -> Any? {
animationLayer?.getOriginalValue(for: keypath, atFrame: atFrame)
}

/// Logs all child keypaths.
public func logHierarchyKeypaths() {
animationLayer?.logHierarchyKeypaths()
Expand Down
27 changes: 27 additions & 0 deletions Tests/ValueProvidersTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// ValueProvidersTests.swift
// LottieTests
//
// Created by Marcelo Fabri on 5/5/22.
//

import Lottie
import XCTest

final class ValueProvidersTests: XCTestCase {

func testGetValue() throws {
let animationView = try XCTUnwrap(SnapshotConfiguration.makeAnimationView(
for: "HamburgerArrow",
configuration: .init(renderingEngine: .mainThread)))

let keypath = AnimationKeypath(keypath: "A1.Shape 1.Stroke 1.Color")
animationView.setValueProvider(ColorValueProvider(.red), keypath: keypath)
let updatedColor = try XCTUnwrap(animationView.getValue(for: keypath, atFrame: 0) as? Color)
XCTAssertEqual(updatedColor, .red)

let originalColor = try XCTUnwrap(animationView.getOriginalValue(for: keypath, atFrame: 0) as? Color)
XCTAssertEqual(originalColor, Color(r: 0.4, g: 0.16, b: 0.7, a: 1))
}

}

0 comments on commit 2037101

Please sign in to comment.