POPDecayAnimation.mm 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /**
  2. Copyright (c) 2014-present, Facebook, Inc.
  3. All rights reserved.
  4. This source code is licensed under the BSD-style license found in the
  5. LICENSE file in the root directory of this source tree. An additional grant
  6. of patent rights can be found in the PATENTS file in the same directory.
  7. */
  8. #import "POPDecayAnimationInternal.h"
  9. #if TARGET_OS_IPHONE
  10. #import <UIKit/UIKit.h>
  11. #endif
  12. const POPValueType supportedVelocityTypes[6] = { kPOPValuePoint, kPOPValueInteger, kPOPValueFloat, kPOPValueRect, kPOPValueSize, kPOPValueEdgeInsets };
  13. @implementation POPDecayAnimation
  14. #pragma mark - Lifecycle
  15. #undef __state
  16. #define __state ((POPDecayAnimationState *)_state)
  17. + (instancetype)animation
  18. {
  19. return [[self alloc] init];
  20. }
  21. + (instancetype)animationWithPropertyNamed:(NSString *)aName
  22. {
  23. POPDecayAnimation *anim = [self animation];
  24. anim.property = [POPAnimatableProperty propertyWithName:aName];
  25. return anim;
  26. }
  27. - (id)init
  28. {
  29. return [self _init];
  30. }
  31. - (void)_initState
  32. {
  33. _state = new POPDecayAnimationState(self);
  34. }
  35. #pragma mark - Properties
  36. DEFINE_RW_PROPERTY(POPDecayAnimationState, deceleration, setDeceleration:, CGFloat, __state->toVec = NULL;);
  37. @dynamic velocity;
  38. - (id)toValue
  39. {
  40. [self _ensureComputedProperties];
  41. return POPBox(__state->toVec, __state->valueType);
  42. }
  43. - (CFTimeInterval)duration
  44. {
  45. [self _ensureComputedProperties];
  46. return __state->duration;
  47. }
  48. - (void)setFromValue:(id)fromValue
  49. {
  50. super.fromValue = fromValue;
  51. [self _invalidateComputedProperties];
  52. }
  53. - (void)setToValue:(id)aValue
  54. {
  55. // no-op
  56. NSLog(@"ignoring to value on decay animation %@", self);
  57. }
  58. - (id)reversedVelocity
  59. {
  60. id reversedVelocity = nil;
  61. POPValueType velocityType = POPSelectValueType(self.originalVelocity, supportedVelocityTypes, POP_ARRAY_COUNT(supportedVelocityTypes));
  62. if (velocityType == kPOPValueFloat) {
  63. #if CGFLOAT_IS_DOUBLE
  64. CGFloat originalVelocityFloat = [(NSNumber *)self.originalVelocity doubleValue];
  65. #else
  66. CGFloat originalVelocityFloat = [(NSNumber *)self.originalVelocity floatValue];
  67. #endif
  68. NSNumber *negativeOriginalVelocityNumber = @(-originalVelocityFloat);
  69. reversedVelocity = negativeOriginalVelocityNumber;
  70. } else if (velocityType == kPOPValueInteger) {
  71. NSInteger originalVelocityInteger = [(NSNumber *)self.originalVelocity integerValue];
  72. NSNumber *negativeOriginalVelocityNumber = @(-originalVelocityInteger);
  73. reversedVelocity = negativeOriginalVelocityNumber;
  74. } else if (velocityType == kPOPValuePoint) {
  75. CGPoint originalVelocityPoint = [self.originalVelocity CGPointValue];
  76. CGPoint negativeOriginalVelocityPoint = CGPointMake(-originalVelocityPoint.x, -originalVelocityPoint.y);
  77. reversedVelocity = [NSValue valueWithCGPoint:negativeOriginalVelocityPoint];
  78. } else if (velocityType == kPOPValueRect) {
  79. CGRect originalVelocityRect = [self.originalVelocity CGRectValue];
  80. CGRect negativeOriginalVelocityRect = CGRectMake(-originalVelocityRect.origin.x, -originalVelocityRect.origin.y, -originalVelocityRect.size.width, -originalVelocityRect.size.height);
  81. reversedVelocity = [NSValue valueWithCGRect:negativeOriginalVelocityRect];
  82. } else if (velocityType == kPOPValueSize) {
  83. CGSize originalVelocitySize = [self.originalVelocity CGSizeValue];
  84. CGSize negativeOriginalVelocitySize = CGSizeMake(-originalVelocitySize.width, -originalVelocitySize.height);
  85. reversedVelocity = [NSValue valueWithCGSize:negativeOriginalVelocitySize];
  86. } else if (velocityType == kPOPValueEdgeInsets) {
  87. #if TARGET_OS_IPHONE
  88. UIEdgeInsets originalVelocityInsets = [self.originalVelocity UIEdgeInsetsValue];
  89. UIEdgeInsets negativeOriginalVelocityInsets = UIEdgeInsetsMake(-originalVelocityInsets.top, -originalVelocityInsets.left, -originalVelocityInsets.bottom, -originalVelocityInsets.right);
  90. reversedVelocity = [NSValue valueWithUIEdgeInsets:negativeOriginalVelocityInsets];
  91. #endif
  92. }
  93. return reversedVelocity;
  94. }
  95. - (id)originalVelocity
  96. {
  97. return POPBox(__state->originalVelocityVec, __state->valueType);
  98. }
  99. - (id)velocity
  100. {
  101. return POPBox(__state->velocityVec, __state->valueType);
  102. }
  103. - (void)setVelocity:(id)aValue
  104. {
  105. POPValueType valueType = POPSelectValueType(aValue, supportedVelocityTypes, POP_ARRAY_COUNT(supportedVelocityTypes));
  106. if (valueType != kPOPValueUnknown) {
  107. VectorRef vec = POPUnbox(aValue, __state->valueType, __state->valueCount, YES);
  108. VectorRef origVec = POPUnbox(aValue, __state->valueType, __state->valueCount, YES);
  109. if (!vec_equal(vec, __state->velocityVec)) {
  110. __state->velocityVec = vec;
  111. __state->originalVelocityVec = origVec;
  112. if (__state->tracing) {
  113. [__state->tracer updateVelocity:aValue];
  114. }
  115. [self _invalidateComputedProperties];
  116. // automatically unpause active animations
  117. if (__state->active && __state->paused) {
  118. __state->fromVec = NULL;
  119. __state->setPaused(false);
  120. }
  121. }
  122. } else {
  123. __state->velocityVec = NULL;
  124. NSLog(@"Invalid velocity value for the decayAnimation: %@", aValue);
  125. }
  126. }
  127. #pragma mark - Utility
  128. - (void)_ensureComputedProperties
  129. {
  130. if (NULL == __state->toVec) {
  131. __state->computeDuration();
  132. __state->computeToValue();
  133. }
  134. }
  135. - (void)_invalidateComputedProperties
  136. {
  137. __state->toVec = NULL;
  138. __state->duration = 0;
  139. }
  140. - (void)_appendDescription:(NSMutableString *)s debug:(BOOL)debug
  141. {
  142. [super _appendDescription:s debug:debug];
  143. if (0 != self.duration) {
  144. [s appendFormat:@"; duration = %f", self.duration];
  145. }
  146. if (__state->deceleration) {
  147. [s appendFormat:@"; deceleration = %f", __state->deceleration];
  148. }
  149. }
  150. @end
  151. @implementation POPDecayAnimation (NSCopying)
  152. - (instancetype)copyWithZone:(NSZone *)zone {
  153. POPDecayAnimation *copy = [super copyWithZone:zone];
  154. if (copy) {
  155. // Set the velocity to the animation's original velocity, not its current.
  156. copy.velocity = self.originalVelocity;
  157. copy.deceleration = self.deceleration;
  158. }
  159. return copy;
  160. }
  161. @end