mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2026-01-26 14:01:24 +00:00
Initial work on interactive props
This commit is contained in:
1968
Example/Pods/Pods.xcodeproj/project.pbxproj
generated
1968
Example/Pods/Pods.xcodeproj/project.pbxproj
generated
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,9 @@
|
||||
#import "LOTAnimationView.h"
|
||||
#import "LOTAnimationView_Compat.h"
|
||||
#import "LOTComposition.h"
|
||||
#import "LOTKeypath.h"
|
||||
#import "Lottie.h"
|
||||
#import "LOTValueCallback.h"
|
||||
|
||||
FOUNDATION_EXPORT double LottieVersionNumber;
|
||||
FOUNDATION_EXPORT const unsigned char LottieVersionString[];
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
#import "LOTAnimationView_Compat.h"
|
||||
#import "LOTCacheProvider.h"
|
||||
#import "LOTComposition.h"
|
||||
#import "LOTKeypath.h"
|
||||
#import "Lottie.h"
|
||||
#import "LOTValueCallback.h"
|
||||
|
||||
FOUNDATION_EXPORT double LottieVersionNumber;
|
||||
FOUNDATION_EXPORT const unsigned char LottieVersionString[];
|
||||
|
||||
1
Example/Tests/GeometryTransformTest.json
Normal file
1
Example/Tests/GeometryTransformTest.json
Normal file
@@ -0,0 +1 @@
|
||||
{"v":"4.12.0","fr":23.9759979248047,"ip":0,"op":48.9999957589018,"w":300,"h":300,"nm":"Comp 2","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Scaled","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[150,150,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[68.52,68.52],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.431255026425,0,0.902665022308,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":48.9999957589018,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"TopLeft","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[150,150,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[68.52,68.52],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.431255026425,0,0.902665022308,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-150,-150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":48.9999957589018,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"BottomRight","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[150,150,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[68.52,68.52],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.431255026425,0,0.902665022308,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[150,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":48.9999957589018,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Center","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[150,150,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[68.52,68.52],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.431255026425,0,0.902665022308,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":48.9999957589018,"st":0,"bm":0}]}
|
||||
62
Example/Tests/LAGeometryTest.m
Normal file
62
Example/Tests/LAGeometryTest.m
Normal file
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// LAGeometryTest.m
|
||||
// lottie-ios_Tests
|
||||
//
|
||||
// Created by brandon_withrow on 12/18/17.
|
||||
// Copyright © 2017 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
#import <Lottie/Lottie.h>
|
||||
|
||||
@interface LAGeometryTest : XCTestCase
|
||||
|
||||
@property (nonatomic, strong) LOTAnimationView *animationView;
|
||||
|
||||
@end
|
||||
|
||||
@implementation LAGeometryTest
|
||||
|
||||
- (void)setUp {
|
||||
[super setUp];
|
||||
self.animationView = [LOTAnimationView animationNamed:@"GeometryTransformTest"];
|
||||
}
|
||||
|
||||
- (void)tearDown {
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
[super tearDown];
|
||||
}
|
||||
|
||||
- (void)testAnimationLoaded {
|
||||
XCTAssertNotNil(self.animationView.sceneModel, @"Animation Composition is nil");
|
||||
}
|
||||
|
||||
- (void)testGeometryCenter {
|
||||
LOTKeypath *keypath = [LOTKeypath keypathWithKeys:@"Center", @"Ellipse 1", nil];
|
||||
CGPoint midPoint = CGPointMake(CGRectGetMidX(self.animationView.bounds), CGRectGetMidY(self.animationView.bounds));
|
||||
CGPoint midPointInChildSpace = [self.animationView convertPoint:midPoint toKeypathLayer:keypath];
|
||||
CGPoint midPointInParentSpace = [self.animationView convertPoint:CGPointZero fromKeypathLayer:keypath];
|
||||
XCTAssertTrue((CGPointEqualToPoint(midPointInChildSpace, CGPointZero)), @"Convert to point incorrect");
|
||||
XCTAssertTrue((CGPointEqualToPoint(midPointInParentSpace, midPoint)), @"Convert from point incorrect");
|
||||
}
|
||||
|
||||
- (void)testGeometryBottomRight {
|
||||
LOTKeypath *keypath = [LOTKeypath keypathWithKeys:@"BottomRight", @"Ellipse 1", nil];
|
||||
CGPoint midPoint = CGPointMake(CGRectGetMidX(self.animationView.bounds), CGRectGetMidY(self.animationView.bounds));
|
||||
CGPoint bottomRightPoint = CGPointMake(CGRectGetMaxX(self.animationView.bounds), CGRectGetMaxY(self.animationView.bounds));
|
||||
CGPoint midPointInChildSpace = [self.animationView convertPoint:midPoint toKeypathLayer:keypath];
|
||||
CGPoint midPointInParentSpace = [self.animationView convertPoint:CGPointZero fromKeypathLayer:keypath];
|
||||
XCTAssertTrue((CGPointEqualToPoint(midPointInChildSpace, CGPointMake(-midPoint.x, -midPoint.y))), @"Convert to point incorrect");
|
||||
XCTAssertTrue((CGPointEqualToPoint(midPointInParentSpace, bottomRightPoint)), @"Convert from point incorrect");
|
||||
}
|
||||
|
||||
- (void)testGeometryScaled {
|
||||
LOTKeypath *keypath = [LOTKeypath keypathWithKeys:@"Scaled", @"Ellipse 1", nil];
|
||||
CGPoint bottomRightPoint = CGPointMake(CGRectGetMaxX(self.animationView.bounds), CGRectGetMaxY(self.animationView.bounds));
|
||||
CGPoint topLeftInChildSpace = [self.animationView convertPoint:CGPointZero toKeypathLayer:keypath];
|
||||
CGPoint bottomRightInParentSpace = [self.animationView convertPoint:CGPointMake(75, 75) fromKeypathLayer:keypath];
|
||||
XCTAssertTrue((CGPointEqualToPoint(bottomRightInParentSpace, bottomRightPoint)), @"Convert to point incorrect");
|
||||
XCTAssertTrue((CGPointEqualToPoint(topLeftInChildSpace, CGPointMake(-75, -75))), @"Convert from point incorrect");
|
||||
}
|
||||
|
||||
@end
|
||||
127
Example/Tests/LAKeypathTest.m
Normal file
127
Example/Tests/LAKeypathTest.m
Normal file
@@ -0,0 +1,127 @@
|
||||
//
|
||||
// LAKeypathTest.m
|
||||
// lottie-ios_Tests
|
||||
//
|
||||
// Created by brandon_withrow on 12/14/17.
|
||||
// Copyright © 2017 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
#import <Lottie/Lottie.h>
|
||||
|
||||
@interface LAKeypathTest : XCTestCase
|
||||
|
||||
@property (nonatomic, strong) LOTAnimationView *animationView;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@implementation LAKeypathTest
|
||||
|
||||
- (void)setUp {
|
||||
[super setUp];
|
||||
self.animationView = [LOTAnimationView animationNamed:@"keypathTest"];
|
||||
}
|
||||
|
||||
- (void)tearDown {
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
[super tearDown];
|
||||
}
|
||||
|
||||
- (void)testAnimationLoaded {
|
||||
XCTAssertNotNil(self.animationView.sceneModel, @"Animation Composition is nil");
|
||||
}
|
||||
|
||||
- (void)testExplicitSearch {
|
||||
NSString *searchTerm = @"Shape Layer 1.Shape 1.Path 1";
|
||||
NSArray *results = [self.animationView keysForKeyPath:[LOTKeypath keypathWithString:searchTerm]];
|
||||
XCTAssertTrue((results.count == 1), @"Wrong number of results");
|
||||
NSString *firstObject = results.firstObject;
|
||||
XCTAssertTrue([searchTerm isEqualToString:firstObject], @"Wrong keypath found");
|
||||
}
|
||||
|
||||
- (void)testFuzzyKeySearch_Shape1 {
|
||||
NSArray *results = [self.animationView keysForKeyPath:[LOTKeypath keypathWithKeys:@"**", @"Shape 1", nil]];
|
||||
NSArray *expectedResults = @[@"Shape Layer 1.Shape 1",
|
||||
@"WiggleLayer.Shape 1",
|
||||
@"GroupShapeLayer.Group 1.Shape 1",
|
||||
@"TwoShapeLayer.Shape 1",
|
||||
@"Precomp.DoubleGroupShape.TopGroup.Group 2.Group 1.Shape 1",
|
||||
@"Precomp.GroupShape.Group 1.Shape 1",
|
||||
@"Precomp.SingleShape.Shape 1",
|
||||
@"Precomp.DoubleGroupShape.TopGroup.Group 1.Group 1.Shape 1"];
|
||||
|
||||
NSSet *set1 = [NSSet setWithArray:results];
|
||||
NSSet *set2 = [NSSet setWithArray:expectedResults];
|
||||
XCTAssertTrue([set1 isEqualToSet:set2], @"Wrong keypath found");
|
||||
}
|
||||
|
||||
- (void)testFuzzyKeySearch_Shape1_Path1 {
|
||||
NSArray *results = [self.animationView keysForKeyPath:[LOTKeypath keypathWithKeys:@"**", @"Shape 1", @"Path 1", nil]];
|
||||
NSArray *expectedResults = @[@"GroupShapeLayer.Group 1.Shape 1.Path 1",
|
||||
@"Shape Layer 1.Shape 1.Path 1",
|
||||
@"TwoShapeLayer.Shape 1.Path 1",
|
||||
@"Precomp.DoubleGroupShape.TopGroup.Group 2.Group 1.Shape 1.Path 1",
|
||||
@"Precomp.GroupShape.Group 1.Shape 1.Path 1",
|
||||
@"Precomp.SingleShape.Shape 1.Path 1",
|
||||
@"Precomp.DoubleGroupShape.TopGroup.Group 1.Group 1.Shape 1.Path 1"];
|
||||
|
||||
NSSet *set1 = [NSSet setWithArray:results];
|
||||
NSSet *set2 = [NSSet setWithArray:expectedResults];
|
||||
XCTAssertTrue([set1 isEqualToSet:set2], @"Wrong keypath found");
|
||||
}
|
||||
|
||||
- (void)testWildcardKeySearch_Shape1 {
|
||||
NSArray *results = [self.animationView keysForKeyPath:[LOTKeypath keypathWithKeys:@"*", @"Shape 1", nil]];
|
||||
NSArray *expectedResults = @[@"Shape Layer 1.Shape 1",
|
||||
@"WiggleLayer.Shape 1",
|
||||
@"TwoShapeLayer.Shape 1"];
|
||||
|
||||
NSSet *set1 = [NSSet setWithArray:results];
|
||||
NSSet *set2 = [NSSet setWithArray:expectedResults];
|
||||
XCTAssertTrue([set1 isEqualToSet:set2], @"Wrong keypath found");
|
||||
}
|
||||
|
||||
- (void)testCompoundFuzzyKeySearch_Shape1 {
|
||||
NSArray *results = [self.animationView keysForKeyPath:[LOTKeypath keypathWithKeys:@"**", @"Shape 1", @"*", @"Stroke Width", nil]];
|
||||
NSArray *expectedResults = @[@"Shape Layer 1.Shape 1.Stroke 1.Stroke Width",
|
||||
@"WiggleLayer.Shape 1.Stroke 1.Stroke Width",
|
||||
@"GroupShapeLayer.Group 1.Shape 1.Stroke 1.Stroke Width",
|
||||
@"TwoShapeLayer.Shape 1.Stroke 1.Stroke Width"];
|
||||
|
||||
NSSet *set1 = [NSSet setWithArray:results];
|
||||
NSSet *set2 = [NSSet setWithArray:expectedResults];
|
||||
XCTAssertTrue([set1 isEqualToSet:set2], @"Wrong keypath found");
|
||||
}
|
||||
|
||||
- (void)testDoubleFuzzyKeySearch_Shape1 {
|
||||
NSArray *results = [self.animationView keysForKeyPath:[LOTKeypath keypathWithKeys:@"**", @"Group 1", @"**", @"Path 1", nil]];
|
||||
NSArray *expectedResults = @[@"Precomp.DoubleGroupShape.TopGroup.Group 2.Group 1.Shape 1.Path 1",
|
||||
@"Precomp.GroupShape.Group 1.Shape 2.Path 1",
|
||||
@"Precomp.GroupShape.Group 1.Shape 1.Path 1",
|
||||
@"GroupShapeLayer.Group 1.Shape 2.Path 1",
|
||||
@"GroupShapeLayer.Group 1.Shape 1.Path 1",
|
||||
@"Precomp.DoubleGroupShape.TopGroup.Group 1.Group 1.Shape 2.Path 1",
|
||||
@"Precomp.DoubleGroupShape.TopGroup.Group 1.Group 1.Shape 1.Path 1",
|
||||
@"Precomp.DoubleGroupShape.TopGroup.Group 2.Group 1.Shape 2.Path 1"];
|
||||
|
||||
NSSet *set1 = [NSSet setWithArray:results];
|
||||
NSSet *set2 = [NSSet setWithArray:expectedResults];
|
||||
XCTAssertTrue([set1 isEqualToSet:set2], @"Wrong keypath found");
|
||||
}
|
||||
|
||||
- (void)testKeySearch_Precomp {
|
||||
NSArray *results = [self.animationView keysForKeyPath:[LOTKeypath keypathWithKeys:@"Precomp", nil]];
|
||||
NSArray *expectedResults = @[@"Precomp"];
|
||||
|
||||
NSSet *set1 = [NSSet setWithArray:results];
|
||||
NSSet *set2 = [NSSet setWithArray:expectedResults];
|
||||
XCTAssertTrue([set1 isEqualToSet:set2], @"Wrong keypath found");
|
||||
}
|
||||
|
||||
- (void)testFuzzyKeySearch_Precomp {
|
||||
NSArray *results = [self.animationView keysForKeyPath:[LOTKeypath keypathWithKeys:@"Precomp", @"**", nil]];
|
||||
XCTAssertTrue((results.count == 33), @"Wrong number of results");
|
||||
}
|
||||
|
||||
@end
|
||||
1
Example/Tests/keypathTest.json
Normal file
1
Example/Tests/keypathTest.json
Normal file
File diff suppressed because one or more lines are too long
1
Example/Tests/setValueTest.json
Normal file
1
Example/Tests/setValueTest.json
Normal file
@@ -0,0 +1 @@
|
||||
{"v":"4.12.0","fr":23.9759979248047,"ip":0,"op":48.9999957589018,"w":300,"h":300,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[150,150,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-51],[0,79]],"o":[[0,51],[0,-79]],"v":[[-52.182,-74.182],[32.818,-38.182]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.431255026425,0,0.902665022308,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"n":"0p833_0p833_0p333_0","t":0,"s":[58.182,-52.818],"e":[58.182,102.182],"to":[0,25.8333339691162],"ti":[0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"n":"0p667_1_0p167_0p167","t":29,"s":[58.182,102.182],"e":[58.182,-52.818],"to":[0,0],"ti":[0,25.8333339691162]},{"t":47.9999958454548}],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[69.723,69.723],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.431255026425,0,0.902665022308,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"n":"0p833_0p833_0p333_0","t":0,"s":[-82.139,-74.139],"e":[-82.139,115.861],"to":[0,0],"ti":[0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"n":"0p667_1_0p167_0p167","t":28,"s":[-82.139,115.861],"e":[-82.139,-74.139],"to":[0,0],"ti":[0,0]},{"t":47.9999958454548}],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"n":["0p833_0p833_0p333_0"],"t":0,"s":[45],"e":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"n":["0p667_1_0p167_0p167"],"t":28,"s":[0],"e":[-45]},{"t":47.9999958454548}],"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":48.9999957589018,"st":0,"bm":0}]}
|
||||
@@ -64,9 +64,16 @@
|
||||
622F77091F2BE63100269858 /* X.json in Resources */ = {isa = PBXBuildFile; fileRef = 622F76EB1F2BE63100269858 /* X.json */; };
|
||||
622F770A1F2BE63100269858 /* Y.json in Resources */ = {isa = PBXBuildFile; fileRef = 622F76EC1F2BE63100269858 /* Y.json */; };
|
||||
622F770B1F2BE63100269858 /* Z.json in Resources */ = {isa = PBXBuildFile; fileRef = 622F76ED1F2BE63100269858 /* Z.json */; };
|
||||
6289F3851FE4A3F500C10B3E /* setValueTest.json in Resources */ = {isa = PBXBuildFile; fileRef = 6289F3841FE4A3F500C10B3E /* setValueTest.json */; };
|
||||
6289F3871FE877FC00C10B3E /* GeometryTransformTest.json in Resources */ = {isa = PBXBuildFile; fileRef = 6289F3861FE877FC00C10B3E /* GeometryTransformTest.json */; };
|
||||
6289F3881FE877FC00C10B3E /* GeometryTransformTest.json in Resources */ = {isa = PBXBuildFile; fileRef = 6289F3861FE877FC00C10B3E /* GeometryTransformTest.json */; };
|
||||
6289F38A1FE8784200C10B3E /* LAGeometryTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6289F3891FE8784200C10B3E /* LAGeometryTest.m */; };
|
||||
629EC57F1F54BFF1005B2C59 /* LAControlsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 629EC57E1F54BFF1005B2C59 /* LAControlsViewController.m */; };
|
||||
629EC5811F54C00B005B2C59 /* Switch.json in Resources */ = {isa = PBXBuildFile; fileRef = 629EC5801F54C00B005B2C59 /* Switch.json */; };
|
||||
629EC5891F54C925005B2C59 /* Switch_States.json in Resources */ = {isa = PBXBuildFile; fileRef = 629EC5881F54C925005B2C59 /* Switch_States.json */; };
|
||||
62A62AE81FE2FF2B001A2C2F /* keypathTest.json in Resources */ = {isa = PBXBuildFile; fileRef = 62A62AE71FE2FF2A001A2C2F /* keypathTest.json */; };
|
||||
62A62AE91FE2FF2B001A2C2F /* keypathTest.json in Resources */ = {isa = PBXBuildFile; fileRef = 62A62AE71FE2FF2A001A2C2F /* keypathTest.json */; };
|
||||
62A62AEB1FE2FFB0001A2C2F /* LAKeypathTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 62A62AEA1FE2FFB0001A2C2F /* LAKeypathTest.m */; };
|
||||
62B2546A1E3A8D310035A842 /* LottieRootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 62B254631E3A8D310035A842 /* LottieRootViewController.m */; };
|
||||
62B2546B1E3A8D310035A842 /* AnimationExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 62B254651E3A8D310035A842 /* AnimationExplorerViewController.m */; };
|
||||
62B2546C1E3A8D310035A842 /* AnimationTransitionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 62B254671E3A8D310035A842 /* AnimationTransitionViewController.m */; };
|
||||
@@ -169,10 +176,15 @@
|
||||
622F76EC1F2BE63100269858 /* Y.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Y.json; sourceTree = "<group>"; };
|
||||
622F76ED1F2BE63100269858 /* Z.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Z.json; sourceTree = "<group>"; };
|
||||
62569CB2461B12ABC97FCB96 /* lottie-ios.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = "lottie-ios.podspec"; path = "../lottie-ios.podspec"; sourceTree = "<group>"; };
|
||||
6289F3841FE4A3F500C10B3E /* setValueTest.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = setValueTest.json; sourceTree = "<group>"; };
|
||||
6289F3861FE877FC00C10B3E /* GeometryTransformTest.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = GeometryTransformTest.json; sourceTree = "<group>"; };
|
||||
6289F3891FE8784200C10B3E /* LAGeometryTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LAGeometryTest.m; sourceTree = "<group>"; };
|
||||
629EC57D1F54BFF1005B2C59 /* LAControlsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LAControlsViewController.h; sourceTree = "<group>"; };
|
||||
629EC57E1F54BFF1005B2C59 /* LAControlsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LAControlsViewController.m; sourceTree = "<group>"; };
|
||||
629EC5801F54C00B005B2C59 /* Switch.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Switch.json; sourceTree = "<group>"; };
|
||||
629EC5881F54C925005B2C59 /* Switch_States.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Switch_States.json; sourceTree = "<group>"; };
|
||||
62A62AE71FE2FF2A001A2C2F /* keypathTest.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = keypathTest.json; sourceTree = "<group>"; };
|
||||
62A62AEA1FE2FFB0001A2C2F /* LAKeypathTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LAKeypathTest.m; sourceTree = "<group>"; };
|
||||
62B254621E3A8D310035A842 /* LottieRootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LottieRootViewController.h; sourceTree = "<group>"; };
|
||||
62B254631E3A8D310035A842 /* LottieRootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LottieRootViewController.m; sourceTree = "<group>"; };
|
||||
62B254641E3A8D310035A842 /* AnimationExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimationExplorerViewController.h; sourceTree = "<group>"; };
|
||||
@@ -337,6 +349,8 @@
|
||||
6003F5B5195388D20070C39A /* Tests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6289F3891FE8784200C10B3E /* LAGeometryTest.m */,
|
||||
62A62AEA1FE2FFB0001A2C2F /* LAKeypathTest.m */,
|
||||
6003F5BB195388D20070C39A /* Tests.m */,
|
||||
);
|
||||
path = Tests;
|
||||
@@ -349,9 +363,12 @@
|
||||
622F76CF1F2BE63100269858 /* TypeFace */,
|
||||
622F76B51F2BE58100269858 /* 9squares-AlBoardman.json */,
|
||||
629EC5801F54C00B005B2C59 /* Switch.json */,
|
||||
62A62AE71FE2FF2A001A2C2F /* keypathTest.json */,
|
||||
622F76B61F2BE58100269858 /* HamburgerArrow.json */,
|
||||
6289F3861FE877FC00C10B3E /* GeometryTransformTest.json */,
|
||||
622F76B71F2BE58100269858 /* IconTransitions.json */,
|
||||
622F76B81F2BE58100269858 /* LottieLogo1_masked.json */,
|
||||
6289F3841FE4A3F500C10B3E /* setValueTest.json */,
|
||||
622F76BA1F2BE58100269858 /* LottieLogo2.json */,
|
||||
622F76B91F2BE58100269858 /* LottieLogo1.json */,
|
||||
622F76BB1F2BE58100269858 /* MotionCorpse-Jrcanest.json */,
|
||||
@@ -592,6 +609,7 @@
|
||||
48A852311E3A9E71000AD155 /* lottie_logo.png in Resources */,
|
||||
622F76F11F2BE63100269858 /* BlinkingCursor.json in Resources */,
|
||||
622F76C71F2BE58100269858 /* LottieLogo2.json in Resources */,
|
||||
62A62AE81FE2FF2B001A2C2F /* keypathTest.json in Resources */,
|
||||
622F76C91F2BE58100269858 /* PinJump.json in Resources */,
|
||||
622F76F51F2BE63100269858 /* D.json in Resources */,
|
||||
622F76CD1F2BE58100269858 /* vcTransition2.json in Resources */,
|
||||
@@ -603,6 +621,7 @@
|
||||
622F77031F2BE63100269858 /* R.json in Resources */,
|
||||
71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */,
|
||||
622F76CA1F2BE58100269858 /* TwitterHeart.json in Resources */,
|
||||
6289F3871FE877FC00C10B3E /* GeometryTransformTest.json in Resources */,
|
||||
622F76F91F2BE63100269858 /* H.json in Resources */,
|
||||
622F76C61F2BE58100269858 /* LottieLogo1.json in Resources */,
|
||||
622F77051F2BE63100269858 /* T.json in Resources */,
|
||||
@@ -629,6 +648,7 @@
|
||||
622F76C51F2BE58100269858 /* LottieLogo1_masked.json in Resources */,
|
||||
622F76FC1F2BE63100269858 /* K.json in Resources */,
|
||||
622F76CC1F2BE58100269858 /* vcTransition1.json in Resources */,
|
||||
6289F3851FE4A3F500C10B3E /* setValueTest.json in Resources */,
|
||||
622F76FA1F2BE63100269858 /* I.json in Resources */,
|
||||
622F76F21F2BE63100269858 /* C.json in Resources */,
|
||||
622F76F81F2BE63100269858 /* G.json in Resources */,
|
||||
@@ -642,6 +662,8 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
62A62AE91FE2FF2B001A2C2F /* keypathTest.json in Resources */,
|
||||
6289F3881FE877FC00C10B3E /* GeometryTransformTest.json in Resources */,
|
||||
6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -820,6 +842,8 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
6003F5BC195388D20070C39A /* Tests.m in Sources */,
|
||||
6289F38A1FE8784200C10B3E /* LAGeometryTest.m in Sources */,
|
||||
62A62AEB1FE2FFB0001A2C2F /* LAKeypathTest.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -1007,7 +1031,7 @@
|
||||
INFOPLIST_FILE = "Tests/Tests-Info.plist";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/lottie-ios_Example.app/lottie-ios_Example";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Lottie-Example.app/Lottie-Example";
|
||||
WRAPPER_EXTENSION = xctest;
|
||||
};
|
||||
name = Debug;
|
||||
@@ -1027,7 +1051,7 @@
|
||||
INFOPLIST_FILE = "Tests/Tests-Info.plist";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/lottie-ios_Example.app/lottie-ios_Example";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Lottie-Example.app/Lottie-Example";
|
||||
WRAPPER_EXTENSION = xctest;
|
||||
};
|
||||
name = Release;
|
||||
|
||||
@@ -101,6 +101,11 @@
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-83.5x83.5@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ios-marketing",
|
||||
"size" : "1024x1024",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
|
||||
@@ -190,6 +190,12 @@
|
||||
6274D0231F1E830E00E05049 /* LOTTransformInterpolator.m in Sources */ = {isa = PBXBuildFile; fileRef = 6274D0201F1E830E00E05049 /* LOTTransformInterpolator.m */; };
|
||||
6274D0241F1E830E00E05049 /* LOTTransformInterpolator.m in Sources */ = {isa = PBXBuildFile; fileRef = 6274D0201F1E830E00E05049 /* LOTTransformInterpolator.m */; };
|
||||
6274D0251F1E830E00E05049 /* LOTTransformInterpolator.m in Sources */ = {isa = PBXBuildFile; fileRef = 6274D0201F1E830E00E05049 /* LOTTransformInterpolator.m */; };
|
||||
6279981B1FE1D04600B2DDD9 /* LOTKeypath.h in Headers */ = {isa = PBXBuildFile; fileRef = 627998191FE1D04600B2DDD9 /* LOTKeypath.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
6279981C1FE1D04600B2DDD9 /* LOTKeypath.m in Sources */ = {isa = PBXBuildFile; fileRef = 6279981A1FE1D04600B2DDD9 /* LOTKeypath.m */; };
|
||||
6279981D1FE1D99F00B2DDD9 /* LOTKeypath.h in Headers */ = {isa = PBXBuildFile; fileRef = 627998191FE1D04600B2DDD9 /* LOTKeypath.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
6279981E1FE1D9AC00B2DDD9 /* LOTKeypath.m in Sources */ = {isa = PBXBuildFile; fileRef = 6279981A1FE1D04600B2DDD9 /* LOTKeypath.m */; };
|
||||
6279981F1FE1D9AD00B2DDD9 /* LOTKeypath.m in Sources */ = {isa = PBXBuildFile; fileRef = 6279981A1FE1D04600B2DDD9 /* LOTKeypath.m */; };
|
||||
627998201FE1D9C800B2DDD9 /* LOTKeypath.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 627998191FE1D04600B2DDD9 /* LOTKeypath.h */; };
|
||||
6289053E1F33EA0F005154FA /* LOTCacheProvider.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = EE498E3D1F336A4900D1DFCD /* LOTCacheProvider.h */; };
|
||||
628905411F352472005154FA /* LOTRadialGradientLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 6289053F1F352472005154FA /* LOTRadialGradientLayer.h */; };
|
||||
628905421F352472005154FA /* LOTRadialGradientLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 6289053F1F352472005154FA /* LOTRadialGradientLayer.h */; };
|
||||
@@ -204,6 +210,11 @@
|
||||
629EC5371F50DFFF005B2C59 /* LOTAnimatedControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 629EC5361F50DFFF005B2C59 /* LOTAnimatedControl.m */; };
|
||||
629EC5381F50E00F005B2C59 /* LOTAnimatedControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 629EC5361F50DFFF005B2C59 /* LOTAnimatedControl.m */; };
|
||||
629EC5391F50E02A005B2C59 /* LOTAnimatedControl.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 629EC5321F50DFE4005B2C59 /* LOTAnimatedControl.h */; };
|
||||
62A62B4A1FE48220001A2C2F /* LOTValueCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 62A62B481FE48220001A2C2F /* LOTValueCallback.h */; };
|
||||
62A62B4B1FE48220001A2C2F /* LOTValueCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 62A62B481FE48220001A2C2F /* LOTValueCallback.h */; };
|
||||
62A62B4C1FE48220001A2C2F /* LOTValueCallback.m in Sources */ = {isa = PBXBuildFile; fileRef = 62A62B491FE48220001A2C2F /* LOTValueCallback.m */; };
|
||||
62A62B4D1FE48220001A2C2F /* LOTValueCallback.m in Sources */ = {isa = PBXBuildFile; fileRef = 62A62B491FE48220001A2C2F /* LOTValueCallback.m */; };
|
||||
62A62B4E1FE4A1DC001A2C2F /* LOTValueCallback.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 62A62B481FE48220001A2C2F /* LOTValueCallback.h */; };
|
||||
62BFC2DE1F14298D0068A342 /* LOTAnimatorNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 62BFC2D01F14298D0068A342 /* LOTAnimatorNode.h */; };
|
||||
62BFC2DF1F14298D0068A342 /* LOTAnimatorNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 62BFC2D01F14298D0068A342 /* LOTAnimatorNode.h */; };
|
||||
62BFC2E01F14298D0068A342 /* LOTAnimatorNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 62BFC2D11F14298D0068A342 /* LOTAnimatorNode.m */; };
|
||||
@@ -300,6 +311,8 @@
|
||||
dstPath = include/Lottie;
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
62A62B4E1FE4A1DC001A2C2F /* LOTValueCallback.h in CopyFiles */,
|
||||
627998201FE1D9C800B2DDD9 /* LOTKeypath.h in CopyFiles */,
|
||||
629EC5391F50E02A005B2C59 /* LOTAnimatedControl.h in CopyFiles */,
|
||||
629EC5311F50CC53005B2C59 /* LOTAnimatedSwitch.h in CopyFiles */,
|
||||
6289053E1F33EA0F005154FA /* LOTCacheProvider.h in CopyFiles */,
|
||||
@@ -398,12 +411,16 @@
|
||||
6274D0191F1E82D000E05049 /* LOTLayerContainer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LOTLayerContainer.m; sourceTree = "<group>"; };
|
||||
6274D01F1F1E830E00E05049 /* LOTTransformInterpolator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LOTTransformInterpolator.h; path = "lottie-ios/Classes/RenderSystem/InterpolatorNodes/LOTTransformInterpolator.h"; sourceTree = SOURCE_ROOT; };
|
||||
6274D0201F1E830E00E05049 /* LOTTransformInterpolator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LOTTransformInterpolator.m; path = "lottie-ios/Classes/RenderSystem/InterpolatorNodes/LOTTransformInterpolator.m"; sourceTree = SOURCE_ROOT; };
|
||||
627998191FE1D04600B2DDD9 /* LOTKeypath.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LOTKeypath.h; sourceTree = "<group>"; };
|
||||
6279981A1FE1D04600B2DDD9 /* LOTKeypath.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LOTKeypath.m; sourceTree = "<group>"; };
|
||||
6289053F1F352472005154FA /* LOTRadialGradientLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LOTRadialGradientLayer.h; sourceTree = "<group>"; };
|
||||
628905401F352472005154FA /* LOTRadialGradientLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LOTRadialGradientLayer.m; sourceTree = "<group>"; };
|
||||
629EC52A1F50CBF7005B2C59 /* LOTAnimatedSwitch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LOTAnimatedSwitch.h; sourceTree = "<group>"; };
|
||||
629EC52E1F50CC2E005B2C59 /* LOTAnimatedSwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LOTAnimatedSwitch.m; sourceTree = "<group>"; };
|
||||
629EC5321F50DFE4005B2C59 /* LOTAnimatedControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LOTAnimatedControl.h; sourceTree = "<group>"; };
|
||||
629EC5361F50DFFF005B2C59 /* LOTAnimatedControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LOTAnimatedControl.m; sourceTree = "<group>"; };
|
||||
62A62B481FE48220001A2C2F /* LOTValueCallback.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LOTValueCallback.h; sourceTree = "<group>"; };
|
||||
62A62B491FE48220001A2C2F /* LOTValueCallback.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LOTValueCallback.m; sourceTree = "<group>"; };
|
||||
62BFC2D01F14298D0068A342 /* LOTAnimatorNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LOTAnimatorNode.h; path = "lottie-ios/Classes/RenderSystem/LOTAnimatorNode.h"; sourceTree = SOURCE_ROOT; };
|
||||
62BFC2D11F14298D0068A342 /* LOTAnimatorNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LOTAnimatorNode.m; path = "lottie-ios/Classes/RenderSystem/LOTAnimatorNode.m"; sourceTree = SOURCE_ROOT; };
|
||||
62BFC2D21F14298D0068A342 /* LOTFillRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LOTFillRenderer.h; path = "lottie-ios/Classes/RenderSystem/RenderNodes/LOTFillRenderer.h"; sourceTree = SOURCE_ROOT; };
|
||||
@@ -552,12 +569,14 @@
|
||||
481A4A571E4A7885003CF62B /* Private */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6279981A1FE1D04600B2DDD9 /* LOTKeypath.m */,
|
||||
629EC5361F50DFFF005B2C59 /* LOTAnimatedControl.m */,
|
||||
629EC52E1F50CC2E005B2C59 /* LOTAnimatedSwitch.m */,
|
||||
EE498E3B1F336A3B00D1DFCD /* LOTCacheProvider.m */,
|
||||
62E27B491F3115AF0098420E /* LOTAnimationCache.m */,
|
||||
622F77101F2BF6AA00269858 /* LOTComposition.m */,
|
||||
481A4A581E4A7885003CF62B /* LOTAnimationTransitionController.m */,
|
||||
62A62B491FE48220001A2C2F /* LOTValueCallback.m */,
|
||||
481A4A591E4A7885003CF62B /* LOTAnimationView.m */,
|
||||
481A4A5A1E4A7885003CF62B /* LOTAnimationView_Internal.h */,
|
||||
);
|
||||
@@ -702,6 +721,8 @@
|
||||
2DBA16351B4FA408937A16CE /* LOTAnimationView_Compat.h */,
|
||||
622F770D1F2BF6A000269858 /* LOTComposition.h */,
|
||||
FA1F5A9F1E42B52800FF36BF /* LOTAnimationView.h */,
|
||||
62A62B481FE48220001A2C2F /* LOTValueCallback.h */,
|
||||
627998191FE1D04600B2DDD9 /* LOTKeypath.h */,
|
||||
62CA59C41E3C179F002D7188 /* LOTAnimationTransitionController.h */,
|
||||
629EC52A1F50CBF7005B2C59 /* LOTAnimatedSwitch.h */,
|
||||
629EC5321F50DFE4005B2C59 /* LOTAnimatedControl.h */,
|
||||
@@ -725,6 +746,7 @@
|
||||
622F770E1F2BF6A000269858 /* LOTComposition.h in Headers */,
|
||||
481A4AAF1E4A7885003CF62B /* LOTModels.h in Headers */,
|
||||
FA1F5AA01E42B52800FF36BF /* LOTAnimationView.h in Headers */,
|
||||
6279981B1FE1D04600B2DDD9 /* LOTKeypath.h in Headers */,
|
||||
481A4A9F1E4A7885003CF62B /* UIColor+Expanded.h in Headers */,
|
||||
481A4AB51E4A7885003CF62B /* LOTShapeFill.h in Headers */,
|
||||
621A4F701F2275980065E14F /* LOTTrimPathNode.h in Headers */,
|
||||
@@ -765,6 +787,7 @@
|
||||
62BFC2DE1F14298D0068A342 /* LOTAnimatorNode.h in Headers */,
|
||||
481A4AB11E4A7885003CF62B /* LOTShapeCircle.h in Headers */,
|
||||
622F75E91F29508D00269858 /* LOTShapeGradientFill.h in Headers */,
|
||||
62A62B4A1FE48220001A2C2F /* LOTValueCallback.h in Headers */,
|
||||
628905411F352472005154FA /* LOTRadialGradientLayer.h in Headers */,
|
||||
62BFC2E31F14298D0068A342 /* LOTFillRenderer.h in Headers */,
|
||||
62BFC3031F1449380068A342 /* LOTBezierData.h in Headers */,
|
||||
@@ -806,6 +829,7 @@
|
||||
481A4AC21E4A7885003CF62B /* LOTShapeRectangle.h in Headers */,
|
||||
62BFC2F31F14298D0068A342 /* LOTRenderGroup.h in Headers */,
|
||||
628905421F352472005154FA /* LOTRadialGradientLayer.h in Headers */,
|
||||
62A62B4B1FE48220001A2C2F /* LOTValueCallback.h in Headers */,
|
||||
62C9EA441F1FDBF000DE7D07 /* LOTCircleAnimator.h in Headers */,
|
||||
62BFC3041F1449380068A342 /* LOTBezierData.h in Headers */,
|
||||
6201FAE71F200B4A00A047C9 /* LOTMaskContainer.h in Headers */,
|
||||
@@ -818,6 +842,7 @@
|
||||
622F76361F2A91CA00269858 /* LOTPolystarAnimator.h in Headers */,
|
||||
481A4AD61E4A7885003CF62B /* LOTAnimationView_Internal.h in Headers */,
|
||||
FA1F5AA11E42B52800FF36BF /* LOTAnimationView.h in Headers */,
|
||||
6279981D1FE1D99F00B2DDD9 /* LOTKeypath.h in Headers */,
|
||||
62BFC2EE1F14298D0068A342 /* LOTPathAnimator.h in Headers */,
|
||||
62E27B471F31158B0098420E /* LOTAnimationCache.h in Headers */,
|
||||
62BFC2DF1F14298D0068A342 /* LOTAnimatorNode.h in Headers */,
|
||||
@@ -988,6 +1013,7 @@
|
||||
6274CF8D1F16F29200E05049 /* LOTPointInterpolator.m in Sources */,
|
||||
481A4AC71E4A7885003CF62B /* LOTShapeStroke.m in Sources */,
|
||||
6274CF9B1F17E92F00E05049 /* LOTSizeInterpolator.m in Sources */,
|
||||
6279981C1FE1D04600B2DDD9 /* LOTKeypath.m in Sources */,
|
||||
62BFC2E51F14298D0068A342 /* LOTFillRenderer.m in Sources */,
|
||||
481A4AA91E4A7885003CF62B /* LOTLayer.m in Sources */,
|
||||
62C9EA4C1F1FE6C800DE7D07 /* LOTRoundedRectAnimator.m in Sources */,
|
||||
@@ -998,6 +1024,7 @@
|
||||
62BFC2F41F14298D0068A342 /* LOTRenderGroup.m in Sources */,
|
||||
6274CEBB1F157DCD00E05049 /* LOTNumberInterpolator.m in Sources */,
|
||||
481A4ABB1E4A7885003CF62B /* LOTShapeGroup.m in Sources */,
|
||||
62A62B4C1FE48220001A2C2F /* LOTValueCallback.m in Sources */,
|
||||
481A4AAD1E4A7885003CF62B /* LOTMask.m in Sources */,
|
||||
62BFC2EF1F14298D0068A342 /* LOTPathAnimator.m in Sources */,
|
||||
622F762E1F2A8CBA00269858 /* LOTShapeStar.m in Sources */,
|
||||
@@ -1048,6 +1075,7 @@
|
||||
62C9EA4E1F1FE6C800DE7D07 /* LOTRoundedRectAnimator.m in Sources */,
|
||||
622F75ED1F29508D00269858 /* LOTShapeGradientFill.m in Sources */,
|
||||
621A4F741F2275980065E14F /* LOTTrimPathNode.m in Sources */,
|
||||
6279981F1FE1D9AD00B2DDD9 /* LOTKeypath.m in Sources */,
|
||||
84FE13081E4C1553009B157C /* UIColor+Expanded.m in Sources */,
|
||||
621A4F6C1F216DC60065E14F /* LOTBezierPath.m in Sources */,
|
||||
62BFC2F61F14298D0068A342 /* LOTRenderGroup.m in Sources */,
|
||||
@@ -1095,6 +1123,7 @@
|
||||
6274D0101F1D6CE200E05049 /* LOTStrokeRenderer.m in Sources */,
|
||||
62BFC3061F1449380068A342 /* LOTBezierData.m in Sources */,
|
||||
62C9EA271F1EB49000DE7D07 /* LOTCompositionContainer.m in Sources */,
|
||||
6279981E1FE1D9AC00B2DDD9 /* LOTKeypath.m in Sources */,
|
||||
48183C9F1E54E20B0039F121 /* CGGeometry+LOTAdditions.m in Sources */,
|
||||
481A4AAE1E4A7885003CF62B /* LOTMask.m in Sources */,
|
||||
62C9EA461F1FDBF000DE7D07 /* LOTCircleAnimator.m in Sources */,
|
||||
@@ -1127,6 +1156,7 @@
|
||||
622F77121F2BF6AA00269858 /* LOTComposition.m in Sources */,
|
||||
62BFC2F01F14298D0068A342 /* LOTPathAnimator.m in Sources */,
|
||||
622F76581F2AC70400269858 /* LOTGradientFillRender.m in Sources */,
|
||||
62A62B4D1FE48220001A2C2F /* LOTValueCallback.m in Sources */,
|
||||
622F76381F2A91CA00269858 /* LOTPolystarAnimator.m in Sources */,
|
||||
6274D01D1F1E82D000E05049 /* LOTLayerContainer.m in Sources */,
|
||||
481A4AAA1E4A7885003CF62B /* LOTLayer.m in Sources */,
|
||||
|
||||
Binary file not shown.
Binary file not shown.
BIN
_AeFiles/KeypathTest.aep
Normal file
BIN
_AeFiles/KeypathTest.aep
Normal file
Binary file not shown.
@@ -16,13 +16,37 @@
|
||||
withLayerGroup:(LOTLayerGroup * _Nullable)childLayerGroup
|
||||
withAssestGroup:(LOTAssetGroup * _Nullable)assetGroup;
|
||||
|
||||
- (nullable NSArray *)keysForKeyPath:(nonnull LOTKeypath *)keypath;
|
||||
|
||||
- (CGPoint)convertPoint:(CGPoint)point
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath
|
||||
withParentLayer:(CALayer *_Nonnull)parent;
|
||||
|
||||
- (CGRect)convertRect:(CGRect)rect
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath
|
||||
withParentLayer:(CALayer *_Nonnull)parent;
|
||||
|
||||
- (CGPoint)convertPoint:(CGPoint)point
|
||||
fromKeypathLayer:(nonnull LOTKeypath *)keypath
|
||||
withParentLayer:(CALayer *_Nonnull)parent;
|
||||
|
||||
- (CGRect)convertRect:(CGRect)rect
|
||||
fromKeypathLayer:(nonnull LOTKeypath *)keypath
|
||||
withParentLayer:(CALayer *_Nonnull)parent;
|
||||
|
||||
- (void)addSublayer:(nonnull CALayer *)subLayer
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath;
|
||||
|
||||
- (void)maskSublayer:(nonnull CALayer *)subLayer
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath;
|
||||
|
||||
- (void)addSublayer:(nonnull CALayer *)subLayer
|
||||
toLayerNamed:(nonnull NSString *)layerName
|
||||
applyTransform:(BOOL)applyTransform;
|
||||
applyTransform:(BOOL)applyTransform __deprecated;
|
||||
|
||||
- (CGRect)convertRect:(CGRect)rect
|
||||
fromLayer:(CALayer *_Nonnull)fromlayer
|
||||
toLayerNamed:(NSString *_Nonnull)layerName;
|
||||
toLayerNamed:(NSString *_Nonnull)layerName __deprecated;
|
||||
|
||||
@property (nonatomic, readonly, nonnull) NSArray<LOTLayerContainer *> *childLayers;
|
||||
@property (nonatomic, readonly, nonnull) NSDictionary *childMap;
|
||||
|
||||
@@ -10,10 +10,15 @@
|
||||
#import "LOTAsset.h"
|
||||
#import "CGGeometry+LOTAdditions.h"
|
||||
#import "LOTHelpers.h"
|
||||
#import "LOTValueInterpolator.h"
|
||||
#import "LOTAnimatorNode.h"
|
||||
#import "LOTRenderNode.h"
|
||||
#import "LOTRenderGroup.h"
|
||||
|
||||
@implementation LOTCompositionContainer {
|
||||
NSNumber *_frameOffset;
|
||||
CALayer *DEBUG_Center;
|
||||
NSMutableDictionary *_keypathCache;
|
||||
}
|
||||
|
||||
- (instancetype)initWithModel:(LOTLayer *)layer
|
||||
@@ -42,7 +47,7 @@
|
||||
}
|
||||
|
||||
- (void)initializeWithChildGroup:(LOTLayerGroup *)childGroup
|
||||
withAssetGroup:(LOTAssetGroup *)assetGroup {
|
||||
withAssetGroup:(LOTAssetGroup *)assetGroup {
|
||||
NSMutableDictionary *childMap = [NSMutableDictionary dictionary];
|
||||
NSMutableArray *children = [NSMutableArray array];
|
||||
NSArray *reversedItems = [[childGroup.layers reverseObjectEnumerator] allObjects];
|
||||
@@ -92,6 +97,134 @@
|
||||
if (ENABLE_DEBUG_LOGGING) NSLog(@"-------------------- ------------------------------- --------------------");
|
||||
}
|
||||
|
||||
- (void)setViewportBounds:(CGRect)viewportBounds {
|
||||
[super setViewportBounds:viewportBounds];
|
||||
for (LOTLayerContainer *layer in _childLayers) {
|
||||
layer.viewportBounds = viewportBounds;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)searchNodesForKeypath:(LOTKeypath * _Nonnull)keypath {
|
||||
if (self.layerName != nil) {
|
||||
[super searchNodesForKeypath:keypath];
|
||||
}
|
||||
if (self.layerName == nil ||
|
||||
[keypath pushKey:self.layerName]) {
|
||||
for (LOTLayerContainer *child in _childLayers) {
|
||||
[child searchNodesForKeypath:keypath];
|
||||
}
|
||||
if (self.layerName != nil) {
|
||||
[keypath popKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setValueCallback:(nonnull LOTValueCallback *)callbackBlock
|
||||
forKeypath:(nonnull LOTKeypath *)keypath {
|
||||
if (self.layerName != nil) {
|
||||
[super setValueCallback:callbackBlock forKeypath:keypath];
|
||||
}
|
||||
if (self.layerName == nil ||
|
||||
[keypath pushKey:self.layerName]) {
|
||||
for (LOTLayerContainer *child in _childLayers) {
|
||||
[child setValueCallback:callbackBlock forKeypath:keypath];
|
||||
}
|
||||
if (self.layerName != nil) {
|
||||
[keypath popKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (nullable NSArray *)keysForKeyPath:(nonnull LOTKeypath *)keypath {
|
||||
if (_keypathCache == nil) {
|
||||
_keypathCache = [NSMutableDictionary dictionary];
|
||||
}
|
||||
[self searchNodesForKeypath:keypath];
|
||||
[_keypathCache addEntriesFromDictionary:keypath.searchResults];
|
||||
return keypath.searchResults.allKeys;
|
||||
}
|
||||
|
||||
- (CALayer *)_layerForKeypath:(nonnull LOTKeypath *)keypath {
|
||||
LOTAnimatorNode *node = _keypathCache[keypath.absoluteKeypath];
|
||||
if (node == nil) {
|
||||
[self keysForKeyPath:keypath];
|
||||
node = _keypathCache[keypath.absoluteKeypath];
|
||||
}
|
||||
if (node == nil) {
|
||||
NSLog(@"LOTComposition could not find layer for keypath:%@", keypath.absoluteKeypath);
|
||||
return nil;
|
||||
}
|
||||
if (![node isKindOfClass:[LOTRenderNode class]]) {
|
||||
NSLog(@"LOTComposition: Keypath return non-layer node:%@ ", keypath.absoluteKeypath);
|
||||
return nil;
|
||||
}
|
||||
if ([node isKindOfClass:[LOTRenderGroup class]]) {
|
||||
return [(LOTRenderGroup *)node containerLayer];
|
||||
}
|
||||
LOTRenderNode *renderNode = (LOTRenderNode *)node;
|
||||
return renderNode.outputLayer;
|
||||
}
|
||||
|
||||
- (CGPoint)convertPoint:(CGPoint)point
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath
|
||||
withParentLayer:(CALayer *_Nonnull)parent{
|
||||
CALayer *layer = [self _layerForKeypath:keypath];
|
||||
if (!layer) {
|
||||
return CGPointZero;
|
||||
}
|
||||
return [parent convertPoint:point toLayer:layer];
|
||||
}
|
||||
|
||||
- (CGRect)convertRect:(CGRect)rect
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath
|
||||
withParentLayer:(CALayer *_Nonnull)parent{
|
||||
CALayer *layer = [self _layerForKeypath:keypath];
|
||||
if (!layer) {
|
||||
return CGRectZero;
|
||||
}
|
||||
return [parent convertRect:rect toLayer:layer];
|
||||
}
|
||||
|
||||
- (CGPoint)convertPoint:(CGPoint)point
|
||||
fromKeypathLayer:(nonnull LOTKeypath *)keypath
|
||||
withParentLayer:(CALayer *_Nonnull)parent{
|
||||
CALayer *layer = [self _layerForKeypath:keypath];
|
||||
if (!layer) {
|
||||
return CGPointZero;
|
||||
}
|
||||
return [parent convertPoint:point fromLayer:layer];
|
||||
}
|
||||
|
||||
- (CGRect)convertRect:(CGRect)rect
|
||||
fromKeypathLayer:(nonnull LOTKeypath *)keypath
|
||||
withParentLayer:(CALayer *_Nonnull)parent{
|
||||
CALayer *layer = [self _layerForKeypath:keypath];
|
||||
if (!layer) {
|
||||
return CGRectZero;
|
||||
}
|
||||
return [parent convertRect:rect fromLayer:layer];
|
||||
}
|
||||
|
||||
- (void)addSublayer:(nonnull CALayer *)subLayer
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath {
|
||||
CALayer *layer = [self _layerForKeypath:keypath];
|
||||
if (layer) {
|
||||
[layer addSublayer:subLayer];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)maskSublayer:(nonnull CALayer *)subLayer
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath {
|
||||
CALayer *layer = [self _layerForKeypath:keypath];
|
||||
if (layer) {
|
||||
[layer.superlayer addSublayer:subLayer];
|
||||
[layer removeFromSuperlayer];
|
||||
subLayer.mask = layer;
|
||||
}
|
||||
}
|
||||
|
||||
# pragma mark - DEPRECATED
|
||||
|
||||
- (BOOL)setValue:(nonnull id)value
|
||||
forKeypath:(nonnull NSString *)keypath
|
||||
atFrame:(nullable NSNumber *)frame {
|
||||
@@ -149,13 +282,6 @@
|
||||
return xRect;
|
||||
}
|
||||
|
||||
- (void)setViewportBounds:(CGRect)viewportBounds {
|
||||
[super setViewportBounds:viewportBounds];
|
||||
for (LOTLayerContainer *layer in _childLayers) {
|
||||
layer.viewportBounds = viewportBounds;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)logHierarchyKeypathsWithParent:(NSString * _Nullable)parent {
|
||||
NSString *keypath = parent;
|
||||
if (parent && self.layerName) {
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#import "LOTPlatformCompat.h"
|
||||
#import "LOTLayer.h"
|
||||
#import "LOTLayerGroup.h"
|
||||
#import "LOTKeypath.h"
|
||||
#import "LOTValueCallback.h"
|
||||
|
||||
@interface LOTLayerContainer : CALayer
|
||||
|
||||
@@ -19,15 +21,21 @@
|
||||
@property (nonatomic, nullable) NSNumber *currentFrame;
|
||||
@property (nonatomic, assign) CGRect viewportBounds;
|
||||
@property (nonatomic, readonly, nonnull) CALayer *wrapperLayer;
|
||||
@property (nonatomic, readonly, nonnull) NSDictionary *valueInterpolators;
|
||||
- (void)displayWithFrame:(NSNumber * _Nonnull)frame;
|
||||
- (void)displayWithFrame:(NSNumber * _Nonnull)frame forceUpdate:(BOOL)forceUpdate;
|
||||
|
||||
- (void)addAndMaskSublayer:(nonnull CALayer *)subLayer;
|
||||
- (void)addAndMaskSublayer:(nonnull CALayer *)subLayer __deprecated;
|
||||
|
||||
- (BOOL)setValue:(nonnull id)value
|
||||
forKeypath:(nonnull NSString *)keypath
|
||||
atFrame:(nullable NSNumber *)frame;
|
||||
atFrame:(nullable NSNumber *)frame __deprecated;
|
||||
|
||||
- (void)logHierarchyKeypathsWithParent:(NSString * _Nullable)parent;
|
||||
- (void)logHierarchyKeypathsWithParent:(NSString * _Nullable)parent __deprecated;
|
||||
|
||||
- (void)searchNodesForKeypath:(LOTKeypath * _Nonnull)keypath;
|
||||
|
||||
- (void)setValueCallback:(nonnull LOTValueCallback *)callbackBlock
|
||||
forKeypath:(nonnull LOTKeypath *)keypath;
|
||||
|
||||
@end
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
CALayer *DEBUG_Center;
|
||||
LOTRenderGroup *_contentsGroup;
|
||||
LOTMaskContainer *_maskLayer;
|
||||
NSDictionary *_valueInterpolators;
|
||||
}
|
||||
|
||||
@dynamic currentFrame;
|
||||
@@ -102,6 +101,19 @@
|
||||
}
|
||||
|
||||
NSMutableDictionary *interpolators = [NSMutableDictionary dictionary];
|
||||
interpolators[@"Opacity"] = _opacityInterpolator;
|
||||
interpolators[@"Anchor Point"] = _transformInterpolator.anchorInterpolator;
|
||||
interpolators[@"Scale"] = _transformInterpolator.scaleInterpolator;
|
||||
interpolators[@"Rotation"] = _transformInterpolator.rotationInterpolator;
|
||||
if (_transformInterpolator.positionXInterpolator &&
|
||||
_transformInterpolator.positionYInterpolator) {
|
||||
interpolators[@"X Position"] = _transformInterpolator.positionXInterpolator;
|
||||
interpolators[@"Y Position"] = _transformInterpolator.positionYInterpolator;
|
||||
} else if (_transformInterpolator.positionInterpolator) {
|
||||
interpolators[@"Position"] = _transformInterpolator.positionInterpolator;
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
interpolators[@"Transform.Opacity"] = _opacityInterpolator;
|
||||
interpolators[@"Transform.Anchor Point"] = _transformInterpolator.anchorInterpolator;
|
||||
interpolators[@"Transform.Scale"] = _transformInterpolator.scaleInterpolator;
|
||||
@@ -241,6 +253,39 @@
|
||||
_maskLayer.currentFrame = frame;
|
||||
}
|
||||
|
||||
- (void)setViewportBounds:(CGRect)viewportBounds {
|
||||
_viewportBounds = viewportBounds;
|
||||
if (_maskLayer) {
|
||||
CGPoint center = LOT_RectGetCenterPoint(viewportBounds);
|
||||
viewportBounds.origin = CGPointMake(-center.x, -center.y);
|
||||
_maskLayer.bounds = viewportBounds;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)searchNodesForKeypath:(LOTKeypath * _Nonnull)keypath {
|
||||
[_contentsGroup searchNodesForKeypath:keypath];
|
||||
}
|
||||
|
||||
- (void)setValueCallback:(nonnull LOTValueCallback *)callbackBlock
|
||||
forKeypath:(nonnull LOTKeypath *)keypath {
|
||||
if ([keypath pushKey:self.layerName]) {
|
||||
// Matches self.
|
||||
if ([keypath pushKey:@"Transform"]) {
|
||||
// Is a transform node, check interpolators
|
||||
LOTValueInterpolator *interpolator = _valueInterpolators[keypath.currentKey];
|
||||
if (interpolator) {
|
||||
// We have a match!
|
||||
[interpolator setValueCallback:callbackBlock];
|
||||
}
|
||||
[keypath popKey];
|
||||
}
|
||||
[keypath popKey];
|
||||
}
|
||||
[_contentsGroup setValueCallback:callbackBlock forKeypath:keypath];
|
||||
}
|
||||
|
||||
# pragma mark - DEPRECATED
|
||||
|
||||
- (void)addAndMaskSublayer:(nonnull CALayer *)subLayer {
|
||||
[_wrapperLayer addSublayer:subLayer];
|
||||
}
|
||||
@@ -289,15 +334,6 @@
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)setViewportBounds:(CGRect)viewportBounds {
|
||||
_viewportBounds = viewportBounds;
|
||||
if (_maskLayer) {
|
||||
CGPoint center = LOT_RectGetCenterPoint(viewportBounds);
|
||||
viewportBounds.origin = CGPointMake(-center.x, -center.y);
|
||||
_maskLayer.bounds = viewportBounds;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)logHierarchyKeypathsWithParent:(NSString * _Nullable)parent {
|
||||
[_contentsGroup logHierarchyKeypathsWithParent:parent];
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface LOTBezierPath : NSObject
|
||||
|
||||
+ (instancetype)pathWithCGPath:(CGPathRef)path;
|
||||
|
||||
+ (instancetype)newPath;
|
||||
|
||||
- (void)LOT_moveToPoint:(CGPoint)point;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#import "CGGeometry+LOTAdditions.h"
|
||||
|
||||
typedef struct LOT_Subpath LOT_Subpath;
|
||||
typedef void(^LOTBezierPathEnumerationHandler)(const CGPathElement *element);
|
||||
|
||||
struct LOT_Subpath {
|
||||
CGPathElementType type;
|
||||
@@ -36,6 +37,12 @@ struct LOT_Subpath {
|
||||
|
||||
// MARK - Lifecycle
|
||||
|
||||
+ (instancetype)pathWithCGPath:(CGPathRef)path {
|
||||
LOTBezierPath *returnPath = [LOTBezierPath newPath];
|
||||
[returnPath setWithCGPath:path];
|
||||
return returnPath;
|
||||
}
|
||||
|
||||
+ (instancetype)newPath {
|
||||
return [[LOTBezierPath alloc] init];
|
||||
}
|
||||
@@ -281,8 +288,7 @@ struct LOT_Subpath {
|
||||
CGFloat totalLength = _length;
|
||||
|
||||
[self _clearPathData];
|
||||
|
||||
|
||||
|
||||
LOT_Subpath *subpath = headSubpath_;
|
||||
headSubpath_ = NULL;
|
||||
tailSubpath_ = NULL;
|
||||
@@ -416,4 +422,50 @@ struct LOT_Subpath {
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - From CGPath
|
||||
|
||||
- (void)setWithCGPath:(CGPathRef)path {
|
||||
[self lot_enumeratePath:path elementsUsingBlock:^(const CGPathElement *element) {
|
||||
switch (element->type) {
|
||||
case kCGPathElementMoveToPoint: {
|
||||
CGPoint point = element ->points[0];
|
||||
[self LOT_moveToPoint:point];
|
||||
break;
|
||||
}
|
||||
case kCGPathElementAddLineToPoint: {
|
||||
CGPoint point = element ->points[0];
|
||||
[self LOT_addLineToPoint:point];
|
||||
break;
|
||||
}
|
||||
case kCGPathElementAddQuadCurveToPoint: {
|
||||
break;
|
||||
}
|
||||
case kCGPathElementAddCurveToPoint: {
|
||||
CGPoint point1 = element->points[0];
|
||||
CGPoint point2 = element->points[1];
|
||||
CGPoint point3 = element->points[2];
|
||||
[self LOT_addCurveToPoint:point3 controlPoint1:point1 controlPoint2:point2];
|
||||
break;
|
||||
}
|
||||
case kCGPathElementCloseSubpath: {
|
||||
[self LOT_closePath];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)lot_enumeratePath:(CGPathRef)cgPath elementsUsingBlock:(LOTBezierPathEnumerationHandler)handler {
|
||||
void CGPathEnumerationCallback(void *info, const CGPathElement *element);
|
||||
CGPathApply(cgPath, (__bridge void * _Nullable)(handler), CGPathEnumerationCallback);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
void CGPathEnumerationCallback(void *info, const CGPathElement *element)
|
||||
{
|
||||
LOTBezierPathEnumerationHandler handler = (__bridge LOTBezierPathEnumerationHandler)(info);
|
||||
if (handler) {
|
||||
handler(element);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ static NSString * const kCompContainerAnimationKey = @"play";
|
||||
CGFloat _playRangeEndProgress;
|
||||
NSBundle *_bundle;
|
||||
CGFloat _animationProgress;
|
||||
|
||||
// Properties for tracking automatic restoration of animation.
|
||||
BOOL _shouldRestoreStateWhenAttachedToWindow;
|
||||
LOTAnimationCompletionBlock _completionBlockToRestoreWhenAttachedToWindow;
|
||||
@@ -159,9 +158,6 @@ static NSString * const kCompContainerAnimationKey = @"play";
|
||||
_sceneModel = model;
|
||||
_compContainer = [[LOTCompositionContainer alloc] initWithModel:nil inLayerGroup:nil withLayerGroup:_sceneModel.layerGroup withAssestGroup:_sceneModel.assetGroup];
|
||||
[self.layer addSublayer:_compContainer];
|
||||
if (ENABLE_DEBUG_LOGGING) {
|
||||
[self logHierarchyKeypaths];
|
||||
}
|
||||
[self _restoreState];
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
@@ -414,66 +410,97 @@ static NSString * const kCompContainerAnimationKey = @"play";
|
||||
}
|
||||
}
|
||||
|
||||
# pragma mark - External Methods - Other
|
||||
# pragma mark - External Methods - Interactive Controls
|
||||
|
||||
- (void)setValueCallback:(nonnull LOTValueCallback *)callbackBlock
|
||||
forKeypath:(nonnull LOTKeypath *)keypath {
|
||||
[_compContainer setValueCallback:callbackBlock forKeypath:keypath];
|
||||
[self _layoutAndForceUpdate];
|
||||
}
|
||||
|
||||
- (nullable NSArray *)keysForKeyPath:(nonnull LOTKeypath *)keypath {
|
||||
return [_compContainer keysForKeyPath:keypath];
|
||||
}
|
||||
|
||||
- (CGPoint)convertPoint:(CGPoint)point
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath {
|
||||
[self _layoutAndForceUpdate];
|
||||
return [_compContainer convertPoint:point toKeypathLayer:keypath withParentLayer:self.layer];
|
||||
}
|
||||
|
||||
- (CGRect)convertRect:(CGRect)rect
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath {
|
||||
[self _layoutAndForceUpdate];
|
||||
return [_compContainer convertRect:rect toKeypathLayer:keypath withParentLayer:self.layer];
|
||||
}
|
||||
|
||||
- (CGPoint)convertPoint:(CGPoint)point
|
||||
fromKeypathLayer:(nonnull LOTKeypath *)keypath {
|
||||
[self _layoutAndForceUpdate];
|
||||
return [_compContainer convertPoint:point fromKeypathLayer:keypath withParentLayer:self.layer];
|
||||
}
|
||||
|
||||
- (CGRect)convertRect:(CGRect)rect
|
||||
fromKeypathLayer:(nonnull LOTKeypath *)keypath {
|
||||
[self _layoutAndForceUpdate];
|
||||
return [_compContainer convertRect:rect fromKeypathLayer:keypath withParentLayer:self.layer];
|
||||
}
|
||||
|
||||
#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
|
||||
|
||||
- (void)addSubview:(nonnull LOTView *)view
|
||||
toLayerNamed:(nonnull NSString *)layer
|
||||
applyTransform:(BOOL)applyTransform {
|
||||
[self _layout];
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath {
|
||||
[self _layoutAndForceUpdate];
|
||||
CGRect viewRect = view.frame;
|
||||
LOTView *wrapperView = [[LOTView alloc] initWithFrame:viewRect];
|
||||
view.frame = view.bounds;
|
||||
view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
[wrapperView addSubview:view];
|
||||
[self addSubview:wrapperView];
|
||||
[_compContainer addSublayer:wrapperView.layer toLayerNamed:layer applyTransform:applyTransform];
|
||||
[_compContainer addSublayer:wrapperView.layer toKeypathLayer:keypath];
|
||||
}
|
||||
|
||||
- (void)maskSubview:(nonnull LOTView *)view
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath {
|
||||
[self _layoutAndForceUpdate];
|
||||
CGRect viewRect = view.frame;
|
||||
LOTView *wrapperView = [[LOTView alloc] initWithFrame:viewRect];
|
||||
view.frame = view.bounds;
|
||||
view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
[wrapperView addSubview:view];
|
||||
[self addSubview:wrapperView];
|
||||
[_compContainer maskSublayer:wrapperView.layer toKeypathLayer:keypath];
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
- (void)addSubview:(nonnull LOTView *)view
|
||||
toLayerNamed:(nonnull NSString *)layer
|
||||
applyTransform:(BOOL)applyTransform {
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath {
|
||||
[self _layout];
|
||||
CGRect viewRect = view.frame;
|
||||
LOTView *wrapperView = [[LOTView alloc] initWithFrame:viewRect];
|
||||
view.frame = view.bounds;
|
||||
view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
||||
[wrapperView addSubview:view];
|
||||
[self addSubview:wrapperView];
|
||||
[_compContainer addSublayer:wrapperView.layer toLayerNamed:layer applyTransform:applyTransform];
|
||||
[_compContainer addSublayer:wrapperView.layer toKeypathLayer:keypath];
|
||||
}
|
||||
|
||||
- (void)maskSubview:(nonnull LOTView *)view
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath {
|
||||
[self _layout];
|
||||
CGRect viewRect = view.frame;
|
||||
LOTView *wrapperView = [[LOTView alloc] initWithFrame:viewRect];
|
||||
view.frame = view.bounds;
|
||||
view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
||||
[wrapperView addSubview:view];
|
||||
[self addSubview:wrapperView];
|
||||
[_compContainer maskSublayer:wrapperView.layer toKeypathLayer:keypath];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
- (CGRect)convertRect:(CGRect)rect
|
||||
toLayerNamed:(NSString *_Nullable)layerName {
|
||||
[self _layout];
|
||||
if (layerName == nil) {
|
||||
return [self.layer convertRect:rect toLayer:_compContainer];
|
||||
}
|
||||
return [_compContainer convertRect:rect fromLayer:self.layer toLayerNamed:layerName];
|
||||
}
|
||||
|
||||
- (void)setValue:(nonnull id)value
|
||||
forKeypath:(nonnull NSString *)keypath
|
||||
atFrame:(nullable NSNumber *)frame{
|
||||
BOOL didUpdate = [_compContainer setValue:value forKeypath:keypath atFrame:frame];
|
||||
if (didUpdate) {
|
||||
[CATransaction begin];
|
||||
[CATransaction setDisableActions:YES];
|
||||
[_compContainer displayWithFrame:_compContainer.currentFrame forceUpdate:YES];
|
||||
[CATransaction commit];
|
||||
} else {
|
||||
NSLog(@"%s: Keypath Not Found: %@", __PRETTY_FUNCTION__, keypath);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)logHierarchyKeypaths {
|
||||
[_compContainer logHierarchyKeypathsWithParent:nil];
|
||||
}
|
||||
|
||||
# pragma mark - Semi-Private Methods
|
||||
|
||||
- (CALayer * _Nullable)layerForKey:(NSString * _Nonnull)keyname {
|
||||
@@ -615,6 +642,14 @@ static NSString * const kCompContainerAnimationKey = @"play";
|
||||
|
||||
#endif
|
||||
|
||||
- (void)_layoutAndForceUpdate {
|
||||
[CATransaction begin];
|
||||
[CATransaction setDisableActions:YES];
|
||||
[self _layout];
|
||||
[_compContainer displayWithFrame:_compContainer.currentFrame forceUpdate:YES];
|
||||
[CATransaction commit];
|
||||
}
|
||||
|
||||
- (void)_layout {
|
||||
CGPoint centerPoint = LOT_RectGetCenterPoint(self.bounds);
|
||||
CATransform3D xform;
|
||||
@@ -671,4 +706,68 @@ static NSString * const kCompContainerAnimationKey = @"play";
|
||||
}
|
||||
}
|
||||
|
||||
# pragma mark - DEPRECATED
|
||||
|
||||
#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
|
||||
|
||||
- (void)addSubview:(nonnull LOTView *)view
|
||||
toLayerNamed:(nonnull NSString *)layer
|
||||
applyTransform:(BOOL)applyTransform {
|
||||
NSLog(@"%s: Function is DEPRECATED. Please use addSubview:forKeypathLayer:", __PRETTY_FUNCTION__);
|
||||
[self _layout];
|
||||
CGRect viewRect = view.frame;
|
||||
LOTView *wrapperView = [[LOTView alloc] initWithFrame:viewRect];
|
||||
view.frame = view.bounds;
|
||||
view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
[wrapperView addSubview:view];
|
||||
[self addSubview:wrapperView];
|
||||
[_compContainer addSublayer:wrapperView.layer toLayerNamed:layer applyTransform:applyTransform];
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
- (void)addSubview:(nonnull LOTView *)view
|
||||
toLayerNamed:(nonnull NSString *)layer
|
||||
applyTransform:(BOOL)applyTransform {
|
||||
NSLog(@"%s: Function is DEPRECATED. Please use addSubview:forKeypathLayer:", __PRETTY_FUNCTION__);
|
||||
CGRect viewRect = view.frame;
|
||||
LOTView *wrapperView = [[LOTView alloc] initWithFrame:viewRect];
|
||||
view.frame = view.bounds;
|
||||
view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
||||
[wrapperView addSubview:view];
|
||||
[self addSubview:wrapperView];
|
||||
[_compContainer addSublayer:wrapperView.layer toLayerNamed:layer applyTransform:applyTransform];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
- (CGRect)convertRect:(CGRect)rect
|
||||
toLayerNamed:(NSString *_Nullable)layerName {
|
||||
NSLog(@"%s: Function is DEPRECATED. Please use convertRect:forKeypathLayer:", __PRETTY_FUNCTION__);
|
||||
[self _layout];
|
||||
if (layerName == nil) {
|
||||
return [self.layer convertRect:rect toLayer:_compContainer];
|
||||
}
|
||||
return [_compContainer convertRect:rect fromLayer:self.layer toLayerNamed:layerName];
|
||||
}
|
||||
|
||||
- (void)setValue:(nonnull id)value
|
||||
forKeypath:(nonnull NSString *)keypath
|
||||
atFrame:(nullable NSNumber *)frame{
|
||||
NSLog(@"%s: Function is DEPRECATED. Please use setValueCallback:forKeypath:", __PRETTY_FUNCTION__);
|
||||
BOOL didUpdate = [_compContainer setValue:value forKeypath:keypath atFrame:frame];
|
||||
if (didUpdate) {
|
||||
[CATransaction begin];
|
||||
[CATransaction setDisableActions:YES];
|
||||
[_compContainer displayWithFrame:_compContainer.currentFrame forceUpdate:YES];
|
||||
[CATransaction commit];
|
||||
} else {
|
||||
NSLog(@"%s: Keypath Not Found: %@", __PRETTY_FUNCTION__, keypath);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)logHierarchyKeypaths {
|
||||
[_compContainer logHierarchyKeypathsWithParent:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
140
lottie-ios/Classes/Private/LOTKeypath.m
Normal file
140
lottie-ios/Classes/Private/LOTKeypath.m
Normal file
@@ -0,0 +1,140 @@
|
||||
//
|
||||
// LOTKeypath.m
|
||||
// Lottie_iOS
|
||||
//
|
||||
// Created by brandon_withrow on 12/13/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTKeypath.h"
|
||||
|
||||
NSString *const kLOTKeypathEnd = @"LOTENDKEYPATH";
|
||||
|
||||
@implementation LOTKeypath {
|
||||
NSInteger _currentDepth;
|
||||
NSMutableArray<NSNumber *> *_fuzzyDepthStack;
|
||||
NSMutableArray *_currentStack;
|
||||
NSArray *_keys;
|
||||
NSMutableDictionary *_searchResults;
|
||||
}
|
||||
|
||||
+ (nonnull LOTKeypath *)keypathWithString:(nonnull NSString *)keypath {
|
||||
return [[LOTKeypath alloc] initWithKeys:[keypath componentsSeparatedByString:@"."]];
|
||||
}
|
||||
|
||||
+ (nonnull LOTKeypath *)keypathWithKeys:(nonnull NSString *)firstKey, ... {
|
||||
NSMutableArray *keys = [NSMutableArray array];
|
||||
va_list args;
|
||||
va_start(args, firstKey);
|
||||
for (NSString *arg = firstKey; arg != nil; arg = va_arg(args, NSString*))
|
||||
{
|
||||
[keys addObject:arg];
|
||||
}
|
||||
va_end(args);
|
||||
return [[LOTKeypath alloc] initWithKeys:keys];
|
||||
}
|
||||
|
||||
- (instancetype)initWithKeys:(NSArray *)keys {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_keys = [NSArray arrayWithArray:keys];
|
||||
NSMutableString *absolutePath = [NSMutableString string];
|
||||
for (int i = 0; i < _keys.count; i++) {
|
||||
if (i > 0) {
|
||||
[absolutePath appendString:@"."];
|
||||
}
|
||||
[absolutePath appendString:_keys[i]];
|
||||
}
|
||||
_currentStack = [NSMutableArray array];
|
||||
_absoluteKeypath = absolutePath;
|
||||
_currentDepth = 0;
|
||||
_fuzzyDepthStack = [NSMutableArray array];
|
||||
_searchResults = [NSMutableDictionary dictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)pushKey:(nonnull NSString *)key {
|
||||
if (_currentDepth == _keys.count &&
|
||||
self.hasFuzzyWildcard == NO) {
|
||||
return NO;
|
||||
}
|
||||
NSString *current = self.currentKey;
|
||||
if (self.hasWildcard ||
|
||||
[current isEqualToString:key]) {
|
||||
[_currentStack addObject:[key copy]];
|
||||
_currentDepth ++;
|
||||
if (self.hasFuzzyWildcard) {
|
||||
[_fuzzyDepthStack addObject:@(_currentDepth)];
|
||||
}
|
||||
return YES;
|
||||
} else if (self.hasFuzzyWildcard) {
|
||||
[_currentStack addObject:[key copy]];
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)popKey {
|
||||
if (_currentDepth == 0) {
|
||||
return;
|
||||
}
|
||||
NSInteger stackCount = _currentStack.count;
|
||||
[_currentStack removeLastObject];
|
||||
|
||||
if (self.hasFuzzyWildcard ) {
|
||||
if (stackCount == _fuzzyDepthStack.lastObject.integerValue) {
|
||||
[_fuzzyDepthStack removeLastObject];
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
_currentDepth --;
|
||||
}
|
||||
|
||||
- (void)popToRootKey {
|
||||
_currentDepth = 0;
|
||||
[_currentStack removeAllObjects];
|
||||
[_fuzzyDepthStack removeAllObjects];
|
||||
}
|
||||
|
||||
- (NSString *)currentKey {
|
||||
if (_currentDepth == _keys.count) {
|
||||
return kLOTKeypathEnd;
|
||||
}
|
||||
return _keys[_currentDepth];
|
||||
}
|
||||
|
||||
- (NSString *)currentKeyPath {
|
||||
return [_currentStack componentsJoinedByString:@"."];
|
||||
}
|
||||
|
||||
- (BOOL)hasWildcard {
|
||||
if (_currentDepth == _keys.count) {
|
||||
return NO;
|
||||
}
|
||||
return ([_keys[_currentDepth] isEqualToString:@"**"] ||
|
||||
[_keys[_currentDepth] isEqualToString:@"*"]);
|
||||
}
|
||||
|
||||
- (BOOL)hasFuzzyWildcard {
|
||||
if (_currentDepth == 0 ||
|
||||
_currentDepth > _keys.count) {
|
||||
return NO;
|
||||
}
|
||||
return [_keys[_currentDepth - 1] isEqualToString:@"**"];
|
||||
}
|
||||
|
||||
- (BOOL)endOfKeypath {
|
||||
return (_currentDepth == _keys.count);
|
||||
}
|
||||
|
||||
- (void)addSearchResultForCurrentPath:(id _Nonnull)result {
|
||||
[_searchResults setObject:result forKey:self.currentKeyPath];
|
||||
}
|
||||
|
||||
- (NSDictionary *)searchResults {
|
||||
return _searchResults;
|
||||
}
|
||||
|
||||
@end
|
||||
63
lottie-ios/Classes/Private/LOTValueCallback.m
Normal file
63
lottie-ios/Classes/Private/LOTValueCallback.m
Normal file
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// LOTValueCallback.m
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 12/15/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTValueCallback.h"
|
||||
|
||||
@implementation LOTValueCallback
|
||||
|
||||
@end
|
||||
|
||||
@implementation LOTColorValueCallback
|
||||
|
||||
+ (instancetype)withBlock:(LOTColorValueCallbackBlock)block {
|
||||
LOTColorValueCallback *colorCallback = [[LOTColorValueCallback alloc] init];
|
||||
colorCallback.callback = block;
|
||||
return colorCallback;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation LOTNumberValueCallback
|
||||
|
||||
+ (instancetype)withBlock:(LOTNumberValueCallbackBlock)block {
|
||||
LOTNumberValueCallback *numberCallback = [[LOTNumberValueCallback alloc] init];
|
||||
numberCallback.callback = block;
|
||||
return numberCallback;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation LOTPointValueCallback
|
||||
|
||||
+ (instancetype)withBlock:(LOTPointValueCallbackBlock)block {
|
||||
LOTPointValueCallback *callback = [[LOTPointValueCallback alloc] init];
|
||||
callback.callback = block;
|
||||
return callback;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation LOTSizeValueCallback
|
||||
|
||||
+ (instancetype)withBlock:(LOTSizeValueCallbackBlock)block {
|
||||
LOTSizeValueCallback *callback = [[LOTSizeValueCallback alloc] init];
|
||||
callback.callback = block;
|
||||
return callback;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation LOTPathValueCallback
|
||||
|
||||
+ (instancetype)withBlock:(LOTPathValueCallbackBlock)block {
|
||||
LOTPathValueCallback *callback = [[LOTPathValueCallback alloc] init];
|
||||
callback.callback = block;
|
||||
return callback;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -9,6 +9,8 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "LOTAnimationView_Compat.h"
|
||||
#import "LOTComposition.h"
|
||||
#import "LOTKeypath.h"
|
||||
#import "LOTValueCallback.h"
|
||||
|
||||
typedef void (^LOTAnimationCompletionBlock)(BOOL animationFinished);
|
||||
|
||||
@@ -66,7 +68,7 @@ typedef void (^LOTAnimationCompletionBlock)(BOOL animationFinished);
|
||||
@property (nonatomic, strong, nullable) LOTComposition *sceneModel;
|
||||
|
||||
/*
|
||||
* Plays the animation from its current position to a specific progress.
|
||||
* Plays the animation from its current position to a specific progress.
|
||||
* The animation will start from its current position.
|
||||
* If loopAnimation is YES the animation will loop from start position to toProgress indefinitely.
|
||||
* If loopAnimation is NO the animation will stop and the comletion block will be called.
|
||||
@@ -94,7 +96,7 @@ typedef void (^LOTAnimationCompletionBlock)(BOOL animationFinished);
|
||||
withCompletion:(nullable LOTAnimationCompletionBlock)completion;
|
||||
|
||||
/*
|
||||
* Plays the animation from specific frame to a specific frame.
|
||||
* Plays the animation from specific frame to a specific frame.
|
||||
* The animation will start from its current position.
|
||||
* If loopAnimation is YES the animation will loop start frame to end frame indefinitely.
|
||||
* If loopAnimation is NO the animation will stop and the comletion block will be called.
|
||||
@@ -132,35 +134,35 @@ typedef void (^LOTAnimationCompletionBlock)(BOOL animationFinished);
|
||||
* @param keypath NSString . separate keypath
|
||||
* The Keypath is a dot seperated key path that specifies the location of the key to
|
||||
* be set from the After Effects file. This will begin with the Layer Name.
|
||||
* EG "Layer 1.Shape 1.Fill 1.Color"
|
||||
* EG "Layer 1.Shape 1.Fill 1.Color"
|
||||
*
|
||||
* @param frame
|
||||
* The frame is the frame to be set.
|
||||
* If the keyframe exists it will be overwritten, if it does not exist a new
|
||||
* The frame is the frame to be set.
|
||||
* If the keyframe exists it will be overwritten, if it does not exist a new
|
||||
* Linearlly interpolated keyframe will be added
|
||||
**/
|
||||
- (void)setValue:(nonnull id)value
|
||||
forKeypath:(nonnull NSString *)keypath
|
||||
atFrame:(nullable NSNumber *)frame;
|
||||
atFrame:(nullable NSNumber *)frame __deprecated;
|
||||
|
||||
/// Logs all child keypaths
|
||||
- (void)logHierarchyKeypaths;
|
||||
- (void)logHierarchyKeypaths __deprecated;
|
||||
|
||||
/**
|
||||
* Adds a custom subview to the animation using a LayerName from After Effects
|
||||
* Adds a custom subview to the animation using a LayerName from After Effects
|
||||
* as a reference point.
|
||||
*
|
||||
* @param view The custom view instance to be added
|
||||
*
|
||||
* @param layer The string name of the After Effects layer to be referenced.
|
||||
*
|
||||
* @param applyTransform If YES the custom view will be animated to move with the
|
||||
* @param applyTransform If YES the custom view will be animated to move with the
|
||||
* specified After Effects layer.
|
||||
* If NO the custom view will be masked by the After Effects layer
|
||||
**/
|
||||
- (void)addSubview:(nonnull LOTView *)view
|
||||
toLayerNamed:(nonnull NSString *)layer
|
||||
applyTransform:(BOOL)applyTransform;
|
||||
applyTransform:(BOOL)applyTransform __deprecated;
|
||||
|
||||
/**
|
||||
* Converts the given CGRect from the recieving animation view's coordinate space
|
||||
@@ -171,7 +173,30 @@ typedef void (^LOTAnimationCompletionBlock)(BOOL animationFinished);
|
||||
**/
|
||||
|
||||
- (CGRect)convertRect:(CGRect)rect
|
||||
toLayerNamed:(NSString *_Nullable)layerName;
|
||||
toLayerNamed:(NSString *_Nullable)layerName __deprecated;
|
||||
|
||||
- (void)setValueCallback:(nonnull LOTValueCallback *)callback
|
||||
forKeypath:(nonnull LOTKeypath *)keypath;
|
||||
|
||||
- (nullable NSArray *)keysForKeyPath:(nonnull LOTKeypath *)keypath;
|
||||
|
||||
- (CGPoint)convertPoint:(CGPoint)point
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath;
|
||||
|
||||
- (CGRect)convertRect:(CGRect)rect
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath;
|
||||
|
||||
- (CGPoint)convertPoint:(CGPoint)point
|
||||
fromKeypathLayer:(nonnull LOTKeypath *)keypath;
|
||||
|
||||
- (CGRect)convertRect:(CGRect)rect
|
||||
fromKeypathLayer:(nonnull LOTKeypath *)keypath;
|
||||
|
||||
- (void)addSubview:(nonnull LOTView *)view
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath;
|
||||
|
||||
- (void)maskSubview:(nonnull LOTView *)view
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath;
|
||||
|
||||
#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
|
||||
@property (nonatomic) LOTViewContentMode contentMode;
|
||||
|
||||
36
lottie-ios/Classes/PublicHeaders/LOTKeypath.h
Normal file
36
lottie-ios/Classes/PublicHeaders/LOTKeypath.h
Normal file
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// LOTKeypath.h
|
||||
// Lottie_iOS
|
||||
//
|
||||
// Created by brandon_withrow on 12/13/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
extern NSString * _Nonnull const kLOTKeypathEnd;
|
||||
|
||||
@interface LOTKeypath : NSObject
|
||||
|
||||
+ (nonnull LOTKeypath *)keypathWithString:(nonnull NSString *)keypath;
|
||||
|
||||
+ (nonnull LOTKeypath *)keypathWithKeys:(nonnull NSString *)firstKey, ...
|
||||
NS_REQUIRES_NIL_TERMINATION;
|
||||
|
||||
@property (nonatomic, readonly, nonnull) NSString *absoluteKeypath;
|
||||
@property (nonatomic, readonly, nonnull) NSString *currentKey;
|
||||
@property (nonatomic, readonly, nonnull) NSString *currentKeyPath;
|
||||
|
||||
@property (nonatomic, readonly, nonnull) NSDictionary *searchResults;
|
||||
|
||||
@property (nonatomic, readonly) BOOL hasFuzzyWildcard;
|
||||
@property (nonatomic, readonly) BOOL hasWildcard;
|
||||
@property (nonatomic, readonly) BOOL endOfKeypath;
|
||||
|
||||
- (BOOL)pushKey:(nonnull NSString *)key;
|
||||
- (void)popKey;
|
||||
- (void)popToRootKey;
|
||||
|
||||
- (void)addSearchResultForCurrentPath:(id _Nonnull)result;
|
||||
|
||||
@end
|
||||
94
lottie-ios/Classes/PublicHeaders/LOTValueCallback.h
Normal file
94
lottie-ios/Classes/PublicHeaders/LOTValueCallback.h
Normal file
@@ -0,0 +1,94 @@
|
||||
//
|
||||
// LOTValueCallback.h
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 12/15/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "LOTPlatformCompat.h"
|
||||
|
||||
typedef UIColor * _Nonnull (^LOTColorValueCallbackBlock)(CGFloat startFrame,
|
||||
CGFloat endFrame,
|
||||
UIColor * _Nullable startColor,
|
||||
UIColor * _Nullable endColor,
|
||||
UIColor * _Nullable interpolatedColor,
|
||||
CGFloat interpolatedProgress,
|
||||
CGFloat currentFrame);
|
||||
|
||||
typedef CGFloat (^LOTNumberValueCallbackBlock)(CGFloat startFrame,
|
||||
CGFloat endFrame,
|
||||
CGFloat startValue,
|
||||
CGFloat endValue,
|
||||
CGFloat interpolatedValue,
|
||||
CGFloat interpolatedProgress,
|
||||
CGFloat currentFrame);
|
||||
|
||||
typedef CGPoint (^LOTPointValueCallbackBlock)(CGFloat startFrame,
|
||||
CGFloat endFrame,
|
||||
CGPoint startPoint,
|
||||
CGPoint endPoint,
|
||||
CGPoint interpolatedPoint,
|
||||
CGFloat interpolatedProgress,
|
||||
CGFloat currentFrame);
|
||||
|
||||
typedef CGSize (^LOTSizeValueCallbackBlock)(CGFloat startFrame,
|
||||
CGFloat endFrame,
|
||||
CGSize startSize,
|
||||
CGSize endSize,
|
||||
CGSize interpolatedSize,
|
||||
CGFloat interpolatedProgress,
|
||||
CGFloat currentFrame);
|
||||
|
||||
typedef UIBezierPath * _Nonnull (^LOTPathValueCallbackBlock)(CGFloat startFrame,
|
||||
CGFloat endFrame,
|
||||
CGFloat interpolatedProgress,
|
||||
CGFloat currentFrame);
|
||||
|
||||
@interface LOTValueCallback : NSObject
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@interface LOTColorValueCallback : LOTValueCallback
|
||||
|
||||
+ (instancetype _Nonnull)withBlock:(LOTColorValueCallbackBlock _Nonnull )block;
|
||||
|
||||
@property (nonatomic, copy, nonnull) LOTColorValueCallbackBlock callback;
|
||||
|
||||
@end
|
||||
|
||||
@interface LOTNumberValueCallback : LOTValueCallback
|
||||
|
||||
+ (instancetype _Nonnull)withBlock:(LOTNumberValueCallbackBlock _Nonnull)block;
|
||||
|
||||
@property (nonatomic, copy, nonnull) LOTNumberValueCallbackBlock callback;
|
||||
|
||||
@end
|
||||
|
||||
@interface LOTPointValueCallback : LOTValueCallback
|
||||
|
||||
+ (instancetype _Nonnull)withBlock:(LOTPointValueCallbackBlock _Nonnull)block;
|
||||
|
||||
@property (nonatomic, copy, nonnull) LOTPointValueCallbackBlock callback;
|
||||
|
||||
@end
|
||||
|
||||
@interface LOTSizeValueCallback : LOTValueCallback
|
||||
|
||||
+ (instancetype _Nonnull)withBlock:(LOTSizeValueCallbackBlock _Nonnull)block;
|
||||
|
||||
@property (nonatomic, copy, nonnull) LOTSizeValueCallbackBlock callback;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@interface LOTPathValueCallback : LOTValueCallback
|
||||
|
||||
+ (instancetype _Nonnull)withBlock:(LOTPathValueCallbackBlock _Nonnull)block;
|
||||
|
||||
@property (nonatomic, copy, nonnull) LOTPathValueCallbackBlock callback;
|
||||
|
||||
|
||||
@end
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#import "LOTValueInterpolator.h"
|
||||
#import "LOTPlatformCompat.h"
|
||||
#import "LOTValueCallback.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@@ -15,6 +16,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (UIColor *)colorForFrame:(NSNumber *)frame;
|
||||
|
||||
@property (nonatomic, strong, nullable) LOTColorValueCallback *colorCallback;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -14,13 +14,19 @@
|
||||
|
||||
- (UIColor *)colorForFrame:(NSNumber *)frame {
|
||||
CGFloat progress = [self progressForFrame:frame];
|
||||
UIColor *returnColor;
|
||||
|
||||
if (progress == 0) {
|
||||
return self.leadingKeyframe.colorValue;
|
||||
returnColor = self.leadingKeyframe.colorValue;
|
||||
} else if (progress == 1) {
|
||||
returnColor = self.trailingKeyframe.colorValue;
|
||||
} else {
|
||||
returnColor = [UIColor LOT_colorByLerpingFromColor:self.leadingKeyframe.colorValue toColor:self.trailingKeyframe.colorValue amount:progress];
|
||||
}
|
||||
if (progress == 1) {
|
||||
return self.trailingKeyframe.colorValue;
|
||||
if (self.hasValueOverride) {
|
||||
return self.colorCallback.callback(self.leadingKeyframe.keyframeTime.floatValue, self.trailingKeyframe.keyframeTime.floatValue, self.leadingKeyframe.colorValue, self.trailingKeyframe.colorValue, returnColor, progress, frame.floatValue);
|
||||
}
|
||||
UIColor *returnColor = [UIColor LOT_colorByLerpingFromColor:self.leadingKeyframe.colorValue toColor:self.trailingKeyframe.colorValue amount:progress];
|
||||
|
||||
return returnColor;
|
||||
}
|
||||
|
||||
@@ -32,4 +38,13 @@
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)setValueCallback:(LOTValueCallback *)valueCallback {
|
||||
NSAssert(([valueCallback isKindOfClass:[LOTColorValueCallback class]]), @"Color Interpolator set with incorrect callback type. Expected LOTColorValueCallback");
|
||||
self.colorCallback = (LOTColorValueCallback *)valueCallback;
|
||||
}
|
||||
|
||||
- (BOOL)hasValueOverride {
|
||||
return self.colorCallback != nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -8,12 +8,15 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "LOTValueInterpolator.h"
|
||||
#import "LOTValueCallback.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
@interface LOTNumberInterpolator : LOTValueInterpolator
|
||||
|
||||
- (CGFloat)floatValueForFrame:(NSNumber *)frame;
|
||||
|
||||
@property (nonatomic, strong, nullable) LOTNumberValueCallback *numberCallback;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -13,13 +13,28 @@
|
||||
|
||||
- (CGFloat)floatValueForFrame:(NSNumber *)frame {
|
||||
CGFloat progress = [self progressForFrame:frame];
|
||||
CGFloat returnValue;
|
||||
if (progress == 0) {
|
||||
return self.leadingKeyframe.floatValue;
|
||||
returnValue = self.leadingKeyframe.floatValue;
|
||||
} else if (progress == 1) {
|
||||
returnValue = self.trailingKeyframe.floatValue;
|
||||
} else {
|
||||
returnValue = LOT_RemapValue(progress, 0, 1, self.leadingKeyframe.floatValue, self.trailingKeyframe.floatValue);
|
||||
}
|
||||
if (progress == 1) {
|
||||
return self.trailingKeyframe.floatValue;
|
||||
if (self.hasValueOverride) {
|
||||
return self.numberCallback.callback(self.leadingKeyframe.keyframeTime.floatValue, self.trailingKeyframe.keyframeTime.floatValue, self.leadingKeyframe.floatValue, self.trailingKeyframe.floatValue, returnValue, progress, frame.floatValue);
|
||||
}
|
||||
return LOT_RemapValue(progress, 0, 1, self.leadingKeyframe.floatValue, self.trailingKeyframe.floatValue);
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
- (BOOL)hasValueOverride {
|
||||
return self.numberCallback != nil;
|
||||
}
|
||||
|
||||
- (void)setValueCallback:(LOTValueCallback *)valueCallback {
|
||||
NSAssert(([valueCallback isKindOfClass:[LOTNumberValueCallback class]]), @"Number Interpolator set with incorrect callback type. Expected LOTNumberValueCallback");
|
||||
self.numberCallback = (LOTNumberValueCallback*)valueCallback;
|
||||
}
|
||||
|
||||
- (id)keyframeDataForValue:(id)value {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#import "LOTValueInterpolator.h"
|
||||
#import "LOTPlatformCompat.h"
|
||||
#import "LOTBezierPath.h"
|
||||
#import "LOTValueCallback.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@@ -16,6 +17,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (LOTBezierPath *)pathForFrame:(NSNumber *)frame cacheLengths:(BOOL)cacheLengths;
|
||||
|
||||
@property (nonatomic, strong, nullable) LOTPathValueCallback *pathCallback;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -13,7 +13,11 @@
|
||||
|
||||
- (LOTBezierPath *)pathForFrame:(NSNumber *)frame cacheLengths:(BOOL)cacheLengths {
|
||||
CGFloat progress = [self progressForFrame:frame];
|
||||
|
||||
if (self.hasValueOverride) {
|
||||
UIBezierPath *path = self.pathCallback.callback(self.leadingKeyframe.keyframeTime.floatValue, self.trailingKeyframe.keyframeTime.floatValue, progress, frame.floatValue);
|
||||
return [LOTBezierPath pathWithCGPath:path.CGPath];
|
||||
}
|
||||
|
||||
LOTBezierPath *returnPath = [[LOTBezierPath alloc] init];
|
||||
returnPath.cacheLengths = cacheLengths;
|
||||
LOTBezierData *leadingData = self.leadingKeyframe.pathData;
|
||||
@@ -62,4 +66,13 @@
|
||||
return returnPath;
|
||||
}
|
||||
|
||||
- (void)setValueCallback:(LOTValueCallback *)valueCallback {
|
||||
NSAssert(([valueCallback isKindOfClass:[LOTPathValueCallback class]]), @"Path Interpolator set with incorrect callback type. Expected LOTPathValueCallback");
|
||||
self.pathCallback = (LOTPathValueCallback*)valueCallback;
|
||||
}
|
||||
|
||||
- (BOOL)hasValueOverride {
|
||||
return self.pathCallback != nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
#import "LOTValueInterpolator.h"
|
||||
#import "LOTValueCallback.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@@ -14,6 +15,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (CGPoint)pointValueForFrame:(NSNumber *)frame;
|
||||
|
||||
@property (nonatomic, strong, nullable) LOTPointValueCallback *pointCallback;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -13,20 +13,33 @@
|
||||
|
||||
- (CGPoint)pointValueForFrame:(NSNumber *)frame {
|
||||
CGFloat progress = [self progressForFrame:frame];
|
||||
CGPoint returnPoint;
|
||||
if (progress == 0) {
|
||||
return self.leadingKeyframe.pointValue;
|
||||
}
|
||||
if (progress == 1) {
|
||||
return self.trailingKeyframe.pointValue;
|
||||
}
|
||||
if (!CGPointEqualToPoint(self.leadingKeyframe.spatialOutTangent, CGPointZero) &&
|
||||
!CGPointEqualToPoint(self.trailingKeyframe.spatialInTangent, CGPointZero)) {
|
||||
returnPoint = self.leadingKeyframe.pointValue;
|
||||
} else if (progress == 1) {
|
||||
returnPoint = self.trailingKeyframe.pointValue;
|
||||
} else if (!CGPointEqualToPoint(self.leadingKeyframe.spatialOutTangent, CGPointZero) ||
|
||||
!CGPointEqualToPoint(self.trailingKeyframe.spatialInTangent, CGPointZero)) {
|
||||
// Spatial Bezier path
|
||||
CGPoint outTan = LOT_PointAddedToPoint(self.leadingKeyframe.pointValue, self.leadingKeyframe.spatialOutTangent);
|
||||
CGPoint inTan = LOT_PointAddedToPoint(self.trailingKeyframe.pointValue, self.trailingKeyframe.spatialInTangent);
|
||||
return LOT_PointInCubicCurve(self.leadingKeyframe.pointValue, outTan, inTan, self.trailingKeyframe.pointValue, progress);
|
||||
returnPoint = LOT_PointInCubicCurve(self.leadingKeyframe.pointValue, outTan, inTan, self.trailingKeyframe.pointValue, progress);
|
||||
} else {
|
||||
returnPoint = LOT_PointInLine(self.leadingKeyframe.pointValue, self.trailingKeyframe.pointValue, progress);
|
||||
}
|
||||
return LOT_PointInLine(self.leadingKeyframe.pointValue, self.trailingKeyframe.pointValue, progress);
|
||||
if (self.hasValueOverride) {
|
||||
return self.pointCallback.callback(self.leadingKeyframe.keyframeTime.floatValue, self.trailingKeyframe.keyframeTime.floatValue, self.leadingKeyframe.pointValue, self.trailingKeyframe.pointValue, returnPoint, progress, frame.floatValue);
|
||||
}
|
||||
return returnPoint;
|
||||
}
|
||||
|
||||
- (BOOL)hasValueOverride {
|
||||
return self.pointCallback != nil;
|
||||
}
|
||||
|
||||
- (void)setValueCallback:(LOTValueCallback *)valueCallback {
|
||||
NSAssert(([valueCallback isKindOfClass:[LOTPointValueCallback class]]), @"Point Interpolator set with incorrect callback type. Expected LOTPointValueCallback");
|
||||
self.pointCallback = (LOTPointValueCallback*)valueCallback;
|
||||
}
|
||||
|
||||
- (id)keyframeDataForValue:(id)value {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
#import "LOTValueInterpolator.h"
|
||||
#import "LOTValueCallback.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@@ -14,6 +15,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (CGSize)sizeValueForFrame:(NSNumber *)frame;
|
||||
|
||||
@property (nonatomic, strong, nullable) LOTSizeValueCallback *sizeCallback;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -14,14 +14,28 @@
|
||||
|
||||
- (CGSize)sizeValueForFrame:(NSNumber *)frame {
|
||||
CGFloat progress = [self progressForFrame:frame];
|
||||
CGSize returnSize;
|
||||
if (progress == 0) {
|
||||
return self.leadingKeyframe.sizeValue;
|
||||
returnSize = self.leadingKeyframe.sizeValue;
|
||||
}else if (progress == 1) {
|
||||
returnSize = self.trailingKeyframe.sizeValue;
|
||||
} else {
|
||||
returnSize = CGSizeMake(LOT_RemapValue(progress, 0, 1, self.leadingKeyframe.sizeValue.width, self.trailingKeyframe.sizeValue.width),
|
||||
LOT_RemapValue(progress, 0, 1, self.leadingKeyframe.sizeValue.height, self.trailingKeyframe.sizeValue.height));
|
||||
}
|
||||
if (progress == 1) {
|
||||
return self.trailingKeyframe.sizeValue;
|
||||
if (self.hasValueOverride) {
|
||||
return self.sizeCallback.callback(self.leadingKeyframe.keyframeTime.floatValue, self.trailingKeyframe.keyframeTime.floatValue, self.leadingKeyframe.sizeValue, self.trailingKeyframe.sizeValue, returnSize, progress, frame.floatValue);
|
||||
}
|
||||
return CGSizeMake(LOT_RemapValue(progress, 0, 1, self.leadingKeyframe.sizeValue.width, self.trailingKeyframe.sizeValue.width),
|
||||
LOT_RemapValue(progress, 0, 1, self.leadingKeyframe.sizeValue.height, self.trailingKeyframe.sizeValue.height));
|
||||
return returnSize;
|
||||
}
|
||||
|
||||
- (BOOL)hasValueOverride {
|
||||
return self.sizeCallback != nil;
|
||||
}
|
||||
|
||||
- (void)setValueCallback:(LOTValueCallback *)valueCallback {
|
||||
NSAssert(([valueCallback isKindOfClass:[LOTSizeValueCallback class]]), @"Size Interpolator set with incorrect callback type. Expected LOTSizeValueCallback");
|
||||
self.sizeCallback = (LOTSizeValueCallback*)valueCallback;
|
||||
}
|
||||
|
||||
- (id)keyframeDataForValue:(id)value {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "LOTKeyframe.h"
|
||||
#import "LOTValueCallback.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@@ -16,11 +17,14 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
- (instancetype)initWithKeyframes:(NSArray <LOTKeyframe *> *)keyframes;
|
||||
|
||||
/// Used to dynamically update keyframe data.
|
||||
- (BOOL)setValue:(id)value atFrame:(NSNumber *)frame;
|
||||
- (BOOL)setValue:(id)value atFrame:(NSNumber *)frame __deprecated;
|
||||
- (id _Nullable)keyframeDataForValue:(id)value;
|
||||
|
||||
@property (nonatomic, weak, nullable) LOTKeyframe *leadingKeyframe;
|
||||
@property (nonatomic, weak, nullable) LOTKeyframe *trailingKeyframe;
|
||||
@property (nonatomic, readonly) BOOL hasValueOverride;
|
||||
|
||||
- (void)setValueCallback:(LOTValueCallback *)valueCallback;
|
||||
|
||||
- (BOOL)hasUpdateForFrame:(NSNumber *)frame;
|
||||
- (CGFloat)progressForFrame:(NSNumber *)frame;
|
||||
|
||||
@@ -30,57 +30,10 @@
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Change keyframe data
|
||||
- (BOOL)setValue:(id)value atFrame:(NSNumber *)frame {
|
||||
id data = [self keyframeDataForValue:value];
|
||||
if (data == nil) {
|
||||
return NO;
|
||||
}
|
||||
if (frame == nil) {
|
||||
frame = @0;
|
||||
}
|
||||
[self updateKeyframeSpanForFrame:frame];
|
||||
if (frame.floatValue == self.leadingKeyframe.keyframeTime.floatValue) {
|
||||
// Is leading frame, replace
|
||||
LOTKeyframe *newKeyframe = [self.leadingKeyframe copyWithData:data];
|
||||
NSMutableArray *keyframes = [NSMutableArray arrayWithArray:_keyframes];
|
||||
NSUInteger idx = [keyframes indexOfObject:self.leadingKeyframe];
|
||||
[keyframes replaceObjectAtIndex:idx withObject:newKeyframe];
|
||||
self.leadingKeyframe = newKeyframe;
|
||||
_keyframes = keyframes;
|
||||
} else if (frame.floatValue == self.trailingKeyframe.keyframeTime.floatValue) {
|
||||
// Is trailing frame
|
||||
LOTKeyframe *newKeyframe = [self.trailingKeyframe copyWithData:data];
|
||||
NSMutableArray *keyframes = [NSMutableArray arrayWithArray:_keyframes];
|
||||
NSUInteger idx = [keyframes indexOfObject:self.trailingKeyframe];
|
||||
[keyframes replaceObjectAtIndex:idx withObject:newKeyframe];
|
||||
self.trailingKeyframe = newKeyframe;
|
||||
_keyframes = keyframes;
|
||||
} else {
|
||||
// Is between leading and trailing. Either can be nil.
|
||||
// For now added keyframes will default to linear interpolation.
|
||||
// TODO BW Add smart bezier interpolation
|
||||
NSMutableDictionary *keyframeDict = [NSMutableDictionary dictionary];
|
||||
keyframeDict[@"s"] = data;
|
||||
keyframeDict[@"t"] = frame;
|
||||
LOTKeyframe *keyframe = [[LOTKeyframe alloc] initWithKeyframe:keyframeDict];
|
||||
NSMutableArray *newKeyframes = [NSMutableArray arrayWithArray:_keyframes];
|
||||
if (self.trailingKeyframe == nil ||
|
||||
self.trailingKeyframe == newKeyframes.lastObject) {
|
||||
[newKeyframes addObject:keyframe];
|
||||
} else {
|
||||
NSInteger idx = [newKeyframes indexOfObject:self.trailingKeyframe];
|
||||
[newKeyframes insertObject:keyframe atIndex:idx];
|
||||
}
|
||||
_keyframes = newKeyframes;
|
||||
self.leadingKeyframe = nil;
|
||||
self.trailingKeyframe = nil;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)hasUpdateForFrame:(NSNumber *)frame {
|
||||
if (self.hasValueOverride) {
|
||||
return YES;
|
||||
}
|
||||
/*
|
||||
Cases we dont update keyframe
|
||||
if time is in span and leading keyframe is hold
|
||||
@@ -212,4 +165,60 @@
|
||||
return progession;
|
||||
}
|
||||
|
||||
- (void)setValueCallback:(LOTValueCallback *)valueCallback {
|
||||
NSAssert((NO), @"Interpolator does not support value callbacks");
|
||||
}
|
||||
|
||||
#pragma mark - DEPRECATED
|
||||
|
||||
// Change keyframe data
|
||||
- (BOOL)setValue:(id)value atFrame:(NSNumber *)frame {
|
||||
id data = [self keyframeDataForValue:value];
|
||||
if (data == nil) {
|
||||
return NO;
|
||||
}
|
||||
if (frame == nil) {
|
||||
frame = @0;
|
||||
}
|
||||
[self updateKeyframeSpanForFrame:frame];
|
||||
if (frame.floatValue == self.leadingKeyframe.keyframeTime.floatValue) {
|
||||
// Is leading frame, replace
|
||||
LOTKeyframe *newKeyframe = [self.leadingKeyframe copyWithData:data];
|
||||
NSMutableArray *keyframes = [NSMutableArray arrayWithArray:_keyframes];
|
||||
NSUInteger idx = [keyframes indexOfObject:self.leadingKeyframe];
|
||||
[keyframes replaceObjectAtIndex:idx withObject:newKeyframe];
|
||||
self.leadingKeyframe = newKeyframe;
|
||||
_keyframes = keyframes;
|
||||
} else if (frame.floatValue == self.trailingKeyframe.keyframeTime.floatValue) {
|
||||
// Is trailing frame
|
||||
LOTKeyframe *newKeyframe = [self.trailingKeyframe copyWithData:data];
|
||||
NSMutableArray *keyframes = [NSMutableArray arrayWithArray:_keyframes];
|
||||
NSUInteger idx = [keyframes indexOfObject:self.trailingKeyframe];
|
||||
[keyframes replaceObjectAtIndex:idx withObject:newKeyframe];
|
||||
self.trailingKeyframe = newKeyframe;
|
||||
_keyframes = keyframes;
|
||||
} else {
|
||||
// Is between leading and trailing. Either can be nil.
|
||||
// For now added keyframes will default to linear interpolation.
|
||||
// TODO BW Add smart bezier interpolation
|
||||
NSMutableDictionary *keyframeDict = [NSMutableDictionary dictionary];
|
||||
keyframeDict[@"s"] = data;
|
||||
keyframeDict[@"t"] = frame;
|
||||
LOTKeyframe *keyframe = [[LOTKeyframe alloc] initWithKeyframe:keyframeDict];
|
||||
NSMutableArray *newKeyframes = [NSMutableArray arrayWithArray:_keyframes];
|
||||
if (self.trailingKeyframe == nil ||
|
||||
self.trailingKeyframe == newKeyframes.lastObject) {
|
||||
[newKeyframes addObject:keyframe];
|
||||
} else {
|
||||
NSInteger idx = [newKeyframes indexOfObject:self.trailingKeyframe];
|
||||
[newKeyframes insertObject:keyframe atIndex:idx];
|
||||
}
|
||||
_keyframes = newKeyframes;
|
||||
self.leadingKeyframe = nil;
|
||||
self.trailingKeyframe = nil;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "LOTPlatformCompat.h"
|
||||
#import "LOTBezierPath.h"
|
||||
#import "LOTKeypath.h"
|
||||
#import "LOTValueCallback.h"
|
||||
|
||||
extern NSInteger indentation_level;
|
||||
@interface LOTAnimatorNode : NSObject
|
||||
@@ -51,18 +53,27 @@ extern NSInteger indentation_level;
|
||||
/// Rebuild all outputs for the node. This is called after upstream updates have been performed.
|
||||
- (void)rebuildOutputs;
|
||||
|
||||
- (void)logString:(NSString *_Nonnull)string;
|
||||
|
||||
- (void)searchNodesForKeypath:(LOTKeypath * _Nonnull)keypath;
|
||||
|
||||
- (void)setValueCallback:(nonnull LOTValueCallback *)callbackBlock
|
||||
forKeypath:(nonnull LOTKeypath *)keypath;
|
||||
|
||||
/*
|
||||
* DEPRECATED
|
||||
*/
|
||||
|
||||
/// Traverses children untill keypath is found and attempts to set the keypath to the value.
|
||||
- (BOOL)setValue:(nonnull id)value
|
||||
forKeyAtPath:(nonnull NSString *)keypath
|
||||
forFrame:(nullable NSNumber *)frame;
|
||||
forFrame:(nullable NSNumber *)frame __deprecated;
|
||||
|
||||
/// Sets the keyframe to the value, to be overwritten by subclasses
|
||||
- (BOOL)setInterpolatorValue:(nonnull id)value
|
||||
forKey:(nonnull NSString *)key
|
||||
forFrame:(nullable NSNumber *)frame;
|
||||
forFrame:(nullable NSNumber *)frame __deprecated;
|
||||
|
||||
- (void)logString:(NSString *_Nonnull)string;
|
||||
|
||||
- (void)logHierarchyKeypathsWithParent:(NSString * _Nullable)parent;
|
||||
- (void)logHierarchyKeypathsWithParent:(NSString * _Nullable)parent __deprecated;
|
||||
|
||||
@end
|
||||
|
||||
@@ -14,7 +14,6 @@ NSInteger indentation_level = 0;
|
||||
|
||||
@implementation LOTAnimatorNode
|
||||
|
||||
|
||||
- (instancetype _Nonnull)initWithInputNode:(LOTAnimatorNode *_Nullable)inputNode
|
||||
keyName:(NSString *_Nullable)keyname {
|
||||
self = [super init];
|
||||
@@ -98,6 +97,39 @@ NSInteger indentation_level = 0;
|
||||
self.inputNode.pathShouldCacheLengths = pathShouldCacheLengths;
|
||||
}
|
||||
|
||||
- (void)searchNodesForKeypath:(LOTKeypath * _Nonnull)keypath {
|
||||
[self.inputNode searchNodesForKeypath:keypath];
|
||||
if ([keypath pushKey:self.keyname]) {
|
||||
// Matches self. Check interpolators
|
||||
if (keypath.endOfKeypath) {
|
||||
// Add self
|
||||
[keypath addSearchResultForCurrentPath:self];
|
||||
} else if (self.valueInterpolators[keypath.currentKey] != nil) {
|
||||
[keypath pushKey:keypath.currentKey];
|
||||
// We have a match!
|
||||
[keypath addSearchResultForCurrentPath:self];
|
||||
[keypath popKey];
|
||||
}
|
||||
[keypath popKey];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setValueCallback:(nonnull LOTValueCallback *)callbackBlock
|
||||
forKeypath:(nonnull LOTKeypath *)keypath {
|
||||
if ([keypath pushKey:self.keyname]) {
|
||||
// Matches self. Check interpolators
|
||||
LOTValueInterpolator *interpolator = self.valueInterpolators[keypath.currentKey];
|
||||
if (interpolator) {
|
||||
// We have a match!
|
||||
[interpolator setValueCallback:callbackBlock];
|
||||
}
|
||||
[keypath popKey];
|
||||
}
|
||||
[self.inputNode setValueCallback:callbackBlock forKeypath:keypath];
|
||||
}
|
||||
|
||||
#pragma mark - DEPRECATED
|
||||
|
||||
/// Traverses children untill keypath is found and attempts to set the keypath to the value.
|
||||
- (BOOL)setValue:(nonnull id)value
|
||||
forKeyAtPath:(nonnull NSString *)keypath
|
||||
|
||||
@@ -48,11 +48,18 @@
|
||||
|
||||
- (NSDictionary *)valueInterpolators {
|
||||
if (_opacityInterpolator && _transformInterolator) {
|
||||
return @{@"Transform.Opacity" : _opacityInterpolator,
|
||||
return @{@"Opacity" : _opacityInterpolator,
|
||||
@"Position" : _transformInterolator.positionInterpolator,
|
||||
@"Scale" : _transformInterolator.scaleInterpolator,
|
||||
@"Rotation" : _transformInterolator.scaleInterpolator,
|
||||
@"Anchor Point" : _transformInterolator.anchorInterpolator,
|
||||
// Deprecated
|
||||
@"Transform.Opacity" : _opacityInterpolator,
|
||||
@"Transform.Position" : _transformInterolator.positionInterpolator,
|
||||
@"Transform.Scale" : _transformInterolator.scaleInterpolator,
|
||||
@"Transform.Rotation" : _transformInterolator.scaleInterpolator,
|
||||
@"Transform.Anchor Point" : _transformInterolator.anchorInterpolator};
|
||||
@"Transform.Anchor Point" : _transformInterolator.anchorInterpolator
|
||||
};
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
@@ -176,6 +183,59 @@
|
||||
return _outputPath;
|
||||
}
|
||||
|
||||
- (void)searchNodesForKeypath:(LOTKeypath * _Nonnull)keypath {
|
||||
[self.inputNode searchNodesForKeypath:keypath];
|
||||
if ([keypath pushKey:self.keyname]) {
|
||||
// Matches self. Dig deeper.
|
||||
// Check interpolators
|
||||
|
||||
if ([keypath pushKey:@"Transform"]) {
|
||||
// Matches a Transform interpolator!
|
||||
if (self.valueInterpolators[keypath.currentKey] != nil) {
|
||||
[keypath pushKey:keypath.currentKey];
|
||||
[keypath addSearchResultForCurrentPath:self];
|
||||
[keypath popKey];
|
||||
}
|
||||
[keypath popKey];
|
||||
}
|
||||
|
||||
if (keypath.endOfKeypath) {
|
||||
// We have a match!
|
||||
[keypath addSearchResultForCurrentPath:self];
|
||||
}
|
||||
// Check child nodes
|
||||
[_rootNode searchNodesForKeypath:keypath];
|
||||
[keypath popKey];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setValueCallback:(nonnull LOTValueCallback *)callbackBlock
|
||||
forKeypath:(nonnull LOTKeypath *)keypath {
|
||||
if ([keypath pushKey:self.keyname]) {
|
||||
// Matches self. Dig deeper.
|
||||
// Check interpolators
|
||||
if ([keypath pushKey:@"Transform"]) {
|
||||
// Matches a Transform interpolator!
|
||||
LOTValueInterpolator *interpolator = self.valueInterpolators[keypath.currentKey];
|
||||
if (interpolator) {
|
||||
// We have a match!
|
||||
[interpolator setValueCallback:callbackBlock];
|
||||
}
|
||||
[keypath popKey];
|
||||
}
|
||||
|
||||
// Check child nodes
|
||||
[_rootNode setValueCallback:callbackBlock forKeypath:keypath];
|
||||
|
||||
[keypath popKey];
|
||||
}
|
||||
|
||||
// Check upstream
|
||||
[self.inputNode setValueCallback:callbackBlock forKeypath:keypath];
|
||||
}
|
||||
|
||||
#pragma mark - DEPRECATED
|
||||
|
||||
- (BOOL)setInterpolatorValue:(id)value
|
||||
forKey:(NSString *)key
|
||||
forFrame:(NSNumber *)frame {
|
||||
|
||||
Reference in New Issue
Block a user