| 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 |