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