123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- //
- // LOTCompositionContainer.m
- // Lottie
- //
- // Created by brandon_withrow on 7/18/17.
- // Copyright © 2017 Airbnb. All rights reserved.
- //
- #import "LOTCompositionContainer.h"
- #import "LOTAsset.h"
- #import "CGGeometry+LOTAdditions.h"
- #import "LOTHelpers.h"
- #import "LOTValueInterpolator.h"
- #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
- inLayerGroup:(LOTLayerGroup *)layerGroup
- withLayerGroup:(LOTLayerGroup *)childLayerGroup
- withAssestGroup:(LOTAssetGroup *)assetGroup {
- self = [super initWithModel:layer inLayerGroup:layerGroup];
- if (self) {
- DEBUG_Center = [CALayer layer];
-
- DEBUG_Center.bounds = CGRectMake(0, 0, 20, 20);
- DEBUG_Center.borderColor = [UIColor orangeColor].CGColor;
- DEBUG_Center.borderWidth = 2;
- DEBUG_Center.masksToBounds = YES;
- if (ENABLE_DEBUG_SHAPES) {
- [self.wrapperLayer addSublayer:DEBUG_Center];
- }
- if (layer.startFrame != nil) {
- _frameOffset = layer.startFrame;
- } else {
- _frameOffset = @0;
- }
- if (layer.timeRemapping) {
- _timeInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:layer.timeRemapping.keyframes];
- }
- [self initializeWithChildGroup:childLayerGroup withAssetGroup:assetGroup];
- }
- return self;
- }
- - (void)initializeWithChildGroup:(LOTLayerGroup *)childGroup
- withAssetGroup:(LOTAssetGroup *)assetGroup {
- NSMutableDictionary *childMap = [NSMutableDictionary dictionary];
- NSMutableArray *children = [NSMutableArray array];
- NSArray *reversedItems = [[childGroup.layers reverseObjectEnumerator] allObjects];
-
- CALayer *maskedLayer = nil;
- for (LOTLayer *layer in reversedItems) {
- LOTAsset *asset;
- if (layer.referenceID) {
- // Get relevant Asset
- asset = [assetGroup assetModelForID:layer.referenceID];
- }
-
- LOTLayerContainer *child = nil;
- if (asset.layerGroup) {
- // Layer is a precomp
- LOTCompositionContainer *compLayer = [[LOTCompositionContainer alloc] initWithModel:layer inLayerGroup:childGroup withLayerGroup:asset.layerGroup withAssestGroup:assetGroup];
- child = compLayer;
- } else {
- child = [[LOTLayerContainer alloc] initWithModel:layer inLayerGroup:childGroup];
- }
- if (maskedLayer) {
- maskedLayer.mask = child;
- maskedLayer = nil;
- } else {
- if (layer.matteType == LOTMatteTypeAdd) {
- maskedLayer = child;
- }
- [self.wrapperLayer addSublayer:child];
- }
- [children addObject:child];
- if (child.layerName) {
- [childMap setObject:child forKey:child.layerName];
- }
- }
- _childMap = childMap;
- _childLayers = children;
- }
- - (void)displayWithFrame:(NSNumber *)frame forceUpdate:(BOOL)forceUpdate {
- if (ENABLE_DEBUG_LOGGING) NSLog(@"-------------------- Composition Displaying Frame %@ --------------------", frame);
- [super displayWithFrame:frame forceUpdate:forceUpdate];
- NSNumber *newFrame = @((frame.floatValue - _frameOffset.floatValue) / self.timeStretchFactor.floatValue);
- if (_timeInterpolator) {
- newFrame = @([_timeInterpolator floatValueForFrame:newFrame]);
- }
- for (LOTLayerContainer *child in _childLayers) {
- [child displayWithFrame:newFrame forceUpdate:forceUpdate];
- }
- if (ENABLE_DEBUG_LOGGING) NSLog(@"-------------------- ------------------------------- --------------------");
- 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)setValueDelegate:(id<LOTValueDelegate> _Nonnull)delegate
- forKeypath:(LOTKeypath * _Nonnull)keypath {
- if (self.layerName != nil) {
- [super setValueDelegate:delegate forKeypath:keypath];
- }
- if (self.layerName == nil ||
- [keypath pushKey:self.layerName]) {
- for (LOTLayerContainer *child in _childLayers) {
- [child setValueDelegate:delegate 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 {
- id 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:[CALayer class]]) {
- return (CALayer *)node;
- }
- 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;
- }
- }
- @end
|