From 0967f30f678d71655b46fc6a26136cb47bdba3eb Mon Sep 17 00:00:00 2001 From: Brandon Withrow Date: Fri, 17 Feb 2017 17:39:37 -0800 Subject: [PATCH] Rework model layer and begin complayer --- Example/Pods/Pods.xcodeproj/project.pbxproj | 24 + Example/lottie-ios.xcodeproj/project.pbxproj | 4 + Example/lottie-ios/precompMadness.json | 628 ++++++++++++++++++ .../AnimatableLayers/LOTCompositionLayer.h | 16 + .../AnimatableLayers/LOTCompositionLayer.m | 69 ++ lottie-ios/Classes/Models/LOTAsset.h | 4 +- lottie-ios/Classes/Models/LOTAsset.m | 21 +- lottie-ios/Classes/Models/LOTAssetGroup.h | 24 + lottie-ios/Classes/Models/LOTAssetGroup.m | 62 ++ lottie-ios/Classes/Models/LOTComposition.h | 6 +- lottie-ios/Classes/Models/LOTComposition.m | 33 +- lottie-ios/Classes/Models/LOTLayer.m | 18 +- lottie-ios/Classes/Models/LOTLayerGroup.h | 4 +- lottie-ios/Classes/Models/LOTLayerGroup.m | 14 +- 14 files changed, 883 insertions(+), 44 deletions(-) create mode 100644 Example/lottie-ios/precompMadness.json create mode 100644 lottie-ios/Classes/AnimatableLayers/LOTCompositionLayer.h create mode 100644 lottie-ios/Classes/AnimatableLayers/LOTCompositionLayer.m create mode 100644 lottie-ios/Classes/Models/LOTAssetGroup.h create mode 100644 lottie-ios/Classes/Models/LOTAssetGroup.m diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index eadac0987d..6a3ecc3d14 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -72,6 +72,14 @@ 484EBA1E1E567CF500D4CAD9 /* LOTLayerGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 484EBA1B1E567CF500D4CAD9 /* LOTLayerGroup.h */; }; 484EBA1F1E567CF500D4CAD9 /* LOTLayerGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 484EBA1C1E567CF500D4CAD9 /* LOTLayerGroup.m */; }; 484EBA201E567CF500D4CAD9 /* LOTLayerGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 484EBA1C1E567CF500D4CAD9 /* LOTLayerGroup.m */; }; + 484EBA2B1E578AE200D4CAD9 /* LOTCompositionLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 484EBA291E578AE200D4CAD9 /* LOTCompositionLayer.h */; }; + 484EBA2C1E578AE200D4CAD9 /* LOTCompositionLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 484EBA291E578AE200D4CAD9 /* LOTCompositionLayer.h */; }; + 484EBA2D1E578AE200D4CAD9 /* LOTCompositionLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 484EBA2A1E578AE200D4CAD9 /* LOTCompositionLayer.m */; }; + 484EBA2E1E578AE200D4CAD9 /* LOTCompositionLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 484EBA2A1E578AE200D4CAD9 /* LOTCompositionLayer.m */; }; + 484EBA311E578BA800D4CAD9 /* LOTAssetGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 484EBA2F1E578BA800D4CAD9 /* LOTAssetGroup.h */; }; + 484EBA321E578BA800D4CAD9 /* LOTAssetGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 484EBA2F1E578BA800D4CAD9 /* LOTAssetGroup.h */; }; + 484EBA331E578BA800D4CAD9 /* LOTAssetGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 484EBA301E578BA800D4CAD9 /* LOTAssetGroup.m */; }; + 484EBA341E578BA800D4CAD9 /* LOTAssetGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 484EBA301E578BA800D4CAD9 /* LOTAssetGroup.m */; }; 484FF8CA1E4A972500B2B4FF /* LOTStrokeShapeLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 484FF8C81E4A972500B2B4FF /* LOTStrokeShapeLayer.h */; }; 484FF8CB1E4A972500B2B4FF /* LOTStrokeShapeLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 484FF8C81E4A972500B2B4FF /* LOTStrokeShapeLayer.h */; }; 484FF8CC1E4A972500B2B4FF /* LOTStrokeShapeLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 484FF8C91E4A972500B2B4FF /* LOTStrokeShapeLayer.m */; }; @@ -255,6 +263,10 @@ 484EBA0F1E5656DD00D4CAD9 /* LOTAsset.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LOTAsset.m; sourceTree = ""; }; 484EBA1B1E567CF500D4CAD9 /* LOTLayerGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LOTLayerGroup.h; sourceTree = ""; }; 484EBA1C1E567CF500D4CAD9 /* LOTLayerGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LOTLayerGroup.m; sourceTree = ""; }; + 484EBA291E578AE200D4CAD9 /* LOTCompositionLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LOTCompositionLayer.h; sourceTree = ""; }; + 484EBA2A1E578AE200D4CAD9 /* LOTCompositionLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LOTCompositionLayer.m; sourceTree = ""; }; + 484EBA2F1E578BA800D4CAD9 /* LOTAssetGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LOTAssetGroup.h; sourceTree = ""; }; + 484EBA301E578BA800D4CAD9 /* LOTAssetGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LOTAssetGroup.m; sourceTree = ""; }; 484FF8C81E4A972500B2B4FF /* LOTStrokeShapeLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LOTStrokeShapeLayer.h; sourceTree = ""; }; 484FF8C91E4A972500B2B4FF /* LOTStrokeShapeLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LOTStrokeShapeLayer.m; sourceTree = ""; }; 4897935C31F44A855C225490165F579E /* CAAnimationGroup+LOTAnimatableGroup.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "CAAnimationGroup+LOTAnimatableGroup.m"; sourceTree = ""; }; @@ -523,6 +535,8 @@ 2B4F91019A41754A4617A095209FAEFB /* LOTShapeLayerView.m */, 484FF8C81E4A972500B2B4FF /* LOTStrokeShapeLayer.h */, 484FF8C91E4A972500B2B4FF /* LOTStrokeShapeLayer.m */, + 484EBA291E578AE200D4CAD9 /* LOTCompositionLayer.h */, + 484EBA2A1E578AE200D4CAD9 /* LOTCompositionLayer.m */, ); path = AnimatableLayers; sourceTree = ""; @@ -609,6 +623,8 @@ 484EBA0F1E5656DD00D4CAD9 /* LOTAsset.m */, 484EBA1B1E567CF500D4CAD9 /* LOTLayerGroup.h */, 484EBA1C1E567CF500D4CAD9 /* LOTLayerGroup.m */, + 484EBA2F1E578BA800D4CAD9 /* LOTAssetGroup.h */, + 484EBA301E578BA800D4CAD9 /* LOTAssetGroup.m */, 91320FA54A945B0D6F0DA1360E66F4EA /* LOTLayer.h */, 0D575B6A057045C18575B20F98F4D18A /* LOTLayer.m */, CCFB05FD8351F6DF6D9DB1678426591E /* LOTMask.h */, @@ -749,7 +765,9 @@ 48183C971E54E1B60039F121 /* CGGeometry+LOTAdditions.h in Headers */, 1B7AD1DB3B240B3F6075DAC7A2C60327 /* LOTPlatformCompat.h in Headers */, 9393029CAB8D0DCFBD598DCA8F9652CB /* LOTRectShapeLayer.h in Headers */, + 484EBA2C1E578AE200D4CAD9 /* LOTCompositionLayer.h in Headers */, 43525BF925E577FA5BC55FA8722D3C95 /* LOTShapeCircle.h in Headers */, + 484EBA321E578BA800D4CAD9 /* LOTAssetGroup.h in Headers */, B6C5A67F95DB839A26C652F10A6F1BD1 /* LOTShapeFill.h in Headers */, CED532CCB58213D9CC1B20F9E02358A0 /* LOTShapeGroup.h in Headers */, AC23444263ED001DBFF7925905AD0186 /* LOTShapeLayerView.h in Headers */, @@ -802,7 +820,9 @@ 48183C961E54E1B60039F121 /* CGGeometry+LOTAdditions.h in Headers */, 019EB390040200530FBD33CFCE1C6C0C /* LOTPlatformCompat.h in Headers */, FB9D8FF758399BF0DDE29DF9D14FD18C /* LOTRectShapeLayer.h in Headers */, + 484EBA2B1E578AE200D4CAD9 /* LOTCompositionLayer.h in Headers */, F9FC80D505B823B40B2B00D5D3D070C6 /* LOTShapeCircle.h in Headers */, + 484EBA311E578BA800D4CAD9 /* LOTAssetGroup.h in Headers */, 71260F5EC2FB27E95FA8C1F5E18335EA /* LOTShapeFill.h in Headers */, 17E6CB11A15CEF17D116EADF1BE32940 /* LOTShapeGroup.h in Headers */, 0FE6D67AC31B34E5650ABE9F9DD2F12C /* LOTShapeLayerView.h in Headers */, @@ -969,6 +989,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 484EBA2D1E578AE200D4CAD9 /* LOTCompositionLayer.m in Sources */, 1AF05E6A1ED488D8A4590E451D16DB25 /* CAAnimationGroup+LOTAnimatableGroup.m in Sources */, 38724389F4AF391B9BC43CD50AA3EDD8 /* CADisplayLink.m in Sources */, 0F981EA0F990063F90AB32883A53CE20 /* CALayer+Compat.m in Sources */, @@ -1003,6 +1024,7 @@ C2F8ACA3161511701D310AD830AB73DA /* LOTShapeStroke.m in Sources */, D99E5F130A06004B71F0CCB62F2213AB /* LOTShapeTransform.m in Sources */, 0224DD121FC30CF8D8EA84DEEDE9E5EF /* LOTShapeTrimPath.m in Sources */, + 484EBA331E578BA800D4CAD9 /* LOTAssetGroup.m in Sources */, BAF2A478D8415FFAD0C6AFEAD2F5C65E /* lottie-ios-iOS-dummy.m in Sources */, 81A41631E43E19BA7747CFC447660357 /* NSValue+Compat.m in Sources */, 23B582AC94E91248DAA79577B7D6B895 /* UIBezierPath.m in Sources */, @@ -1031,6 +1053,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 484EBA2E1E578AE200D4CAD9 /* LOTCompositionLayer.m in Sources */, 07DF80DAF9334BF948557F2B6E25CA41 /* CAAnimationGroup+LOTAnimatableGroup.m in Sources */, 03667BC5DD6C96DC5FA10669D8D1169C /* CADisplayLink.m in Sources */, 7EB6832366B45B6EA7B484FC55BD065C /* CALayer+Compat.m in Sources */, @@ -1065,6 +1088,7 @@ 099861D88F2BD9EEFDAF48C506F7E759 /* LOTShapeStroke.m in Sources */, 28E9535414CE1BEC591C89E7A06EAEF0 /* LOTShapeTransform.m in Sources */, 9BA1D5723FE30B61B46BFAE9EEB219A2 /* LOTShapeTrimPath.m in Sources */, + 484EBA341E578BA800D4CAD9 /* LOTAssetGroup.m in Sources */, 49DEF831442B05BED78E24E963AFC601 /* lottie-ios-OSX-dummy.m in Sources */, AAB4BB60CC3237D11259AD486F2DDF0F /* NSValue+Compat.m in Sources */, 08EEF536571B1944EEE24963FE47D796 /* UIBezierPath.m in Sources */, diff --git a/Example/lottie-ios.xcodeproj/project.pbxproj b/Example/lottie-ios.xcodeproj/project.pbxproj index 9bbd4f69e1..c02d54b3b5 100644 --- a/Example/lottie-ios.xcodeproj/project.pbxproj +++ b/Example/lottie-ios.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 484EBA381E57D8E600D4CAD9 /* precompMadness.json in Resources */ = {isa = PBXBuildFile; fileRef = 484EBA371E57D8E600D4CAD9 /* precompMadness.json */; }; 48A852311E3A9E71000AD155 /* lottie_logo.png in Resources */ = {isa = PBXBuildFile; fileRef = 48A852301E3A9E71000AD155 /* lottie_logo.png */; }; 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58F195388D20070C39A /* CoreGraphics.framework */; }; @@ -96,6 +97,7 @@ 05ACBD6FE5DF79DB2906251A /* Pods-lottie-ios_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-lottie-ios_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-lottie-ios_Tests/Pods-lottie-ios_Tests.debug.xcconfig"; sourceTree = ""; }; 278F8B6FD5D7B8D80A860E31 /* Pods-lottie-ios_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-lottie-ios_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-lottie-ios_Tests/Pods-lottie-ios_Tests.release.xcconfig"; sourceTree = ""; }; 3B15EF764A3BC631B7F802E1 /* Pods_Lottie_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Lottie_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 484EBA371E57D8E600D4CAD9 /* precompMadness.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = precompMadness.json; sourceTree = ""; }; 48A852301E3A9E71000AD155 /* lottie_logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = lottie_logo.png; sourceTree = ""; }; 4EBDFEA18138A27DD5A89337 /* Pods_lottie_ios_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_lottie_ios_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6003F58A195388D20070C39A /* Lottie-Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Lottie-Example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -296,6 +298,7 @@ 6003F594195388D20070C39A /* Supporting Files */ = { isa = PBXGroup; children = ( + 484EBA371E57D8E600D4CAD9 /* precompMadness.json */, 6003F5B6195388D20070C39A /* Supporting Files */, 48A852301E3A9E71000AD155 /* lottie_logo.png */, 6003F595195388D20070C39A /* lottie-ios-Info.plist */, @@ -560,6 +563,7 @@ 62B254BB1E3A90040035A842 /* M.json in Resources */, 62B254B11E3A90040035A842 /* Comma.json in Resources */, 62B254B51E3A90040035A842 /* G.json in Resources */, + 484EBA381E57D8E600D4CAD9 /* precompMadness.json in Resources */, 62B254A21E3A90040035A842 /* 9squares-AlBoardman.json in Resources */, 71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */, 62B254AB1E3A90040035A842 /* A.json in Resources */, diff --git a/Example/lottie-ios/precompMadness.json b/Example/lottie-ios/precompMadness.json new file mode 100644 index 0000000000..d9ce2e34ed --- /dev/null +++ b/Example/lottie-ios/precompMadness.json @@ -0,0 +1,628 @@ +{ + "assets": [ + { + "id": "comp_22", + "layers": [ + { + "ddd": 0, + "ind": 0, + "ty": 0, + "nm": "100x", + "refId": "comp_23", + "ks": { + "o": { + "k": 100 + }, + "r": { + "k": 0 + }, + "p": { + "k": [ + 150, + 150, + 0 + ] + }, + "a": { + "k": [ + 50, + 50, + 0 + ] + }, + "s": { + "k": [ + 100, + 100, + 100 + ] + } + }, + "ao": 0, + "w": 100, + "h": 100, + "ip": 0, + "op": 120, + "st": 0, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 1, + "ty": 4, + "nm": "Shape Layer 1", + "ks": { + "o": { + "k": 100 + }, + "r": { + "k": 0 + }, + "p": { + "k": [ + 150, + 150, + 0 + ] + }, + "a": { + "k": [ + 0, + 0, + 0 + ] + }, + "s": { + "k": [ + 100, + 100, + 100 + ] + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ty": "rc", + "d": 1, + "s": { + "k": [ + 387.016, + 354.523 + ] + }, + "p": { + "k": [ + 0, + 0 + ] + }, + "r": { + "k": 0 + }, + "nm": "Rectangle Path 1", + "mn": "ADBE Vector Shape - Rect" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { + "k": [ + 1, + 1, + 1, + 1 + ] + }, + "o": { + "k": 100 + }, + "w": { + "k": 2 + }, + "lc": 1, + "lj": 1, + "ml": 4, + "nm": "Stroke 1", + "mn": "ADBE Vector Graphic - Stroke" + }, + { + "ty": "fl", + "fillEnabled": true, + "c": { + "k": [ + 0.76, + 0.1, + 0.82, + 1 + ] + }, + "o": { + "k": 100 + }, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill" + }, + { + "ty": "tr", + "p": { + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "a": { + "k": [ + { + "i": { + "x": 0.833, + "y": 0.833 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p833_0p833_0p167_0p167", + "t": 0, + "s": [ + 0, + 0 + ], + "e": [ + 187, + -127 + ], + "to": [ + 31.1666660308838, + -21.1666660308838 + ], + "ti": [ + -31.1666660308838, + 21.1666660308838 + ] + }, + { + "t": 119 + } + ], + "ix": 1 + }, + "s": { + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Rectangle 1", + "np": 3, + "mn": "ADBE Vector Group" + } + ], + "ip": 0, + "op": 120, + "st": 0, + "bm": 0, + "sr": 1 + } + ] + }, + { + "id": "comp_23", + "layers": [ + { + "ddd": 0, + "ind": 0, + "ty": 4, + "nm": "Shape Layer 1", + "ks": { + "o": { + "k": 100 + }, + "r": { + "k": 0 + }, + "p": { + "k": [ + 50, + 50, + 0 + ] + }, + "a": { + "k": [ + 0, + 0, + 0 + ] + }, + "s": { + "k": [ + 100, + 100, + 100 + ] + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ty": "rc", + "d": 1, + "s": { + "k": [ + 145.863, + 106.325 + ] + }, + "p": { + "k": [ + 0, + 0 + ] + }, + "r": { + "k": 0 + }, + "nm": "Rectangle Path 1", + "mn": "ADBE Vector Shape - Rect" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { + "k": [ + 1, + 1, + 1, + 1 + ] + }, + "o": { + "k": 100 + }, + "w": { + "k": 2 + }, + "lc": 1, + "lj": 1, + "ml": 4, + "nm": "Stroke 1", + "mn": "ADBE Vector Graphic - Stroke" + }, + { + "ty": "fl", + "fillEnabled": true, + "c": { + "k": [ + 0, + 0.82, + 0.76, + 1 + ] + }, + "o": { + "k": 100 + }, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill" + }, + { + "ty": "tr", + "p": { + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "a": { + "k": [ + { + "i": { + "x": 0.833, + "y": 0.833 + }, + "o": { + "x": 0.167, + "y": 0.167 + }, + "n": "0p833_0p833_0p167_0p167", + "t": 0, + "s": [ + 0, + 0 + ], + "e": [ + 0, + 55 + ], + "to": [ + 0, + 9.16666698455811 + ], + "ti": [ + 0, + -9.16666698455811 + ] + }, + { + "t": 119 + } + ], + "ix": 1 + }, + "s": { + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Rectangle 1", + "np": 3, + "mn": "ADBE Vector Group" + } + ], + "ip": 0, + "op": 120, + "st": 0, + "bm": 0, + "sr": 1 + } + ] + } + ], + "layers": [ + { + "ddd": 0, + "ind": 0, + "ty": 0, + "nm": "300x", + "refId": "comp_22", + "ks": { + "o": { + "k": 100 + }, + "r": { + "k": 0 + }, + "p": { + "k": [ + 250, + 250, + 0 + ] + }, + "a": { + "k": [ + 150, + 150, + 0 + ] + }, + "s": { + "k": [ + 100, + 100, + 100 + ] + } + }, + "ao": 0, + "w": 300, + "h": 300, + "ip": 0, + "op": 120, + "st": 0, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 1, + "ty": 4, + "nm": "Shape Layer 1", + "ks": { + "o": { + "k": 100 + }, + "r": { + "k": 0 + }, + "p": { + "k": [ + 250, + 250, + 0 + ] + }, + "a": { + "k": [ + 0, + 0, + 0 + ] + }, + "s": { + "k": [ + 100, + 100, + 100 + ] + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ty": "rc", + "d": 1, + "s": { + "k": [ + 652.143, + 622.474 + ] + }, + "p": { + "k": [ + 0, + 0 + ] + }, + "r": { + "k": 0 + }, + "nm": "Rectangle Path 1", + "mn": "ADBE Vector Shape - Rect" + }, + { + "ty": "st", + "fillEnabled": true, + "c": { + "k": [ + 1, + 1, + 1, + 1 + ] + }, + "o": { + "k": 100 + }, + "w": { + "k": 2 + }, + "lc": 1, + "lj": 1, + "ml": 4, + "nm": "Stroke 1", + "mn": "ADBE Vector Graphic - Stroke" + }, + { + "ty": "fl", + "fillEnabled": true, + "c": { + "k": [ + 0.37, + 0.34, + 0.82, + 1 + ] + }, + "o": { + "k": 100 + }, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill" + }, + { + "ty": "tr", + "p": { + "k": [ + 52.262, + 57.478 + ], + "ix": 2 + }, + "a": { + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "k": 0, + "ix": 6 + }, + "o": { + "k": 100, + "ix": 7 + }, + "sk": { + "k": 0, + "ix": 4 + }, + "sa": { + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Rectangle 1", + "np": 3, + "mn": "ADBE Vector Group" + } + ], + "ip": 0, + "op": 120, + "st": 0, + "bm": 0, + "sr": 1 + } + ], + "v": "4.5.0", + "ddd": 0, + "ip": 0, + "op": 120, + "fr": 30, + "w": 500, + "h": 500 +} \ No newline at end of file diff --git a/lottie-ios/Classes/AnimatableLayers/LOTCompositionLayer.h b/lottie-ios/Classes/AnimatableLayers/LOTCompositionLayer.h new file mode 100644 index 0000000000..e8351ff8d5 --- /dev/null +++ b/lottie-ios/Classes/AnimatableLayers/LOTCompositionLayer.h @@ -0,0 +1,16 @@ +// +// LOTCompositionLayer.h +// Pods +// +// Created by Brandon Withrow on 2/17/17. +// +// + +#import +@class LOTLayerGroup; + +@interface LOTCompositionLayer : CALayer + +- (instancetype)initWithLayerGroup:(LOTLayerGroup *)layerGroup; + +@end diff --git a/lottie-ios/Classes/AnimatableLayers/LOTCompositionLayer.m b/lottie-ios/Classes/AnimatableLayers/LOTCompositionLayer.m new file mode 100644 index 0000000000..40a9d3db3c --- /dev/null +++ b/lottie-ios/Classes/AnimatableLayers/LOTCompositionLayer.m @@ -0,0 +1,69 @@ +// +// LOTCompositionLayer.m +// Pods +// +// Created by Brandon Withrow on 2/17/17. +// +// + +#import "LOTCompositionLayer.h" + +@implementation LOTCompositionLayer { + +} + +- (instancetype)initWithLayerGroup:(LOTLayerGroup *)layerGroup { + self = [super init]; + if (self) { + self.masksToBounds = YES; + [self _setupWithLayerGroup:layerGroup]; + } + return self; +} + +- (void)_setupWithLayerGroup:(LOTLayerGroup *)layerGroup { + if (_customLayers) { + for (LOTCustomChild *child in _customLayers) { + [child.childView.layer removeFromSuperlayer]; + } + _customLayers = nil; + } + + if (_layerMap) { + _layerMap = nil; + [_animationContainer removeAllAnimations]; + [_animationContainer.sublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; + } + + if (_layerNameMap) { + _layerNameMap = nil; + } + + _animationContainer.transform = CATransform3DIdentity; + _animationContainer.bounds = _sceneModel.compBounds; + + NSMutableDictionary *layerMap = [NSMutableDictionary dictionary]; + NSMutableDictionary *layerNameMap = [NSMutableDictionary dictionary]; + + NSArray *reversedItems = [[_sceneModel.layerGroup.layers reverseObjectEnumerator] allObjects]; + + LOTLayerView *maskedLayer = nil; + for (LOTLayer *layer in reversedItems) { + LOTLayerView *layerView = [[LOTLayerView alloc] initWithModel:layer inLayerGroup:_sceneModel.layerGroup]; + layerMap[layer.layerID] = layerView; + layerNameMap[layer.layerName] = layerView; + if (maskedLayer) { + maskedLayer.mask = layerView; + maskedLayer = nil; + } else { + if (layer.matteType == LOTMatteTypeAdd) { + maskedLayer = layerView; + } + [_animationContainer addSublayer:layerView]; + } + } + _layerMap = layerMap; + _layerNameMap = layerNameMap; +} + +@end diff --git a/lottie-ios/Classes/Models/LOTAsset.h b/lottie-ios/Classes/Models/LOTAsset.h index 6f2c8975c4..d1cffd859d 100644 --- a/lottie-ios/Classes/Models/LOTAsset.h +++ b/lottie-ios/Classes/Models/LOTAsset.h @@ -11,12 +11,14 @@ @class LOTLayerGroup; @class LOTLayer; +@class LOTAssetGroup; @interface LOTAsset : NSObject - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary withBounds:(CGRect)bounds - withFramerate:(NSNumber *)framerate; + withFramerate:(NSNumber * _Nullable)framerate + withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup; @property (nonatomic, readonly) NSString *referenceID; @property (nonatomic, readonly) NSNumber *assetWidth; diff --git a/lottie-ios/Classes/Models/LOTAsset.m b/lottie-ios/Classes/Models/LOTAsset.m index 0918797ac6..e5713294af 100644 --- a/lottie-ios/Classes/Models/LOTAsset.m +++ b/lottie-ios/Classes/Models/LOTAsset.m @@ -9,15 +9,20 @@ #import "LOTAsset.h" #import "LOTLayer.h" #import "LOTLayerGroup.h" +#import "LOTAssetGroup.h" @implementation LOTAsset - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary withBounds:(CGRect)bounds - withFramerate:(NSNumber *)framerate { + withFramerate:(NSNumber *)framerate + withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup{ self = [super init]; if (self) { - [self _mapFromJSON:jsonDictionary withBounds:bounds withFramerate:framerate]; + [self _mapFromJSON:jsonDictionary + withBounds:bounds + withFramerate:framerate + withAssetGroup:assetGroup]; } return self; } @@ -25,7 +30,8 @@ - (void)_mapFromJSON:(NSDictionary *)jsonDictionary withBounds:(CGRect)bounds - withFramerate:(NSNumber *)framerate { + withFramerate:(NSNumber *)framerate + withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup{ _referenceID = [jsonDictionary[@"id"] copy]; if (jsonDictionary[@"w"]) { @@ -43,12 +49,15 @@ if (jsonDictionary[@"p"]) { _imageName = [jsonDictionary[@"p"] copy]; } - + NSArray *layersJSON = jsonDictionary[@"layers"]; if (layersJSON) { - _layerGroup = [[LOTLayerGroup alloc] initWithLayerJSON:layersJSON withBounds:bounds withFramerate:framerate]; + _layerGroup = [[LOTLayerGroup alloc] initWithLayerJSON:layersJSON + withBounds:bounds + withFramerate:framerate + withAssetGroup:assetGroup]; } - + } @end diff --git a/lottie-ios/Classes/Models/LOTAssetGroup.h b/lottie-ios/Classes/Models/LOTAssetGroup.h new file mode 100644 index 0000000000..0fcac076dc --- /dev/null +++ b/lottie-ios/Classes/Models/LOTAssetGroup.h @@ -0,0 +1,24 @@ +// +// LOTAssetGroup.h +// Pods +// +// Created by Brandon Withrow on 2/17/17. +// +// + +#import +@class LOTAsset; +@class LOTLayerGroup; +@interface LOTAssetGroup : NSObject + +- (instancetype)initWithJSON:(NSArray *)jsonArray; + +- (void)buildAssetNamed:(NSString *)refID + withBounds:(CGRect)bounds + andFramerate:(NSNumber * _Nullable)framerate; + +- (void)finalizeInitialization; + +- (LOTAsset *)assetModelForID:(NSNumber *)assetID; + +@end diff --git a/lottie-ios/Classes/Models/LOTAssetGroup.m b/lottie-ios/Classes/Models/LOTAssetGroup.m new file mode 100644 index 0000000000..f81b1a6ab7 --- /dev/null +++ b/lottie-ios/Classes/Models/LOTAssetGroup.m @@ -0,0 +1,62 @@ +// +// LOTAssetGroup.m +// Pods +// +// Created by Brandon Withrow on 2/17/17. +// +// + +#import "LOTAssetGroup.h" +#import "LOTAsset.h" + +@implementation LOTAssetGroup { + NSMutableDictionary *_assetMap; + NSDictionary *_assetJSONMap; +} + +- (instancetype)initWithJSON:(NSArray *)jsonArray { + self = [super init]; + if (self) { + _assetMap = [NSMutableDictionary dictionary]; + NSMutableDictionary *assetJSONMap = [NSMutableDictionary dictionary]; + for (NSDictionary *assetDictionary in jsonArray) { + NSString *referenceID = assetDictionary[@"id"]; + if (referenceID) { + assetJSONMap[referenceID] = assetDictionary; + } + } + _assetJSONMap = assetJSONMap; + } + return self; +} + +- (void)buildAssetNamed:(NSString *)refID + withBounds:(CGRect)bounds + andFramerate:(NSNumber * _Nullable)framerate { + + if ([self assetModelForID:refID]) { + return; + } + + NSDictionary *assetDictionary = _assetJSONMap[refID]; + if (assetDictionary) { + LOTAsset *asset = [[LOTAsset alloc] initWithJSON:assetDictionary + withBounds:bounds + withFramerate:framerate + withAssetGroup:self]; + _assetMap[refID] = asset; + } +} + +- (void)finalizeInitialization { + for (NSString *refID in _assetJSONMap.allKeys) { + [self buildAssetNamed:refID withBounds:CGRectZero andFramerate:nil]; + } + _assetJSONMap = nil; +} + +- (LOTAsset *)assetModelForID:(NSNumber *)assetID { + return _assetMap[assetID]; +} + +@end diff --git a/lottie-ios/Classes/Models/LOTComposition.h b/lottie-ios/Classes/Models/LOTComposition.h index 61833d9c92..fd4d6780a2 100644 --- a/lottie-ios/Classes/Models/LOTComposition.h +++ b/lottie-ios/Classes/Models/LOTComposition.h @@ -11,20 +11,18 @@ @class LOTLayerGroup; @class LOTLayer; -@class LOTAsset; +@class LOTAssetGroup; @interface LOTComposition : NSObject - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary; - @property (nonatomic, readonly) CGRect compBounds; @property (nonatomic, readonly) NSNumber *startFrame; @property (nonatomic, readonly) NSNumber *endFrame; @property (nonatomic, readonly) NSNumber *framerate; @property (nonatomic, readonly) NSTimeInterval timeDuration; @property (nonatomic, readonly) LOTLayerGroup *layerGroup; - -- (LOTAsset *)assetModelForID:(NSNumber *)assetID; +@property (nonatomic, readonly) LOTAssetGroup *assetGroup; @end diff --git a/lottie-ios/Classes/Models/LOTComposition.m b/lottie-ios/Classes/Models/LOTComposition.m index 641df4a2db..4f58a49292 100644 --- a/lottie-ios/Classes/Models/LOTComposition.m +++ b/lottie-ios/Classes/Models/LOTComposition.m @@ -8,12 +8,10 @@ #import "LOTComposition.h" #import "LOTLayer.h" -#import "LOTAsset.h" +#import "LOTAssetGroup.h" #import "LOTLayerGroup.h" -@implementation LOTComposition { - NSDictionary *_assetMap; -} +@implementation LOTComposition - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary { self = [super init]; @@ -41,27 +39,20 @@ _timeDuration = timeDuration; } + NSArray *assetArray = jsonDictionary[@"assets"]; + if (assetArray.count) { + _assetGroup = [[LOTAssetGroup alloc] initWithJSON:assetArray]; + } + NSArray *layersJSON = jsonDictionary[@"layers"]; if (layersJSON) { - _layerGroup = [[LOTLayerGroup alloc] initWithLayerJSON:layersJSON withBounds:_compBounds withFramerate:_framerate]; + _layerGroup = [[LOTLayerGroup alloc] initWithLayerJSON:layersJSON + withBounds:_compBounds + withFramerate:_framerate + withAssetGroup:_assetGroup]; } - NSMutableDictionary *assets = [NSMutableDictionary dictionary]; - NSArray *assetArray = jsonDictionary[@"assets"]; - - for (NSDictionary *assetDictionary in assetArray) { - NSString *referenceID = assetDictionary[@"id"]; - LOTLayer *layer = [_layerGroup layerForReferenceID:referenceID]; - if (layer) { - LOTAsset *asset = [[LOTAsset alloc] initWithJSON:assetDictionary withBounds:layer.layerBounds withFramerate:layer.framerate]; - assets[asset.referenceID] = asset; - } - } - _assetMap = assets; -} - -- (LOTAsset *)assetModelForID:(NSNumber *)assetID { - return _assetMap[assetID]; + [_assetGroup finalizeInitialization]; } @end diff --git a/lottie-ios/Classes/Models/LOTLayer.m b/lottie-ios/Classes/Models/LOTLayer.m index 2c8966d798..cbc50a362d 100644 --- a/lottie-ios/Classes/Models/LOTLayer.m +++ b/lottie-ios/Classes/Models/LOTLayer.m @@ -35,21 +35,26 @@ _layerName = [jsonDictionary[@"nm"] copy]; _layerID = [jsonDictionary[@"ind"] copy]; - _layerBounds = compBounds; - _framerate = framerate; + NSNumber *layerType = jsonDictionary[@"ty"]; _layerType = layerType.integerValue; - if (jsonDictionary[@"refID"]) { - _referenceID = [jsonDictionary[@"refID"] copy]; + if (jsonDictionary[@"refId"]) { + _referenceID = [jsonDictionary[@"refId"] copy]; } _parentID = [jsonDictionary[@"parent"] copy]; + _inFrame = [jsonDictionary[@"ip"] copy]; _outFrame = [jsonDictionary[@"op"] copy]; + _framerate = framerate; - if (_layerType == LOTLayerTypePrecomp) { + _layerWidth = @(compBounds.size.width); + _layerHeight = @(compBounds.size.height); + + if (_layerType == LOTLayerTypePrecomp || + _layerType == LOTLayerTypeImage) { _layerHeight = [jsonDictionary[@"h"] copy]; _layerWidth = [jsonDictionary[@"w"] copy]; } @@ -57,11 +62,12 @@ if (_layerType == LOTLayerTypeSolid) { _layerWidth = jsonDictionary[@"sw"]; _layerHeight = jsonDictionary[@"sh"]; - _layerBounds = CGRectMake(0, 0, _layerWidth.floatValue, _layerHeight.floatValue); NSString *solidColor = jsonDictionary[@"sc"]; _solidColor = [UIColor LOT_colorWithHexString:solidColor]; } + _layerBounds = CGRectMake(0, 0, _layerWidth.floatValue, _layerHeight.floatValue); + NSDictionary *ks = jsonDictionary[@"ks"]; NSDictionary *opacity = ks[@"o"]; diff --git a/lottie-ios/Classes/Models/LOTLayerGroup.h b/lottie-ios/Classes/Models/LOTLayerGroup.h index 5aca90c36f..b723546a9c 100644 --- a/lottie-ios/Classes/Models/LOTLayerGroup.h +++ b/lottie-ios/Classes/Models/LOTLayerGroup.h @@ -10,12 +10,14 @@ #import @class LOTLayer; +@class LOTAssetGroup; @interface LOTLayerGroup : NSObject - (instancetype)initWithLayerJSON:(NSArray *)layersJSON withBounds:(CGRect)bounds - withFramerate:(NSNumber *)framerate; + withFramerate:(NSNumber *)framerate + withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup; @property (nonatomic, readonly) NSArray *layers; diff --git a/lottie-ios/Classes/Models/LOTLayerGroup.m b/lottie-ios/Classes/Models/LOTLayerGroup.m index c2a3ff0c34..27d1cad42c 100644 --- a/lottie-ios/Classes/Models/LOTLayerGroup.m +++ b/lottie-ios/Classes/Models/LOTLayerGroup.m @@ -8,27 +8,30 @@ #import "LOTLayerGroup.h" #import "LOTLayer.h" +#import "LOTAssetGroup.h" @implementation LOTLayerGroup { CGRect _bounds; NSNumber *_framerate; NSDictionary *_modelMap; NSDictionary *_referenceIDMap; + NSArray *layersJSON; } - (instancetype)initWithLayerJSON:(NSArray *)layersJSON - withBounds:(CGRect)bounds - withFramerate:(NSNumber *)framerate { + withBounds:(CGRect)bounds + withFramerate:(NSNumber *)framerate + withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup { self = [super init]; if (self) { _framerate = framerate; _bounds = bounds; - [self _mapFromJSON:layersJSON]; + [self _mapFromJSON:layersJSON withAssetGroup:assetGroup]; } return self; } -- (void)_mapFromJSON:(NSArray *)layersJSON { +- (void)_mapFromJSON:(NSArray *)layersJSON withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup { NSMutableArray *layers = [NSMutableArray array]; NSMutableDictionary *modelMap = [NSMutableDictionary dictionary]; NSMutableDictionary *referenceMap = [NSMutableDictionary dictionary]; @@ -37,8 +40,9 @@ LOTLayer *layer = [[LOTLayer alloc] initWithJSON:layerJSON withCompBounds:_bounds withFramerate:_framerate]; [layers addObject:layer]; modelMap[layer.layerID] = layer; - if (layer.referenceID) { + if (layer.referenceID && assetGroup) { referenceMap[layer.referenceID] = layer; + [assetGroup buildAssetNamed:layer.referenceID withBounds:layer.layerBounds andFramerate:layer.framerate]; } }