| OLD | NEW |
| (Empty) |
| 1 // Copyright 2012 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 "cc/layer_animation_controller.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 #include "cc/animation.h" | |
| 10 #include "cc/animation_registrar.h" | |
| 11 #include "cc/base/scoped_ptr_algorithm.h" | |
| 12 #include "cc/keyframed_animation_curve.h" | |
| 13 #include "cc/layer_animation_value_observer.h" | |
| 14 #include "ui/gfx/transform.h" | |
| 15 | |
| 16 namespace cc { | |
| 17 | |
| 18 LayerAnimationController::LayerAnimationController(int id) | |
| 19 : force_sync_(false), | |
| 20 registrar_(0), | |
| 21 id_(id), | |
| 22 is_active_(false), | |
| 23 last_tick_time_(0) {} | |
| 24 | |
| 25 LayerAnimationController::~LayerAnimationController() { | |
| 26 if (registrar_) | |
| 27 registrar_->UnregisterAnimationController(this); | |
| 28 } | |
| 29 | |
| 30 scoped_refptr<LayerAnimationController> LayerAnimationController::Create( | |
| 31 int id) { | |
| 32 return make_scoped_refptr(new LayerAnimationController(id)); | |
| 33 } | |
| 34 | |
| 35 void LayerAnimationController::PauseAnimation(int animation_id, | |
| 36 double time_offset) { | |
| 37 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
| 38 if (active_animations_[i]->id() == animation_id) { | |
| 39 active_animations_[i]->SetRunState( | |
| 40 Animation::Paused, time_offset + active_animations_[i]->start_time()); | |
| 41 } | |
| 42 } | |
| 43 } | |
| 44 | |
| 45 struct HasAnimationId { | |
| 46 HasAnimationId(int id) : id_(id) {} | |
| 47 bool operator()(Animation* animation) const { | |
| 48 return animation->id() == id_; | |
| 49 } | |
| 50 | |
| 51 private: | |
| 52 int id_; | |
| 53 }; | |
| 54 | |
| 55 void LayerAnimationController::RemoveAnimation(int animation_id) { | |
| 56 ScopedPtrVector<Animation>& animations = active_animations_; | |
| 57 animations.erase(cc::remove_if(animations, | |
| 58 animations.begin(), | |
| 59 animations.end(), | |
| 60 HasAnimationId(animation_id)), | |
| 61 animations.end()); | |
| 62 UpdateActivation(NormalActivation); | |
| 63 } | |
| 64 | |
| 65 struct HasAnimationIdAndProperty { | |
| 66 HasAnimationIdAndProperty(int id, Animation::TargetProperty target_property) | |
| 67 : id_(id), target_property_(target_property) {} | |
| 68 bool operator()(Animation* animation) const { | |
| 69 return animation->id() == id_ && | |
| 70 animation->target_property() == target_property_; | |
| 71 } | |
| 72 | |
| 73 private: | |
| 74 int id_; | |
| 75 Animation::TargetProperty target_property_; | |
| 76 }; | |
| 77 | |
| 78 void LayerAnimationController::RemoveAnimation( | |
| 79 int animation_id, | |
| 80 Animation::TargetProperty target_property) { | |
| 81 ScopedPtrVector<Animation>& animations = active_animations_; | |
| 82 animations.erase(cc::remove_if(animations, | |
| 83 animations.begin(), | |
| 84 animations.end(), | |
| 85 HasAnimationIdAndProperty(animation_id, | |
| 86 target_property)), | |
| 87 animations.end()); | |
| 88 UpdateActivation(NormalActivation); | |
| 89 } | |
| 90 | |
| 91 // According to render layer backing, these are for testing only. | |
| 92 void LayerAnimationController::SuspendAnimations(double monotonic_time) { | |
| 93 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
| 94 if (!active_animations_[i]->is_finished()) | |
| 95 active_animations_[i]->SetRunState(Animation::Paused, monotonic_time); | |
| 96 } | |
| 97 } | |
| 98 | |
| 99 // Looking at GraphicsLayerCA, this appears to be the analog to | |
| 100 // suspendAnimations, which is for testing. | |
| 101 void LayerAnimationController::ResumeAnimations(double monotonic_time) { | |
| 102 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
| 103 if (active_animations_[i]->run_state() == Animation::Paused) | |
| 104 active_animations_[i]->SetRunState(Animation::Running, monotonic_time); | |
| 105 } | |
| 106 } | |
| 107 | |
| 108 // Ensures that the list of active animations on the main thread and the impl | |
| 109 // thread are kept in sync. | |
| 110 void LayerAnimationController::PushAnimationUpdatesTo( | |
| 111 LayerAnimationController* controller_impl) { | |
| 112 if (force_sync_) { | |
| 113 ReplaceImplThreadAnimations(controller_impl); | |
| 114 force_sync_ = false; | |
| 115 } else { | |
| 116 PurgeAnimationsMarkedForDeletion(); | |
| 117 PushNewAnimationsToImplThread(controller_impl); | |
| 118 | |
| 119 // Remove finished impl side animations only after pushing, | |
| 120 // and only after the animations are deleted on the main thread | |
| 121 // this insures we will never push an animation twice. | |
| 122 RemoveAnimationsCompletedOnMainThread(controller_impl); | |
| 123 | |
| 124 PushPropertiesToImplThread(controller_impl); | |
| 125 } | |
| 126 controller_impl->UpdateActivation(NormalActivation); | |
| 127 UpdateActivation(NormalActivation); | |
| 128 } | |
| 129 | |
| 130 void LayerAnimationController::Animate(double monotonic_time) { | |
| 131 if (!HasActiveObserver()) | |
| 132 return; | |
| 133 | |
| 134 StartAnimationsWaitingForNextTick(monotonic_time); | |
| 135 StartAnimationsWaitingForStartTime(monotonic_time); | |
| 136 StartAnimationsWaitingForTargetAvailability(monotonic_time); | |
| 137 ResolveConflicts(monotonic_time); | |
| 138 TickAnimations(monotonic_time); | |
| 139 last_tick_time_ = monotonic_time; | |
| 140 } | |
| 141 | |
| 142 void LayerAnimationController::AccumulatePropertyUpdates( | |
| 143 double monotonic_time, | |
| 144 AnimationEventsVector* events) { | |
| 145 if (!events) | |
| 146 return; | |
| 147 | |
| 148 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
| 149 Animation* animation = active_animations_[i]; | |
| 150 if (!animation->is_impl_only()) | |
| 151 continue; | |
| 152 | |
| 153 if (animation->target_property() == Animation::Opacity) { | |
| 154 AnimationEvent event(AnimationEvent::PropertyUpdate, | |
| 155 id_, | |
| 156 animation->group(), | |
| 157 Animation::Opacity, | |
| 158 monotonic_time); | |
| 159 event.opacity = animation->curve()->ToFloatAnimationCurve()->GetValue( | |
| 160 monotonic_time); | |
| 161 | |
| 162 events->push_back(event); | |
| 163 } | |
| 164 else if (animation->target_property() == Animation::Transform) { | |
| 165 AnimationEvent event(AnimationEvent::PropertyUpdate, | |
| 166 id_, | |
| 167 animation->group(), | |
| 168 Animation::Transform, | |
| 169 monotonic_time); | |
| 170 event.transform = | |
| 171 animation->curve()->ToTransformAnimationCurve()->GetValue( | |
| 172 monotonic_time); | |
| 173 events->push_back(event); | |
| 174 } | |
| 175 } | |
| 176 } | |
| 177 | |
| 178 void LayerAnimationController::UpdateState(AnimationEventsVector* events) { | |
| 179 if (!HasActiveObserver()) | |
| 180 return; | |
| 181 | |
| 182 PromoteStartedAnimations(last_tick_time_, events); | |
| 183 MarkFinishedAnimations(last_tick_time_); | |
| 184 MarkAnimationsForDeletion(last_tick_time_, events); | |
| 185 StartAnimationsWaitingForTargetAvailability(last_tick_time_); | |
| 186 PromoteStartedAnimations(last_tick_time_, events); | |
| 187 | |
| 188 AccumulatePropertyUpdates(last_tick_time_, events); | |
| 189 | |
| 190 UpdateActivation(NormalActivation); | |
| 191 } | |
| 192 | |
| 193 void LayerAnimationController::AddAnimation(scoped_ptr<Animation> animation) { | |
| 194 active_animations_.push_back(animation.Pass()); | |
| 195 UpdateActivation(NormalActivation); | |
| 196 } | |
| 197 | |
| 198 Animation* LayerAnimationController::GetAnimation( | |
| 199 int group_id, | |
| 200 Animation::TargetProperty target_property) const { | |
| 201 for (size_t i = 0; i < active_animations_.size(); ++i) | |
| 202 if (active_animations_[i]->group() == group_id && | |
| 203 active_animations_[i]->target_property() == target_property) | |
| 204 return active_animations_[i]; | |
| 205 return 0; | |
| 206 } | |
| 207 | |
| 208 Animation* LayerAnimationController::GetAnimation( | |
| 209 Animation::TargetProperty target_property) const { | |
| 210 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
| 211 size_t index = active_animations_.size() - i - 1; | |
| 212 if (active_animations_[index]->target_property() == target_property) | |
| 213 return active_animations_[index]; | |
| 214 } | |
| 215 return 0; | |
| 216 } | |
| 217 | |
| 218 bool LayerAnimationController::HasActiveAnimation() const { | |
| 219 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
| 220 if (!active_animations_[i]->is_finished()) | |
| 221 return true; | |
| 222 } | |
| 223 return false; | |
| 224 } | |
| 225 | |
| 226 bool LayerAnimationController::IsAnimatingProperty( | |
| 227 Animation::TargetProperty target_property) const { | |
| 228 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
| 229 if (active_animations_[i]->run_state() != Animation::Finished && | |
| 230 active_animations_[i]->run_state() != Animation::Aborted && | |
| 231 active_animations_[i]->target_property() == target_property) | |
| 232 return true; | |
| 233 } | |
| 234 return false; | |
| 235 } | |
| 236 | |
| 237 void LayerAnimationController::OnAnimationStarted( | |
| 238 const AnimationEvent& event) { | |
| 239 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
| 240 if (active_animations_[i]->group() == event.group_id && | |
| 241 active_animations_[i]->target_property() == event.target_property && | |
| 242 active_animations_[i]->needs_synchronized_start_time()) { | |
| 243 active_animations_[i]->set_needs_synchronized_start_time(false); | |
| 244 active_animations_[i]->set_start_time(event.monotonic_time); | |
| 245 return; | |
| 246 } | |
| 247 } | |
| 248 } | |
| 249 | |
| 250 void LayerAnimationController::SetAnimationRegistrar( | |
| 251 AnimationRegistrar* registrar) { | |
| 252 if (registrar_ == registrar) | |
| 253 return; | |
| 254 | |
| 255 if (registrar_) | |
| 256 registrar_->UnregisterAnimationController(this); | |
| 257 | |
| 258 registrar_ = registrar; | |
| 259 if (registrar_) | |
| 260 registrar_->RegisterAnimationController(this); | |
| 261 | |
| 262 UpdateActivation(ForceActivation); | |
| 263 } | |
| 264 | |
| 265 void LayerAnimationController::AddObserver( | |
| 266 LayerAnimationValueObserver* observer) { | |
| 267 if (!observers_.HasObserver(observer)) | |
| 268 observers_.AddObserver(observer); | |
| 269 } | |
| 270 | |
| 271 void LayerAnimationController::RemoveObserver( | |
| 272 LayerAnimationValueObserver* observer) { | |
| 273 observers_.RemoveObserver(observer); | |
| 274 } | |
| 275 | |
| 276 void LayerAnimationController::PushNewAnimationsToImplThread( | |
| 277 LayerAnimationController* controller_impl) const { | |
| 278 // Any new animations owned by the main thread's controller are cloned and | |
| 279 // add to the impl thread's controller. | |
| 280 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
| 281 // If the animation is already running on the impl thread, there is no | |
| 282 // need to copy it over. | |
| 283 if (controller_impl->GetAnimation(active_animations_[i]->group(), | |
| 284 active_animations_[i]->target_property())) | |
| 285 continue; | |
| 286 | |
| 287 // If the animation is not running on the impl thread, it does not | |
| 288 // necessarily mean that it needs to be copied over and started; it may | |
| 289 // have already finished. In this case, the impl thread animation will | |
| 290 // have already notified that it has started and the main thread animation | |
| 291 // will no longer need | |
| 292 // a synchronized start time. | |
| 293 if (!active_animations_[i]->needs_synchronized_start_time()) | |
| 294 continue; | |
| 295 | |
| 296 // The new animation should be set to run as soon as possible. | |
| 297 Animation::RunState initial_run_state = | |
| 298 Animation::WaitingForTargetAvailability; | |
| 299 double start_time = 0; | |
| 300 scoped_ptr<Animation> to_add(active_animations_[i]->CloneAndInitialize( | |
| 301 Animation::ControllingInstance, initial_run_state, start_time)); | |
| 302 DCHECK(!to_add->needs_synchronized_start_time()); | |
| 303 controller_impl->AddAnimation(to_add.Pass()); | |
| 304 } | |
| 305 } | |
| 306 | |
| 307 struct IsCompleted { | |
| 308 IsCompleted(const LayerAnimationController& main_thread_controller) | |
| 309 : main_thread_controller_(main_thread_controller) {} | |
| 310 bool operator()(Animation* animation) const { | |
| 311 if (animation->is_impl_only()) | |
| 312 return false; | |
| 313 return !main_thread_controller_.GetAnimation(animation->group(), | |
| 314 animation->target_property()); | |
| 315 } | |
| 316 | |
| 317 private: | |
| 318 const LayerAnimationController& main_thread_controller_; | |
| 319 }; | |
| 320 | |
| 321 void LayerAnimationController::RemoveAnimationsCompletedOnMainThread( | |
| 322 LayerAnimationController* controller_impl) const { | |
| 323 // Delete all impl thread animations for which there is no corresponding | |
| 324 // main thread animation. Each iteration, | |
| 325 // controller->active_animations_.size() is decremented or i is incremented | |
| 326 // guaranteeing progress towards loop termination. | |
| 327 ScopedPtrVector<Animation>& animations = | |
| 328 controller_impl->active_animations_; | |
| 329 animations.erase(cc::remove_if(animations, | |
| 330 animations.begin(), | |
| 331 animations.end(), | |
| 332 IsCompleted(*this)), | |
| 333 animations.end()); | |
| 334 } | |
| 335 | |
| 336 void LayerAnimationController::PushPropertiesToImplThread( | |
| 337 LayerAnimationController* controller_impl) const { | |
| 338 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
| 339 Animation* current_impl = | |
| 340 controller_impl->GetAnimation( | |
| 341 active_animations_[i]->group(), | |
| 342 active_animations_[i]->target_property()); | |
| 343 if (current_impl) | |
| 344 active_animations_[i]->PushPropertiesTo(current_impl); | |
| 345 } | |
| 346 } | |
| 347 | |
| 348 void LayerAnimationController::StartAnimationsWaitingForNextTick( | |
| 349 double monotonic_time) { | |
| 350 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
| 351 if (active_animations_[i]->run_state() == Animation::WaitingForNextTick) | |
| 352 active_animations_[i]->SetRunState(Animation::Starting, monotonic_time); | |
| 353 } | |
| 354 } | |
| 355 | |
| 356 void LayerAnimationController::StartAnimationsWaitingForStartTime( | |
| 357 double monotonic_time) { | |
| 358 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
| 359 if (active_animations_[i]->run_state() == Animation::WaitingForStartTime && | |
| 360 active_animations_[i]->start_time() <= monotonic_time) | |
| 361 active_animations_[i]->SetRunState(Animation::Starting, monotonic_time); | |
| 362 } | |
| 363 } | |
| 364 | |
| 365 void LayerAnimationController::StartAnimationsWaitingForTargetAvailability( | |
| 366 double monotonic_time) { | |
| 367 // First collect running properties. | |
| 368 TargetProperties blocked_properties; | |
| 369 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
| 370 if (active_animations_[i]->run_state() == Animation::Starting || | |
| 371 active_animations_[i]->run_state() == Animation::Running || | |
| 372 active_animations_[i]->run_state() == Animation::Finished) | |
| 373 blocked_properties.insert(active_animations_[i]->target_property()); | |
| 374 } | |
| 375 | |
| 376 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
| 377 if (active_animations_[i]->run_state() == | |
| 378 Animation::WaitingForTargetAvailability) { | |
| 379 // Collect all properties for animations with the same group id (they | |
| 380 // should all also be in the list of animations). | |
| 381 TargetProperties enqueued_properties; | |
| 382 enqueued_properties.insert(active_animations_[i]->target_property()); | |
| 383 for (size_t j = i + 1; j < active_animations_.size(); ++j) { | |
| 384 if (active_animations_[i]->group() == active_animations_[j]->group()) | |
| 385 enqueued_properties.insert(active_animations_[j]->target_property()); | |
| 386 } | |
| 387 | |
| 388 // Check to see if intersection of the list of properties affected by | |
| 389 // the group and the list of currently blocked properties is null. In | |
| 390 // any case, the group's target properties need to be added to the list | |
| 391 // of blocked properties. | |
| 392 bool null_intersection = true; | |
| 393 for (TargetProperties::iterator p_iter = enqueued_properties.begin(); | |
| 394 p_iter != enqueued_properties.end(); | |
| 395 ++p_iter) { | |
| 396 if (!blocked_properties.insert(*p_iter).second) | |
| 397 null_intersection = false; | |
| 398 } | |
| 399 | |
| 400 // If the intersection is null, then we are free to start the animations | |
| 401 // in the group. | |
| 402 if (null_intersection) { | |
| 403 active_animations_[i]->SetRunState( | |
| 404 Animation::Starting, monotonic_time); | |
| 405 for (size_t j = i + 1; j < active_animations_.size(); ++j) { | |
| 406 if (active_animations_[i]->group() == | |
| 407 active_animations_[j]->group()) { | |
| 408 active_animations_[j]->SetRunState( | |
| 409 Animation::Starting, monotonic_time); | |
| 410 } | |
| 411 } | |
| 412 } | |
| 413 } | |
| 414 } | |
| 415 } | |
| 416 | |
| 417 void LayerAnimationController::PromoteStartedAnimations( | |
| 418 double monotonic_time, | |
| 419 AnimationEventsVector* events) { | |
| 420 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
| 421 if (active_animations_[i]->run_state() == Animation::Starting) { | |
| 422 active_animations_[i]->SetRunState(Animation::Running, monotonic_time); | |
| 423 if (!active_animations_[i]->has_set_start_time()) | |
| 424 active_animations_[i]->set_start_time(monotonic_time); | |
| 425 if (events) { | |
| 426 events->push_back(AnimationEvent( | |
| 427 AnimationEvent::Started, | |
| 428 id_, | |
| 429 active_animations_[i]->group(), | |
| 430 active_animations_[i]->target_property(), | |
| 431 monotonic_time)); | |
| 432 } | |
| 433 } | |
| 434 } | |
| 435 } | |
| 436 | |
| 437 void LayerAnimationController::MarkFinishedAnimations(double monotonic_time) { | |
| 438 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
| 439 if (active_animations_[i]->IsFinishedAt(monotonic_time)) | |
| 440 active_animations_[i]->SetRunState(Animation::Finished, monotonic_time); | |
| 441 } | |
| 442 } | |
| 443 | |
| 444 void LayerAnimationController::ResolveConflicts(double monotonic_time) { | |
| 445 // Find any animations that are animating the same property and resolve the | |
| 446 // confict. We could eventually blend, but for now we'll just abort the | |
| 447 // previous animation (where 'previous' means: (1) has a prior start time or | |
| 448 // (2) has an equal start time, but was added to the queue earlier, i.e., | |
| 449 // has a lower index in active_animations_). | |
| 450 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
| 451 if (active_animations_[i]->run_state() == Animation::Starting || | |
| 452 active_animations_[i]->run_state() == Animation::Running) { | |
| 453 for (size_t j = i + 1; j < active_animations_.size(); ++j) { | |
| 454 if ((active_animations_[j]->run_state() == Animation::Starting || | |
| 455 active_animations_[j]->run_state() == Animation::Running) && | |
| 456 active_animations_[i]->target_property() == | |
| 457 active_animations_[j]->target_property()) { | |
| 458 if (active_animations_[i]->start_time() > | |
| 459 active_animations_[j]->start_time()) { | |
| 460 active_animations_[j]->SetRunState(Animation::Aborted, | |
| 461 monotonic_time); | |
| 462 } else { | |
| 463 active_animations_[i]->SetRunState(Animation::Aborted, | |
| 464 monotonic_time); | |
| 465 } | |
| 466 } | |
| 467 } | |
| 468 } | |
| 469 } | |
| 470 } | |
| 471 | |
| 472 void LayerAnimationController::MarkAnimationsForDeletion( | |
| 473 double monotonic_time, AnimationEventsVector* events) { | |
| 474 for (size_t i = 0; i < active_animations_.size(); i++) { | |
| 475 int group_id = active_animations_[i]->group(); | |
| 476 bool all_anims_with_same_id_are_finished = false; | |
| 477 // If an animation is finished, and not already marked for deletion, | |
| 478 // Find out if all other animations in the same group are also finished. | |
| 479 if (active_animations_[i]->is_finished() && | |
| 480 active_animations_[i]->run_state() != Animation::WaitingForDeletion) { | |
| 481 all_anims_with_same_id_are_finished = true; | |
| 482 for (size_t j = 0; j < active_animations_.size(); ++j) { | |
| 483 if (group_id == active_animations_[j]->group() && | |
| 484 !active_animations_[j]->is_finished()) { | |
| 485 all_anims_with_same_id_are_finished = false; | |
| 486 break; | |
| 487 } | |
| 488 } | |
| 489 } | |
| 490 if (all_anims_with_same_id_are_finished) { | |
| 491 // We now need to remove all animations with the same group id as | |
| 492 // group_id (and send along animation finished notifications, if | |
| 493 // necessary). | |
| 494 for (size_t j = i; j < active_animations_.size(); j++) { | |
| 495 if (group_id == active_animations_[j]->group()) { | |
| 496 if (events) { | |
| 497 events->push_back(AnimationEvent( | |
| 498 AnimationEvent::Finished, | |
| 499 id_, | |
| 500 active_animations_[j]->group(), | |
| 501 active_animations_[j]->target_property(), | |
| 502 monotonic_time)); | |
| 503 } | |
| 504 active_animations_[j]->SetRunState(Animation::WaitingForDeletion, | |
| 505 monotonic_time); | |
| 506 } | |
| 507 } | |
| 508 } | |
| 509 } | |
| 510 } | |
| 511 | |
| 512 static bool IsWaitingForDeletion(Animation* animation) { | |
| 513 return animation->run_state() == Animation::WaitingForDeletion; | |
| 514 } | |
| 515 | |
| 516 void LayerAnimationController::PurgeAnimationsMarkedForDeletion() { | |
| 517 ScopedPtrVector<Animation>& animations = active_animations_; | |
| 518 animations.erase(cc::remove_if(animations, | |
| 519 animations.begin(), | |
| 520 animations.end(), | |
| 521 IsWaitingForDeletion), | |
| 522 animations.end()); | |
| 523 } | |
| 524 | |
| 525 void LayerAnimationController::ReplaceImplThreadAnimations( | |
| 526 LayerAnimationController* controller_impl) const { | |
| 527 controller_impl->active_animations_.clear(); | |
| 528 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
| 529 scoped_ptr<Animation> to_add; | |
| 530 if (active_animations_[i]->needs_synchronized_start_time()) { | |
| 531 // We haven't received an animation started notification yet, so it | |
| 532 // is important that we add it in a 'waiting' and not 'running' state. | |
| 533 Animation::RunState initial_run_state = | |
| 534 Animation::WaitingForTargetAvailability; | |
| 535 double start_time = 0; | |
| 536 to_add = active_animations_[i]->CloneAndInitialize( | |
| 537 Animation::ControllingInstance, | |
| 538 initial_run_state, start_time).Pass(); | |
| 539 } else { | |
| 540 to_add = active_animations_[i]->Clone( | |
| 541 Animation::ControllingInstance).Pass(); | |
| 542 } | |
| 543 | |
| 544 controller_impl->AddAnimation(to_add.Pass()); | |
| 545 } | |
| 546 } | |
| 547 | |
| 548 void LayerAnimationController::TickAnimations(double monotonic_time) { | |
| 549 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
| 550 if (active_animations_[i]->run_state() == Animation::Starting || | |
| 551 active_animations_[i]->run_state() == Animation::Running || | |
| 552 active_animations_[i]->run_state() == Animation::Paused) { | |
| 553 double trimmed = | |
| 554 active_animations_[i]->TrimTimeToCurrentIteration(monotonic_time); | |
| 555 | |
| 556 // Animation assumes its initial value until it gets the synchronized | |
| 557 // start time from the impl thread and can start ticking. | |
| 558 if (active_animations_[i]->needs_synchronized_start_time()) | |
| 559 trimmed = 0; | |
| 560 | |
| 561 // A just-started animation assumes its initial value. | |
| 562 if (active_animations_[i]->run_state() == Animation::Starting && | |
| 563 !active_animations_[i]->has_set_start_time()) | |
| 564 trimmed = 0; | |
| 565 | |
| 566 switch (active_animations_[i]->target_property()) { | |
| 567 | |
| 568 case Animation::Transform: { | |
| 569 const TransformAnimationCurve* transform_animation_curve = | |
| 570 active_animations_[i]->curve()->ToTransformAnimationCurve(); | |
| 571 const gfx::Transform transform = | |
| 572 transform_animation_curve->GetValue(trimmed); | |
| 573 NotifyObserversTransformAnimated(transform); | |
| 574 break; | |
| 575 } | |
| 576 | |
| 577 case Animation::Opacity: { | |
| 578 const FloatAnimationCurve* float_animation_curve = | |
| 579 active_animations_[i]->curve()->ToFloatAnimationCurve(); | |
| 580 const float opacity = float_animation_curve->GetValue(trimmed); | |
| 581 NotifyObserversOpacityAnimated(opacity); | |
| 582 break; | |
| 583 } | |
| 584 | |
| 585 // Do nothing for sentinel value. | |
| 586 case Animation::TargetPropertyEnumSize: | |
| 587 NOTREACHED(); | |
| 588 } | |
| 589 } | |
| 590 } | |
| 591 } | |
| 592 | |
| 593 void LayerAnimationController::UpdateActivation(UpdateActivationType type) { | |
| 594 bool force = type == ForceActivation; | |
| 595 if (registrar_) { | |
| 596 if (!active_animations_.empty() && (!is_active_ || force)) | |
| 597 registrar_->DidActivateAnimationController(this); | |
| 598 else if (active_animations_.empty() && (is_active_ || force)) | |
| 599 registrar_->DidDeactivateAnimationController(this); | |
| 600 is_active_ = !active_animations_.empty(); | |
| 601 } | |
| 602 } | |
| 603 | |
| 604 void LayerAnimationController::NotifyObserversOpacityAnimated(float opacity) { | |
| 605 FOR_EACH_OBSERVER(LayerAnimationValueObserver, | |
| 606 observers_, | |
| 607 OnOpacityAnimated(opacity)); | |
| 608 } | |
| 609 | |
| 610 void LayerAnimationController::NotifyObserversTransformAnimated( | |
| 611 const gfx::Transform& transform) { | |
| 612 FOR_EACH_OBSERVER(LayerAnimationValueObserver, | |
| 613 observers_, | |
| 614 OnTransformAnimated(transform)); | |
| 615 } | |
| 616 | |
| 617 bool LayerAnimationController::HasActiveObserver() { | |
| 618 if (observers_.might_have_observers()) { | |
| 619 ObserverListBase<LayerAnimationValueObserver>::Iterator it(observers_); | |
| 620 LayerAnimationValueObserver* obs; | |
| 621 while ((obs = it.GetNext()) != NULL) | |
| 622 if (obs->IsActive()) | |
| 623 return true; | |
| 624 } | |
| 625 return false; | |
| 626 } | |
| 627 | |
| 628 } // namespace cc | |
| OLD | NEW |