POPSpringAnimation.mm 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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 "POPSpringAnimationInternal.h"
  9. @implementation POPSpringAnimation
  10. #pragma mark - Lifecycle
  11. #undef __state
  12. #define __state ((POPSpringAnimationState *)_state)
  13. + (instancetype)animation
  14. {
  15. return [[self alloc] init];
  16. }
  17. + (instancetype)animationWithPropertyNamed:(NSString *)aName
  18. {
  19. POPSpringAnimation *anim = [self animation];
  20. anim.property = [POPAnimatableProperty propertyWithName:aName];
  21. return anim;
  22. }
  23. - (void)_initState
  24. {
  25. _state = new POPSpringAnimationState(self);
  26. }
  27. - (id)init
  28. {
  29. self = [super _init];
  30. if (nil != self) {
  31. __state->solver = new SpringSolver4d(1, 1, 1);
  32. __state->updatedDynamicsThreshold();
  33. __state->updatedBouncinessAndSpeed();
  34. }
  35. return self;
  36. }
  37. - (void)dealloc
  38. {
  39. if (__state) {
  40. delete __state->solver;
  41. __state->solver = NULL;
  42. }
  43. }
  44. #pragma mark - Properties
  45. - (id)velocity
  46. {
  47. return POPBox(__state->velocityVec, __state->valueType);
  48. }
  49. - (void)setVelocity:(id)aValue
  50. {
  51. POPPropertyAnimationState *s = __state;
  52. VectorRef vec = POPUnbox(aValue, s->valueType, s->valueCount, YES);
  53. VectorRef origVec = POPUnbox(aValue, s->valueType, s->valueCount, YES);
  54. if (!vec_equal(vec, s->velocityVec)) {
  55. s->velocityVec = vec;
  56. s->originalVelocityVec = origVec;
  57. if (s->tracing) {
  58. [s->tracer updateVelocity:aValue];
  59. }
  60. }
  61. }
  62. DEFINE_RW_PROPERTY(POPSpringAnimationState, dynamicsTension, setDynamicsTension:, CGFloat, [self _updatedDynamicsTension];);
  63. DEFINE_RW_PROPERTY(POPSpringAnimationState, dynamicsFriction, setDynamicsFriction:, CGFloat, [self _updatedDynamicsFriction];);
  64. DEFINE_RW_PROPERTY(POPSpringAnimationState, dynamicsMass, setDynamicsMass:, CGFloat, [self _updatedDynamicsMass];);
  65. FB_PROPERTY_GET(POPSpringAnimationState, springSpeed, CGFloat);
  66. - (void)setSpringSpeed:(CGFloat)aFloat
  67. {
  68. POPSpringAnimationState *s = __state;
  69. if (s->userSpecifiedDynamics || aFloat != s->springSpeed) {
  70. s->springSpeed = aFloat;
  71. s->userSpecifiedDynamics = false;
  72. s->updatedBouncinessAndSpeed();
  73. if (s->tracing) {
  74. [s->tracer updateSpeed:aFloat];
  75. }
  76. }
  77. }
  78. FB_PROPERTY_GET(POPSpringAnimationState, springBounciness, CGFloat);
  79. - (void)setSpringBounciness:(CGFloat)aFloat
  80. {
  81. POPSpringAnimationState *s = __state;
  82. if (s->userSpecifiedDynamics || aFloat != s->springBounciness) {
  83. s->springBounciness = aFloat;
  84. s->userSpecifiedDynamics = false;
  85. s->updatedBouncinessAndSpeed();
  86. if (s->tracing) {
  87. [s->tracer updateBounciness:aFloat];
  88. }
  89. }
  90. }
  91. - (SpringSolver4d *)solver
  92. {
  93. return __state->solver;
  94. }
  95. - (void)setSolver:(SpringSolver4d *)aSolver
  96. {
  97. if (aSolver != __state->solver) {
  98. if (__state->solver) {
  99. delete(__state->solver);
  100. }
  101. __state->solver = aSolver;
  102. }
  103. }
  104. #pragma mark - Utility
  105. - (void)_updatedDynamicsTension
  106. {
  107. __state->userSpecifiedDynamics = true;
  108. if(__state->tracing) {
  109. [__state->tracer updateTension:__state->dynamicsTension];
  110. }
  111. __state->updatedDynamics();
  112. }
  113. - (void)_updatedDynamicsFriction
  114. {
  115. __state->userSpecifiedDynamics = true;
  116. if(__state->tracing) {
  117. [__state->tracer updateFriction:__state->dynamicsFriction];
  118. }
  119. __state->updatedDynamics();
  120. }
  121. - (void)_updatedDynamicsMass
  122. {
  123. __state->userSpecifiedDynamics = true;
  124. if(__state->tracing) {
  125. [__state->tracer updateMass:__state->dynamicsMass];
  126. }
  127. __state->updatedDynamics();
  128. }
  129. - (void)_appendDescription:(NSMutableString *)s debug:(BOOL)debug
  130. {
  131. [super _appendDescription:s debug:debug];
  132. if (debug) {
  133. if (_state->userSpecifiedDynamics) {
  134. [s appendFormat:@"; dynamics = (tension:%f, friction:%f, mass:%f)", __state->dynamicsTension, __state->dynamicsFriction, __state->dynamicsMass];
  135. } else {
  136. [s appendFormat:@"; bounciness = %f; speed = %f", __state->springBounciness, __state->springSpeed];
  137. }
  138. }
  139. }
  140. @end
  141. @implementation POPSpringAnimation (NSCopying)
  142. - (instancetype)copyWithZone:(NSZone *)zone {
  143. POPSpringAnimation *copy = [super copyWithZone:zone];
  144. if (copy) {
  145. id velocity = POPBox(__state->originalVelocityVec, __state->valueType);
  146. // If velocity never gets set, then POPBox will return nil, messing up __state->valueCount.
  147. if (velocity) {
  148. copy.velocity = velocity;
  149. }
  150. copy.springBounciness = self.springBounciness;
  151. copy.springSpeed = self.springSpeed;
  152. copy.dynamicsTension = self.dynamicsTension;
  153. copy.dynamicsFriction = self.dynamicsFriction;
  154. copy.dynamicsMass = self.dynamicsMass;
  155. }
  156. return copy;
  157. }
  158. @end