LOTLayer.m 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. //
  2. // LOTLayer.m
  3. // LottieAnimator
  4. //
  5. // Created by Brandon Withrow on 12/14/15.
  6. // Copyright © 2015 Brandon Withrow. All rights reserved.
  7. //
  8. #import "LOTLayer.h"
  9. #import "LOTAsset.h"
  10. #import "LOTAssetGroup.h"
  11. #import "LOTShapeGroup.h"
  12. #import "LOTComposition.h"
  13. #import "LOTHelpers.h"
  14. #import "LOTMask.h"
  15. #import "LOTHelpers.h"
  16. @implementation LOTLayer
  17. - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary
  18. withAssetGroup:(LOTAssetGroup *)assetGroup
  19. withFramerate:(NSNumber *)framerate {
  20. self = [super init];
  21. if (self) {
  22. [self _mapFromJSON:jsonDictionary
  23. withAssetGroup:assetGroup
  24. withFramerate:framerate];
  25. }
  26. return self;
  27. }
  28. - (void)_mapFromJSON:(NSDictionary *)jsonDictionary
  29. withAssetGroup:(LOTAssetGroup *)assetGroup
  30. withFramerate:(NSNumber *)framerate {
  31. _layerName = [jsonDictionary[@"nm"] copy];
  32. _layerID = [jsonDictionary[@"ind"] copy];
  33. NSNumber *layerType = jsonDictionary[@"ty"];
  34. _layerType = layerType.integerValue;
  35. if (jsonDictionary[@"refId"]) {
  36. _referenceID = [jsonDictionary[@"refId"] copy];
  37. }
  38. _parentID = [jsonDictionary[@"parent"] copy];
  39. if (jsonDictionary[@"st"]) {
  40. _startFrame = [jsonDictionary[@"st"] copy];
  41. }
  42. _inFrame = [jsonDictionary[@"ip"] copy];
  43. _outFrame = [jsonDictionary[@"op"] copy];
  44. if (jsonDictionary[@"sr"]) {
  45. _timeStretch = [jsonDictionary[@"sr"] copy];
  46. } else {
  47. _timeStretch = @1;
  48. }
  49. if (_layerType == LOTLayerTypePrecomp) {
  50. _layerHeight = [jsonDictionary[@"h"] copy];
  51. _layerWidth = [jsonDictionary[@"w"] copy];
  52. [assetGroup buildAssetNamed:_referenceID withFramerate:framerate];
  53. } else if (_layerType == LOTLayerTypeImage) {
  54. [assetGroup buildAssetNamed:_referenceID withFramerate:framerate];
  55. _imageAsset = [assetGroup assetModelForID:_referenceID];
  56. _layerWidth = [_imageAsset.assetWidth copy];
  57. _layerHeight = [_imageAsset.assetHeight copy];
  58. } else if (_layerType == LOTLayerTypeSolid) {
  59. _layerWidth = jsonDictionary[@"sw"];
  60. _layerHeight = jsonDictionary[@"sh"];
  61. NSString *solidColor = jsonDictionary[@"sc"];
  62. _solidColor = [UIColor LOT_colorWithHexString:solidColor];
  63. }
  64. _layerBounds = CGRectMake(0, 0, _layerWidth.floatValue, _layerHeight.floatValue);
  65. NSDictionary *ks = jsonDictionary[@"ks"];
  66. NSDictionary *opacity = ks[@"o"];
  67. if (opacity) {
  68. _opacity = [[LOTKeyframeGroup alloc] initWithData:opacity];
  69. [_opacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
  70. return LOT_RemapValue(inValue, 0, 100, 0, 1);
  71. }];
  72. }
  73. NSDictionary *timeRemap = jsonDictionary[@"tm"];
  74. if (timeRemap) {
  75. _timeRemapping = [[LOTKeyframeGroup alloc] initWithData:timeRemap];
  76. [_timeRemapping remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
  77. return inValue * framerate.doubleValue;
  78. }];
  79. }
  80. NSDictionary *rotation = ks[@"r"];
  81. if (rotation == nil) {
  82. rotation = ks[@"rz"];
  83. }
  84. if (rotation) {
  85. _rotation = [[LOTKeyframeGroup alloc] initWithData:rotation];
  86. [_rotation remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
  87. return LOT_DegreesToRadians(inValue);
  88. }];
  89. }
  90. NSDictionary *position = ks[@"p"];
  91. if ([position[@"s"] boolValue]) {
  92. // Separate dimensions
  93. _positionX = [[LOTKeyframeGroup alloc] initWithData:position[@"x"]];
  94. _positionY = [[LOTKeyframeGroup alloc] initWithData:position[@"y"]];
  95. } else {
  96. _position = [[LOTKeyframeGroup alloc] initWithData:position ];
  97. }
  98. NSDictionary *anchor = ks[@"a"];
  99. if (anchor) {
  100. _anchor = [[LOTKeyframeGroup alloc] initWithData:anchor];
  101. }
  102. NSDictionary *scale = ks[@"s"];
  103. if (scale) {
  104. _scale = [[LOTKeyframeGroup alloc] initWithData:scale];
  105. [_scale remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
  106. return LOT_RemapValue(inValue, -100, 100, -1, 1);
  107. }];
  108. }
  109. _matteType = [jsonDictionary[@"tt"] integerValue];
  110. NSMutableArray *masks = [NSMutableArray array];
  111. for (NSDictionary *maskJSON in jsonDictionary[@"masksProperties"]) {
  112. LOTMask *mask = [[LOTMask alloc] initWithJSON:maskJSON];
  113. [masks addObject:mask];
  114. }
  115. _masks = masks.count ? masks : nil;
  116. NSMutableArray *shapes = [NSMutableArray array];
  117. for (NSDictionary *shapeJSON in jsonDictionary[@"shapes"]) {
  118. id shapeItem = [LOTShapeGroup shapeItemWithJSON:shapeJSON];
  119. if (shapeItem) {
  120. [shapes addObject:shapeItem];
  121. }
  122. }
  123. _shapes = shapes;
  124. NSArray *effects = jsonDictionary[@"ef"];
  125. if (effects.count > 0) {
  126. NSDictionary *effectNames = @{ @0: @"slider",
  127. @1: @"angle",
  128. @2: @"color",
  129. @3: @"point",
  130. @4: @"checkbox",
  131. @5: @"group",
  132. @6: @"noValue",
  133. @7: @"dropDown",
  134. @9: @"customValue",
  135. @10: @"layerIndex",
  136. @20: @"tint",
  137. @21: @"fill" };
  138. for (NSDictionary *effect in effects) {
  139. NSNumber *typeNumber = effect[@"ty"];
  140. NSString *name = effect[@"nm"];
  141. NSString *internalName = effect[@"mn"];
  142. NSString *typeString = effectNames[typeNumber];
  143. if (typeString) {
  144. NSLog(@"%s: Warning: %@ effect not supported: %@ / %@", __PRETTY_FUNCTION__, typeString, internalName, name);
  145. }
  146. }
  147. }
  148. }
  149. - (NSString *)description {
  150. NSMutableString *text = [[super description] mutableCopy];
  151. [text appendFormat:@" %@ id: %d pid: %d frames: %d-%d", _layerName, (int)_layerID.integerValue, (int)_parentID.integerValue,
  152. (int)_inFrame.integerValue, (int)_outFrame.integerValue];
  153. return text;
  154. }
  155. @end