1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/animation/layer_animation_controller.h"
9 #include "cc/animation/animation.h"
10 #include "cc/animation/animation_delegate.h"
11 #include "cc/animation/animation_registrar.h"
12 #include "cc/animation/keyframed_animation_curve.h"
13 #include "cc/animation/layer_animation_value_observer.h"
14 #include "cc/animation/layer_animation_value_provider.h"
15 #include "cc/animation/scroll_offset_animation_curve.h"
16 #include "cc/base/scoped_ptr_algorithm.h"
17 #include "cc/output/filter_operations.h"
18 #include "ui/gfx/box_f.h"
19 #include "ui/gfx/transform.h"
23 LayerAnimationController::LayerAnimationController(int id
)
28 value_provider_(NULL
),
29 layer_animation_delegate_(NULL
) {}
31 LayerAnimationController::~LayerAnimationController() {
33 registrar_
->UnregisterAnimationController(this);
36 scoped_refptr
<LayerAnimationController
> LayerAnimationController::Create(
38 return make_scoped_refptr(new LayerAnimationController(id
));
41 void LayerAnimationController::PauseAnimation(int animation_id
,
43 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
44 if (active_animations_
[i
]->id() == animation_id
) {
45 active_animations_
[i
]->SetRunState(
46 Animation::Paused
, time_offset
+ active_animations_
[i
]->start_time());
51 struct HasAnimationId
{
52 explicit HasAnimationId(int id
) : id_(id
) {}
53 bool operator()(Animation
* animation
) const {
54 return animation
->id() == id_
;
61 void LayerAnimationController::RemoveAnimation(int animation_id
) {
62 ScopedPtrVector
<Animation
>& animations
= active_animations_
;
63 animations
.erase(cc::remove_if(&animations
,
66 HasAnimationId(animation_id
)),
68 UpdateActivation(NormalActivation
);
71 struct HasAnimationIdAndProperty
{
72 HasAnimationIdAndProperty(int id
, Animation::TargetProperty target_property
)
73 : id_(id
), target_property_(target_property
) {}
74 bool operator()(Animation
* animation
) const {
75 return animation
->id() == id_
&&
76 animation
->target_property() == target_property_
;
81 Animation::TargetProperty target_property_
;
84 void LayerAnimationController::RemoveAnimation(
86 Animation::TargetProperty target_property
) {
87 ScopedPtrVector
<Animation
>& animations
= active_animations_
;
89 cc::remove_if(&animations
,
92 HasAnimationIdAndProperty(animation_id
, target_property
)),
94 UpdateActivation(NormalActivation
);
97 void LayerAnimationController::AbortAnimations(
98 Animation::TargetProperty target_property
) {
99 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
100 if (active_animations_
[i
]->target_property() == target_property
&&
101 !active_animations_
[i
]->is_finished())
102 active_animations_
[i
]->SetRunState(Animation::Aborted
, last_tick_time_
);
106 // Ensures that the list of active animations on the main thread and the impl
107 // thread are kept in sync.
108 void LayerAnimationController::PushAnimationUpdatesTo(
109 LayerAnimationController
* controller_impl
) {
110 DCHECK(this != controller_impl
);
111 if (!has_any_animation() && !controller_impl
->has_any_animation())
113 PurgeAnimationsMarkedForDeletion();
114 PushNewAnimationsToImplThread(controller_impl
);
116 // Remove finished impl side animations only after pushing,
117 // and only after the animations are deleted on the main thread
118 // this insures we will never push an animation twice.
119 RemoveAnimationsCompletedOnMainThread(controller_impl
);
121 PushPropertiesToImplThread(controller_impl
);
122 controller_impl
->UpdateActivation(NormalActivation
);
123 UpdateActivation(NormalActivation
);
126 void LayerAnimationController::Animate(double monotonic_time
) {
127 DCHECK(monotonic_time
);
128 if (!HasValueObserver())
131 StartAnimations(monotonic_time
);
132 TickAnimations(monotonic_time
);
133 last_tick_time_
= monotonic_time
;
136 void LayerAnimationController::AccumulatePropertyUpdates(
137 double monotonic_time
,
138 AnimationEventsVector
* events
) {
142 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
143 Animation
* animation
= active_animations_
[i
];
144 if (!animation
->is_impl_only())
147 double trimmed
= animation
->TrimTimeToCurrentIteration(monotonic_time
);
148 switch (animation
->target_property()) {
149 case Animation::Opacity
: {
150 AnimationEvent
event(AnimationEvent::PropertyUpdate
,
155 event
.opacity
= animation
->curve()->ToFloatAnimationCurve()->GetValue(
157 event
.is_impl_only
= true;
158 events
->push_back(event
);
162 case Animation::Transform
: {
163 AnimationEvent
event(AnimationEvent::PropertyUpdate
,
166 Animation::Transform
,
169 animation
->curve()->ToTransformAnimationCurve()->GetValue(trimmed
);
170 event
.is_impl_only
= true;
171 events
->push_back(event
);
175 case Animation::Filter
: {
176 AnimationEvent
event(AnimationEvent::PropertyUpdate
,
181 event
.filters
= animation
->curve()->ToFilterAnimationCurve()->GetValue(
183 event
.is_impl_only
= true;
184 events
->push_back(event
);
188 case Animation::BackgroundColor
: { break; }
190 case Animation::ScrollOffset
: {
191 // Impl-side changes to scroll offset are already sent back to the
192 // main thread (e.g. for user-driven scrolling), so a PropertyUpdate
197 case Animation::TargetPropertyEnumSize
:
203 void LayerAnimationController::UpdateState(bool start_ready_animations
,
204 AnimationEventsVector
* events
) {
205 if (!HasActiveValueObserver())
208 if (start_ready_animations
)
209 PromoteStartedAnimations(last_tick_time_
, events
);
211 MarkFinishedAnimations(last_tick_time_
);
212 MarkAnimationsForDeletion(last_tick_time_
, events
);
214 if (start_ready_animations
) {
215 StartAnimations(last_tick_time_
);
216 PromoteStartedAnimations(last_tick_time_
, events
);
219 AccumulatePropertyUpdates(last_tick_time_
, events
);
221 UpdateActivation(NormalActivation
);
224 void LayerAnimationController::AddAnimation(scoped_ptr
<Animation
> animation
) {
225 active_animations_
.push_back(animation
.Pass());
226 UpdateActivation(NormalActivation
);
229 Animation
* LayerAnimationController::GetAnimation(
231 Animation::TargetProperty target_property
) const {
232 for (size_t i
= 0; i
< active_animations_
.size(); ++i
)
233 if (active_animations_
[i
]->group() == group_id
&&
234 active_animations_
[i
]->target_property() == target_property
)
235 return active_animations_
[i
];
239 Animation
* LayerAnimationController::GetAnimation(
240 Animation::TargetProperty target_property
) const {
241 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
242 size_t index
= active_animations_
.size() - i
- 1;
243 if (active_animations_
[index
]->target_property() == target_property
)
244 return active_animations_
[index
];
249 bool LayerAnimationController::HasActiveAnimation() const {
250 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
251 if (!active_animations_
[i
]->is_finished())
257 bool LayerAnimationController::IsAnimatingProperty(
258 Animation::TargetProperty target_property
) const {
259 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
260 if (!active_animations_
[i
]->is_finished() &&
261 active_animations_
[i
]->target_property() == target_property
)
267 void LayerAnimationController::SetAnimationRegistrar(
268 AnimationRegistrar
* registrar
) {
269 if (registrar_
== registrar
)
273 registrar_
->UnregisterAnimationController(this);
275 registrar_
= registrar
;
277 registrar_
->RegisterAnimationController(this);
279 UpdateActivation(ForceActivation
);
282 void LayerAnimationController::NotifyAnimationStarted(
283 const AnimationEvent
& event
) {
284 base::TimeTicks monotonic_time
= base::TimeTicks::FromInternalValue(
285 event
.monotonic_time
* base::Time::kMicrosecondsPerSecond
);
286 if (event
.is_impl_only
) {
287 FOR_EACH_OBSERVER(LayerAnimationEventObserver
, event_observers_
,
288 OnAnimationStarted(event
));
289 if (layer_animation_delegate_
)
290 layer_animation_delegate_
->NotifyAnimationStarted(monotonic_time
,
291 event
.target_property
);
296 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
297 if (active_animations_
[i
]->group() == event
.group_id
&&
298 active_animations_
[i
]->target_property() == event
.target_property
&&
299 active_animations_
[i
]->needs_synchronized_start_time()) {
300 active_animations_
[i
]->set_needs_synchronized_start_time(false);
301 if (!active_animations_
[i
]->has_set_start_time())
302 active_animations_
[i
]->set_start_time(event
.monotonic_time
);
304 FOR_EACH_OBSERVER(LayerAnimationEventObserver
, event_observers_
,
305 OnAnimationStarted(event
));
306 if (layer_animation_delegate_
)
307 layer_animation_delegate_
->NotifyAnimationStarted(
308 monotonic_time
, event
.target_property
);
315 void LayerAnimationController::NotifyAnimationFinished(
316 const AnimationEvent
& event
) {
317 base::TimeTicks monotonic_time
= base::TimeTicks::FromInternalValue(
318 event
.monotonic_time
* base::Time::kMicrosecondsPerSecond
);
319 if (event
.is_impl_only
) {
320 if (layer_animation_delegate_
)
321 layer_animation_delegate_
->NotifyAnimationFinished(monotonic_time
,
322 event
.target_property
);
326 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
327 if (active_animations_
[i
]->group() == event
.group_id
&&
328 active_animations_
[i
]->target_property() == event
.target_property
) {
329 active_animations_
[i
]->set_received_finished_event(true);
330 if (layer_animation_delegate_
)
331 layer_animation_delegate_
->NotifyAnimationFinished(
332 monotonic_time
, event
.target_property
);
339 void LayerAnimationController::NotifyAnimationAborted(
340 const AnimationEvent
& event
) {
341 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
342 if (active_animations_
[i
]->group() == event
.group_id
&&
343 active_animations_
[i
]->target_property() == event
.target_property
) {
344 active_animations_
[i
]->SetRunState(Animation::Aborted
,
345 event
.monotonic_time
);
350 void LayerAnimationController::NotifyAnimationPropertyUpdate(
351 const AnimationEvent
& event
) {
352 switch (event
.target_property
) {
353 case Animation::Opacity
:
354 NotifyObserversOpacityAnimated(event
.opacity
);
356 case Animation::Transform
:
357 NotifyObserversTransformAnimated(event
.transform
);
364 void LayerAnimationController::AddValueObserver(
365 LayerAnimationValueObserver
* observer
) {
366 if (!value_observers_
.HasObserver(observer
))
367 value_observers_
.AddObserver(observer
);
370 void LayerAnimationController::RemoveValueObserver(
371 LayerAnimationValueObserver
* observer
) {
372 value_observers_
.RemoveObserver(observer
);
375 void LayerAnimationController::AddEventObserver(
376 LayerAnimationEventObserver
* observer
) {
377 if (!event_observers_
.HasObserver(observer
))
378 event_observers_
.AddObserver(observer
);
381 void LayerAnimationController::RemoveEventObserver(
382 LayerAnimationEventObserver
* observer
) {
383 event_observers_
.RemoveObserver(observer
);
386 bool LayerAnimationController::HasFilterAnimationThatInflatesBounds() const {
387 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
388 if (!active_animations_
[i
]->is_finished() &&
389 active_animations_
[i
]->target_property() == Animation::Filter
&&
390 active_animations_
[i
]
392 ->ToFilterAnimationCurve()
393 ->HasFilterThatMovesPixels())
400 bool LayerAnimationController::HasTransformAnimationThatInflatesBounds() const {
401 return IsAnimatingProperty(Animation::Transform
);
404 bool LayerAnimationController::FilterAnimationBoundsForBox(
405 const gfx::BoxF
& box
, gfx::BoxF
* bounds
) const {
406 // TODO(avallee): Implement.
410 bool LayerAnimationController::TransformAnimationBoundsForBox(
411 const gfx::BoxF
& box
,
412 gfx::BoxF
* bounds
) const {
413 DCHECK(HasTransformAnimationThatInflatesBounds())
414 << "TransformAnimationBoundsForBox will give incorrect results if there "
415 << "are no transform animations affecting bounds, non-animated transform "
418 // Compute bounds based on animations for which is_finished() is false.
419 // Do nothing if there are no such animations; in this case, it is assumed
420 // that callers will take care of computing bounds based on the owning layer's
422 *bounds
= gfx::BoxF();
423 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
424 if (active_animations_
[i
]->is_finished() ||
425 active_animations_
[i
]->target_property() != Animation::Transform
)
428 const TransformAnimationCurve
* transform_animation_curve
=
429 active_animations_
[i
]->curve()->ToTransformAnimationCurve();
430 gfx::BoxF animation_bounds
;
432 transform_animation_curve
->AnimatedBoundsForBox(box
, &animation_bounds
);
435 bounds
->Union(animation_bounds
);
441 bool LayerAnimationController::HasAnimationThatAffectsScale() const {
442 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
443 if (active_animations_
[i
]->is_finished() ||
444 active_animations_
[i
]->target_property() != Animation::Transform
)
447 const TransformAnimationCurve
* transform_animation_curve
=
448 active_animations_
[i
]->curve()->ToTransformAnimationCurve();
449 if (transform_animation_curve
->AffectsScale())
456 bool LayerAnimationController::HasOnlyTranslationTransforms() const {
457 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
458 if (active_animations_
[i
]->is_finished() ||
459 active_animations_
[i
]->target_property() != Animation::Transform
)
462 const TransformAnimationCurve
* transform_animation_curve
=
463 active_animations_
[i
]->curve()->ToTransformAnimationCurve();
464 if (!transform_animation_curve
->IsTranslation())
471 bool LayerAnimationController::MaximumScale(float* max_scale
) const {
473 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
474 if (active_animations_
[i
]->is_finished() ||
475 active_animations_
[i
]->target_property() != Animation::Transform
)
478 const TransformAnimationCurve
* transform_animation_curve
=
479 active_animations_
[i
]->curve()->ToTransformAnimationCurve();
480 float animation_scale
= 0.f
;
481 if (!transform_animation_curve
->MaximumScale(&animation_scale
))
483 *max_scale
= std::max(*max_scale
, animation_scale
);
489 void LayerAnimationController::PushNewAnimationsToImplThread(
490 LayerAnimationController
* controller_impl
) const {
491 // Any new animations owned by the main thread's controller are cloned and
492 // add to the impl thread's controller.
493 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
494 // If the animation is already running on the impl thread, there is no
495 // need to copy it over.
496 if (controller_impl
->GetAnimation(active_animations_
[i
]->group(),
497 active_animations_
[i
]->target_property()))
500 // If the animation is not running on the impl thread, it does not
501 // necessarily mean that it needs to be copied over and started; it may
502 // have already finished. In this case, the impl thread animation will
503 // have already notified that it has started and the main thread animation
504 // will no longer need
505 // a synchronized start time.
506 if (!active_animations_
[i
]->needs_synchronized_start_time())
509 // Scroll animations always start at the current scroll offset.
510 if (active_animations_
[i
]->target_property() == Animation::ScrollOffset
) {
511 gfx::Vector2dF current_scroll_offset
;
512 if (controller_impl
->value_provider_
) {
513 current_scroll_offset
=
514 controller_impl
->value_provider_
->ScrollOffsetForAnimation();
516 // The owning layer isn't yet in the active tree, so the main thread
517 // scroll offset will be up-to-date.
518 current_scroll_offset
= value_provider_
->ScrollOffsetForAnimation();
520 active_animations_
[i
]->curve()->ToScrollOffsetAnimationCurve()
521 ->SetInitialValue(current_scroll_offset
);
524 // The new animation should be set to run as soon as possible.
525 Animation::RunState initial_run_state
=
526 Animation::WaitingForTargetAvailability
;
527 scoped_ptr
<Animation
> to_add(active_animations_
[i
]->CloneAndInitialize(
529 DCHECK(!to_add
->needs_synchronized_start_time());
530 controller_impl
->AddAnimation(to_add
.Pass());
535 explicit IsCompleted(const LayerAnimationController
& main_thread_controller
)
536 : main_thread_controller_(main_thread_controller
) {}
537 bool operator()(Animation
* animation
) const {
538 if (animation
->is_impl_only()) {
539 return (animation
->run_state() == Animation::WaitingForDeletion
);
541 return !main_thread_controller_
.GetAnimation(
543 animation
->target_property());
548 const LayerAnimationController
& main_thread_controller_
;
551 void LayerAnimationController::RemoveAnimationsCompletedOnMainThread(
552 LayerAnimationController
* controller_impl
) const {
553 // Delete all impl thread animations for which there is no corresponding
554 // main thread animation. Each iteration,
555 // controller->active_animations_.size() is decremented or i is incremented
556 // guaranteeing progress towards loop termination.
557 ScopedPtrVector
<Animation
>& animations
=
558 controller_impl
->active_animations_
;
559 animations
.erase(cc::remove_if(&animations
,
566 void LayerAnimationController::PushPropertiesToImplThread(
567 LayerAnimationController
* controller_impl
) const {
568 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
569 Animation
* current_impl
=
570 controller_impl
->GetAnimation(
571 active_animations_
[i
]->group(),
572 active_animations_
[i
]->target_property());
574 active_animations_
[i
]->PushPropertiesTo(current_impl
);
578 void LayerAnimationController::StartAnimations(double monotonic_time
) {
579 // First collect running properties.
580 TargetProperties blocked_properties
;
581 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
582 if (active_animations_
[i
]->run_state() == Animation::Starting
||
583 active_animations_
[i
]->run_state() == Animation::Running
)
584 blocked_properties
.insert(active_animations_
[i
]->target_property());
587 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
588 if (active_animations_
[i
]->run_state() ==
589 Animation::WaitingForTargetAvailability
) {
590 // Collect all properties for animations with the same group id (they
591 // should all also be in the list of animations).
592 TargetProperties enqueued_properties
;
593 enqueued_properties
.insert(active_animations_
[i
]->target_property());
594 for (size_t j
= i
+ 1; j
< active_animations_
.size(); ++j
) {
595 if (active_animations_
[i
]->group() == active_animations_
[j
]->group())
596 enqueued_properties
.insert(active_animations_
[j
]->target_property());
599 // Check to see if intersection of the list of properties affected by
600 // the group and the list of currently blocked properties is null. In
601 // any case, the group's target properties need to be added to the list
602 // of blocked properties.
603 bool null_intersection
= true;
604 for (TargetProperties::iterator p_iter
= enqueued_properties
.begin();
605 p_iter
!= enqueued_properties
.end();
607 if (!blocked_properties
.insert(*p_iter
).second
)
608 null_intersection
= false;
611 // If the intersection is null, then we are free to start the animations
613 if (null_intersection
) {
614 active_animations_
[i
]->SetRunState(
615 Animation::Starting
, monotonic_time
);
616 for (size_t j
= i
+ 1; j
< active_animations_
.size(); ++j
) {
617 if (active_animations_
[i
]->group() ==
618 active_animations_
[j
]->group()) {
619 active_animations_
[j
]->SetRunState(
620 Animation::Starting
, monotonic_time
);
628 void LayerAnimationController::PromoteStartedAnimations(
629 double monotonic_time
,
630 AnimationEventsVector
* events
) {
631 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
632 if (active_animations_
[i
]->run_state() == Animation::Starting
) {
633 active_animations_
[i
]->SetRunState(Animation::Running
, monotonic_time
);
634 if (!active_animations_
[i
]->has_set_start_time() &&
635 !active_animations_
[i
]->needs_synchronized_start_time())
636 active_animations_
[i
]->set_start_time(monotonic_time
);
638 AnimationEvent
started_event(
639 AnimationEvent::Started
,
641 active_animations_
[i
]->group(),
642 active_animations_
[i
]->target_property(),
644 started_event
.is_impl_only
= active_animations_
[i
]->is_impl_only();
645 events
->push_back(started_event
);
651 void LayerAnimationController::MarkFinishedAnimations(double monotonic_time
) {
652 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
653 if (active_animations_
[i
]->IsFinishedAt(monotonic_time
) &&
654 active_animations_
[i
]->run_state() != Animation::Aborted
&&
655 active_animations_
[i
]->run_state() != Animation::WaitingForDeletion
)
656 active_animations_
[i
]->SetRunState(Animation::Finished
, monotonic_time
);
660 void LayerAnimationController::MarkAnimationsForDeletion(
661 double monotonic_time
, AnimationEventsVector
* events
) {
662 bool marked_animations_for_deletions
= false;
664 // Non-aborted animations are marked for deletion after a corresponding
665 // AnimationEvent::Finished event is sent or received. This means that if
666 // we don't have an events vector, we must ensure that non-aborted animations
667 // have received a finished event before marking them for deletion.
668 for (size_t i
= 0; i
< active_animations_
.size(); i
++) {
669 int group_id
= active_animations_
[i
]->group();
670 if (active_animations_
[i
]->run_state() == Animation::Aborted
) {
671 if (events
&& !active_animations_
[i
]->is_impl_only()) {
672 AnimationEvent
aborted_event(
673 AnimationEvent::Aborted
,
676 active_animations_
[i
]->target_property(),
678 events
->push_back(aborted_event
);
680 active_animations_
[i
]->SetRunState(Animation::WaitingForDeletion
,
682 marked_animations_for_deletions
= true;
686 bool all_anims_with_same_id_are_finished
= false;
688 // Since deleting an animation on the main thread leads to its deletion
689 // on the impl thread, we only mark a Finished main thread animation for
690 // deletion once it has received a Finished event from the impl thread.
691 bool animation_i_will_send_or_has_received_finish_event
=
692 events
|| active_animations_
[i
]->received_finished_event();
693 // If an animation is finished, and not already marked for deletion,
694 // find out if all other animations in the same group are also finished.
695 if (active_animations_
[i
]->run_state() == Animation::Finished
&&
696 animation_i_will_send_or_has_received_finish_event
) {
697 all_anims_with_same_id_are_finished
= true;
698 for (size_t j
= 0; j
< active_animations_
.size(); ++j
) {
699 bool animation_j_will_send_or_has_received_finish_event
=
700 events
|| active_animations_
[j
]->received_finished_event();
701 if (group_id
== active_animations_
[j
]->group() &&
702 (!active_animations_
[j
]->is_finished() ||
703 (active_animations_
[j
]->run_state() == Animation::Finished
&&
704 !animation_j_will_send_or_has_received_finish_event
))) {
705 all_anims_with_same_id_are_finished
= false;
710 if (all_anims_with_same_id_are_finished
) {
711 // We now need to remove all animations with the same group id as
712 // group_id (and send along animation finished notifications, if
714 for (size_t j
= i
; j
< active_animations_
.size(); j
++) {
715 if (active_animations_
[j
]->group() == group_id
&&
716 active_animations_
[j
]->run_state() != Animation::Aborted
) {
718 AnimationEvent
finished_event(
719 AnimationEvent::Finished
,
721 active_animations_
[j
]->group(),
722 active_animations_
[j
]->target_property(),
724 finished_event
.is_impl_only
= active_animations_
[j
]->is_impl_only();
725 events
->push_back(finished_event
);
727 active_animations_
[j
]->SetRunState(Animation::WaitingForDeletion
,
731 marked_animations_for_deletions
= true;
734 if (marked_animations_for_deletions
)
735 NotifyObserversAnimationWaitingForDeletion();
738 static bool IsWaitingForDeletion(Animation
* animation
) {
739 return animation
->run_state() == Animation::WaitingForDeletion
;
742 void LayerAnimationController::PurgeAnimationsMarkedForDeletion() {
743 ScopedPtrVector
<Animation
>& animations
= active_animations_
;
744 animations
.erase(cc::remove_if(&animations
,
747 IsWaitingForDeletion
),
751 void LayerAnimationController::TickAnimations(double monotonic_time
) {
752 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
753 if (active_animations_
[i
]->run_state() == Animation::Starting
||
754 active_animations_
[i
]->run_state() == Animation::Running
||
755 active_animations_
[i
]->run_state() == Animation::Paused
) {
757 active_animations_
[i
]->TrimTimeToCurrentIteration(monotonic_time
);
759 switch (active_animations_
[i
]->target_property()) {
760 case Animation::Transform
: {
761 const TransformAnimationCurve
* transform_animation_curve
=
762 active_animations_
[i
]->curve()->ToTransformAnimationCurve();
763 const gfx::Transform transform
=
764 transform_animation_curve
->GetValue(trimmed
);
765 NotifyObserversTransformAnimated(transform
);
769 case Animation::Opacity
: {
770 const FloatAnimationCurve
* float_animation_curve
=
771 active_animations_
[i
]->curve()->ToFloatAnimationCurve();
772 const float opacity
= float_animation_curve
->GetValue(trimmed
);
773 NotifyObserversOpacityAnimated(opacity
);
777 case Animation::Filter
: {
778 const FilterAnimationCurve
* filter_animation_curve
=
779 active_animations_
[i
]->curve()->ToFilterAnimationCurve();
780 const FilterOperations filter
=
781 filter_animation_curve
->GetValue(trimmed
);
782 NotifyObserversFilterAnimated(filter
);
786 case Animation::BackgroundColor
: {
787 // Not yet implemented.
791 case Animation::ScrollOffset
: {
792 const ScrollOffsetAnimationCurve
* scroll_offset_animation_curve
=
793 active_animations_
[i
]->curve()->ToScrollOffsetAnimationCurve();
794 const gfx::Vector2dF scroll_offset
=
795 scroll_offset_animation_curve
->GetValue(trimmed
);
796 NotifyObserversScrollOffsetAnimated(scroll_offset
);
800 // Do nothing for sentinel value.
801 case Animation::TargetPropertyEnumSize
:
808 void LayerAnimationController::UpdateActivation(UpdateActivationType type
) {
809 bool force
= type
== ForceActivation
;
811 bool was_active
= is_active_
;
813 for (size_t i
= 0; i
< active_animations_
.size(); ++i
) {
814 if (active_animations_
[i
]->run_state() != Animation::WaitingForDeletion
) {
820 if (is_active_
&& (!was_active
|| force
))
821 registrar_
->DidActivateAnimationController(this);
822 else if (!is_active_
&& (was_active
|| force
))
823 registrar_
->DidDeactivateAnimationController(this);
827 void LayerAnimationController::NotifyObserversOpacityAnimated(float opacity
) {
828 FOR_EACH_OBSERVER(LayerAnimationValueObserver
,
830 OnOpacityAnimated(opacity
));
833 void LayerAnimationController::NotifyObserversTransformAnimated(
834 const gfx::Transform
& transform
) {
835 FOR_EACH_OBSERVER(LayerAnimationValueObserver
,
837 OnTransformAnimated(transform
));
840 void LayerAnimationController::NotifyObserversFilterAnimated(
841 const FilterOperations
& filters
) {
842 FOR_EACH_OBSERVER(LayerAnimationValueObserver
,
844 OnFilterAnimated(filters
));
847 void LayerAnimationController::NotifyObserversScrollOffsetAnimated(
848 const gfx::Vector2dF
& scroll_offset
) {
849 FOR_EACH_OBSERVER(LayerAnimationValueObserver
,
851 OnScrollOffsetAnimated(scroll_offset
));
854 void LayerAnimationController::NotifyObserversAnimationWaitingForDeletion() {
855 FOR_EACH_OBSERVER(LayerAnimationValueObserver
,
857 OnAnimationWaitingForDeletion());
860 bool LayerAnimationController::HasValueObserver() {
861 if (value_observers_
.might_have_observers()) {
862 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
864 return it
.GetNext() != NULL
;
869 bool LayerAnimationController::HasActiveValueObserver() {
870 if (value_observers_
.might_have_observers()) {
871 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
873 LayerAnimationValueObserver
* obs
;
874 while ((obs
= it
.GetNext()) != NULL
)