summaryrefslogtreecommitdiff
path: root/Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp')
-rw-r--r--Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp519
1 files changed, 480 insertions, 39 deletions
diff --git a/Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp b/Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp
index c4f103a3c..fa95a2ac5 100644
--- a/Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp
+++ b/Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp
@@ -56,7 +56,8 @@ PassOwnPtr<CCActiveAnimation> createActiveAnimation(PassOwnPtr<CCAnimationCurve>
TEST(CCLayerAnimationControllerTest, createOpacityAnimation)
{
- OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy));
const double duration = 1;
WebCore::KeyframeValueList values(AnimatedPropertyOpacity);
values.insert(new FloatAnimationValue(0, 0));
@@ -85,9 +86,37 @@ TEST(CCLayerAnimationControllerTest, createOpacityAnimation)
EXPECT_EQ(1, curve->getValue(duration));
}
+TEST(CCLayerAnimationControllerTest, ignoreUnsupportedAnimationDirections)
+{
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy));
+ const double duration = 1;
+ WebCore::KeyframeValueList values(AnimatedPropertyOpacity);
+ values.insert(new FloatAnimationValue(0, 0));
+ values.insert(new FloatAnimationValue(duration, 1));
+
+ RefPtr<Animation> animation = Animation::create();
+ animation->setDuration(duration);
+
+ IntSize boxSize;
+
+ animation->setDirection(Animation::AnimationDirectionAlternate);
+ EXPECT_FALSE(controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0));
+
+ animation->setDirection(Animation::AnimationDirectionAlternateReverse);
+ EXPECT_FALSE(controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0));
+
+ animation->setDirection(Animation::AnimationDirectionReverse);
+ EXPECT_FALSE(controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0));
+
+ animation->setDirection(Animation::AnimationDirectionNormal);
+ EXPECT_TRUE(controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0));
+}
+
TEST(CCLayerAnimationControllerTest, createTransformAnimation)
{
- OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy));
const double duration = 1;
WebCore::KeyframeValueList values(AnimatedPropertyWebkitTransform);
@@ -124,92 +153,504 @@ TEST(CCLayerAnimationControllerTest, createTransformAnimation)
TEST(CCLayerAnimationControllerTest, syncNewAnimation)
{
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy));
- OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+ FakeLayerAnimationControllerClient dummyImpl;
+ OwnPtr<CCLayerAnimationController> controllerImpl(CCLayerAnimationController::create(&dummyImpl));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy));
EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
- addOpacityTransitionToController(*controller, 1, 0, 1);
+ addOpacityTransitionToController(*controller, 1, 0, 1, false);
- controller->synchronizeAnimations(controllerImpl.get());
+ controller->pushAnimationUpdatesTo(controllerImpl.get());
EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
}
-TEST(CCLayerAnimationControllerTest, syncAnimationProperties)
+// If an animation is started on the impl thread before it is ticked on the main
+// thread, we must be sure to respect the synchronized start time.
+TEST(CCLayerAnimationControllerTest, doNotClobberStartTimes)
{
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy));
- OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+ FakeLayerAnimationControllerClient dummyImpl;
+ OwnPtr<CCLayerAnimationController> controllerImpl(CCLayerAnimationController::create(&dummyImpl));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy));
EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
- addOpacityTransitionToController(*controller, 1, 0, 1);
+ addOpacityTransitionToController(*controller, 1, 0, 1, false);
- controller->synchronizeAnimations(controllerImpl.get());
+ controller->pushAnimationUpdatesTo(controllerImpl.get());
EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
- // Push an animation property change to the impl thread (should not cause an animation to be added).
- controller->pauseAnimation(0, 0);
- controller->synchronizeAnimations(controllerImpl.get());
+ CCAnimationEventsVector events;
+ controllerImpl->animate(1, &events);
- EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
- EXPECT_EQ(CCActiveAnimation::Paused, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
+ // Synchronize the start times.
+ EXPECT_EQ(1u, events.size());
+ controller->notifyAnimationStarted(events[0]);
+ EXPECT_EQ(controller->getActiveAnimation(0, CCActiveAnimation::Opacity)->startTime(), controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->startTime());
+
+ // Start the animation on the main thread. Should not affect the start time.
+ controller->animate(1.5, 0);
+ EXPECT_EQ(controller->getActiveAnimation(0, CCActiveAnimation::Opacity)->startTime(), controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->startTime());
}
-TEST(CCLayerAnimationControllerTest, syncAbortedAnimation)
+TEST(CCLayerAnimationControllerTest, syncPauseAndResume)
{
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy));
- OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+ FakeLayerAnimationControllerClient dummyImpl;
+ OwnPtr<CCLayerAnimationController> controllerImpl(CCLayerAnimationController::create(&dummyImpl));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy));
EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
- addOpacityTransitionToController(*controller, 1, 0, 1);
+ addOpacityTransitionToController(*controller, 1, 0, 1, false);
- controller->synchronizeAnimations(controllerImpl.get());
+ controller->pushAnimationUpdatesTo(controllerImpl.get());
EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
- controller->removeAnimation(0);
+ // Start the animations on each controller.
+ CCAnimationEventsVector events;
+ controllerImpl->animate(0, &events);
+ controller->animate(0, 0);
+ EXPECT_EQ(CCActiveAnimation::Running, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
+ EXPECT_EQ(CCActiveAnimation::Running, controller->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
- // Abort an animation from the main thread.
- controller->synchronizeAnimations(controllerImpl.get());
+ // Pause the main-thread animation.
+ controller->suspendAnimations(1);
+ EXPECT_EQ(CCActiveAnimation::Paused, controller->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
- EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+ // The pause run state change should make it to the impl thread controller.
+ controller->pushAnimationUpdatesTo(controllerImpl.get());
+ EXPECT_EQ(CCActiveAnimation::Paused, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
+
+ // Resume the main-thread animation.
+ controller->resumeAnimations(2);
+ EXPECT_EQ(CCActiveAnimation::Running, controller->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
+
+ // The pause run state change should make it to the impl thread controller.
+ controller->pushAnimationUpdatesTo(controllerImpl.get());
+ EXPECT_EQ(CCActiveAnimation::Running, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
}
-TEST(CCLayerAnimationControllerTest, syncCompletedAnimation)
+
+TEST(CCLayerAnimationControllerTest, doNotSyncFinishedAnimation)
{
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy));
- OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+ FakeLayerAnimationControllerClient dummyImpl;
+ OwnPtr<CCLayerAnimationController> controllerImpl(CCLayerAnimationController::create(&dummyImpl));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy));
EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
- addOpacityTransitionToController(*controller, 1, 0, 1);
+ addOpacityTransitionToController(*controller, 1, 0, 1, false);
- controller->synchronizeAnimations(controllerImpl.get());
+ controller->pushAnimationUpdatesTo(controllerImpl.get());
EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
- // Step through the animation until it is finished. At the next sync, the main thread's animation should be cleared.
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- controllerImpl->animate(0, *events);
- controllerImpl->animate(2, *events);
+ // Notify main thread controller that the animation has started.
+ CCAnimationEvent animationStartedEvent(CCAnimationEvent::Started, 0, 0, CCActiveAnimation::Opacity, 0);
+ controller->notifyAnimationStarted(animationStartedEvent);
+
+ // Force animation to complete on impl thread.
+ controllerImpl->removeAnimation(0);
EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+
+ controller->pushAnimationUpdatesTo(controllerImpl.get());
+
+ // Even though the main thread has a 'new' animation, it should not be pushed because the animation has already completed on the impl thread.
+ EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+}
+
+// Tests that transitioning opacity from 0 to 1 works as expected.
+TEST(CCLayerAnimationControllerTest, TrivialTransition)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+
+ controller->add(toAdd.release());
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1, events.get());
+ EXPECT_EQ(1, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Tests animations that are waiting for a synchronized start time do not finish.
+TEST(CCLayerAnimationControllerTest, AnimationsWaitingForStartTimeDoNotFinishIfTheyWaitLongerToStartThanTheirDuration)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ toAdd->setNeedsSynchronizedStartTime(true);
+
+ // We should pause at the first keyframe indefinitely waiting for that animation to start.
+ controller->add(toAdd.release());
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(2, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+
+ // Send the synchronized start time.
+ controller->notifyAnimationStarted(CCAnimationEvent(CCAnimationEvent::Started, 0, 1, CCActiveAnimation::Opacity, 2));
+ controller->animate(5, events.get());
+ EXPECT_EQ(1, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Tests that two queued animations affecting the same property run in sequence.
+TEST(CCLayerAnimationControllerTest, TrivialQueuing)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5)), 2, CCActiveAnimation::Opacity));
+
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(1, dummy.opacity());
+ controller->animate(2, events.get());
+ EXPECT_EQ(0.5, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Tests interrupting a transition with another transition.
+TEST(CCLayerAnimationControllerTest, Interrupt)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5)), 2, CCActiveAnimation::Opacity));
+ toAdd->setRunState(CCActiveAnimation::WaitingForNextTick, 0);
+ controller->add(toAdd.release());
+
+ // Since the animation was in the WaitingForNextTick state, it should start right in
+ // this call to animate.
+ controller->animate(0.5, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(1, dummy.opacity());
+ controller->animate(1.5, events.get());
+ EXPECT_EQ(0.5, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Tests scheduling two animations to run together when only one property is free.
+TEST(CCLayerAnimationControllerTest, ScheduleTogetherWhenAPropertyIsBlocked)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
- controller->synchronizeAnimations(controllerImpl.get());
+ controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), 1, CCActiveAnimation::Transform));
+ controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), 2, CCActiveAnimation::Transform));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 2, CCActiveAnimation::Opacity));
+ controller->animate(0, events.get());
+ EXPECT_EQ(0, dummy.opacity());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ controller->animate(1, events.get());
+ // Should not have started the float transition yet.
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ // The float animation should have started at time 1 and should be done.
+ controller->animate(2, events.get());
+ EXPECT_EQ(1, dummy.opacity());
EXPECT_FALSE(controller->hasActiveAnimation());
}
+// Tests scheduling two animations to run together with different lengths and another
+// animation queued to start when the shorter animation finishes (should wait
+// for both to finish).
+TEST(CCLayerAnimationControllerTest, ScheduleTogetherWithAnAnimWaiting)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(2)), 1, CCActiveAnimation::Transform));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5)), 2, CCActiveAnimation::Opacity));
+
+ // Animations with id 1 should both start now.
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ // The opacity animation should have finished at time 1, but the group
+ // of animations with id 1 don't finish until time 2 because of the length
+ // of the transform animation.
+ controller->animate(2, events.get());
+ // Should not have started the float transition yet.
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(1, dummy.opacity());
+
+ // The second opacity animation should start at time 2 and should be done by time 3
+ controller->animate(3, events.get());
+ EXPECT_EQ(0.5, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Tests scheduling an animation to start in the future.
+TEST(CCLayerAnimationControllerTest, ScheduleAnimation)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0);
+ toAdd->setStartTime(1);
+ controller->add(toAdd.release());
+
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(2, events.get());
+ EXPECT_EQ(1, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Tests scheduling an animation to start in the future that's interrupting a running animation.
+TEST(CCLayerAnimationControllerTest, ScheduledAnimationInterruptsRunningAnimation)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity));
+
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0.5, 0)), 2, CCActiveAnimation::Opacity));
+ toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0);
+ toAdd->setStartTime(1);
+ controller->add(toAdd.release());
+
+ // First 2s opacity transition should start immediately.
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(0.5, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25, dummy.opacity());
+ controller->animate(1, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.5, dummy.opacity());
+ controller->animate(2, events.get());
+ EXPECT_EQ(0, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Tests scheduling an animation to start in the future that interrupts a running animation
+// and there is yet another animation queued to start later.
+TEST(CCLayerAnimationControllerTest, ScheduledAnimationInterruptsRunningAnimationWithAnimInQueue)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity));
+
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0.5, 0)), 2, CCActiveAnimation::Opacity));
+ toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0);
+ toAdd->setStartTime(1);
+ controller->add(toAdd.release());
+
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 0.75)), 3, CCActiveAnimation::Opacity));
+
+ // First 2s opacity transition should start immediately.
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(0.5, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25, dummy.opacity());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ controller->animate(1, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.5, dummy.opacity());
+ controller->animate(3, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(4, events.get());
+ EXPECT_EQ(0.75, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Test that a looping animation loops and for the correct number of iterations.
+TEST(CCLayerAnimationControllerTest, TrivialLooping)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ toAdd->setIterations(3);
+ controller->add(toAdd.release());
+
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1.25, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25, dummy.opacity());
+ controller->animate(1.75, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75, dummy.opacity());
+ controller->animate(2.25, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25, dummy.opacity());
+ controller->animate(2.75, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75, dummy.opacity());
+ controller->animate(3, events.get());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+ EXPECT_EQ(1, dummy.opacity());
+
+ // Just be extra sure.
+ controller->animate(4, events.get());
+ EXPECT_EQ(1, dummy.opacity());
+}
+
+// Test that an infinitely looping animation does indeed go until aborted.
+TEST(CCLayerAnimationControllerTest, InfiniteLooping)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ const int id = 1;
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity));
+ toAdd->setIterations(-1);
+ controller->add(toAdd.release());
+
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1.25, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25, dummy.opacity());
+ controller->animate(1.75, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75, dummy.opacity());
+
+ controller->animate(1073741824.25, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25, dummy.opacity());
+ controller->animate(1073741824.75, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75, dummy.opacity());
+
+ EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
+ controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Aborted, 0.75);
+ EXPECT_FALSE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75, dummy.opacity());
+}
+
+// Test that pausing and resuming work as expected.
+TEST(CCLayerAnimationControllerTest, PauseResume)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ const int id = 1;
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity));
+
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(0.5, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.5, dummy.opacity());
+
+ EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
+ controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Paused, 0.5);
+
+ controller->animate(1024, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.5, dummy.opacity());
+
+ EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
+ controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Running, 1024);
+
+ controller->animate(1024.25, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75, dummy.opacity());
+ controller->animate(1024.5, events.get());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+ EXPECT_EQ(1, dummy.opacity());
+}
+
+TEST(CCLayerAnimationControllerTest, AbortAGroupedAnimation)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ const int id = 1;
+ controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), id, CCActiveAnimation::Transform));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), id, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.75)), 2, CCActiveAnimation::Opacity));
+
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.5, dummy.opacity());
+
+ EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
+ controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Aborted, 1);
+ controller->animate(1, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(1, dummy.opacity());
+ controller->animate(2, events.get());
+ EXPECT_TRUE(!controller->hasActiveAnimation());
+ EXPECT_EQ(0.75, dummy.opacity());
+}
+
} // namespace