| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- /**
- Copyright (c) 2014-present, Facebook, Inc.
- All rights reserved.
- This source code is licensed under the BSD-style license found in the
- LICENSE file in the root directory of this source tree. An additional grant
- of patent rights can be found in the PATENTS file in the same directory.
- */
- #import "POPDecayAnimationInternal.h"
- #if TARGET_OS_IPHONE
- #import <UIKit/UIKit.h>
- #endif
- const POPValueType supportedVelocityTypes[6] = { kPOPValuePoint, kPOPValueInteger, kPOPValueFloat, kPOPValueRect, kPOPValueSize, kPOPValueEdgeInsets };
- @implementation POPDecayAnimation
- #pragma mark - Lifecycle
- #undef __state
- #define __state ((POPDecayAnimationState *)_state)
- + (instancetype)animation
- {
- return [[self alloc] init];
- }
- + (instancetype)animationWithPropertyNamed:(NSString *)aName
- {
- POPDecayAnimation *anim = [self animation];
- anim.property = [POPAnimatableProperty propertyWithName:aName];
- return anim;
- }
- - (id)init
- {
- return [self _init];
- }
- - (void)_initState
- {
- _state = new POPDecayAnimationState(self);
- }
- #pragma mark - Properties
- DEFINE_RW_PROPERTY(POPDecayAnimationState, deceleration, setDeceleration:, CGFloat, __state->toVec = NULL;);
- @dynamic velocity;
- - (id)toValue
- {
- [self _ensureComputedProperties];
- return POPBox(__state->toVec, __state->valueType);
- }
- - (CFTimeInterval)duration
- {
- [self _ensureComputedProperties];
- return __state->duration;
- }
- - (void)setFromValue:(id)fromValue
- {
- super.fromValue = fromValue;
- [self _invalidateComputedProperties];
- }
- - (void)setToValue:(id)aValue
- {
- // no-op
- NSLog(@"ignoring to value on decay animation %@", self);
- }
- - (id)reversedVelocity
- {
- id reversedVelocity = nil;
- POPValueType velocityType = POPSelectValueType(self.originalVelocity, supportedVelocityTypes, POP_ARRAY_COUNT(supportedVelocityTypes));
- if (velocityType == kPOPValueFloat) {
- #if CGFLOAT_IS_DOUBLE
- CGFloat originalVelocityFloat = [(NSNumber *)self.originalVelocity doubleValue];
- #else
- CGFloat originalVelocityFloat = [(NSNumber *)self.originalVelocity floatValue];
- #endif
- NSNumber *negativeOriginalVelocityNumber = @(-originalVelocityFloat);
- reversedVelocity = negativeOriginalVelocityNumber;
- } else if (velocityType == kPOPValueInteger) {
- NSInteger originalVelocityInteger = [(NSNumber *)self.originalVelocity integerValue];
- NSNumber *negativeOriginalVelocityNumber = @(-originalVelocityInteger);
- reversedVelocity = negativeOriginalVelocityNumber;
- } else if (velocityType == kPOPValuePoint) {
- CGPoint originalVelocityPoint = [self.originalVelocity CGPointValue];
- CGPoint negativeOriginalVelocityPoint = CGPointMake(-originalVelocityPoint.x, -originalVelocityPoint.y);
- reversedVelocity = [NSValue valueWithCGPoint:negativeOriginalVelocityPoint];
- } else if (velocityType == kPOPValueRect) {
- CGRect originalVelocityRect = [self.originalVelocity CGRectValue];
- CGRect negativeOriginalVelocityRect = CGRectMake(-originalVelocityRect.origin.x, -originalVelocityRect.origin.y, -originalVelocityRect.size.width, -originalVelocityRect.size.height);
- reversedVelocity = [NSValue valueWithCGRect:negativeOriginalVelocityRect];
- } else if (velocityType == kPOPValueSize) {
- CGSize originalVelocitySize = [self.originalVelocity CGSizeValue];
- CGSize negativeOriginalVelocitySize = CGSizeMake(-originalVelocitySize.width, -originalVelocitySize.height);
- reversedVelocity = [NSValue valueWithCGSize:negativeOriginalVelocitySize];
- } else if (velocityType == kPOPValueEdgeInsets) {
- #if TARGET_OS_IPHONE
- UIEdgeInsets originalVelocityInsets = [self.originalVelocity UIEdgeInsetsValue];
- UIEdgeInsets negativeOriginalVelocityInsets = UIEdgeInsetsMake(-originalVelocityInsets.top, -originalVelocityInsets.left, -originalVelocityInsets.bottom, -originalVelocityInsets.right);
- reversedVelocity = [NSValue valueWithUIEdgeInsets:negativeOriginalVelocityInsets];
- #endif
- }
- return reversedVelocity;
- }
- - (id)originalVelocity
- {
- return POPBox(__state->originalVelocityVec, __state->valueType);
- }
- - (id)velocity
- {
- return POPBox(__state->velocityVec, __state->valueType);
- }
- - (void)setVelocity:(id)aValue
- {
- POPValueType valueType = POPSelectValueType(aValue, supportedVelocityTypes, POP_ARRAY_COUNT(supportedVelocityTypes));
- if (valueType != kPOPValueUnknown) {
- VectorRef vec = POPUnbox(aValue, __state->valueType, __state->valueCount, YES);
- VectorRef origVec = POPUnbox(aValue, __state->valueType, __state->valueCount, YES);
- if (!vec_equal(vec, __state->velocityVec)) {
- __state->velocityVec = vec;
- __state->originalVelocityVec = origVec;
- if (__state->tracing) {
- [__state->tracer updateVelocity:aValue];
- }
- [self _invalidateComputedProperties];
- // automatically unpause active animations
- if (__state->active && __state->paused) {
- __state->fromVec = NULL;
- __state->setPaused(false);
- }
- }
- } else {
- __state->velocityVec = NULL;
- NSLog(@"Invalid velocity value for the decayAnimation: %@", aValue);
- }
- }
- #pragma mark - Utility
- - (void)_ensureComputedProperties
- {
- if (NULL == __state->toVec) {
- __state->computeDuration();
- __state->computeToValue();
- }
- }
- - (void)_invalidateComputedProperties
- {
- __state->toVec = NULL;
- __state->duration = 0;
- }
- - (void)_appendDescription:(NSMutableString *)s debug:(BOOL)debug
- {
- [super _appendDescription:s debug:debug];
- if (0 != self.duration) {
- [s appendFormat:@"; duration = %f", self.duration];
- }
- if (__state->deceleration) {
- [s appendFormat:@"; deceleration = %f", __state->deceleration];
- }
- }
- @end
- @implementation POPDecayAnimation (NSCopying)
- - (instancetype)copyWithZone:(NSZone *)zone {
-
- POPDecayAnimation *copy = [super copyWithZone:zone];
-
- if (copy) {
- // Set the velocity to the animation's original velocity, not its current.
- copy.velocity = self.originalVelocity;
- copy.deceleration = self.deceleration;
-
- }
-
- return copy;
- }
- @end
|