2017-04-04 14:29:08 -07:00

157 lines
4.4 KiB
Objective-C

//
// LOTCompositionLayer.m
// Pods
//
// Created by Brandon Withrow on 2/17/17.
//
//
#import "LOTCompositionLayer.h"
#import "LOTPlatformCompat.h"
#import "LOTLayerView.h"
#import "LOTAnimationView_Internal.h"
#import "LOTAsset.h"
#import "LOTAssetGroup.h"
@interface LOTCustomChild : NSObject
@property (nonatomic, strong) LOTView *childView;
@property (nonatomic, weak) LOTLayerView *layer;
@property (nonatomic, assign) LOTConstraintType constraint;
@end
@implementation LOTCustomChild
@end
@implementation LOTCompositionLayer {
NSDictionary *_layerMap;
NSDictionary *_layerNameMap;
NSMutableArray *_customLayers;
}
- (instancetype)initWithLayerGroup:(LOTLayerGroup *)layerGroup
withAssetGroup:(LOTAssetGroup *)assetGroup
withBounds:(CGRect)bounds {
self = [super init];
if (self) {
self.masksToBounds = YES;
[self _setupWithLayerGroup:layerGroup withAssetGroup:assetGroup withBounds:bounds];
}
return self;
}
- (void)_setupWithLayerGroup:(LOTLayerGroup *)layerGroup
withAssetGroup:(LOTAssetGroup *)assetGroup
withBounds:(CGRect)bounds
{
if (_customLayers) {
for (LOTCustomChild *child in _customLayers) {
[child.childView.layer removeFromSuperlayer];
}
_customLayers = nil;
}
if (_layerMap) {
_layerMap = nil;
[self removeAllAnimations];
[self.sublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)];
}
if (_layerNameMap) {
_layerNameMap = nil;
}
self.bounds = bounds;
NSMutableDictionary *layerMap = [NSMutableDictionary dictionary];
NSMutableDictionary *layerNameMap = [NSMutableDictionary dictionary];
NSArray *reversedItems = [[layerGroup.layers reverseObjectEnumerator] allObjects];
CALayer *maskedLayer = nil;
for (LOTLayer *layer in reversedItems) {
LOTAsset *asset;
if (layer.referenceID) {
asset = [assetGroup assetModelForID:layer.referenceID];
}
LOTLayerView *layerView = [[LOTLayerView alloc] initWithModel:layer inLayerGroup:layerGroup];
if (asset.layerGroup) {
LOTCompositionLayer *precompLayer = [[LOTCompositionLayer alloc] initWithLayerGroup:asset.layerGroup
withAssetGroup:assetGroup
withBounds:layer.layerBounds];
precompLayer.frame = layer.layerBounds;
[layerView LOT_addChildLayer:precompLayer];
}
layerMap[layer.layerID] = layerView;
layerNameMap[layer.layerName] = layerView;
if (maskedLayer) {
maskedLayer.mask = layerView;
maskedLayer = nil;
} else {
if (layer.matteType == LOTMatteTypeAdd) {
maskedLayer = layerView;
}
[self addSublayer:layerView];
}
}
_layerMap = layerMap;
_layerNameMap = layerNameMap;
}
- (void)layoutCustomChildLayers {
if (!_customLayers.count) {
return;
}
for (LOTCustomChild *child in _customLayers) {
switch (child.constraint) {
case LOTConstraintTypeAlignToLayer:
child.childView.frame = child.layer.bounds;
break;
case LOTConstraintTypeAlignToBounds: {
CGRect selfBounds = self.bounds;
CGRect convertedBounds = [child.childView.layer.superlayer convertRect:selfBounds fromLayer:self];
child.childView.layer.frame = convertedBounds;
} break;
default:
break;
}
}
}
- (void)addSublayer:(LOTView *)view
toLayerNamed:(NSString *)layer {
LOTConstraintType constraint = LOTConstraintTypeAlignToBounds;
LOTLayerView *layerObject = _layerNameMap[layer];
LOTCustomChild *newChild = [[LOTCustomChild alloc] init];
newChild.constraint = constraint;
newChild.childView = view;
if (!layer) {
NSException* layerNotFoundExpection = [NSException exceptionWithName:@"LayerNotFoundException"
reason:@"The required layer was not specified."
userInfo:nil];
@throw layerNotFoundExpection;
} else {
newChild.layer = layerObject;
[layerObject.superlayer insertSublayer:view.layer above:layerObject];
[layerObject removeFromSuperlayer];
view.layer.mask = layerObject;
}
if (!_customLayers) {
_customLayers = [NSMutableArray array];
}
[_customLayers addObject:newChild];
[self layoutCustomChildLayers];
}
@end