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