From 2d32d8e6fdcef5acf5081e7beec1d7a698e2f19a Mon Sep 17 00:00:00 2001 From: Brandon Withrow Date: Tue, 15 Dec 2015 11:59:36 -0800 Subject: [PATCH] Added basic support for shape layers --- LotteAnimator.xcodeproj/project.pbxproj | 40 +++++++++- .../UserInterfaceState.xcuserstate | Bin 54613 -> 59403 bytes .../xcdebugger/Breakpoints_v2.xcbkptlist | 62 +++++----------- LotteAnimator/LALayer.m | 9 ++- LotteAnimator/LALayerView.h | 1 + LotteAnimator/LALayerView.m | 42 +++++++++++ LotteAnimator/LAModels.h | 23 ++++++ LotteAnimator/LAShape.h | 19 ++--- LotteAnimator/LAShape.m | 70 ++++++++++++++++++ LotteAnimator/LAShapeFill.h | 19 +++++ LotteAnimator/LAShapeFill.m | 41 ++++++++++ LotteAnimator/LAShapeItem.h | 24 ++++++ LotteAnimator/LAShapeItem.m | 44 +++++++++++ LotteAnimator/LAShapePath.h | 16 ++++ LotteAnimator/LAShapePath.m | 28 +++++++ LotteAnimator/LAShapeStroke.h | 21 ++++++ LotteAnimator/LAShapeStroke.m | 42 +++++++++++ LotteAnimator/LAShapeTransform.h | 25 +++++++ LotteAnimator/LAShapeTransform.m | 63 ++++++++++++++++ LotteAnimator/data.json | 2 +- PrefixHeader.pch | 5 +- 21 files changed, 529 insertions(+), 67 deletions(-) create mode 100644 LotteAnimator/LAModels.h create mode 100644 LotteAnimator/LAShapeFill.h create mode 100644 LotteAnimator/LAShapeFill.m create mode 100644 LotteAnimator/LAShapeItem.h create mode 100644 LotteAnimator/LAShapeItem.m create mode 100644 LotteAnimator/LAShapePath.h create mode 100644 LotteAnimator/LAShapePath.m create mode 100644 LotteAnimator/LAShapeStroke.h create mode 100644 LotteAnimator/LAShapeStroke.m create mode 100644 LotteAnimator/LAShapeTransform.h create mode 100644 LotteAnimator/LAShapeTransform.m diff --git a/LotteAnimator.xcodeproj/project.pbxproj b/LotteAnimator.xcodeproj/project.pbxproj index 89eff1863a..cc582a180f 100644 --- a/LotteAnimator.xcodeproj/project.pbxproj +++ b/LotteAnimator.xcodeproj/project.pbxproj @@ -22,8 +22,13 @@ 48372A441C1F84D700AD0293 /* LACompView.m in Sources */ = {isa = PBXBuildFile; fileRef = 48372A431C1F84D700AD0293 /* LACompView.m */; }; 48372A471C1F8B4C00AD0293 /* LAPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 48372A461C1F8B4C00AD0293 /* LAPath.m */; }; 48372A4A1C1F8D7D00AD0293 /* LAMask.m in Sources */ = {isa = PBXBuildFile; fileRef = 48372A491C1F8D7D00AD0293 /* LAMask.m */; }; - 48372A4C1C1F94A200AD0293 /* data.json in Resources */ = {isa = PBXBuildFile; fileRef = 48372A4B1C1F94A200AD0293 /* data.json */; }; 48372A4F1C1F99C600AD0293 /* LAShape.m in Sources */ = {isa = PBXBuildFile; fileRef = 48372A4E1C1F99C600AD0293 /* LAShape.m */; }; + 48372A521C20973300AD0293 /* LAShapeItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 48372A511C20973300AD0293 /* LAShapeItem.m */; }; + 48372A551C209A5F00AD0293 /* LAShapePath.m in Sources */ = {isa = PBXBuildFile; fileRef = 48372A541C209A5F00AD0293 /* LAShapePath.m */; }; + 48372A581C209A6C00AD0293 /* LAShapeStroke.m in Sources */ = {isa = PBXBuildFile; fileRef = 48372A571C209A6C00AD0293 /* LAShapeStroke.m */; }; + 48372A5B1C209A7A00AD0293 /* LAShapeFill.m in Sources */ = {isa = PBXBuildFile; fileRef = 48372A5A1C209A7A00AD0293 /* LAShapeFill.m */; }; + 48372A5E1C209A8900AD0293 /* LAShapeTransform.m in Sources */ = {isa = PBXBuildFile; fileRef = 48372A5D1C209A8900AD0293 /* LAShapeTransform.m */; }; + 48372A611C20A88E00AD0293 /* data.json in Resources */ = {isa = PBXBuildFile; fileRef = 48372A601C20A88E00AD0293 /* data.json */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -55,9 +60,20 @@ 48372A461C1F8B4C00AD0293 /* LAPath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LAPath.m; sourceTree = ""; }; 48372A481C1F8D7D00AD0293 /* LAMask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LAMask.h; sourceTree = ""; }; 48372A491C1F8D7D00AD0293 /* LAMask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LAMask.m; sourceTree = ""; }; - 48372A4B1C1F94A200AD0293 /* data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = data.json; sourceTree = ""; }; 48372A4D1C1F99C600AD0293 /* LAShape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LAShape.h; sourceTree = ""; }; 48372A4E1C1F99C600AD0293 /* LAShape.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LAShape.m; sourceTree = ""; }; + 48372A501C20973300AD0293 /* LAShapeItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LAShapeItem.h; sourceTree = ""; }; + 48372A511C20973300AD0293 /* LAShapeItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LAShapeItem.m; sourceTree = ""; }; + 48372A531C209A5F00AD0293 /* LAShapePath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LAShapePath.h; sourceTree = ""; }; + 48372A541C209A5F00AD0293 /* LAShapePath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LAShapePath.m; sourceTree = ""; }; + 48372A561C209A6C00AD0293 /* LAShapeStroke.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LAShapeStroke.h; sourceTree = ""; }; + 48372A571C209A6C00AD0293 /* LAShapeStroke.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LAShapeStroke.m; sourceTree = ""; }; + 48372A591C209A7A00AD0293 /* LAShapeFill.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LAShapeFill.h; sourceTree = ""; }; + 48372A5A1C209A7A00AD0293 /* LAShapeFill.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LAShapeFill.m; sourceTree = ""; }; + 48372A5C1C209A8900AD0293 /* LAShapeTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LAShapeTransform.h; sourceTree = ""; }; + 48372A5D1C209A8900AD0293 /* LAShapeTransform.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LAShapeTransform.m; sourceTree = ""; }; + 48372A5F1C209AA200AD0293 /* LAModels.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LAModels.h; sourceTree = ""; }; + 48372A601C20A88E00AD0293 /* data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = data.json; sourceTree = ""; }; 64D18A4F59FB72C8B3DEBCDE /* Pods-LotteAnimator.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LotteAnimator.release.xcconfig"; path = "Pods/Target Support Files/Pods-LotteAnimator/Pods-LotteAnimator.release.xcconfig"; sourceTree = ""; }; A3DACE6859B88B69187ADCF9 /* Pods-LotteAnimator.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LotteAnimator.debug.xcconfig"; path = "Pods/Target Support Files/Pods-LotteAnimator/Pods-LotteAnimator.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -118,7 +134,7 @@ 4804B3051C1F55E600DA8AF7 /* LaunchScreen.storyboard */, 4804B3081C1F55E600DA8AF7 /* Info.plist */, 4804B31B1C1F738800DA8AF7 /* PrefixHeader.pch */, - 48372A4B1C1F94A200AD0293 /* data.json */, + 48372A601C20A88E00AD0293 /* data.json */, 4804B2F71C1F55E600DA8AF7 /* Supporting Files */, ); path = LotteAnimator; @@ -135,6 +151,7 @@ 4804B3131C1F5B0900DA8AF7 /* Models */ = { isa = PBXGroup; children = ( + 48372A5F1C209AA200AD0293 /* LAModels.h */, 4804B3141C1F5B2000DA8AF7 /* LALayer.h */, 4804B3151C1F5B2000DA8AF7 /* LALayer.m */, 4804B3171C1F6DEA00DA8AF7 /* LAScene.h */, @@ -145,6 +162,16 @@ 48372A491C1F8D7D00AD0293 /* LAMask.m */, 48372A4D1C1F99C600AD0293 /* LAShape.h */, 48372A4E1C1F99C600AD0293 /* LAShape.m */, + 48372A501C20973300AD0293 /* LAShapeItem.h */, + 48372A511C20973300AD0293 /* LAShapeItem.m */, + 48372A531C209A5F00AD0293 /* LAShapePath.h */, + 48372A541C209A5F00AD0293 /* LAShapePath.m */, + 48372A561C209A6C00AD0293 /* LAShapeStroke.h */, + 48372A571C209A6C00AD0293 /* LAShapeStroke.m */, + 48372A591C209A7A00AD0293 /* LAShapeFill.h */, + 48372A5A1C209A7A00AD0293 /* LAShapeFill.m */, + 48372A5C1C209A8900AD0293 /* LAShapeTransform.h */, + 48372A5D1C209A8900AD0293 /* LAShapeTransform.m */, ); name = Models; sourceTree = ""; @@ -231,7 +258,7 @@ 4804B3071C1F55E600DA8AF7 /* LaunchScreen.storyboard in Resources */, 4804B3041C1F55E600DA8AF7 /* Assets.xcassets in Resources */, 4804B3021C1F55E600DA8AF7 /* Main.storyboard in Resources */, - 48372A4C1C1F94A200AD0293 /* data.json in Resources */, + 48372A611C20A88E00AD0293 /* data.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -285,8 +312,13 @@ 4804B32C1C1F835F00DA8AF7 /* LALayerView.m in Sources */, 48372A4A1C1F8D7D00AD0293 /* LAMask.m in Sources */, 4804B3161C1F5B2000DA8AF7 /* LALayer.m in Sources */, + 48372A521C20973300AD0293 /* LAShapeItem.m in Sources */, 48372A4F1C1F99C600AD0293 /* LAShape.m in Sources */, + 48372A581C209A6C00AD0293 /* LAShapeStroke.m in Sources */, + 48372A5B1C209A7A00AD0293 /* LAShapeFill.m in Sources */, 4804B2F91C1F55E600DA8AF7 /* main.m in Sources */, + 48372A551C209A5F00AD0293 /* LAShapePath.m in Sources */, + 48372A5E1C209A8900AD0293 /* LAShapeTransform.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/LotteAnimator.xcworkspace/xcuserdata/brandonwithrow.xcuserdatad/UserInterfaceState.xcuserstate b/LotteAnimator.xcworkspace/xcuserdata/brandonwithrow.xcuserdatad/UserInterfaceState.xcuserstate index 02fe3fd2883d689480d58547780562397ca6bfba..698f48fc85475ef4e8d42a09a6b24f60280b4510 100644 GIT binary patch delta 28749 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�L|CX9(^vY8U5 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 U&HZ<`kd*Yd$E^L^|FF&be*zpoIRF3v diff --git a/LotteAnimator.xcworkspace/xcuserdata/brandonwithrow.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/LotteAnimator.xcworkspace/xcuserdata/brandonwithrow.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index 65ae7783ca..3e73dcabaf 100644 --- a/LotteAnimator.xcworkspace/xcuserdata/brandonwithrow.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/LotteAnimator.xcworkspace/xcuserdata/brandonwithrow.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -3,19 +3,29 @@ type = "0" version = "2.0"> + + + + @@ -25,45 +35,13 @@ shouldBeEnabled = "Yes" ignoreCount = "0" continueAfterRunningActions = "No" - filePath = "LotteAnimator/LACompView.m" - timestampString = "471828350.46684" + filePath = "LotteAnimator/LAShapeItem.m" + timestampString = "471902261.314685" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "30" - endingLineNumber = "30" - landmarkName = "-_viewtapped" - landmarkType = "5"> - - - - - - - - diff --git a/LotteAnimator/LALayer.m b/LotteAnimator/LALayer.m index acfeff4914..25cefe74e8 100644 --- a/LotteAnimator/LALayer.m +++ b/LotteAnimator/LALayer.m @@ -18,16 +18,21 @@ @"layerID" : @"ind", @"width" : @"width", @"height" : @"height", - @"rotation" : @"", + @"rotation" : @"ks.r", @"positionArray" : @"ks.p", @"anchorPointArray" : @"ks.a", @"scaleArray" : @"ks.s", @"opacity" : @"ks.o", @"color" : @"color", - @"masks" : @"masksProperties" + @"masks" : @"masksProperties", + @"shapes" : @"shapes" }; } ++ (NSValueTransformer *)shapesJSONTransformer { + return [MTLJSONAdapter arrayTransformerWithModelClass:[LAShape class]]; +} + + (NSValueTransformer *)masksJSONTransformer { return [MTLJSONAdapter arrayTransformerWithModelClass:[LAMask class]]; } diff --git a/LotteAnimator/LALayerView.h b/LotteAnimator/LALayerView.h index 5d7bfd4fd6..da988306ea 100644 --- a/LotteAnimator/LALayerView.h +++ b/LotteAnimator/LALayerView.h @@ -7,6 +7,7 @@ // #import +#import "LAModels.h" @interface LALayerView : UIView diff --git a/LotteAnimator/LALayerView.m b/LotteAnimator/LALayerView.m index a857097c82..064f642a0c 100644 --- a/LotteAnimator/LALayerView.m +++ b/LotteAnimator/LALayerView.m @@ -20,6 +20,7 @@ self.alpha = model.alpha; _layerModel = model; if (model.masks) { + self.clipsToBounds = NO; LAMask *maskModel = model.masks.firstObject; UIBezierPath *myClippingPath = [maskModel.maskPath bezierPath:maskModel.isClosed]; @@ -29,6 +30,47 @@ self.layer.mask = mask; } + if (model.shapes) { + self.clipsToBounds = NO; + for (LAShape *shape in model.shapes) { + // Get Path + LAShapePath *path = shape.paths.count ? shape.paths.firstObject : nil; + + // Get Stroke + LAShapeStroke *stroke = shape.strokes.count ? shape.strokes.firstObject : nil; + + //Get Fill + LAShapeFill *fill = shape.fills.count ? shape.fills.firstObject : nil; + + //Get Transform + LAShapeTransform *transform = shape.transforms.count ? shape.transforms.firstObject : nil; + + if (!path) { + continue; + } + UIBezierPath *shapePath = [path.shapePath bezierPath:path.isClosed]; + CAShapeLayer *shapeLayer = [CAShapeLayer layer]; + shapeLayer.path = shapePath.CGPath; + + if (stroke) { + shapeLayer.strokeColor = stroke.color.CGColor; + shapeLayer.lineWidth = stroke.width.floatValue; + } + + if (fill) { + shapeLayer.fillColor = fill.color.CGColor; + shapeLayer.opacity = fill.alpha; + } + + if (transform) { +// shapeLayer.anchorPoint = transform.anchorPoint; +// shapeLayer.position = +// shapeLayer.transform = CATransform3DMakeAffineTransform(transform.transform); + } + [self.layer addSublayer:shapeLayer]; + } + } + UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_viewtapped)]; [self addGestureRecognizer:tapGesture]; } diff --git a/LotteAnimator/LAModels.h b/LotteAnimator/LAModels.h new file mode 100644 index 0000000000..9dc8920b58 --- /dev/null +++ b/LotteAnimator/LAModels.h @@ -0,0 +1,23 @@ +// +// LAModels.h +// LotteAnimator +// +// Created by Brandon Withrow on 12/15/15. +// Copyright © 2015 Brandon Withrow. All rights reserved. +// + +#ifndef LAModels_h +#define LAModels_h + +#import "LAPath.h" +#import "LAMask.h" +#import "LAScene.h" +#import "LALayer.h" +#import "LAShape.h" +#import "LAShapeItem.h" +#import "LAShapePath.h" +#import "LAShapeStroke.h" +#import "LAShapeFill.h" +#import "LAShapeTransform.h" + +#endif /* LAModels_h */ diff --git a/LotteAnimator/LAShape.h b/LotteAnimator/LAShape.h index f434adfa1a..8f16780bde 100644 --- a/LotteAnimator/LAShape.h +++ b/LotteAnimator/LAShape.h @@ -10,20 +10,11 @@ @interface LAShape : MTLModel -@property (nonatomic, getter=isClosed) BOOL closed; -@property (nonatomic, strong) LAPath *shapePath; +@property (nonatomic, copy) NSArray *shapeItems; -@property (nonatomic, strong) NSNumber *strokeWidth; -@property (nonatomic, strong) NSNumber *strokeOpacity; -@property (nonatomic, strong) NSArray *strokeColorElements; - -@property (nonatomic, strong) NSNumber *fillOpacity; -@property (nonatomic, strong) NSArray *fillColorElements; - -@property (nonatomic, copy) NSArray *positionArray; -@property (nonatomic, copy) NSArray *anchorPointArray; -@property (nonatomic, copy) NSArray *scaleArray; -@property (nonatomic, copy) NSNumber *rotation; -@property (nonatomic, copy) NSNumber *opacity; +@property (nonatomic, readonly) NSArray *paths; +@property (nonatomic, readonly) NSArray *strokes; +@property (nonatomic, readonly) NSArray *fills; +@property (nonatomic, readonly) NSArray *transforms; @end diff --git a/LotteAnimator/LAShape.m b/LotteAnimator/LAShape.m index b2981f0fe4..a9f3b079e5 100644 --- a/LotteAnimator/LAShape.m +++ b/LotteAnimator/LAShape.m @@ -7,7 +7,77 @@ // #import "LAShape.h" +#import "LAShapeItem.h" @implementation LAShape ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{@"shapeItems" : @"it"}; +} + ++ (NSValueTransformer *)shapeItemsJSONTransformer { + // tell Mantle to populate diaAttributes property with an array of MDAttribute objects + return [MTLJSONAdapter arrayTransformerWithModelClass:[LAShapeItem class]]; +} + +- (NSArray *)paths { + if (!self.shapeItems) { + return @[]; + } + NSMutableArray *paths = [NSMutableArray array]; + + for (LAShapeItem *item in self.shapeItems) { + if ([item.itemType isEqualToString:LAShapeItemType.Path]) { + [paths addObject:item]; + } + } + + return paths; +} + +- (NSArray *)strokes { + if (!self.shapeItems) { + return @[]; + } + NSMutableArray *strokes = [NSMutableArray array]; + + for (LAShapeItem *item in self.shapeItems) { + if ([item.itemType isEqualToString:LAShapeItemType.Stroke]) { + [strokes addObject:item]; + } + } + + return strokes; +} + +- (NSArray *)fills { + if (!self.shapeItems) { + return @[]; + } + NSMutableArray *fills = [NSMutableArray array]; + + for (LAShapeItem *item in self.shapeItems) { + if ([item.itemType isEqualToString:LAShapeItemType.Fill]) { + [fills addObject:item]; + } + } + + return fills; +} + +- (NSArray *)transforms { + if (!self.shapeItems) { + return @[]; + } + NSMutableArray *transforms = [NSMutableArray array]; + + for (LAShapeItem *item in self.shapeItems) { + if ([item.itemType isEqualToString:LAShapeItemType.Transform]) { + [transforms addObject:item]; + } + } + + return transforms; +} + @end diff --git a/LotteAnimator/LAShapeFill.h b/LotteAnimator/LAShapeFill.h new file mode 100644 index 0000000000..72cb5d0fd4 --- /dev/null +++ b/LotteAnimator/LAShapeFill.h @@ -0,0 +1,19 @@ +// +// LAShapeFill.h +// LotteAnimator +// +// Created by Brandon Withrow on 12/15/15. +// Copyright © 2015 Brandon Withrow. All rights reserved. +// + +#import "LAShapeItem.h" + +@interface LAShapeFill : LAShapeItem + +@property (nonatomic, getter=isFillEnabled) BOOL fillEnabled; +@property (nonatomic, copy) NSArray *colorElements; +@property (nonatomic, copy) NSNumber *opacity; + +@property (nonatomic, readonly) UIColor *color; +@property (nonatomic, readonly) CGFloat alpha; +@end diff --git a/LotteAnimator/LAShapeFill.m b/LotteAnimator/LAShapeFill.m new file mode 100644 index 0000000000..e779f5086f --- /dev/null +++ b/LotteAnimator/LAShapeFill.m @@ -0,0 +1,41 @@ +// +// LAShapeFill.m +// LotteAnimator +// +// Created by Brandon Withrow on 12/15/15. +// Copyright © 2015 Brandon Withrow. All rights reserved. +// + +#import "LAShapeFill.h" + +@implementation LAShapeFill + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{@"itemType" : @"ty", + @"fillEnabled" : @"fillEnabled", + @"colorElements" : @"c", + @"opacity" : @"o"}; +} + ++ (NSValueTransformer *)fillEnabledJSONTransformer { + return [NSValueTransformer valueTransformerForName:MTLBooleanValueTransformerName]; +} + +- (CGFloat)alpha { + if (!self.opacity) { + return 1; + } + return self.opacity.floatValue / 100.f; +} + +- (UIColor *)color { + if (!self.colorElements) { + return [UIColor clearColor]; + } + return [UIColor colorWithRed:([self.colorElements[0] floatValue]/255.f) + green:([self.colorElements[1] floatValue]/255.f) + blue:([self.colorElements[2] floatValue]/255.f) + alpha:([self.colorElements[3] floatValue]/255.f)]; +} + +@end diff --git a/LotteAnimator/LAShapeItem.h b/LotteAnimator/LAShapeItem.h new file mode 100644 index 0000000000..fc43958fd9 --- /dev/null +++ b/LotteAnimator/LAShapeItem.h @@ -0,0 +1,24 @@ +// +// LAShapeItem.h +// LotteAnimator +// +// Created by Brandon Withrow on 12/15/15. +// Copyright © 2015 Brandon Withrow. All rights reserved. +// + +#import "MTLModel.h" + +struct LAShapeItemType { + __unsafe_unretained NSString * const Path; + __unsafe_unretained NSString * const Stroke; + __unsafe_unretained NSString * const Fill; + __unsafe_unretained NSString * const Transform; +}; + +extern const struct LAShapeItemType LAShapeItemType; + +@interface LAShapeItem : MTLModel + +@property (nonatomic, copy) NSString *itemType; + +@end diff --git a/LotteAnimator/LAShapeItem.m b/LotteAnimator/LAShapeItem.m new file mode 100644 index 0000000000..f64133ea72 --- /dev/null +++ b/LotteAnimator/LAShapeItem.m @@ -0,0 +1,44 @@ +// +// LAShapeItem.m +// LotteAnimator +// +// Created by Brandon Withrow on 12/15/15. +// Copyright © 2015 Brandon Withrow. All rights reserved. +// + +#import "LAShapeItem.h" + +const struct LAShapeItemType LAShapeItemType = { + .Path = @"sh", + .Stroke = @"st", + .Fill = @"fl", + .Transform = @"tr" +}; + +@implementation LAShapeItem + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{@"itemType" : @"ty"}; +} + ++ (Class)classForParsingJSONDictionary:(NSDictionary *)JSONDictionary { + if ([JSONDictionary[@"ty"] isEqual:LAShapeItemType.Path]) { + return LAShapePath.class; + } + + if ([JSONDictionary[@"ty"] isEqual:LAShapeItemType.Stroke]) { + return LAShapeStroke.class; + } + + if ([JSONDictionary[@"ty"] isEqual:LAShapeItemType.Fill]) { + return LAShapeFill.class; + } + + if ([JSONDictionary[@"ty"] isEqual:LAShapeItemType.Transform]) { + return LAShapeTransform.class; + } + + return self; +} + +@end diff --git a/LotteAnimator/LAShapePath.h b/LotteAnimator/LAShapePath.h new file mode 100644 index 0000000000..5410460dfe --- /dev/null +++ b/LotteAnimator/LAShapePath.h @@ -0,0 +1,16 @@ +// +// LAShapePath.h +// LotteAnimator +// +// Created by Brandon Withrow on 12/15/15. +// Copyright © 2015 Brandon Withrow. All rights reserved. +// + +#import "LAShapeItem.h" + +@interface LAShapePath : LAShapeItem + +@property (nonatomic, getter=isClosed) BOOL closed; +@property (nonatomic, strong) LAPath *shapePath; + +@end diff --git a/LotteAnimator/LAShapePath.m b/LotteAnimator/LAShapePath.m new file mode 100644 index 0000000000..a5d1ff1fdc --- /dev/null +++ b/LotteAnimator/LAShapePath.m @@ -0,0 +1,28 @@ +// +// LAShapePath.m +// LotteAnimator +// +// Created by Brandon Withrow on 12/15/15. +// Copyright © 2015 Brandon Withrow. All rights reserved. +// + +#import "LAShapePath.h" + +@implementation LAShapePath + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{@"itemType" : @"ty", + @"closed" : @"closed", + @"shapePath" : @"ks"}; +} + ++ (NSValueTransformer *)shapePathJSONTransformer { + // tell Mantle to populate diaAttributes property with an array of MDAttribute objects + return [MTLJSONAdapter dictionaryTransformerWithModelClass:[LAPath class]]; +} + ++ (NSValueTransformer *)closedJSONTransformer { + return [NSValueTransformer valueTransformerForName:MTLBooleanValueTransformerName]; +} + +@end diff --git a/LotteAnimator/LAShapeStroke.h b/LotteAnimator/LAShapeStroke.h new file mode 100644 index 0000000000..49d01f4de7 --- /dev/null +++ b/LotteAnimator/LAShapeStroke.h @@ -0,0 +1,21 @@ +// +// LAShapeStroke.h +// LotteAnimator +// +// Created by Brandon Withrow on 12/15/15. +// Copyright © 2015 Brandon Withrow. All rights reserved. +// + +#import "LAShapeItem.h" + +@interface LAShapeStroke : LAShapeItem + +@property (nonatomic, getter=isFillEnabled) BOOL fillEnabled; +@property (nonatomic, copy) NSArray *colorElements; +@property (nonatomic, copy) NSNumber *opacity; +@property (nonatomic, copy) NSNumber *width; + +@property (nonatomic, readonly) UIColor *color; +@property (nonatomic, readonly) CGFloat alpha; + +@end diff --git a/LotteAnimator/LAShapeStroke.m b/LotteAnimator/LAShapeStroke.m new file mode 100644 index 0000000000..d0ddb31c87 --- /dev/null +++ b/LotteAnimator/LAShapeStroke.m @@ -0,0 +1,42 @@ +// +// LAShapeStroke.m +// LotteAnimator +// +// Created by Brandon Withrow on 12/15/15. +// Copyright © 2015 Brandon Withrow. All rights reserved. +// + +#import "LAShapeStroke.h" + +@implementation LAShapeStroke + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{@"itemType" : @"ty", + @"fillEnabled" : @"fillEnabled", + @"colorElements" : @"c", + @"opacity" : @"o", + @"width" : @"w"}; +} + ++ (NSValueTransformer *)fillEnabledJSONTransformer { + return [NSValueTransformer valueTransformerForName:MTLBooleanValueTransformerName]; +} + +- (CGFloat)alpha { + if (!self.opacity) { + return 1; + } + return self.opacity.floatValue / 100.f; +} + +- (UIColor *)color { + if (!self.colorElements) { + return [UIColor clearColor]; + } + return [UIColor colorWithRed:([self.colorElements[0] floatValue]/255.f) + green:([self.colorElements[1] floatValue]/255.f) + blue:([self.colorElements[2] floatValue]/255.f) + alpha:([self.colorElements[3] floatValue]/255.f)]; +} + +@end diff --git a/LotteAnimator/LAShapeTransform.h b/LotteAnimator/LAShapeTransform.h new file mode 100644 index 0000000000..60a5393220 --- /dev/null +++ b/LotteAnimator/LAShapeTransform.h @@ -0,0 +1,25 @@ +// +// LAShapeTransform.h +// LotteAnimator +// +// Created by Brandon Withrow on 12/15/15. +// Copyright © 2015 Brandon Withrow. All rights reserved. +// + +#import "LAShapeItem.h" + +@interface LAShapeTransform : LAShapeItem + +@property (nonatomic, copy) NSArray *positionArray; +@property (nonatomic, copy) NSArray *anchorPointArray; +@property (nonatomic, copy) NSArray *scaleArray; +@property (nonatomic, copy) NSNumber *rotation; +@property (nonatomic, copy) NSNumber *opacity; + +@property (nonatomic, readonly) CGPoint position; +@property (nonatomic, readonly) CGPoint anchorPoint; +@property (nonatomic, readonly) CGSize scale; +@property (nonatomic, readonly) CGFloat alpha; +@property (nonatomic, readonly) CGAffineTransform transform; + +@end diff --git a/LotteAnimator/LAShapeTransform.m b/LotteAnimator/LAShapeTransform.m new file mode 100644 index 0000000000..a9a786b6fc --- /dev/null +++ b/LotteAnimator/LAShapeTransform.m @@ -0,0 +1,63 @@ +// +// LAShapeTransform.m +// LotteAnimator +// +// Created by Brandon Withrow on 12/15/15. +// Copyright © 2015 Brandon Withrow. All rights reserved. +// + +#import "LAShapeTransform.h" + +@implementation LAShapeTransform + ++ (NSDictionary *)JSONKeyPathsByPropertyKey { + return @{@"itemType" : @"ty", + @"positionArray" : @"p", + @"anchorPointArray" : @"a", + @"scaleArray" : @"s", + @"rotation" : @"r", + @"opacity" : @"o"}; +} + +- (CGPoint)position { + if (!self.positionArray) { + return CGPointZero; + } + CGPoint aePosition = CGPointMake([self.positionArray[0] floatValue], [self.positionArray[1] floatValue]); + if (self.anchorPointArray) { + aePosition.x -= [self.anchorPointArray[0] floatValue]; + aePosition.y -= [self.anchorPointArray[1] floatValue]; + } + return aePosition; +} + +- (CGPoint)anchorPoint { + if (!self.anchorPointArray) { + return CGPointZero; + } + CGPoint aeAnchorPoint = CGPointMake([self.anchorPointArray[0] floatValue], [self.anchorPointArray[1] floatValue]); +// CGPoint uikitAnchorPoint = CGPointMake(aeAnchorPoint.x / self.size.width, +// aeAnchorPoint.y / self.size.height); + // TODO Figure out this crazy thing + return aeAnchorPoint; +} + +- (CGSize)scale { + if (!self.scaleArray) { + return CGSizeZero; + } + return CGSizeMake([self.scaleArray[0] floatValue] / 100.f, [self.scaleArray[1] floatValue] / 100.f); +} + +- (CGFloat)alpha { + if (!self.opacity) { + return 1; + } + return self.opacity.floatValue / 100.f; +} + +- (CGAffineTransform)transform { + return CGAffineTransformRotate(CGAffineTransformMakeScale(self.scale.width, self.scale.height), DegreesToRadians(self.rotation ? self.rotation.floatValue : 0.f)); +} + +@end diff --git a/LotteAnimator/data.json b/LotteAnimator/data.json index 044cb470c4..1b546c24b8 100644 --- a/LotteAnimator/data.json +++ b/LotteAnimator/data.json @@ -1 +1 @@ -{"animation":{"layers":[{"ind":0,"type":"SolidLayer","layerName":"SquareLayer","threeD":false,"an":{},"width":150,"height":150,"color":"#f62fec","inPoint":0,"outPoint":121,"startTime":0,"ks":{"o":100,"r":0,"p":[228,200.5,0],"a":[75,75,0],"s":[100,100,100]}},{"ind":1,"type":"ShapeLayer","shapes":[{"ty":"gr","it":[{"ty":"sh","closed":true,"ks":{"i":[[92,36],[52,-72],[0,0],[0,44]],"o":[[-92,-36],[-52,72],[0,0],[0,-44]],"v":[[8,-256.5],[-92,-192.5],[-116,-76.5],[-48,-152.5]]}},{"ty":"st","fillEnabled":true,"c":[255,255,255,255],"o":100,"w":2},{"ty":"fl","fillEnabled":true,"c":[255,0,0,255],"o":100},{"ty":"tr","p":[0,0],"a":[0,0],"s":[100,100],"r":0,"o":100}]}],"rectData":{"l":0,"t":0,"b":0,"r":0,"w":0,"h":0},"layerName":"ShapeLayer","threeD":false,"an":{},"width":320,"height":585,"inPoint":0,"outPoint":121,"startTime":0,"ks":{"o":100,"r":0,"p":[210,312.5,0],"a":[0,0,0],"s":[100,100,100]}},{"ind":2,"masksProperties":[{"cl":true,"inv":false,"mode":"a","pt":{"i":[[84,0],[122,-80],[-76,136],[-75.735,21.822]],"o":[[-84,0],[-63.862,41.877],[46.831,-83.802],[118,-34]],"v":[[144,164],[144,428],[250,402],[260,200]]},"o":100}],"hasMask":true,"type":"SolidLayer","layerName":"PathLayer","threeD":false,"an":{},"width":320,"height":585,"color":"#3df673","inPoint":0,"outPoint":121,"startTime":0,"ks":{"o":100,"r":0,"p":[152,366.5,0],"a":[160,292.5,0],"s":[100,100,100]}},{"ind":3,"type":"NullLayer","layerName":"Null 1","threeD":false,"an":{},"inPoint":0,"outPoint":121,"startTime":0,"ks":{"o":0,"r":0,"p":[92,36,0],"a":[0,0,0],"s":[100,100,100]}}],"totalFrames":86,"frameRate":24,"ff":1.45833333333333,"compWidth":320,"compHeight":585},"assets":[],"v":"2.0.6"} \ No newline at end of file +{"animation":{"layers":[{"ind":0,"type":"SolidLayer","layerName":"SquareLayer","threeD":false,"an":{},"width":150,"height":150,"color":"#f62fec","inPoint":0,"outPoint":121,"startTime":0,"ks":{"o":100,"r":0,"p":[228,200.5,0],"a":[75,75,0],"s":[100,100,100]}},{"ind":1,"type":"ShapeLayer","shapes":[{"ty":"gr","it":[{"ty":"sh","closed":true,"ks":{"i":[[92,36],[52,-72],[0,0],[0,44]],"o":[[-92,-36],[-52,72],[0,0],[0,-44]],"v":[[8,-256.5],[-92,-192.5],[-116,-76.5],[-48,-152.5]]}},{"ty":"st","fillEnabled":true,"c":[255,0,0,255],"o":100,"w":2},{"ty":"fl","fillEnabled":true,"c":[255,0,0,255],"o":100},{"ty":"tr","p":[0,0],"a":[0,0],"s":[100,100],"r":0,"o":100}]}],"rectData":{"l":0,"t":0,"b":0,"r":0,"w":0,"h":0},"layerName":"ShapeLayer","threeD":false,"an":{},"width":320,"height":585,"inPoint":0,"outPoint":121,"startTime":0,"ks":{"o":100,"r":0,"p":[146,334.5,0],"a":[0,0,0],"s":[100,100,100]}},{"ind":2,"masksProperties":[{"cl":true,"inv":false,"mode":"a","pt":{"i":[[84,0],[122,-80],[-76,136],[-75.735,21.822]],"o":[[-84,0],[-63.862,41.877],[46.831,-83.802],[118,-34]],"v":[[144,164],[144,428],[250,402],[260,200]]},"o":100}],"hasMask":true,"type":"SolidLayer","layerName":"PathLayer","threeD":false,"an":{},"width":320,"height":585,"color":"#3df673","inPoint":0,"outPoint":121,"startTime":0,"ks":{"o":100,"r":0,"p":[152,366.5,0],"a":[160,292.5,0],"s":[100,100,100]}},{"ind":3,"type":"NullLayer","layerName":"Null 1","threeD":false,"an":{},"inPoint":0,"outPoint":121,"startTime":0,"ks":{"o":0,"r":0,"p":[92,36,0],"a":[0,0,0],"s":[100,100,100]}}],"totalFrames":86,"frameRate":24,"ff":1.45833333333333,"compWidth":320,"compHeight":585},"assets":[],"v":"2.0.6"} \ No newline at end of file diff --git a/PrefixHeader.pch b/PrefixHeader.pch index a9c2580114..8eda0a27b5 100644 --- a/PrefixHeader.pch +++ b/PrefixHeader.pch @@ -16,11 +16,8 @@ #import #import "UIColor+Expanded.h" #import "BWMath.h" -#import "LAScene.h" -#import "LALayer.h" #import "LALayerView.h" #import "LACompView.h" -#import "LAPath.h" -#import "LAMask.h" +#import "LAModels.h" #endif /* PrefixHeader_pch */