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 |