Skip to content
This repository has been archived by the owner on Mar 3, 2020. It is now read-only.

Transactions #276

Open
wants to merge 35 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
1d00d9b
added support for GLKIt types GLKVector3 and GLKQuaternion
naftaly Sep 17, 2015
6dcfafd
support for automatic animatable properties
naftaly Sep 17, 2015
7ab8e20
updated docs for keyPath animations.
naftaly Sep 17, 2015
1657986
fixed a some tests that could not resolve a layers position. fixed an…
naftaly Sep 17, 2015
f3376b3
added tests for basic animation keyPayh
naftaly Sep 17, 2015
2631a57
small fix when val was nil when calling valueForKeyPath: in automated…
naftaly Sep 17, 2015
fbeb68e
added tests for automated properties.
naftaly Sep 17, 2015
8fb24be
Merge branch 'master' into default_value_for_key
naftaly Sep 17, 2015
b19cc79
added POPGroupAnimation and tests.
naftaly Sep 18, 2015
172a1a8
added an assert when changing the animations of an animation group wh…
naftaly Sep 18, 2015
bf49cd6
started work on implicit animations
naftaly Sep 18, 2015
b20e3b6
Merge branch 'default_value_for_key' into implicit_animations
naftaly Sep 18, 2015
45b9ecb
fixed merge problem with group and explicit tests
naftaly Sep 18, 2015
e50d284
implicit animations are now being created on pop_animator and basics …
naftaly Sep 18, 2015
d9b46b7
first draft of POPTransaction
naftaly Sep 18, 2015
e22f51e
working out some inks in transactions
naftaly Sep 18, 2015
de1321c
fixed an issue with integer based implicit animations
naftaly Sep 18, 2015
84e2fe1
added block based transactional animations
naftaly Sep 19, 2015
eaefcf0
added quikhand animations
naftaly Sep 19, 2015
dedfded
added custom build status
naftaly Sep 19, 2015
a4a184c
fixed an issue where stopping a group animation would not stop all it…
naftaly Sep 20, 2015
8606865
Merge branch 'implicit_animations' of https://github.com/naftaly/pop …
naftaly Sep 20, 2015
d71c02f
moved some private group animation methods to a private file.
naftaly Sep 21, 2015
2c595eb
added code to change implicit animations on the fly
naftaly Sep 21, 2015
0939742
added docs for shorthand and proxy animations.
naftaly Sep 21, 2015
ae50ce3
added docs and more tests for transactions and shorthand animations
naftaly Sep 21, 2015
9b0be27
added POPTransaction.h to the umbrella header
naftaly Sep 21, 2015
3451df1
fixed an issue where GLK structures don't animate correctly if not us…
naftaly Sep 21, 2015
f3d09ca
fixed an error in the animation proxy and quaternions
naftaly Sep 21, 2015
a444c27
fixed a possible buffer overflow
naftaly Oct 5, 2015
9b0f13e
small fix to order of method for signature
naftaly Oct 5, 2015
708aec0
updated transactions
naftaly Oct 13, 2015
b25e34c
fixed an issue with floats and doubles
naftaly Oct 15, 2015
f1f508c
updated to Xcode 7.1
naftaly Oct 26, 2015
7b7fb64
enabled use of shared display link
naftaly Nov 13, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ DEPENDENCIES:
SPEC CHECKSUMS:
OCMock: a6a7dc0e3997fb9f35d99f72528698ebf60d64f2

COCOAPODS: 0.37.1
COCOAPODS: 0.38.2
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Pop is an extensible animation engine for iOS and OS X. In addition to basic static animations, it supports spring and decay dynamic animations, making it useful for building realistic, physics-based interactions. The API allows quick integration with existing Objective-C codebases and enables the animation of any property on any object. It's a mature and well-tested framework that drives all the animations and transitions in [Paper](http://www.facebook.com/paper).

[![Build Status](https://travis-ci.org/facebook/pop.svg)](https://travis-ci.org/facebook/pop)
[![Build Status](https://travis-ci.org/naftaly/pop.svg?branch=implicit_animations)](https://travis-ci.org/naftaly/pop)

## Installation

Expand Down
242 changes: 230 additions & 12 deletions pop-tests/POPAnimationTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,60 @@
#import "POPBaseAnimationTests.h"
#import "POPCGUtils.h"
#import "POPAnimationInternal.h"
#import "POPGroupAnimation.h"
#import "POPTransaction.h"

using namespace POP;

@interface POPRandomPropertyGivingObject : NSObject

@property (nonatomic,assign) NSInteger number;
@property (nonatomic,assign) NSInteger secondNumber;

@end

@implementation POPRandomPropertyGivingObject

@synthesize number, secondNumber;

- (POPAnimatableProperty*)animationPropertyForNumber
{
return [POPAnimatableProperty propertyWithName:@"com.pop.tests.number" initializer:^(POPMutableAnimatableProperty *prop) {
prop.readBlock = ^(POPRandomPropertyGivingObject* obj, CGFloat values[]) {
values[0] = obj.number;
};
prop.writeBlock = ^(POPRandomPropertyGivingObject* obj, const CGFloat values[]) {
obj.number = values[0];
};
prop.threshold = 1.0;
}];
}

- (void)setValue:(id)value forKeyPath:(NSString *)keyPath
{
if ( [keyPath isEqualToString:@"number"] ) {
self.number = [value integerValue];
} else if ( [keyPath isEqualToString:@"secondNumber"] ) {
self.secondNumber = [value integerValue];
} else {
[super setValue:value forKeyPath:keyPath];
}
}

- (id)valueForKeyPath:(NSString *)keyPath
{
if ( [keyPath isEqualToString:@"number"] ) {
return @(self.number);
} else if ( [keyPath isEqualToString:@"secondNumber"] ) {
return @(self.secondNumber);
} else {
return [super valueForKeyPath:keyPath];
}
return nil;
}

@end

@interface POPAnimation (TestExtensions)
@property (strong, nonatomic) NSString *sampleKey;
@end
Expand Down Expand Up @@ -110,10 +161,10 @@ - (void)testAnimationValues
anim.roundingFactor = 1.0;

id layer = [OCMockObject niceMockForClass:[CALayer class]];
[[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.25).cg_point()];
[[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.5).cg_point()];
[[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.75).cg_point()];
[[layer expect] setPosition:[anim.toValue CGPointValue]];
[(CALayer*)[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.25).cg_point()];
[(CALayer*)[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.5).cg_point()];
[(CALayer*)[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.75).cg_point()];
[(CALayer*)[layer expect] setPosition:[anim.toValue CGPointValue]];

[layer pop_addAnimation:anim forKey:@"key"];
POPAnimatorRenderDuration(self.animator, self.beginTime, 1, 0.25);
Expand Down Expand Up @@ -401,8 +452,8 @@ - (void)testReuse

id layer = [OCMockObject niceMockForClass:[CALayer class]];

[[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([fromValue CGPointValue]), Vector2r([toValue CGPointValue]), testProgress).cg_point()];
[[layer expect] setPosition:[toValue CGPointValue]];
[(CALayer*)[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([fromValue CGPointValue]), Vector2r([toValue CGPointValue]), testProgress).cg_point()];
[(CALayer*)[layer expect] setPosition:[toValue CGPointValue]];

[layer pop_addAnimation:anim forKey:@"key"];

Expand All @@ -418,8 +469,8 @@ - (void)testReuse

layer = [OCMockObject niceMockForClass:[CALayer class]];

[[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([fromValue CGPointValue]), Vector2r([toValue CGPointValue]), testProgress).cg_point()];
[[layer expect] setPosition:[toValue CGPointValue]];
[(CALayer*)[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([fromValue CGPointValue]), Vector2r([toValue CGPointValue]), testProgress).cg_point()];
[(CALayer*)[layer expect] setPosition:[toValue CGPointValue]];

[layer pop_addAnimation:anim forKey:@"key"];

Expand Down Expand Up @@ -754,10 +805,10 @@ - (void)testNilKey
anim.roundingFactor = 1.0;

id layer = [OCMockObject niceMockForClass:[CALayer class]];
[[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.25).cg_point()];
[[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.5).cg_point()];
[[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.75).cg_point()];
[[layer expect] setPosition:[anim.toValue CGPointValue]];
[(CALayer*)[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.25).cg_point()];
[(CALayer*)[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.5).cg_point()];
[(CALayer*)[layer expect] setPosition:FBTestInterpolateLinear(Vector2r([anim.fromValue CGPointValue]), Vector2r([anim.toValue CGPointValue]), 0.75).cg_point()];
[(CALayer*)[layer expect] setPosition:[anim.toValue CGPointValue]];

// verify nil key can be added, same as CA
[layer pop_addAnimation:anim forKey:nil];
Expand Down Expand Up @@ -888,4 +939,171 @@ - (void)testNSCopyingSupportPOPBasicAnimation
XCTAssertEqualObjects(copy.timingFunction, anim.timingFunction, @"expected equality; value1:%@ value2:%@", copy.timingFunction, anim.timingFunction);
}

- (void)testNSCopyingSupportPOPBasicAnimationWithKeyPath
{
POPBasicAnimation *anim = [POPBasicAnimation animationWithKeyPath:@"contentOffset"];

configureConcretePropertyAnimation(anim);
[self testCopyingSucceedsForConcretePropertyAnimation:anim];

anim.duration = 1.8;
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

POPBasicAnimation *copy = [anim copy];

XCTAssertEqual(copy.duration, anim.duration, @"expected equality; value1:%@ value2:%@", @(copy.duration), @(anim.duration));
XCTAssertEqualObjects(copy.timingFunction, anim.timingFunction, @"expected equality; value1:%@ value2:%@", copy.timingFunction, anim.timingFunction);
}

- (void)testAutomatedAnimatedPropertyInBasicAnimation
{
CALayer* layer = [CALayer layer];
POPBasicAnimation *anim = [POPBasicAnimation animationWithKeyPath:@"position"];
[layer pop_addAnimation:anim forKey:@"test"];
XCTAssertNotNil( anim.property, @"expected non-nil property for keyPath:%@", anim.keyPath );

anim = [POPBasicAnimation animationWithKeyPath:@"nonExistingKeyPath"];
[layer pop_addAnimation:anim forKey:@"test"];
XCTAssertNil( anim.property, @"expected nil property for keyPath:%@ (%@)", anim.keyPath, anim.property );
}

- (void)testAutomatedAnimatedPropertyInSpringAnimation
{
CALayer* layer = [CALayer layer];
POPSpringAnimation *anim = [POPSpringAnimation animationWithKeyPath:@"position"];
[layer pop_addAnimation:anim forKey:@"test"];
XCTAssertNotNil( anim.property, @"expected non-nil property for keyPath:%@", anim.keyPath );

anim = [POPSpringAnimation animationWithKeyPath:@"nonExistingKeyPath"];
[layer pop_addAnimation:anim forKey:@"test"];
XCTAssertNil( anim.property, @"expected nil property for keyPath:%@ (%@)", anim.keyPath, anim.property );
}

- (void)testAutomatedAnimatedPropertyInDecayAnimation
{
CALayer* layer = [CALayer layer];
POPDecayAnimation *anim = [POPDecayAnimation animationWithKeyPath:@"position"];
[layer pop_addAnimation:anim forKey:@"test"];
XCTAssertNotNil( anim.property, @"expected non-nil property for keyPath:%@", anim.keyPath );

anim = [POPDecayAnimation animationWithKeyPath:@"nonExistingKeyPath"];
[layer pop_addAnimation:anim forKey:@"test"];
XCTAssertNil( anim.property, @"expected nil property for keyPath:%@ (%@)", anim.keyPath, anim.property );
}

- (void)testAutomatedUserDefinedAnimatedProperty
{
POPRandomPropertyGivingObject* object = [[POPRandomPropertyGivingObject alloc] init];
POPBasicAnimation *anim = [POPBasicAnimation animationWithKeyPath:@"number"];
[object pop_addAnimation:anim forKey:@"test"];
XCTAssertNotNil( anim.property, @"expected non-nil property for keyPath:%@", anim.keyPath );
}

- (void)testAutomatedKeyValueDefinedAnimatedProperty
{
POPRandomPropertyGivingObject* object = [[POPRandomPropertyGivingObject alloc] init];
POPBasicAnimation *anim = [POPBasicAnimation animationWithKeyPath:@"secondNumber"];
[object pop_addAnimation:anim forKey:@"test"];
XCTAssertNotNil( anim.property, @"expected non-nil property for keyPath:%@", anim.keyPath );
}

- (void)testGroupAnimation
{
CALayer* layer = [CALayer layer];

__block NSInteger testValue = 0;

POPGroupAnimation* group = [POPGroupAnimation animation];
group.animationDidStartBlock = ^(POPAnimation* anim) {
XCTAssertEqual(testValue, 0, @"expected 0 but got %ld", (long)testValue);
testValue++;
};

POPBasicAnimation* test = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerBorderWidth];
test.toValue = @(5);
test.animationDidStartBlock = ^(POPAnimation* anim) {
XCTAssertEqual(testValue, 1, @"expected 1 but got %ld", (long)testValue);
testValue++;
};
test.completionBlock = ^(POPAnimation* anim, BOOL finished) {
XCTAssertEqual(testValue, 2, @"expected 2 but got %ld", (long)testValue);
testValue++;
};

group.animations = @[ test ];

group.completionBlock = ^(POPAnimation* anim, BOOL finished) {
XCTAssertEqual(testValue, 3, @"expected 3 but got %ld", (long)testValue);
testValue++;
};
[layer pop_addAnimation:group forKey:@"group"];

POPAnimatorRenderDuration(self.animator, self.beginTime, 5, 0.01);
}

- (void)testImplicitAnimations
{
POPRandomPropertyGivingObject* obj = [[POPRandomPropertyGivingObject alloc] init];
obj.secondNumber = 0;

XCTAssertTrue(obj.secondNumber == 0, @"expect 0 but got %ld", (long)obj.secondNumber );

[POPTransaction begin];
[POPTransaction setAnimationDuration:10];

obj.pop_animator.secondNumber = 10;

[POPTransaction commit];

POPAnimatorRenderDuration(self.animator, self.beginTime, 20, 0.01);

XCTAssertTrue(obj.secondNumber == 10, @"expect 10 but got %ld", (long)obj.secondNumber );
}

- (void)testImplicitAnimationValueChange
{
POPRandomPropertyGivingObject* obj = [[POPRandomPropertyGivingObject alloc] init];
obj.secondNumber = 0;

XCTAssertTrue(obj.secondNumber == 0, @"expect 0 but got %ld", (long)obj.secondNumber );

[POPTransaction begin];
[POPTransaction setAnimationDuration:10];

obj.pop_animator.secondNumber = 10;
obj.pop_animator.secondNumber = 20;

[POPTransaction commit];

POPAnimatorRenderDuration(self.animator, self.beginTime, 20, 0.01);

XCTAssertTrue(obj.secondNumber == 20, @"expect 20 but got %ld", (long)obj.secondNumber );
}

- (void)testObjectImplicitAnimations
{
POPRandomPropertyGivingObject* obj = [[POPRandomPropertyGivingObject alloc] init];
obj.secondNumber = 0;

XCTAssertTrue(obj.secondNumber == 0, @"expect 0 but got %ld", (long)obj.secondNumber );

[NSObject pop_animateWithDuration:10 delay:0 options:0 animations:^{
obj.pop_animator.secondNumber = 10;
} completion:^(BOOL finished) {
}];

POPAnimatorRenderDuration(self.animator, self.beginTime, 20, 0.01);

XCTAssertTrue(obj.secondNumber == 10, @"expect 10 but got %ld", (long)obj.secondNumber );
}

- (void)testObjectExplicitAnimations
{
POPRandomPropertyGivingObject* obj = [[POPRandomPropertyGivingObject alloc] init];
obj.secondNumber = 0;
XCTAssertTrue(obj.secondNumber == 0, @"expect 0 but got %ld", (long)obj.secondNumber );
obj.pop_animator.secondNumber = 10;
XCTAssertTrue(obj.secondNumber == 10, @"expect 10 but got %ld", (long)obj.secondNumber );
}

@end
1 change: 1 addition & 0 deletions pop-tests/POPBaseAnimationTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ - (void)testCopyingSucceedsForConcretePropertyAnimation:(POPPropertyAnimation *)
XCTAssertEqual(copy.roundingFactor, anim.roundingFactor, @"expected equality; value1:%@ value2:%@", @(copy.roundingFactor), @(anim.roundingFactor));
XCTAssertEqual(copy.clampMode, anim.clampMode, @"expected equality; value1:%@ value2:%@", @(copy.clampMode), @(anim.clampMode));
XCTAssertEqual(copy.additive, anim.additive, @"expected equality; value1:%@ value2:%@", @(copy.additive), @(anim.additive));
XCTAssertEqualObjects(copy.keyPath, anim.keyPath, @"expected equality; value1:%@ value2:%@", copy.keyPath, anim.keyPath);
}

@end
Expand Down
2 changes: 1 addition & 1 deletion pop.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Pod::Spec.new do |spec|
spec.summary = 'Extensible animation framework for iOS and OS X.'
spec.source = { :git => 'https://github.com/facebook/pop.git', :tag => '1.0.8' }
spec.source_files = 'pop/**/*.{h,m,mm,cpp}'
spec.public_header_files = 'pop/{POP,POPAnimatableProperty,POPAnimation,POPAnimationEvent,POPAnimationExtras,POPAnimationTracer,POPAnimator,POPBasicAnimation,POPCustomAnimation,POPDecayAnimation,POPDefines,POPGeometry,POPLayerExtras,POPPropertyAnimation,POPSpringAnimation}.h'
spec.public_header_files = 'pop/{POP,POPAnimatableProperty,POPAnimation,POPAnimationEvent,POPAnimationExtras,POPAnimationTracer,POPAnimator,POPBasicAnimation,POPCustomAnimation,POPDecayAnimation,POPDefines,POPGeometry,POPLayerExtras,POPPropertyAnimation,POPSpringAnimation,POPTransaction,POPGroupAnimation}.h'
spec.requires_arc = true
spec.social_media_url = 'https://twitter.com/fbOpenSource'
spec.library = 'c++'
Expand Down
Loading