mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-16 03:09:56 +00:00
Enable time remapping
This commit is contained in:
parent
650a82eb2d
commit
6434ec156f
1916
Example/Pods/Pods.xcodeproj/project.pbxproj
generated
1916
Example/Pods/Pods.xcodeproj/project.pbxproj
generated
File diff suppressed because it is too large
Load Diff
1
Example/Tests/timeremap.json
Normal file
1
Example/Tests/timeremap.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"4.12.0","fr":23.9759979248047,"ip":0,"op":48.9999957589018,"w":300,"h":300,"nm":"TimeRemap","ddd":0,"assets":[{"id":"comp_1","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":0,"s":[0],"e":[360]},{"t":47.9999958454548}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[150,60,0],"e":[150,225,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":13,"s":[150,225,0],"e":[150,60,0],"to":[0,0,0],"ti":[0,0,0]},{"t":47.9999958454548}],"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":[{"ty":"rc","d":1,"s":{"a":0,"k":[109.172,109.172],"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":0,"k":[0.32,4.668],"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":"Rectangle 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":48.9999957589018,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Freeze","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[146,220,0],"ix":2},"a":{"a":0,"k":[150,150,0],"ix":1},"s":{"a":0,"k":[50.667,50.667,100],"ix":6}},"ao":0,"tm":{"a":0,"k":0.876,"ix":2},"w":300,"h":300,"ip":0,"op":48.9999957589018,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"Reverse","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[247,220,0],"ix":2},"a":{"a":0,"k":[150,150,0],"ix":1},"s":{"a":0,"k":[50.667,50.667,100],"ix":6}},"ao":0,"tm":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":0,"s":[2.044],"e":[0]},{"t":48.9999957589018}],"ix":2},"w":300,"h":300,"ip":0,"op":48.9999957589018,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":0,"nm":"Regular","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[43,220,0],"ix":2},"a":{"a":0,"k":[150,150,0],"ix":1},"s":{"a":0,"k":[50.667,50.667,100],"ix":6}},"ao":0,"w":300,"h":300,"ip":0,"op":48.9999957589018,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":0,"nm":"Stretch","refId":"comp_1","sr":0.2,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[44,71,0],"ix":2},"a":{"a":0,"k":[150,150,0],"ix":1},"s":{"a":0,"k":[50.667,50.667,100],"ix":6}},"ao":0,"w":300,"h":300,"ip":0,"op":9.79999915178036,"st":0,"bm":0}]}
|
||||
@ -64,6 +64,7 @@
|
||||
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 */; };
|
||||
6257F31E1FFD65BC00DAE7B2 /* timeremap.json in Resources */ = {isa = PBXBuildFile; fileRef = 6257F31D1FFD65BB00DAE7B2 /* timeremap.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 */; };
|
||||
@ -176,6 +177,7 @@
|
||||
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>"; };
|
||||
6257F31D1FFD65BB00DAE7B2 /* timeremap.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = timeremap.json; 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>"; };
|
||||
@ -373,6 +375,7 @@
|
||||
622F76B91F2BE58100269858 /* LottieLogo1.json */,
|
||||
622F76BB1F2BE58100269858 /* MotionCorpse-Jrcanest.json */,
|
||||
622F76BC1F2BE58100269858 /* PinJump.json */,
|
||||
6257F31D1FFD65BB00DAE7B2 /* timeremap.json */,
|
||||
622F76BD1F2BE58100269858 /* TwitterHeart.json */,
|
||||
622F76BF1F2BE58100269858 /* vcTransition1.json */,
|
||||
622F76C01F2BE58100269858 /* vcTransition2.json */,
|
||||
@ -628,6 +631,7 @@
|
||||
622F77021F2BE63100269858 /* Q.json in Resources */,
|
||||
629EC5811F54C00B005B2C59 /* Switch.json in Resources */,
|
||||
622F76FB1F2BE63100269858 /* J.json in Resources */,
|
||||
6257F31E1FFD65BC00DAE7B2 /* timeremap.json in Resources */,
|
||||
622F77081F2BE63100269858 /* W.json in Resources */,
|
||||
622F76F61F2BE63100269858 /* E.json in Resources */,
|
||||
622F76C41F2BE58100269858 /* IconTransitions.json in Resources */,
|
||||
|
||||
@ -939,7 +939,7 @@
|
||||
62CA59AF1E3C173B002D7188 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0830;
|
||||
LastUpgradeCheck = 0910;
|
||||
ORGANIZATIONNAME = Airbnb;
|
||||
TargetAttributes = {
|
||||
62CA59B71E3C173B002D7188 = {
|
||||
@ -1187,7 +1187,9 @@
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
@ -1195,7 +1197,11 @@
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
@ -1240,7 +1246,9 @@
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
@ -1248,7 +1256,11 @@
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0830"
|
||||
LastUpgradeVersion = "0910"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
@ -26,6 +26,7 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
@ -36,6 +37,7 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0830"
|
||||
LastUpgradeVersion = "0910"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
@ -26,6 +26,7 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
@ -36,6 +37,7 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
||||
BIN
_AeFiles/Adobe After Effects Auto-Save/TimeRemap auto-save 1.aep
Normal file
BIN
_AeFiles/Adobe After Effects Auto-Save/TimeRemap auto-save 1.aep
Normal file
Binary file not shown.
BIN
_AeFiles/Adobe After Effects Auto-Save/TimeRemap auto-save 2.aep
Normal file
BIN
_AeFiles/Adobe After Effects Auto-Save/TimeRemap auto-save 2.aep
Normal file
Binary file not shown.
BIN
_AeFiles/TimeRemap.aep
Normal file
BIN
_AeFiles/TimeRemap.aep
Normal file
Binary file not shown.
@ -14,11 +14,13 @@
|
||||
#import "LOTAnimatorNode.h"
|
||||
#import "LOTRenderNode.h"
|
||||
#import "LOTRenderGroup.h"
|
||||
#import "LOTNumberInterpolator.h"
|
||||
|
||||
@implementation LOTCompositionContainer {
|
||||
NSNumber *_frameOffset;
|
||||
CALayer *DEBUG_Center;
|
||||
NSMutableDictionary *_keypathCache;
|
||||
LOTNumberInterpolator *_timeInterpolator;
|
||||
}
|
||||
|
||||
- (instancetype)initWithModel:(LOTLayer *)layer
|
||||
@ -41,6 +43,11 @@
|
||||
} else {
|
||||
_frameOffset = @0;
|
||||
}
|
||||
|
||||
if (layer.timeRemapping) {
|
||||
_timeInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:layer.timeRemapping.keyframes];
|
||||
}
|
||||
|
||||
[self initializeWithChildGroup:childLayerGroup withAssetGroup:assetGroup];
|
||||
}
|
||||
return self;
|
||||
@ -89,9 +96,12 @@
|
||||
- (void)displayWithFrame:(NSNumber *)frame forceUpdate:(BOOL)forceUpdate {
|
||||
if (ENABLE_DEBUG_LOGGING) NSLog(@"-------------------- Composition Displaying Frame %@ --------------------", frame);
|
||||
[super displayWithFrame:frame forceUpdate:forceUpdate];
|
||||
NSNumber *childFrame = @(frame.floatValue - _frameOffset.floatValue);
|
||||
NSNumber *newFrame = @((frame.floatValue - _frameOffset.floatValue) / self.timeStretchFactor.floatValue);
|
||||
if (_timeInterpolator) {
|
||||
newFrame = @([_timeInterpolator floatValueForFrame:newFrame]);
|
||||
}
|
||||
for (LOTLayerContainer *child in _childLayers) {
|
||||
[child displayWithFrame:childFrame forceUpdate:forceUpdate];
|
||||
[child displayWithFrame:newFrame forceUpdate:forceUpdate];
|
||||
}
|
||||
if (ENABLE_DEBUG_LOGGING) NSLog(@"-------------------- ------------------------------- --------------------");
|
||||
if (ENABLE_DEBUG_LOGGING) NSLog(@"-------------------- ------------------------------- --------------------");
|
||||
|
||||
@ -10,7 +10,8 @@
|
||||
#import "LOTLayer.h"
|
||||
#import "LOTLayerGroup.h"
|
||||
#import "LOTKeypath.h"
|
||||
#import "LOTValueCallback.h"
|
||||
|
||||
@class LOTValueCallback;
|
||||
|
||||
@interface LOTLayerContainer : CALayer
|
||||
|
||||
@ -19,9 +20,11 @@
|
||||
|
||||
@property (nonatomic, readonly, strong, nullable) NSString *layerName;
|
||||
@property (nonatomic, nullable) NSNumber *currentFrame;
|
||||
@property (nonatomic, readonly, nonnull) NSNumber *timeStretchFactor;
|
||||
@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;
|
||||
|
||||
|
||||
@ -49,6 +49,7 @@
|
||||
}
|
||||
self.actions = @{@"hidden" : [NSNull null], @"opacity" : [NSNull null], @"transform" : [NSNull null]};
|
||||
_wrapperLayer.actions = [self.actions copy];
|
||||
_timeStretchFactor = @1;
|
||||
[self commonInitializeWith:layer inLayerGroup:layerGroup];
|
||||
}
|
||||
return self;
|
||||
@ -75,7 +76,10 @@
|
||||
|
||||
_inFrame = [layer.inFrame copy];
|
||||
_outFrame = [layer.outFrame copy];
|
||||
|
||||
_timeStretchFactor = [layer.timeStretch copy];
|
||||
_transformInterpolator = [LOTTransformInterpolator transformForLayer:layer];
|
||||
|
||||
if (layer.parentID) {
|
||||
NSNumber *parentID = layer.parentID;
|
||||
LOTTransformInterpolator *childInterpolator = _transformInterpolator;
|
||||
@ -233,7 +237,8 @@
|
||||
}
|
||||
|
||||
- (void)displayWithFrame:(NSNumber *)frame forceUpdate:(BOOL)forceUpdate {
|
||||
if (ENABLE_DEBUG_LOGGING) NSLog(@"View %@ Displaying Frame %@", self, frame);
|
||||
NSNumber *newFrame = @(frame.floatValue / self.timeStretchFactor.floatValue);
|
||||
if (ENABLE_DEBUG_LOGGING) NSLog(@"View %@ Displaying Frame %@, with local time %@", self, frame, newFrame);
|
||||
BOOL hidden = NO;
|
||||
if (_inFrame && _outFrame) {
|
||||
hidden = (frame.floatValue < _inFrame.floatValue ||
|
||||
@ -243,14 +248,14 @@
|
||||
if (hidden) {
|
||||
return;
|
||||
}
|
||||
if (_opacityInterpolator && [_opacityInterpolator hasUpdateForFrame:frame]) {
|
||||
self.opacity = [_opacityInterpolator floatValueForFrame:frame];
|
||||
if (_opacityInterpolator && [_opacityInterpolator hasUpdateForFrame:newFrame]) {
|
||||
self.opacity = [_opacityInterpolator floatValueForFrame:newFrame];
|
||||
}
|
||||
if (_transformInterpolator && [_transformInterpolator hasUpdateForFrame:frame]) {
|
||||
_wrapperLayer.transform = [_transformInterpolator transformForFrame:frame];
|
||||
if (_transformInterpolator && [_transformInterpolator hasUpdateForFrame:newFrame]) {
|
||||
_wrapperLayer.transform = [_transformInterpolator transformForFrame:newFrame];
|
||||
}
|
||||
[_contentsGroup updateWithFrame:frame withModifierBlock:nil forceLocalUpdate:forceUpdate];
|
||||
_maskLayer.currentFrame = frame;
|
||||
[_contentsGroup updateWithFrame:newFrame withModifierBlock:nil forceLocalUpdate:forceUpdate];
|
||||
_maskLayer.currentFrame = newFrame;
|
||||
}
|
||||
|
||||
- (void)setViewportBounds:(CGRect)viewportBounds {
|
||||
|
||||
@ -19,7 +19,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary
|
||||
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup
|
||||
withAssetBundle:(NSBundle *_Nonnull)bundle;
|
||||
withAssetBundle:(NSBundle *_Nonnull)bundle
|
||||
withFramerate:(NSNumber *)framerate;
|
||||
|
||||
@property (nonatomic, readonly, nullable) NSString *referenceID;
|
||||
@property (nonatomic, readonly, nullable) NSNumber *assetWidth;
|
||||
|
||||
@ -15,18 +15,21 @@
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary
|
||||
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup
|
||||
withAssetBundle:(NSBundle *_Nonnull)bundle {
|
||||
withAssetBundle:(NSBundle *_Nonnull)bundle
|
||||
withFramerate:(NSNumber *)framerate {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_assetBundle = bundle;
|
||||
[self _mapFromJSON:jsonDictionary
|
||||
withAssetGroup:assetGroup];
|
||||
withAssetGroup:assetGroup
|
||||
withFramerate:framerate];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary
|
||||
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup {
|
||||
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup
|
||||
withFramerate:(NSNumber *)framerate {
|
||||
_referenceID = [jsonDictionary[@"id"] copy];
|
||||
|
||||
if (jsonDictionary[@"w"]) {
|
||||
@ -48,7 +51,8 @@
|
||||
NSArray *layersJSON = jsonDictionary[@"layers"];
|
||||
if (layersJSON) {
|
||||
_layerGroup = [[LOTLayerGroup alloc] initWithLayerJSON:layersJSON
|
||||
withAssetGroup:assetGroup];
|
||||
withAssetGroup:assetGroup
|
||||
withFramerate:framerate];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -16,11 +16,12 @@
|
||||
@property (nonatomic, readonly, nullable) NSBundle *assetBundle;
|
||||
|
||||
- (instancetype _Nonnull)initWithJSON:(NSArray * _Nonnull)jsonArray
|
||||
withAssetBundle:(NSBundle *_Nullable)bundle;
|
||||
withAssetBundle:(NSBundle *_Nullable)bundle
|
||||
withFramerate:(NSNumber * _Nonnull)framerate;
|
||||
|
||||
- (void)buildAssetNamed:(NSString * _Nonnull)refID;
|
||||
- (void)buildAssetNamed:(NSString * _Nonnull)refID withFramerate:(NSNumber * _Nonnull)framerate;
|
||||
|
||||
- (void)finalizeInitialization;
|
||||
- (void)finalizeInitializationWithFramerate:(NSNumber * _Nonnull)framerate;
|
||||
|
||||
- (LOTAsset * _Nullable)assetModelForID:(NSString * _Nonnull)assetID;
|
||||
|
||||
|
||||
@ -15,7 +15,8 @@
|
||||
}
|
||||
|
||||
- (instancetype _Nonnull)initWithJSON:(NSArray * _Nonnull)jsonArray
|
||||
withAssetBundle:(NSBundle *_Nullable)bundle {
|
||||
withAssetBundle:(NSBundle * _Nullable)bundle
|
||||
withFramerate:(NSNumber * _Nonnull)framerate {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_assetBundle = bundle;
|
||||
@ -32,7 +33,8 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)buildAssetNamed:(NSString *)refID {
|
||||
- (void)buildAssetNamed:(NSString *)refID
|
||||
withFramerate:(NSNumber * _Nonnull)framerate {
|
||||
|
||||
if ([self assetModelForID:refID]) {
|
||||
return;
|
||||
@ -42,14 +44,15 @@
|
||||
if (assetDictionary) {
|
||||
LOTAsset *asset = [[LOTAsset alloc] initWithJSON:assetDictionary
|
||||
withAssetGroup:self
|
||||
withAssetBundle:_assetBundle];
|
||||
withAssetBundle:_assetBundle
|
||||
withFramerate:framerate];
|
||||
_assetMap[refID] = asset;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)finalizeInitialization {
|
||||
- (void)finalizeInitializationWithFramerate:(NSNumber * _Nonnull)framerate {
|
||||
for (NSString *refID in _assetJSONMap.allKeys) {
|
||||
[self buildAssetNamed:refID];
|
||||
[self buildAssetNamed:refID withFramerate:framerate];
|
||||
}
|
||||
_assetJSONMap = nil;
|
||||
}
|
||||
|
||||
@ -36,7 +36,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@interface LOTLayer : NSObject
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary
|
||||
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup;
|
||||
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup
|
||||
withFramerate:(NSNumber *)framerate;
|
||||
|
||||
@property (nonatomic, readonly) NSString *layerName;
|
||||
@property (nonatomic, readonly, nullable) NSString *referenceID;
|
||||
@ -46,6 +47,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@property (nonatomic, readonly) NSNumber *startFrame;
|
||||
@property (nonatomic, readonly) NSNumber *inFrame;
|
||||
@property (nonatomic, readonly) NSNumber *outFrame;
|
||||
@property (nonatomic, readonly) NSNumber *timeStretch;
|
||||
@property (nonatomic, readonly) CGRect layerBounds;
|
||||
|
||||
@property (nonatomic, readonly, nullable) NSArray<LOTShapeGroup *> *shapes;
|
||||
@ -57,6 +59,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@property (nonatomic, readonly, nullable) LOTAsset *imageAsset;
|
||||
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *opacity;
|
||||
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *timeRemapping;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *rotation;
|
||||
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *position;
|
||||
|
||||
|
||||
@ -18,17 +18,20 @@
|
||||
@implementation LOTLayer
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary
|
||||
withAssetGroup:(LOTAssetGroup *)assetGroup {
|
||||
withAssetGroup:(LOTAssetGroup *)assetGroup
|
||||
withFramerate:(NSNumber *)framerate {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self _mapFromJSON:jsonDictionary
|
||||
withAssetGroup:assetGroup];
|
||||
withAssetGroup:assetGroup
|
||||
withFramerate:framerate];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary
|
||||
withAssetGroup:(LOTAssetGroup *)assetGroup {
|
||||
withAssetGroup:(LOTAssetGroup *)assetGroup
|
||||
withFramerate:(NSNumber *)framerate {
|
||||
|
||||
_layerName = [jsonDictionary[@"nm"] copy];
|
||||
_layerID = [jsonDictionary[@"ind"] copy];
|
||||
@ -48,12 +51,18 @@
|
||||
_inFrame = [jsonDictionary[@"ip"] copy];
|
||||
_outFrame = [jsonDictionary[@"op"] copy];
|
||||
|
||||
if (jsonDictionary[@"sr"]) {
|
||||
_timeStretch = [jsonDictionary[@"sr"] copy];
|
||||
} else {
|
||||
_timeStretch = @1;
|
||||
}
|
||||
|
||||
if (_layerType == LOTLayerTypePrecomp) {
|
||||
_layerHeight = [jsonDictionary[@"h"] copy];
|
||||
_layerWidth = [jsonDictionary[@"w"] copy];
|
||||
[assetGroup buildAssetNamed:_referenceID];
|
||||
[assetGroup buildAssetNamed:_referenceID withFramerate:framerate];
|
||||
} else if (_layerType == LOTLayerTypeImage) {
|
||||
[assetGroup buildAssetNamed:_referenceID];
|
||||
[assetGroup buildAssetNamed:_referenceID withFramerate:framerate];
|
||||
_imageAsset = [assetGroup assetModelForID:_referenceID];
|
||||
_layerWidth = [_imageAsset.assetWidth copy];
|
||||
_layerHeight = [_imageAsset.assetHeight copy];
|
||||
@ -75,6 +84,14 @@
|
||||
return LOT_RemapValue(inValue, 0, 100, 0, 1);
|
||||
}];
|
||||
}
|
||||
|
||||
NSDictionary *timeRemap = jsonDictionary[@"tm"];
|
||||
if (timeRemap) {
|
||||
_timeRemapping = [[LOTKeyframeGroup alloc] initWithData:timeRemap];
|
||||
[_timeRemapping remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
|
||||
return inValue * framerate.doubleValue;
|
||||
}];
|
||||
}
|
||||
|
||||
NSDictionary *rotation = ks[@"r"];
|
||||
if (rotation == nil) {
|
||||
|
||||
@ -17,7 +17,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@interface LOTLayerGroup : NSObject
|
||||
|
||||
- (instancetype)initWithLayerJSON:(NSArray *)layersJSON
|
||||
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup;
|
||||
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup
|
||||
withFramerate:(NSNumber *)framerate;
|
||||
|
||||
@property (nonatomic, readonly) NSArray <LOTLayer *> *layers;
|
||||
|
||||
|
||||
@ -16,15 +16,18 @@
|
||||
}
|
||||
|
||||
- (instancetype)initWithLayerJSON:(NSArray *)layersJSON
|
||||
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup {
|
||||
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup
|
||||
withFramerate:(NSNumber *)framerate {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self _mapFromJSON:layersJSON withAssetGroup:assetGroup];
|
||||
[self _mapFromJSON:layersJSON withAssetGroup:assetGroup withFramerate:framerate];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_mapFromJSON:(NSArray *)layersJSON withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup {
|
||||
- (void)_mapFromJSON:(NSArray *)layersJSON
|
||||
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup
|
||||
withFramerate:(NSNumber *)framerate {
|
||||
|
||||
NSMutableArray *layers = [NSMutableArray array];
|
||||
NSMutableDictionary *modelMap = [NSMutableDictionary dictionary];
|
||||
@ -32,7 +35,8 @@
|
||||
|
||||
for (NSDictionary *layerJSON in layersJSON) {
|
||||
LOTLayer *layer = [[LOTLayer alloc] initWithJSON:layerJSON
|
||||
withAssetGroup:assetGroup];
|
||||
withAssetGroup:assetGroup
|
||||
withFramerate:framerate];
|
||||
[layers addObject:layer];
|
||||
modelMap[layer.layerID] = layer;
|
||||
if (layer.referenceID) {
|
||||
|
||||
@ -112,16 +112,17 @@
|
||||
|
||||
NSArray *assetArray = jsonDictionary[@"assets"];
|
||||
if (assetArray.count) {
|
||||
_assetGroup = [[LOTAssetGroup alloc] initWithJSON:assetArray withAssetBundle:bundle];
|
||||
_assetGroup = [[LOTAssetGroup alloc] initWithJSON:assetArray withAssetBundle:bundle withFramerate:_framerate];
|
||||
}
|
||||
|
||||
NSArray *layersJSON = jsonDictionary[@"layers"];
|
||||
if (layersJSON) {
|
||||
_layerGroup = [[LOTLayerGroup alloc] initWithLayerJSON:layersJSON
|
||||
withAssetGroup:_assetGroup];
|
||||
withAssetGroup:_assetGroup
|
||||
withFramerate:_framerate];
|
||||
}
|
||||
|
||||
[_assetGroup finalizeInitialization];
|
||||
[_assetGroup finalizeInitializationWithFramerate:_framerate];
|
||||
}
|
||||
|
||||
- (void)setRootDirectory:(NSString *)rootDirectory {
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "LOTPlatformCompat.h"
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
|
||||
/*!
|
||||
@brief A block that is used to change a Color value at keytime, the block is called continuously for a keypath while the aniamtion plays.
|
||||
@ -19,14 +19,15 @@
|
||||
@param interpolatedProgress A value from 0-1 that represents the current progress between keyframes. It respects the keyframes current easing curves.
|
||||
@param currentFrame The current frame of the animation in the parent compositions time space.
|
||||
@return UIColor the color to set the keypath node for the current frame
|
||||
*/
|
||||
typedef UIColor * _Nonnull (^LOTColorValueCallbackBlock)(CGFloat startFrame,
|
||||
CGFloat endFrame,
|
||||
UIColor * _Nullable startColor,
|
||||
UIColor * _Nullable endColor,
|
||||
UIColor * _Nullable interpolatedColor,
|
||||
CGFloat interpolatedProgress,
|
||||
CGFloat currentFrame);
|
||||
*/
|
||||
typedef CGColorRef _Nonnull (^LOTColorValueCallbackBlock)(CGFloat startFrame,
|
||||
CGFloat endFrame,
|
||||
CGColorRef _Nullable startColor,
|
||||
CGColorRef _Nullable endColor,
|
||||
CGColorRef _Nullable interpolatedColor,
|
||||
CGFloat interpolatedProgress,
|
||||
CGFloat currentFrame);
|
||||
|
||||
/*!
|
||||
@brief A block that is used to change a Number value at keytime, the block is called continuously for a keypath while the aniamtion plays.
|
||||
@param startFrame When the block is called, startFrame is the most recent keyframe for the keypath in relation to the current time.
|
||||
@ -91,10 +92,11 @@ typedef CGSize (^LOTSizeValueCallbackBlock)(CGFloat startFrame,
|
||||
@param currentFrame The current frame of the animation in the parent compositions time space.
|
||||
@return UIBezierPath the path to set the keypath node for the current frame.
|
||||
*/
|
||||
typedef UIBezierPath * _Nonnull (^LOTPathValueCallbackBlock)(CGFloat startFrame,
|
||||
CGFloat endFrame,
|
||||
CGFloat interpolatedProgress,
|
||||
CGFloat currentFrame);
|
||||
typedef CGPathRef _Nonnull (^LOTPathValueCallbackBlock)(CGFloat startFrame,
|
||||
CGFloat endFrame,
|
||||
CGFloat interpolatedProgress,
|
||||
CGFloat currentFrame);
|
||||
|
||||
|
||||
/*!
|
||||
@brief LOTValueCallback is a thin wrapper around a value block. It is not intended to be used directly. It has several child classes that are each associated with a value type that can be used to change animations at runtime.
|
||||
@ -163,5 +165,4 @@ typedef UIBezierPath * _Nonnull (^LOTPathValueCallbackBlock)(CGFloat startFrame,
|
||||
|
||||
@property (nonatomic, copy, nonnull) LOTPathValueCallbackBlock callback;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface LOTColorInterpolator : LOTValueInterpolator
|
||||
|
||||
- (UIColor *)colorForFrame:(NSNumber *)frame;
|
||||
- (CGColorRef)colorForFrame:(NSNumber *)frame;
|
||||
|
||||
@property (nonatomic, strong, nullable) LOTColorValueCallback *colorCallback;
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
@implementation LOTColorInterpolator
|
||||
|
||||
- (UIColor *)colorForFrame:(NSNumber *)frame {
|
||||
- (CGColorRef)colorForFrame:(NSNumber *)frame {
|
||||
CGFloat progress = [self progressForFrame:frame];
|
||||
UIColor *returnColor;
|
||||
|
||||
@ -24,10 +24,10 @@
|
||||
returnColor = [UIColor LOT_colorByLerpingFromColor:self.leadingKeyframe.colorValue toColor:self.trailingKeyframe.colorValue amount:progress];
|
||||
}
|
||||
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);
|
||||
return self.colorCallback.callback(self.leadingKeyframe.keyframeTime.floatValue, self.trailingKeyframe.keyframeTime.floatValue, self.leadingKeyframe.colorValue.CGColor, self.trailingKeyframe.colorValue.CGColor, returnColor.CGColor, progress, frame.floatValue);
|
||||
}
|
||||
|
||||
return returnColor;
|
||||
return returnColor.CGColor;
|
||||
}
|
||||
|
||||
- (void)setValueCallback:(LOTValueCallback *)valueCallback {
|
||||
|
||||
@ -14,8 +14,8 @@
|
||||
- (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];
|
||||
CGPathRef callBackPath = self.pathCallback.callback(self.leadingKeyframe.keyframeTime.floatValue, self.trailingKeyframe.keyframeTime.floatValue, progress, frame.floatValue);
|
||||
return [LOTBezierPath pathWithCGPath:callBackPath];
|
||||
}
|
||||
|
||||
LOTBezierPath *returnPath = [[LOTBezierPath alloc] init];
|
||||
|
||||
@ -46,10 +46,10 @@
|
||||
}
|
||||
|
||||
- (void)performLocalUpdate {
|
||||
centerPoint_DEBUG.backgroundColor = [colorInterpolator_ colorForFrame:self.currentFrame].CGColor;
|
||||
centerPoint_DEBUG.backgroundColor = [colorInterpolator_ colorForFrame:self.currentFrame];
|
||||
centerPoint_DEBUG.borderColor = [UIColor lightGrayColor].CGColor;
|
||||
centerPoint_DEBUG.borderWidth = 2.f;
|
||||
self.outputLayer.fillColor = [colorInterpolator_ colorForFrame:self.currentFrame].CGColor;
|
||||
self.outputLayer.fillColor = [colorInterpolator_ colorForFrame:self.currentFrame];
|
||||
self.outputLayer.opacity = [opacityInterpolator_ floatValueForFrame:self.currentFrame];
|
||||
}
|
||||
|
||||
|
||||
@ -104,7 +104,7 @@
|
||||
|
||||
- (void)performLocalUpdate {
|
||||
self.outputLayer.lineDashPhase = [_dashOffsetInterpolator floatValueForFrame:self.currentFrame];
|
||||
self.outputLayer.strokeColor = [_colorInterpolator colorForFrame:self.currentFrame].CGColor;
|
||||
self.outputLayer.strokeColor = [_colorInterpolator colorForFrame:self.currentFrame];
|
||||
self.outputLayer.lineWidth = [_widthInterpolator floatValueForFrame:self.currentFrame];
|
||||
self.outputLayer.opacity = [_opacityInterpolator floatValueForFrame:self.currentFrame];
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user