| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "services/view_manager/animation_runner.h" |
| 6 |
| 7 #include "base/strings/stringprintf.h" |
| 8 #include "mojo/converters/geometry/geometry_type_converters.h" |
| 9 #include "mojo/services/view_manager/interfaces/view_manager_constants.mojom.h" |
| 10 #include "services/view_manager/animation_runner_observer.h" |
| 11 #include "services/view_manager/scheduled_animation_group.h" |
| 12 #include "services/view_manager/server_view.h" |
| 13 #include "services/view_manager/test_server_view_delegate.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" |
| 15 |
| 16 using base::TimeDelta; |
| 17 using mojo::AnimationElement; |
| 18 using mojo::AnimationGroup; |
| 19 using mojo::AnimationProperty; |
| 20 using mojo::AnimationSequence; |
| 21 using mojo::AnimationTweenType; |
| 22 using mojo::AnimationValue; |
| 23 using mojo::AnimationValuePtr; |
| 24 using mojo::Transform; |
| 25 |
| 26 namespace view_manager { |
| 27 namespace { |
| 28 |
| 29 class TestAnimationRunnerObserver : public AnimationRunnerObserver { |
| 30 public: |
| 31 TestAnimationRunnerObserver() {} |
| 32 ~TestAnimationRunnerObserver() override {} |
| 33 |
| 34 std::vector<std::string>* changes() { return &changes_; } |
| 35 std::vector<uint32_t>* change_ids() { return &change_ids_; } |
| 36 |
| 37 void clear_changes() { |
| 38 changes_.clear(); |
| 39 change_ids_.clear(); |
| 40 } |
| 41 |
| 42 // AnimationRunnerDelgate: |
| 43 void OnAnimationScheduled(uint32_t id) override { |
| 44 change_ids_.push_back(id); |
| 45 changes_.push_back("scheduled"); |
| 46 } |
| 47 void OnAnimationDone(uint32_t id) override { |
| 48 change_ids_.push_back(id); |
| 49 changes_.push_back("done"); |
| 50 } |
| 51 void OnAnimationInterrupted(uint32_t id) override { |
| 52 change_ids_.push_back(id); |
| 53 changes_.push_back("interrupted"); |
| 54 } |
| 55 void OnAnimationCanceled(uint32_t id) override { |
| 56 change_ids_.push_back(id); |
| 57 changes_.push_back("canceled"); |
| 58 } |
| 59 |
| 60 private: |
| 61 std::vector<uint32_t> change_ids_; |
| 62 std::vector<std::string> changes_; |
| 63 |
| 64 DISALLOW_COPY_AND_ASSIGN(TestAnimationRunnerObserver); |
| 65 }; |
| 66 |
| 67 // Creates an AnimationValuePtr from the specified float value. |
| 68 AnimationValuePtr FloatAnimationValue(float float_value) { |
| 69 AnimationValuePtr value(AnimationValue::New()); |
| 70 value->float_value = float_value; |
| 71 return value; |
| 72 } |
| 73 |
| 74 // Creates an AnimationValuePtr from the specified transform. |
| 75 AnimationValuePtr TransformAnimationValue(const gfx::Transform& transform) { |
| 76 AnimationValuePtr value(AnimationValue::New()); |
| 77 value->transform = Transform::From(transform); |
| 78 return value; |
| 79 } |
| 80 |
| 81 // Adds an AnimationElement to |group|s last sequence with the specified value. |
| 82 void AddElement(AnimationGroup* group, |
| 83 TimeDelta time, |
| 84 AnimationValuePtr start_value, |
| 85 AnimationValuePtr target_value, |
| 86 AnimationProperty property, |
| 87 AnimationTweenType tween_type) { |
| 88 AnimationSequence& sequence = |
| 89 *(group->sequences[group->sequences.size() - 1]); |
| 90 sequence.elements.push_back(AnimationElement::New()); |
| 91 AnimationElement& element = |
| 92 *(sequence.elements[sequence.elements.size() - 1]); |
| 93 element.property = property; |
| 94 element.duration = time.InMicroseconds(); |
| 95 element.tween_type = tween_type; |
| 96 element.start_value = start_value.Pass(); |
| 97 element.target_value = target_value.Pass(); |
| 98 } |
| 99 |
| 100 void AddOpacityElement(AnimationGroup* group, |
| 101 TimeDelta time, |
| 102 AnimationValuePtr start_value, |
| 103 AnimationValuePtr target_value) { |
| 104 AddElement(group, time, start_value.Pass(), target_value.Pass(), |
| 105 AnimationProperty::OPACITY, AnimationTweenType::LINEAR); |
| 106 } |
| 107 |
| 108 void AddTransformElement(AnimationGroup* group, |
| 109 TimeDelta time, |
| 110 AnimationValuePtr start_value, |
| 111 AnimationValuePtr target_value) { |
| 112 AddElement(group, time, start_value.Pass(), target_value.Pass(), |
| 113 AnimationProperty::TRANSFORM, AnimationTweenType::LINEAR); |
| 114 } |
| 115 |
| 116 void AddPauseElement(AnimationGroup* group, TimeDelta time) { |
| 117 AddElement(group, time, AnimationValuePtr(), AnimationValuePtr(), |
| 118 AnimationProperty::NONE, AnimationTweenType::LINEAR); |
| 119 } |
| 120 |
| 121 void InitGroupForView(AnimationGroup* group, |
| 122 const ViewId& id, |
| 123 int cycle_count) { |
| 124 group->view_id = ViewIdToTransportId(id); |
| 125 group->sequences.push_back(AnimationSequence::New()); |
| 126 group->sequences[group->sequences.size() - 1]->cycle_count = cycle_count; |
| 127 } |
| 128 |
| 129 } // namespace |
| 130 |
| 131 class AnimationRunnerTest : public testing::Test { |
| 132 public: |
| 133 AnimationRunnerTest() |
| 134 : initial_time_(base::TimeTicks::Now()), runner_(initial_time_) { |
| 135 runner_.AddObserver(&runner_observer_); |
| 136 } |
| 137 ~AnimationRunnerTest() override { runner_.RemoveObserver(&runner_observer_); } |
| 138 |
| 139 protected: |
| 140 // Convenience to schedule an animation for a single view/group pair. |
| 141 AnimationRunner::AnimationId ScheduleForSingleView( |
| 142 ServerView* view, |
| 143 const AnimationGroup* group, |
| 144 base::TimeTicks now) { |
| 145 std::vector<AnimationRunner::ViewAndAnimationPair> pairs; |
| 146 pairs.push_back(std::make_pair(view, group)); |
| 147 return runner_.Schedule(pairs, now); |
| 148 } |
| 149 |
| 150 // If |id| is valid and there is only one view schedule against the animation |
| 151 // it is returned; otherwise returns null. |
| 152 ServerView* GetSingleViewAnimating(AnimationRunner::AnimationId id) { |
| 153 std::set<ServerView*> views(runner_.GetViewsAnimating(id)); |
| 154 return views.size() == 1 ? *views.begin() : nullptr; |
| 155 } |
| 156 |
| 157 const base::TimeTicks initial_time_; |
| 158 TestAnimationRunnerObserver runner_observer_; |
| 159 AnimationRunner runner_; |
| 160 |
| 161 private: |
| 162 DISALLOW_COPY_AND_ASSIGN(AnimationRunnerTest); |
| 163 }; |
| 164 |
| 165 // Opacity from 1 to .5 over 1000. |
| 166 TEST_F(AnimationRunnerTest, SingleProperty) { |
| 167 TestServerViewDelegate view_delegate; |
| 168 ServerView view(&view_delegate, ViewId()); |
| 169 |
| 170 AnimationGroup group; |
| 171 InitGroupForView(&group, view.id(), 1); |
| 172 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), |
| 173 AnimationValuePtr(), FloatAnimationValue(.5)); |
| 174 |
| 175 const uint32_t animation_id = |
| 176 ScheduleForSingleView(&view, &group, initial_time_); |
| 177 |
| 178 ASSERT_EQ(1u, runner_observer_.changes()->size()); |
| 179 EXPECT_EQ("scheduled", runner_observer_.changes()->at(0)); |
| 180 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); |
| 181 runner_observer_.clear_changes(); |
| 182 |
| 183 EXPECT_TRUE(runner_.HasAnimations()); |
| 184 |
| 185 // Opacity should still be 1 (the initial value). |
| 186 EXPECT_EQ(1.f, view.opacity()); |
| 187 |
| 188 // Animate half way. |
| 189 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(500)); |
| 190 |
| 191 EXPECT_EQ(.75f, view.opacity()); |
| 192 EXPECT_TRUE(runner_observer_.changes()->empty()); |
| 193 |
| 194 // Run well past the end. Value should progress to end and delegate should |
| 195 // be notified. |
| 196 runner_.Tick(initial_time_ + TimeDelta::FromSeconds(10)); |
| 197 EXPECT_EQ(.5f, view.opacity()); |
| 198 |
| 199 ASSERT_EQ(1u, runner_observer_.changes()->size()); |
| 200 EXPECT_EQ("done", runner_observer_.changes()->at(0)); |
| 201 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); |
| 202 |
| 203 EXPECT_FALSE(runner_.HasAnimations()); |
| 204 } |
| 205 |
| 206 // Opacity from 1 to .5, followed by transform from identity to 2x,3x. |
| 207 TEST_F(AnimationRunnerTest, TwoPropertiesInSequence) { |
| 208 TestServerViewDelegate view_delegate; |
| 209 ServerView view(&view_delegate, ViewId()); |
| 210 |
| 211 AnimationGroup group; |
| 212 InitGroupForView(&group, view.id(), 1); |
| 213 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), |
| 214 AnimationValuePtr(), FloatAnimationValue(.5f)); |
| 215 |
| 216 gfx::Transform done_transform; |
| 217 done_transform.Scale(2, 4); |
| 218 AddTransformElement(&group, TimeDelta::FromMicroseconds(2000), |
| 219 AnimationValuePtr(), |
| 220 TransformAnimationValue(done_transform)); |
| 221 |
| 222 const uint32_t animation_id = |
| 223 ScheduleForSingleView(&view, &group, initial_time_); |
| 224 runner_observer_.clear_changes(); |
| 225 |
| 226 // Nothing in the view should have changed yet. |
| 227 EXPECT_EQ(1.f, view.opacity()); |
| 228 EXPECT_TRUE(view.transform().IsIdentity()); |
| 229 |
| 230 // Animate half way from through opacity animation. |
| 231 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(500)); |
| 232 |
| 233 EXPECT_EQ(.75f, view.opacity()); |
| 234 EXPECT_TRUE(view.transform().IsIdentity()); |
| 235 |
| 236 // Finish first element (opacity). |
| 237 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(1000)); |
| 238 EXPECT_EQ(.5f, view.opacity()); |
| 239 EXPECT_TRUE(view.transform().IsIdentity()); |
| 240 |
| 241 // Half way through second (transform). |
| 242 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(2000)); |
| 243 EXPECT_EQ(.5f, view.opacity()); |
| 244 gfx::Transform half_way_transform; |
| 245 half_way_transform.Scale(1.5, 2.5); |
| 246 EXPECT_EQ(half_way_transform, view.transform()); |
| 247 |
| 248 EXPECT_TRUE(runner_observer_.changes()->empty()); |
| 249 |
| 250 // To end. |
| 251 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(3500)); |
| 252 EXPECT_EQ(.5f, view.opacity()); |
| 253 EXPECT_EQ(done_transform, view.transform()); |
| 254 |
| 255 ASSERT_EQ(1u, runner_observer_.changes()->size()); |
| 256 EXPECT_EQ("done", runner_observer_.changes()->at(0)); |
| 257 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); |
| 258 } |
| 259 |
| 260 // Opacity from .5 to 1 over 1000, transform to 2x,4x over 500. |
| 261 TEST_F(AnimationRunnerTest, TwoPropertiesInParallel) { |
| 262 TestServerViewDelegate view_delegate; |
| 263 ServerView view(&view_delegate, ViewId(1, 1)); |
| 264 |
| 265 AnimationGroup group; |
| 266 InitGroupForView(&group, view.id(), 1); |
| 267 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), |
| 268 FloatAnimationValue(.5f), FloatAnimationValue(1)); |
| 269 |
| 270 group.sequences.push_back(AnimationSequence::New()); |
| 271 group.sequences[1]->cycle_count = 1; |
| 272 gfx::Transform done_transform; |
| 273 done_transform.Scale(2, 4); |
| 274 AddTransformElement(&group, TimeDelta::FromMicroseconds(500), |
| 275 AnimationValuePtr(), |
| 276 TransformAnimationValue(done_transform)); |
| 277 |
| 278 const uint32_t animation_id = |
| 279 ScheduleForSingleView(&view, &group, initial_time_); |
| 280 |
| 281 runner_observer_.clear_changes(); |
| 282 |
| 283 // Nothing in the view should have changed yet. |
| 284 EXPECT_EQ(1.f, view.opacity()); |
| 285 EXPECT_TRUE(view.transform().IsIdentity()); |
| 286 |
| 287 // Animate to 250, which is 1/4 way through opacity and half way through |
| 288 // transform. |
| 289 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(250)); |
| 290 |
| 291 EXPECT_EQ(.625f, view.opacity()); |
| 292 gfx::Transform half_way_transform; |
| 293 half_way_transform.Scale(1.5, 2.5); |
| 294 EXPECT_EQ(half_way_transform, view.transform()); |
| 295 |
| 296 // Animate to 500, which is 1/2 way through opacity and transform done. |
| 297 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(500)); |
| 298 EXPECT_EQ(.75f, view.opacity()); |
| 299 EXPECT_EQ(done_transform, view.transform()); |
| 300 |
| 301 // Animate to 750, which is 3/4 way through opacity and transform done. |
| 302 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(750)); |
| 303 EXPECT_EQ(.875f, view.opacity()); |
| 304 EXPECT_EQ(done_transform, view.transform()); |
| 305 |
| 306 EXPECT_TRUE(runner_observer_.changes()->empty()); |
| 307 |
| 308 // To end. |
| 309 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(3500)); |
| 310 EXPECT_EQ(1.f, view.opacity()); |
| 311 EXPECT_EQ(done_transform, view.transform()); |
| 312 |
| 313 ASSERT_EQ(1u, runner_observer_.changes()->size()); |
| 314 EXPECT_EQ("done", runner_observer_.changes()->at(0)); |
| 315 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); |
| 316 } |
| 317 |
| 318 // Opacity from .5 to 1 over 1000, pause for 500, 1 to .5 over 500, with a cycle |
| 319 // count of 3. |
| 320 TEST_F(AnimationRunnerTest, Cycles) { |
| 321 TestServerViewDelegate view_delegate; |
| 322 ServerView view(&view_delegate, ViewId(1, 2)); |
| 323 |
| 324 view.SetOpacity(.5f); |
| 325 |
| 326 AnimationGroup group; |
| 327 InitGroupForView(&group, view.id(), 3); |
| 328 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), |
| 329 AnimationValuePtr(), FloatAnimationValue(1)); |
| 330 AddPauseElement(&group, TimeDelta::FromMicroseconds(500)); |
| 331 AddOpacityElement(&group, TimeDelta::FromMicroseconds(500), |
| 332 AnimationValuePtr(), FloatAnimationValue(.5)); |
| 333 |
| 334 ScheduleForSingleView(&view, &group, initial_time_); |
| 335 runner_observer_.clear_changes(); |
| 336 |
| 337 // Nothing in the view should have changed yet. |
| 338 EXPECT_EQ(.5f, view.opacity()); |
| 339 |
| 340 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(500)); |
| 341 EXPECT_EQ(.75f, view.opacity()); |
| 342 |
| 343 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(1250)); |
| 344 EXPECT_EQ(1.f, view.opacity()); |
| 345 |
| 346 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(1750)); |
| 347 EXPECT_EQ(.75f, view.opacity()); |
| 348 |
| 349 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(2500)); |
| 350 EXPECT_EQ(.75f, view.opacity()); |
| 351 |
| 352 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(3250)); |
| 353 EXPECT_EQ(1.f, view.opacity()); |
| 354 |
| 355 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(3750)); |
| 356 EXPECT_EQ(.75f, view.opacity()); |
| 357 |
| 358 // Animate to the end. |
| 359 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(6500)); |
| 360 EXPECT_EQ(.5f, view.opacity()); |
| 361 |
| 362 ASSERT_EQ(1u, runner_observer_.changes()->size()); |
| 363 EXPECT_EQ("done", runner_observer_.changes()->at(0)); |
| 364 } |
| 365 |
| 366 // Verifies scheduling the same view twice sends an interrupt. |
| 367 TEST_F(AnimationRunnerTest, ScheduleTwice) { |
| 368 TestServerViewDelegate view_delegate; |
| 369 ServerView view(&view_delegate, ViewId(1, 2)); |
| 370 |
| 371 AnimationGroup group; |
| 372 InitGroupForView(&group, view.id(), 1); |
| 373 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), |
| 374 AnimationValuePtr(), FloatAnimationValue(.5)); |
| 375 |
| 376 const uint32_t animation_id = |
| 377 ScheduleForSingleView(&view, &group, initial_time_); |
| 378 runner_observer_.clear_changes(); |
| 379 |
| 380 // Animate half way. |
| 381 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(500)); |
| 382 |
| 383 EXPECT_EQ(.75f, view.opacity()); |
| 384 EXPECT_TRUE(runner_observer_.changes()->empty()); |
| 385 |
| 386 // Schedule again. We should get an interrupt, but opacity shouldn't change. |
| 387 const uint32_t animation2_id = ScheduleForSingleView( |
| 388 &view, &group, initial_time_ + TimeDelta::FromMicroseconds(500)); |
| 389 |
| 390 // Id should have changed. |
| 391 EXPECT_NE(animation_id, animation2_id); |
| 392 |
| 393 EXPECT_FALSE(runner_.IsAnimating(animation_id)); |
| 394 EXPECT_EQ(&view, GetSingleViewAnimating(animation2_id)); |
| 395 |
| 396 EXPECT_EQ(.75f, view.opacity()); |
| 397 EXPECT_EQ(2u, runner_observer_.changes()->size()); |
| 398 EXPECT_EQ("interrupted", runner_observer_.changes()->at(0)); |
| 399 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); |
| 400 EXPECT_EQ("scheduled", runner_observer_.changes()->at(1)); |
| 401 EXPECT_EQ(animation2_id, runner_observer_.change_ids()->at(1)); |
| 402 runner_observer_.clear_changes(); |
| 403 |
| 404 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(1000)); |
| 405 EXPECT_EQ(.625f, view.opacity()); |
| 406 EXPECT_TRUE(runner_observer_.changes()->empty()); |
| 407 |
| 408 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(2000)); |
| 409 EXPECT_EQ(.5f, view.opacity()); |
| 410 EXPECT_EQ(1u, runner_observer_.changes()->size()); |
| 411 EXPECT_EQ("done", runner_observer_.changes()->at(0)); |
| 412 EXPECT_EQ(animation2_id, runner_observer_.change_ids()->at(0)); |
| 413 } |
| 414 |
| 415 // Verifies Remove() works. |
| 416 TEST_F(AnimationRunnerTest, CancelAnimationForView) { |
| 417 // Create an animation and advance it part way. |
| 418 TestServerViewDelegate view_delegate; |
| 419 ServerView view(&view_delegate, ViewId()); |
| 420 AnimationGroup group; |
| 421 InitGroupForView(&group, view.id(), 1); |
| 422 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), |
| 423 AnimationValuePtr(), FloatAnimationValue(.5)); |
| 424 |
| 425 const uint32_t animation_id = |
| 426 ScheduleForSingleView(&view, &group, initial_time_); |
| 427 runner_observer_.clear_changes(); |
| 428 EXPECT_EQ(&view, GetSingleViewAnimating(animation_id)); |
| 429 |
| 430 EXPECT_TRUE(runner_.HasAnimations()); |
| 431 |
| 432 // Animate half way. |
| 433 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(500)); |
| 434 EXPECT_EQ(.75f, view.opacity()); |
| 435 EXPECT_TRUE(runner_observer_.changes()->empty()); |
| 436 |
| 437 // Cancel the animation. |
| 438 runner_.CancelAnimationForView(&view); |
| 439 |
| 440 EXPECT_FALSE(runner_.HasAnimations()); |
| 441 EXPECT_EQ(nullptr, GetSingleViewAnimating(animation_id)); |
| 442 |
| 443 EXPECT_EQ(.75f, view.opacity()); |
| 444 |
| 445 EXPECT_EQ(1u, runner_observer_.changes()->size()); |
| 446 EXPECT_EQ("canceled", runner_observer_.changes()->at(0)); |
| 447 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); |
| 448 } |
| 449 |
| 450 // Verifies a tick with a very large delta and a sequence that repeats forever |
| 451 // doesn't take a long time. |
| 452 TEST_F(AnimationRunnerTest, InfiniteRepeatWithHugeGap) { |
| 453 TestServerViewDelegate view_delegate; |
| 454 ServerView view(&view_delegate, ViewId(1, 2)); |
| 455 |
| 456 view.SetOpacity(.5f); |
| 457 |
| 458 AnimationGroup group; |
| 459 InitGroupForView(&group, view.id(), 0); |
| 460 AddOpacityElement(&group, TimeDelta::FromMicroseconds(500), |
| 461 AnimationValuePtr(), FloatAnimationValue(1)); |
| 462 AddOpacityElement(&group, TimeDelta::FromMicroseconds(500), |
| 463 AnimationValuePtr(), FloatAnimationValue(.5)); |
| 464 |
| 465 ScheduleForSingleView(&view, &group, initial_time_); |
| 466 runner_observer_.clear_changes(); |
| 467 |
| 468 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(1000000000750)); |
| 469 |
| 470 EXPECT_EQ(.75f, view.opacity()); |
| 471 |
| 472 ASSERT_EQ(0u, runner_observer_.changes()->size()); |
| 473 } |
| 474 |
| 475 // Verifies a second schedule sets any properties that are no longer animating |
| 476 // to their final value. |
| 477 TEST_F(AnimationRunnerTest, RescheduleSetsPropertiesToFinalValue) { |
| 478 TestServerViewDelegate view_delegate; |
| 479 ServerView view(&view_delegate, ViewId()); |
| 480 |
| 481 AnimationGroup group; |
| 482 InitGroupForView(&group, view.id(), 1); |
| 483 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), |
| 484 AnimationValuePtr(), FloatAnimationValue(.5)); |
| 485 |
| 486 gfx::Transform done_transform; |
| 487 done_transform.Scale(2, 4); |
| 488 AddTransformElement(&group, TimeDelta::FromMicroseconds(500), |
| 489 AnimationValuePtr(), |
| 490 TransformAnimationValue(done_transform)); |
| 491 |
| 492 ScheduleForSingleView(&view, &group, initial_time_); |
| 493 |
| 494 // Schedule() again, this time without animating opacity. |
| 495 group.sequences[0]->elements[0]->property = AnimationProperty::NONE; |
| 496 ScheduleForSingleView(&view, &group, initial_time_); |
| 497 |
| 498 // Opacity should go to final value. |
| 499 EXPECT_EQ(.5f, view.opacity()); |
| 500 // Transform shouldn't have changed since newly scheduled animation also has |
| 501 // transform in it. |
| 502 EXPECT_TRUE(view.transform().IsIdentity()); |
| 503 } |
| 504 |
| 505 // Opacity from 1 to .5 over 1000 of v1 and v2 transform to 2x,4x over 500. |
| 506 TEST_F(AnimationRunnerTest, TwoViews) { |
| 507 TestServerViewDelegate view_delegate; |
| 508 ServerView view1(&view_delegate, ViewId()); |
| 509 ServerView view2(&view_delegate, ViewId(1, 2)); |
| 510 |
| 511 AnimationGroup group1; |
| 512 InitGroupForView(&group1, view1.id(), 1); |
| 513 AddOpacityElement(&group1, TimeDelta::FromMicroseconds(1000), |
| 514 AnimationValuePtr(), FloatAnimationValue(.5)); |
| 515 |
| 516 AnimationGroup group2; |
| 517 InitGroupForView(&group2, view2.id(), 1); |
| 518 gfx::Transform done_transform; |
| 519 done_transform.Scale(2, 4); |
| 520 AddTransformElement(&group2, TimeDelta::FromMicroseconds(500), |
| 521 AnimationValuePtr(), |
| 522 TransformAnimationValue(done_transform)); |
| 523 |
| 524 std::vector<AnimationRunner::ViewAndAnimationPair> pairs; |
| 525 pairs.push_back(std::make_pair(&view1, &group1)); |
| 526 pairs.push_back(std::make_pair(&view2, &group2)); |
| 527 |
| 528 const uint32_t animation_id = runner_.Schedule(pairs, initial_time_); |
| 529 |
| 530 ASSERT_EQ(1u, runner_observer_.changes()->size()); |
| 531 EXPECT_EQ("scheduled", runner_observer_.changes()->at(0)); |
| 532 EXPECT_EQ(animation_id, runner_observer_.change_ids()->at(0)); |
| 533 runner_observer_.clear_changes(); |
| 534 |
| 535 EXPECT_TRUE(runner_.HasAnimations()); |
| 536 EXPECT_TRUE(runner_.IsAnimating(animation_id)); |
| 537 |
| 538 // Properties should be at the initial value. |
| 539 EXPECT_EQ(1.f, view1.opacity()); |
| 540 EXPECT_TRUE(view2.transform().IsIdentity()); |
| 541 |
| 542 // Animate 250ms in, which is quarter way for opacity and half way for |
| 543 // transform. |
| 544 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(250)); |
| 545 EXPECT_EQ(.875f, view1.opacity()); |
| 546 gfx::Transform half_way_transform; |
| 547 half_way_transform.Scale(1.5, 2.5); |
| 548 EXPECT_EQ(half_way_transform, view2.transform()); |
| 549 std::set<ServerView*> views_animating( |
| 550 runner_.GetViewsAnimating(animation_id)); |
| 551 EXPECT_EQ(2u, views_animating.size()); |
| 552 EXPECT_EQ(1u, views_animating.count(&view1)); |
| 553 EXPECT_EQ(1u, views_animating.count(&view2)); |
| 554 |
| 555 // Animate 750ms in, view1 should be done 3/4 done, and view2 done. |
| 556 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(750)); |
| 557 EXPECT_EQ(.625, view1.opacity()); |
| 558 EXPECT_EQ(done_transform, view2.transform()); |
| 559 views_animating = runner_.GetViewsAnimating(animation_id); |
| 560 EXPECT_EQ(1u, views_animating.size()); |
| 561 EXPECT_EQ(1u, views_animating.count(&view1)); |
| 562 EXPECT_TRUE(runner_.HasAnimations()); |
| 563 EXPECT_TRUE(runner_.IsAnimating(animation_id)); |
| 564 |
| 565 // Animate to end. |
| 566 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(1750)); |
| 567 EXPECT_EQ(.5, view1.opacity()); |
| 568 EXPECT_EQ(done_transform, view2.transform()); |
| 569 views_animating = runner_.GetViewsAnimating(animation_id); |
| 570 EXPECT_TRUE(views_animating.empty()); |
| 571 EXPECT_FALSE(runner_.HasAnimations()); |
| 572 EXPECT_FALSE(runner_.IsAnimating(animation_id)); |
| 573 } |
| 574 |
| 575 TEST_F(AnimationRunnerTest, Reschedule) { |
| 576 TestServerViewDelegate view_delegate; |
| 577 ServerView view(&view_delegate, ViewId()); |
| 578 |
| 579 // Animation from 1-0 over 1ms and in parallel transform to 2x,4x over 1ms. |
| 580 AnimationGroup group; |
| 581 InitGroupForView(&group, view.id(), 1); |
| 582 AddOpacityElement(&group, TimeDelta::FromMicroseconds(1000), |
| 583 AnimationValuePtr(), FloatAnimationValue(0)); |
| 584 group.sequences.push_back(AnimationSequence::New()); |
| 585 group.sequences[1]->cycle_count = 1; |
| 586 gfx::Transform done_transform; |
| 587 done_transform.Scale(2, 4); |
| 588 AddTransformElement(&group, TimeDelta::FromMicroseconds(1000), |
| 589 AnimationValuePtr(), |
| 590 TransformAnimationValue(done_transform)); |
| 591 const uint32_t animation_id1 = |
| 592 ScheduleForSingleView(&view, &group, initial_time_); |
| 593 |
| 594 // Animate half way in. |
| 595 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(500)); |
| 596 EXPECT_EQ(.5f, view.opacity()); |
| 597 gfx::Transform half_way_transform; |
| 598 half_way_transform.Scale(1.5, 2.5); |
| 599 EXPECT_EQ(half_way_transform, view.transform()); |
| 600 |
| 601 runner_observer_.clear_changes(); |
| 602 |
| 603 // Schedule the same view animating opacity to 1. |
| 604 AnimationGroup group2; |
| 605 InitGroupForView(&group2, view.id(), 1); |
| 606 AddOpacityElement(&group2, TimeDelta::FromMicroseconds(1000), |
| 607 AnimationValuePtr(), FloatAnimationValue(1)); |
| 608 const uint32_t animation_id2 = ScheduleForSingleView( |
| 609 &view, &group2, initial_time_ + TimeDelta::FromMicroseconds(500)); |
| 610 |
| 611 // Opacity should remain at .5, but transform should go to end state. |
| 612 EXPECT_EQ(.5f, view.opacity()); |
| 613 EXPECT_EQ(done_transform, view.transform()); |
| 614 |
| 615 ASSERT_EQ(2u, runner_observer_.changes()->size()); |
| 616 EXPECT_EQ("interrupted", runner_observer_.changes()->at(0)); |
| 617 EXPECT_EQ(animation_id1, runner_observer_.change_ids()->at(0)); |
| 618 EXPECT_EQ("scheduled", runner_observer_.changes()->at(1)); |
| 619 EXPECT_EQ(animation_id2, runner_observer_.change_ids()->at(1)); |
| 620 runner_observer_.clear_changes(); |
| 621 |
| 622 // Animate half way through new sequence. Opacity should be the only thing |
| 623 // changing. |
| 624 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(1000)); |
| 625 EXPECT_EQ(.75f, view.opacity()); |
| 626 EXPECT_EQ(done_transform, view.transform()); |
| 627 ASSERT_EQ(0u, runner_observer_.changes()->size()); |
| 628 |
| 629 // Animate to end. |
| 630 runner_.Tick(initial_time_ + TimeDelta::FromMicroseconds(2000)); |
| 631 ASSERT_EQ(1u, runner_observer_.changes()->size()); |
| 632 EXPECT_EQ("done", runner_observer_.changes()->at(0)); |
| 633 EXPECT_EQ(animation_id2, runner_observer_.change_ids()->at(0)); |
| 634 } |
| 635 |
| 636 } // namespace view_manager |
| OLD | NEW |