LOTTrimPathNode.m 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. //
  2. // LOTTrimPathNode.m
  3. // Lottie
  4. //
  5. // Created by brandon_withrow on 7/21/17.
  6. // Copyright © 2017 Airbnb. All rights reserved.
  7. //
  8. #import "LOTTrimPathNode.h"
  9. #import "LOTNumberInterpolator.h"
  10. #import "LOTPathAnimator.h"
  11. #import "LOTCircleAnimator.h"
  12. #import "LOTRoundedRectAnimator.h"
  13. #import "LOTRenderGroup.h"
  14. @implementation LOTTrimPathNode {
  15. LOTNumberInterpolator *_startInterpolator;
  16. LOTNumberInterpolator *_endInterpolator;
  17. LOTNumberInterpolator *_offsetInterpolator;
  18. CGFloat _startT;
  19. CGFloat _endT;
  20. CGFloat _offsetT;
  21. }
  22. - (instancetype _Nonnull)initWithInputNode:(LOTAnimatorNode *_Nullable)inputNode
  23. trimPath:(LOTShapeTrimPath *_Nonnull)trimPath {
  24. self = [super initWithInputNode:inputNode keyName:trimPath.keyname];
  25. if (self) {
  26. inputNode.pathShouldCacheLengths = YES;
  27. _startInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:trimPath.start.keyframes];
  28. _endInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:trimPath.end.keyframes];
  29. _offsetInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:trimPath.offset.keyframes];
  30. }
  31. return self;
  32. }
  33. - (NSDictionary *)valueInterpolators {
  34. return @{@"Start" : _startInterpolator,
  35. @"End" : _endInterpolator,
  36. @"Offset" : _offsetInterpolator};
  37. }
  38. - (BOOL)needsUpdateForFrame:(NSNumber *)frame {
  39. return ([_startInterpolator hasUpdateForFrame:frame] ||
  40. [_endInterpolator hasUpdateForFrame:frame] ||
  41. [_offsetInterpolator hasUpdateForFrame:frame]);
  42. }
  43. - (BOOL)updateWithFrame:(NSNumber *)frame
  44. withModifierBlock:(void (^ _Nullable)(LOTAnimatorNode * _Nonnull))modifier
  45. forceLocalUpdate:(BOOL)forceUpdate {
  46. BOOL localUpdate = [self needsUpdateForFrame:frame];
  47. [self forceSetCurrentFrame:frame];
  48. if (localUpdate) {
  49. [self performLocalUpdate];
  50. }
  51. if (self.inputNode == nil) {
  52. return localUpdate;
  53. }
  54. BOOL inputUpdated = [self.inputNode updateWithFrame:frame withModifierBlock:^(LOTAnimatorNode * _Nonnull inputNode) {
  55. if ([inputNode isKindOfClass:[LOTPathAnimator class]] ||
  56. [inputNode isKindOfClass:[LOTCircleAnimator class]] ||
  57. [inputNode isKindOfClass:[LOTRoundedRectAnimator class]]) {
  58. [inputNode.localPath trimPathFromT:self->_startT toT:self->_endT offset:self->_offsetT];
  59. }
  60. if (modifier) {
  61. modifier(inputNode);
  62. }
  63. } forceLocalUpdate:(localUpdate || forceUpdate)];
  64. return inputUpdated;
  65. }
  66. - (void)performLocalUpdate {
  67. _startT = [_startInterpolator floatValueForFrame:self.currentFrame] / 100;
  68. _endT = [_endInterpolator floatValueForFrame:self.currentFrame] / 100;
  69. _offsetT = [_offsetInterpolator floatValueForFrame:self.currentFrame] / 360;
  70. }
  71. - (void)rebuildOutputs {
  72. // Skip this step.
  73. }
  74. - (LOTBezierPath *)localPath {
  75. return self.inputNode.localPath;
  76. }
  77. /// Forwards its input node's output path forwards downstream
  78. - (LOTBezierPath *)outputPath {
  79. return self.inputNode.outputPath;
  80. }
  81. @end