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
)
27 value_provider_(NULL
),
28 layer_animation_delegate_(NULL
),
29 needs_to_start_animations_(false) {
32 LayerAnimationController::~LayerAnimationController() {
34 registrar_
->UnregisterAnimationController(this);
37 scoped_refptr
<LayerAnimationController
> LayerAnimationController::Create(
39 return make_scoped_refptr(new LayerAnimationController(id
));
42 void LayerAnimationController::PauseAnimation(int animation_id
,
43 base::TimeDelta time_offset
) {
44 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
45 if (animations_
[i
]->id() == animation_id
) {
46 animations_
[i
]->SetRunState(Animation::Paused
,
47 time_offset
+ animations_
[i
]->start_time());
52 struct HasAnimationId
{
53 explicit HasAnimationId(int id
) : id_(id
) {}
54 bool operator()(Animation
* animation
) const {
55 return animation
->id() == id_
;
62 void LayerAnimationController::RemoveAnimation(int animation_id
) {
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
) {
88 cc::remove_if(&animations_
,
91 HasAnimationIdAndProperty(animation_id
, target_property
)),
93 UpdateActivation(NormalActivation
);
96 void LayerAnimationController::AbortAnimations(
97 Animation::TargetProperty target_property
) {
98 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
99 if (animations_
[i
]->target_property() == target_property
&&
100 !animations_
[i
]->is_finished())
101 animations_
[i
]->SetRunState(Animation::Aborted
, last_tick_time_
);
105 // Ensures that the list of active animations on the main thread and the impl
106 // thread are kept in sync.
107 void LayerAnimationController::PushAnimationUpdatesTo(
108 LayerAnimationController
* controller_impl
) {
109 DCHECK(this != controller_impl
);
110 if (!has_any_animation() && !controller_impl
->has_any_animation())
112 PurgeAnimationsMarkedForDeletion();
113 PushNewAnimationsToImplThread(controller_impl
);
115 // Remove finished impl side animations only after pushing,
116 // and only after the animations are deleted on the main thread
117 // this insures we will never push an animation twice.
118 RemoveAnimationsCompletedOnMainThread(controller_impl
);
120 PushPropertiesToImplThread(controller_impl
);
121 controller_impl
->UpdateActivation(NormalActivation
);
122 UpdateActivation(NormalActivation
);
125 void LayerAnimationController::Animate(base::TimeTicks monotonic_time
) {
126 DCHECK(!monotonic_time
.is_null());
127 if (!HasValueObserver())
130 if (needs_to_start_animations_
)
131 StartAnimations(monotonic_time
);
132 TickAnimations(monotonic_time
);
133 last_tick_time_
= monotonic_time
;
136 void LayerAnimationController::AccumulatePropertyUpdates(
137 base::TimeTicks monotonic_time
,
138 AnimationEventsVector
* events
) {
142 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
143 Animation
* animation
= animations_
[i
];
144 if (!animation
->is_impl_only())
147 if (!animation
->InEffect(monotonic_time
))
150 double trimmed
= animation
->TrimTimeToCurrentIteration(monotonic_time
);
151 switch (animation
->target_property()) {
152 case Animation::Opacity
: {
153 AnimationEvent
event(AnimationEvent::PropertyUpdate
,
158 const FloatAnimationCurve
* float_animation_curve
=
159 animation
->curve()->ToFloatAnimationCurve();
160 event
.opacity
= float_animation_curve
->GetValue(trimmed
);
161 event
.is_impl_only
= true;
162 events
->push_back(event
);
166 case Animation::Transform
: {
167 AnimationEvent
event(AnimationEvent::PropertyUpdate
,
170 Animation::Transform
,
172 const TransformAnimationCurve
* transform_animation_curve
=
173 animation
->curve()->ToTransformAnimationCurve();
174 event
.transform
= transform_animation_curve
->GetValue(trimmed
);
175 event
.is_impl_only
= true;
176 events
->push_back(event
);
180 case Animation::Filter
: {
181 AnimationEvent
event(AnimationEvent::PropertyUpdate
,
186 const FilterAnimationCurve
* filter_animation_curve
=
187 animation
->curve()->ToFilterAnimationCurve();
188 event
.filters
= filter_animation_curve
->GetValue(trimmed
);
189 event
.is_impl_only
= true;
190 events
->push_back(event
);
194 case Animation::BackgroundColor
: { break; }
196 case Animation::ScrollOffset
: {
197 // Impl-side changes to scroll offset are already sent back to the
198 // main thread (e.g. for user-driven scrolling), so a PropertyUpdate
203 case Animation::TargetPropertyEnumSize
:
209 void LayerAnimationController::UpdateState(bool start_ready_animations
,
210 AnimationEventsVector
* events
) {
211 if (!HasActiveValueObserver())
214 DCHECK(last_tick_time_
!= base::TimeTicks());
215 if (start_ready_animations
)
216 PromoteStartedAnimations(last_tick_time_
, events
);
218 MarkFinishedAnimations(last_tick_time_
);
219 MarkAnimationsForDeletion(last_tick_time_
, events
);
221 if (needs_to_start_animations_
&& start_ready_animations
) {
222 StartAnimations(last_tick_time_
);
223 PromoteStartedAnimations(last_tick_time_
, events
);
226 AccumulatePropertyUpdates(last_tick_time_
, events
);
228 UpdateActivation(NormalActivation
);
231 struct AffectsNoObservers
{
232 bool operator()(Animation
* animation
) const {
233 return !animation
->affects_active_observers() &&
234 !animation
->affects_pending_observers();
238 void LayerAnimationController::ActivateAnimations() {
239 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
240 animations_
[i
]->set_affects_active_observers(
241 animations_
[i
]->affects_pending_observers());
243 animations_
.erase(cc::remove_if(&animations_
,
246 AffectsNoObservers()),
248 UpdateActivation(NormalActivation
);
251 void LayerAnimationController::AddAnimation(scoped_ptr
<Animation
> animation
) {
252 animations_
.push_back(animation
.Pass());
253 needs_to_start_animations_
= true;
254 UpdateActivation(NormalActivation
);
257 Animation
* LayerAnimationController::GetAnimation(
259 Animation::TargetProperty target_property
) const {
260 for (size_t i
= 0; i
< animations_
.size(); ++i
)
261 if (animations_
[i
]->group() == group_id
&&
262 animations_
[i
]->target_property() == target_property
)
263 return animations_
[i
];
267 Animation
* LayerAnimationController::GetAnimation(
268 Animation::TargetProperty target_property
) const {
269 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
270 size_t index
= animations_
.size() - i
- 1;
271 if (animations_
[index
]->target_property() == target_property
)
272 return animations_
[index
];
277 bool LayerAnimationController::HasActiveAnimation() const {
278 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
279 if (!animations_
[i
]->is_finished())
285 bool LayerAnimationController::IsAnimatingProperty(
286 Animation::TargetProperty target_property
) const {
287 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
288 if (!animations_
[i
]->is_finished() &&
289 animations_
[i
]->target_property() == target_property
)
295 void LayerAnimationController::SetAnimationRegistrar(
296 AnimationRegistrar
* registrar
) {
297 if (registrar_
== registrar
)
301 registrar_
->UnregisterAnimationController(this);
303 registrar_
= registrar
;
305 registrar_
->RegisterAnimationController(this);
307 UpdateActivation(ForceActivation
);
310 void LayerAnimationController::NotifyAnimationStarted(
311 const AnimationEvent
& event
) {
312 if (event
.is_impl_only
) {
313 FOR_EACH_OBSERVER(LayerAnimationEventObserver
, event_observers_
,
314 OnAnimationStarted(event
));
315 if (layer_animation_delegate_
)
316 layer_animation_delegate_
->NotifyAnimationStarted(event
.monotonic_time
,
317 event
.target_property
);
321 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
322 if (animations_
[i
]->group() == event
.group_id
&&
323 animations_
[i
]->target_property() == event
.target_property
&&
324 animations_
[i
]->needs_synchronized_start_time()) {
325 animations_
[i
]->set_needs_synchronized_start_time(false);
326 if (!animations_
[i
]->has_set_start_time())
327 animations_
[i
]->set_start_time(event
.monotonic_time
);
329 FOR_EACH_OBSERVER(LayerAnimationEventObserver
, event_observers_
,
330 OnAnimationStarted(event
));
331 if (layer_animation_delegate_
)
332 layer_animation_delegate_
->NotifyAnimationStarted(
333 event
.monotonic_time
, event
.target_property
);
340 void LayerAnimationController::NotifyAnimationFinished(
341 const AnimationEvent
& event
) {
342 if (event
.is_impl_only
) {
343 if (layer_animation_delegate_
)
344 layer_animation_delegate_
->NotifyAnimationFinished(event
.monotonic_time
,
345 event
.target_property
);
349 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
350 if (animations_
[i
]->group() == event
.group_id
&&
351 animations_
[i
]->target_property() == event
.target_property
) {
352 animations_
[i
]->set_received_finished_event(true);
353 if (layer_animation_delegate_
)
354 layer_animation_delegate_
->NotifyAnimationFinished(
355 event
.monotonic_time
, event
.target_property
);
362 void LayerAnimationController::NotifyAnimationAborted(
363 const AnimationEvent
& event
) {
364 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
365 if (animations_
[i
]->group() == event
.group_id
&&
366 animations_
[i
]->target_property() == event
.target_property
) {
367 animations_
[i
]->SetRunState(Animation::Aborted
, event
.monotonic_time
);
372 void LayerAnimationController::NotifyAnimationPropertyUpdate(
373 const AnimationEvent
& event
) {
374 bool notify_active_observers
= true;
375 bool notify_pending_observers
= true;
376 switch (event
.target_property
) {
377 case Animation::Opacity
:
378 NotifyObserversOpacityAnimated(
379 event
.opacity
, notify_active_observers
, notify_pending_observers
);
381 case Animation::Transform
:
382 NotifyObserversTransformAnimated(
383 event
.transform
, notify_active_observers
, notify_pending_observers
);
390 void LayerAnimationController::AddValueObserver(
391 LayerAnimationValueObserver
* observer
) {
392 if (!value_observers_
.HasObserver(observer
))
393 value_observers_
.AddObserver(observer
);
396 void LayerAnimationController::RemoveValueObserver(
397 LayerAnimationValueObserver
* observer
) {
398 value_observers_
.RemoveObserver(observer
);
401 void LayerAnimationController::AddEventObserver(
402 LayerAnimationEventObserver
* observer
) {
403 if (!event_observers_
.HasObserver(observer
))
404 event_observers_
.AddObserver(observer
);
407 void LayerAnimationController::RemoveEventObserver(
408 LayerAnimationEventObserver
* observer
) {
409 event_observers_
.RemoveObserver(observer
);
412 bool LayerAnimationController::HasFilterAnimationThatInflatesBounds() const {
413 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
414 if (!animations_
[i
]->is_finished() &&
415 animations_
[i
]->target_property() == Animation::Filter
&&
418 ->ToFilterAnimationCurve()
419 ->HasFilterThatMovesPixels())
426 bool LayerAnimationController::HasTransformAnimationThatInflatesBounds() const {
427 return IsAnimatingProperty(Animation::Transform
);
430 bool LayerAnimationController::FilterAnimationBoundsForBox(
431 const gfx::BoxF
& box
, gfx::BoxF
* bounds
) const {
432 // TODO(avallee): Implement.
436 bool LayerAnimationController::TransformAnimationBoundsForBox(
437 const gfx::BoxF
& box
,
438 gfx::BoxF
* bounds
) const {
439 DCHECK(HasTransformAnimationThatInflatesBounds())
440 << "TransformAnimationBoundsForBox will give incorrect results if there "
441 << "are no transform animations affecting bounds, non-animated transform "
444 // Compute bounds based on animations for which is_finished() is false.
445 // Do nothing if there are no such animations; in this case, it is assumed
446 // that callers will take care of computing bounds based on the owning layer's
448 *bounds
= gfx::BoxF();
449 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
450 if (animations_
[i
]->is_finished() ||
451 animations_
[i
]->target_property() != Animation::Transform
)
454 const TransformAnimationCurve
* transform_animation_curve
=
455 animations_
[i
]->curve()->ToTransformAnimationCurve();
456 gfx::BoxF animation_bounds
;
458 transform_animation_curve
->AnimatedBoundsForBox(box
, &animation_bounds
);
461 bounds
->Union(animation_bounds
);
467 bool LayerAnimationController::HasAnimationThatAffectsScale() const {
468 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
469 if (animations_
[i
]->is_finished() ||
470 animations_
[i
]->target_property() != Animation::Transform
)
473 const TransformAnimationCurve
* transform_animation_curve
=
474 animations_
[i
]->curve()->ToTransformAnimationCurve();
475 if (transform_animation_curve
->AffectsScale())
482 bool LayerAnimationController::HasOnlyTranslationTransforms() const {
483 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
484 if (animations_
[i
]->is_finished() ||
485 animations_
[i
]->target_property() != Animation::Transform
)
488 const TransformAnimationCurve
* transform_animation_curve
=
489 animations_
[i
]->curve()->ToTransformAnimationCurve();
490 if (!transform_animation_curve
->IsTranslation())
497 bool LayerAnimationController::MaximumScale(float* max_scale
) const {
499 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
500 if (animations_
[i
]->is_finished() ||
501 animations_
[i
]->target_property() != Animation::Transform
)
504 const TransformAnimationCurve
* transform_animation_curve
=
505 animations_
[i
]->curve()->ToTransformAnimationCurve();
506 float animation_scale
= 0.f
;
507 if (!transform_animation_curve
->MaximumScale(&animation_scale
))
509 *max_scale
= std::max(*max_scale
, animation_scale
);
515 void LayerAnimationController::PushNewAnimationsToImplThread(
516 LayerAnimationController
* controller_impl
) const {
517 // Any new animations owned by the main thread's controller are cloned and
518 // add to the impl thread's controller.
519 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
520 // If the animation is already running on the impl thread, there is no
521 // need to copy it over.
522 if (controller_impl
->GetAnimation(animations_
[i
]->group(),
523 animations_
[i
]->target_property()))
526 // If the animation is not running on the impl thread, it does not
527 // necessarily mean that it needs to be copied over and started; it may
528 // have already finished. In this case, the impl thread animation will
529 // have already notified that it has started and the main thread animation
530 // will no longer need
531 // a synchronized start time.
532 if (!animations_
[i
]->needs_synchronized_start_time())
535 // Scroll animations always start at the current scroll offset.
536 if (animations_
[i
]->target_property() == Animation::ScrollOffset
) {
537 gfx::Vector2dF current_scroll_offset
;
538 if (controller_impl
->value_provider_
) {
539 current_scroll_offset
=
540 controller_impl
->value_provider_
->ScrollOffsetForAnimation();
542 // The owning layer isn't yet in the active tree, so the main thread
543 // scroll offset will be up-to-date.
544 current_scroll_offset
= value_provider_
->ScrollOffsetForAnimation();
546 animations_
[i
]->curve()->ToScrollOffsetAnimationCurve()->SetInitialValue(
547 current_scroll_offset
);
550 // The new animation should be set to run as soon as possible.
551 Animation::RunState initial_run_state
=
552 Animation::WaitingForTargetAvailability
;
553 scoped_ptr
<Animation
> to_add(
554 animations_
[i
]->CloneAndInitialize(initial_run_state
));
555 DCHECK(!to_add
->needs_synchronized_start_time());
556 to_add
->set_affects_active_observers(false);
557 controller_impl
->AddAnimation(to_add
.Pass());
561 static bool IsCompleted(
562 Animation
* animation
,
563 const LayerAnimationController
* main_thread_controller
) {
564 if (animation
->is_impl_only()) {
565 return (animation
->run_state() == Animation::WaitingForDeletion
);
567 return !main_thread_controller
->GetAnimation(animation
->group(),
568 animation
->target_property());
572 static bool AffectsActiveOnlyAndIsWaitingForDeletion(Animation
* animation
) {
573 return animation
->run_state() == Animation::WaitingForDeletion
&&
574 !animation
->affects_pending_observers();
577 void LayerAnimationController::RemoveAnimationsCompletedOnMainThread(
578 LayerAnimationController
* controller_impl
) const {
579 // Animations removed on the main thread should no longer affect pending
580 // observers, and should stop affecting active observers after the next call
581 // to ActivateAnimations. If already WaitingForDeletion, they can be removed
583 ScopedPtrVector
<Animation
>& animations
= controller_impl
->animations_
;
584 for (size_t i
= 0; i
< animations
.size(); ++i
) {
585 if (IsCompleted(animations
[i
], this))
586 animations
[i
]->set_affects_pending_observers(false);
588 animations
.erase(cc::remove_if(&animations
,
591 AffectsActiveOnlyAndIsWaitingForDeletion
),
595 void LayerAnimationController::PushPropertiesToImplThread(
596 LayerAnimationController
* controller_impl
) const {
597 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
598 Animation
* current_impl
= controller_impl
->GetAnimation(
599 animations_
[i
]->group(), animations_
[i
]->target_property());
601 animations_
[i
]->PushPropertiesTo(current_impl
);
605 void LayerAnimationController::StartAnimations(base::TimeTicks monotonic_time
) {
606 DCHECK(needs_to_start_animations_
);
607 needs_to_start_animations_
= false;
608 // First collect running properties affecting each type of observer.
609 TargetProperties blocked_properties_for_active_observers
;
610 TargetProperties blocked_properties_for_pending_observers
;
611 std::vector
<size_t> animations_waiting_for_target
;
613 animations_waiting_for_target
.reserve(animations_
.size());
614 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
615 if (animations_
[i
]->run_state() == Animation::Starting
||
616 animations_
[i
]->run_state() == Animation::Running
) {
617 if (animations_
[i
]->affects_active_observers()) {
618 blocked_properties_for_active_observers
.insert(
619 animations_
[i
]->target_property());
621 if (animations_
[i
]->affects_pending_observers()) {
622 blocked_properties_for_pending_observers
.insert(
623 animations_
[i
]->target_property());
625 } else if (animations_
[i
]->run_state() ==
626 Animation::WaitingForTargetAvailability
) {
627 animations_waiting_for_target
.push_back(i
);
631 for (size_t i
= 0; i
< animations_waiting_for_target
.size(); ++i
) {
632 // Collect all properties for animations with the same group id (they
633 // should all also be in the list of animations).
634 size_t animation_index
= animations_waiting_for_target
[i
];
635 Animation
* animation_waiting_for_target
= animations_
[animation_index
];
636 // Check for the run state again even though the animation was waiting
637 // for target because it might have changed the run state while handling
638 // previous animation in this loop (if they belong to same group).
639 if (animation_waiting_for_target
->run_state() ==
640 Animation::WaitingForTargetAvailability
) {
641 TargetProperties enqueued_properties
;
642 bool affects_active_observers
=
643 animation_waiting_for_target
->affects_active_observers();
644 bool affects_pending_observers
=
645 animation_waiting_for_target
->affects_pending_observers();
646 enqueued_properties
.insert(
647 animation_waiting_for_target
->target_property());
648 for (size_t j
= animation_index
+ 1; j
< animations_
.size(); ++j
) {
649 if (animation_waiting_for_target
->group() == animations_
[j
]->group()) {
650 enqueued_properties
.insert(animations_
[j
]->target_property());
651 affects_active_observers
|=
652 animations_
[j
]->affects_active_observers();
653 affects_pending_observers
|=
654 animations_
[j
]->affects_pending_observers();
658 // Check to see if intersection of the list of properties affected by
659 // the group and the list of currently blocked properties is null, taking
660 // into account the type(s) of observers affected by the group. In any
661 // case, the group's target properties need to be added to the lists of
662 // blocked properties.
663 bool null_intersection
= true;
664 for (TargetProperties::iterator p_iter
= enqueued_properties
.begin();
665 p_iter
!= enqueued_properties
.end();
667 if (affects_active_observers
&&
668 !blocked_properties_for_active_observers
.insert(*p_iter
).second
)
669 null_intersection
= false;
670 if (affects_pending_observers
&&
671 !blocked_properties_for_pending_observers
.insert(*p_iter
).second
)
672 null_intersection
= false;
675 // If the intersection is null, then we are free to start the animations
677 if (null_intersection
) {
678 animation_waiting_for_target
->SetRunState(Animation::Starting
,
680 for (size_t j
= animation_index
+ 1; j
< animations_
.size(); ++j
) {
681 if (animation_waiting_for_target
->group() ==
682 animations_
[j
]->group()) {
683 animations_
[j
]->SetRunState(Animation::Starting
, monotonic_time
);
687 needs_to_start_animations_
= true;
693 void LayerAnimationController::PromoteStartedAnimations(
694 base::TimeTicks monotonic_time
,
695 AnimationEventsVector
* events
) {
696 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
697 if (animations_
[i
]->run_state() == Animation::Starting
&&
698 animations_
[i
]->affects_active_observers()) {
699 animations_
[i
]->SetRunState(Animation::Running
, monotonic_time
);
700 if (!animations_
[i
]->has_set_start_time() &&
701 !animations_
[i
]->needs_synchronized_start_time())
702 animations_
[i
]->set_start_time(monotonic_time
);
704 AnimationEvent
started_event(AnimationEvent::Started
,
706 animations_
[i
]->group(),
707 animations_
[i
]->target_property(),
709 started_event
.is_impl_only
= animations_
[i
]->is_impl_only();
710 if (started_event
.is_impl_only
)
711 NotifyAnimationStarted(started_event
);
713 events
->push_back(started_event
);
719 void LayerAnimationController::MarkFinishedAnimations(
720 base::TimeTicks monotonic_time
) {
721 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
722 if (animations_
[i
]->IsFinishedAt(monotonic_time
) &&
723 animations_
[i
]->run_state() != Animation::Aborted
&&
724 animations_
[i
]->run_state() != Animation::WaitingForDeletion
)
725 animations_
[i
]->SetRunState(Animation::Finished
, monotonic_time
);
729 void LayerAnimationController::MarkAnimationsForDeletion(
730 base::TimeTicks monotonic_time
,
731 AnimationEventsVector
* events
) {
732 bool marked_animations_for_deletions
= false;
733 std::vector
<size_t> animations_with_same_group_id
;
735 animations_with_same_group_id
.reserve(animations_
.size());
736 // Non-aborted animations are marked for deletion after a corresponding
737 // AnimationEvent::Finished event is sent or received. This means that if
738 // we don't have an events vector, we must ensure that non-aborted animations
739 // have received a finished event before marking them for deletion.
740 for (size_t i
= 0; i
< animations_
.size(); i
++) {
741 int group_id
= animations_
[i
]->group();
742 if (animations_
[i
]->run_state() == Animation::Aborted
) {
743 if (events
&& !animations_
[i
]->is_impl_only()) {
744 AnimationEvent
aborted_event(AnimationEvent::Aborted
,
747 animations_
[i
]->target_property(),
749 events
->push_back(aborted_event
);
751 animations_
[i
]->SetRunState(Animation::WaitingForDeletion
,
753 marked_animations_for_deletions
= true;
757 bool all_anims_with_same_id_are_finished
= false;
759 // Since deleting an animation on the main thread leads to its deletion
760 // on the impl thread, we only mark a Finished main thread animation for
761 // deletion once it has received a Finished event from the impl thread.
762 bool animation_i_will_send_or_has_received_finish_event
=
763 events
|| animations_
[i
]->received_finished_event();
764 // If an animation is finished, and not already marked for deletion,
765 // find out if all other animations in the same group are also finished.
766 if (animations_
[i
]->run_state() == Animation::Finished
&&
767 animation_i_will_send_or_has_received_finish_event
) {
768 // Clear the animations_with_same_group_id if it was added for
769 // the previous animation's iteration.
770 if (animations_with_same_group_id
.size() > 0)
771 animations_with_same_group_id
.clear();
772 all_anims_with_same_id_are_finished
= true;
773 for (size_t j
= 0; j
< animations_
.size(); ++j
) {
774 bool animation_j_will_send_or_has_received_finish_event
=
775 events
|| animations_
[j
]->received_finished_event();
776 if (group_id
== animations_
[j
]->group()) {
777 if (!animations_
[j
]->is_finished() ||
778 (animations_
[j
]->run_state() == Animation::Finished
&&
779 !animation_j_will_send_or_has_received_finish_event
)) {
780 all_anims_with_same_id_are_finished
= false;
783 animations_
[j
]->run_state() != Animation::Aborted
) {
784 // Mark down the animations which belong to the same group
785 // and is not yet aborted. If this current iteration finds that all
786 // animations with same ID are finished, then the marked
787 // animations below will be set to WaitingForDeletion in next
789 animations_with_same_group_id
.push_back(j
);
794 if (all_anims_with_same_id_are_finished
) {
795 // We now need to remove all animations with the same group id as
796 // group_id (and send along animation finished notifications, if
798 for (size_t j
= 0; j
< animations_with_same_group_id
.size(); j
++) {
799 size_t animation_index
= animations_with_same_group_id
[j
];
801 AnimationEvent
finished_event(
802 AnimationEvent::Finished
,
804 animations_
[animation_index
]->group(),
805 animations_
[animation_index
]->target_property(),
807 finished_event
.is_impl_only
=
808 animations_
[animation_index
]->is_impl_only();
809 if (finished_event
.is_impl_only
)
810 NotifyAnimationFinished(finished_event
);
812 events
->push_back(finished_event
);
814 animations_
[animation_index
]->SetRunState(
815 Animation::WaitingForDeletion
, monotonic_time
);
817 marked_animations_for_deletions
= true;
820 if (marked_animations_for_deletions
)
821 NotifyObserversAnimationWaitingForDeletion();
824 static bool IsWaitingForDeletion(Animation
* animation
) {
825 return animation
->run_state() == Animation::WaitingForDeletion
;
828 void LayerAnimationController::PurgeAnimationsMarkedForDeletion() {
829 animations_
.erase(cc::remove_if(&animations_
,
832 IsWaitingForDeletion
),
836 void LayerAnimationController::TickAnimations(base::TimeTicks monotonic_time
) {
837 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
838 if (animations_
[i
]->run_state() == Animation::Starting
||
839 animations_
[i
]->run_state() == Animation::Running
||
840 animations_
[i
]->run_state() == Animation::Paused
) {
841 if (!animations_
[i
]->InEffect(monotonic_time
))
845 animations_
[i
]->TrimTimeToCurrentIteration(monotonic_time
);
847 switch (animations_
[i
]->target_property()) {
848 case Animation::Transform
: {
849 const TransformAnimationCurve
* transform_animation_curve
=
850 animations_
[i
]->curve()->ToTransformAnimationCurve();
851 const gfx::Transform transform
=
852 transform_animation_curve
->GetValue(trimmed
);
853 NotifyObserversTransformAnimated(
855 animations_
[i
]->affects_active_observers(),
856 animations_
[i
]->affects_pending_observers());
860 case Animation::Opacity
: {
861 const FloatAnimationCurve
* float_animation_curve
=
862 animations_
[i
]->curve()->ToFloatAnimationCurve();
863 const float opacity
= std::max(
864 std::min(float_animation_curve
->GetValue(trimmed
), 1.0f
), 0.f
);
865 NotifyObserversOpacityAnimated(
867 animations_
[i
]->affects_active_observers(),
868 animations_
[i
]->affects_pending_observers());
872 case Animation::Filter
: {
873 const FilterAnimationCurve
* filter_animation_curve
=
874 animations_
[i
]->curve()->ToFilterAnimationCurve();
875 const FilterOperations filter
=
876 filter_animation_curve
->GetValue(trimmed
);
877 NotifyObserversFilterAnimated(
879 animations_
[i
]->affects_active_observers(),
880 animations_
[i
]->affects_pending_observers());
884 case Animation::BackgroundColor
: {
885 // Not yet implemented.
889 case Animation::ScrollOffset
: {
890 const ScrollOffsetAnimationCurve
* scroll_offset_animation_curve
=
891 animations_
[i
]->curve()->ToScrollOffsetAnimationCurve();
892 const gfx::Vector2dF scroll_offset
=
893 scroll_offset_animation_curve
->GetValue(trimmed
);
894 NotifyObserversScrollOffsetAnimated(
896 animations_
[i
]->affects_active_observers(),
897 animations_
[i
]->affects_pending_observers());
901 // Do nothing for sentinel value.
902 case Animation::TargetPropertyEnumSize
:
909 void LayerAnimationController::UpdateActivation(UpdateActivationType type
) {
910 bool force
= type
== ForceActivation
;
912 bool was_active
= is_active_
;
914 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
915 if (animations_
[i
]->run_state() != Animation::WaitingForDeletion
) {
921 if (is_active_
&& (!was_active
|| force
))
922 registrar_
->DidActivateAnimationController(this);
923 else if (!is_active_
&& (was_active
|| force
))
924 registrar_
->DidDeactivateAnimationController(this);
928 void LayerAnimationController::NotifyObserversOpacityAnimated(
930 bool notify_active_observers
,
931 bool notify_pending_observers
) {
932 if (value_observers_
.might_have_observers()) {
933 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
935 LayerAnimationValueObserver
* obs
;
936 while ((obs
= it
.GetNext()) != NULL
) {
937 if ((notify_active_observers
&& notify_pending_observers
) ||
938 (notify_active_observers
&& obs
->IsActive()) ||
939 (notify_pending_observers
&& !obs
->IsActive()))
940 obs
->OnOpacityAnimated(opacity
);
945 void LayerAnimationController::NotifyObserversTransformAnimated(
946 const gfx::Transform
& transform
,
947 bool notify_active_observers
,
948 bool notify_pending_observers
) {
949 if (value_observers_
.might_have_observers()) {
950 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
952 LayerAnimationValueObserver
* obs
;
953 while ((obs
= it
.GetNext()) != NULL
) {
954 if ((notify_active_observers
&& notify_pending_observers
) ||
955 (notify_active_observers
&& obs
->IsActive()) ||
956 (notify_pending_observers
&& !obs
->IsActive()))
957 obs
->OnTransformAnimated(transform
);
962 void LayerAnimationController::NotifyObserversFilterAnimated(
963 const FilterOperations
& filters
,
964 bool notify_active_observers
,
965 bool notify_pending_observers
) {
966 if (value_observers_
.might_have_observers()) {
967 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
969 LayerAnimationValueObserver
* obs
;
970 while ((obs
= it
.GetNext()) != NULL
) {
971 if ((notify_active_observers
&& notify_pending_observers
) ||
972 (notify_active_observers
&& obs
->IsActive()) ||
973 (notify_pending_observers
&& !obs
->IsActive()))
974 obs
->OnFilterAnimated(filters
);
979 void LayerAnimationController::NotifyObserversScrollOffsetAnimated(
980 const gfx::Vector2dF
& scroll_offset
,
981 bool notify_active_observers
,
982 bool notify_pending_observers
) {
983 if (value_observers_
.might_have_observers()) {
984 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
986 LayerAnimationValueObserver
* obs
;
987 while ((obs
= it
.GetNext()) != NULL
) {
988 if ((notify_active_observers
&& notify_pending_observers
) ||
989 (notify_active_observers
&& obs
->IsActive()) ||
990 (notify_pending_observers
&& !obs
->IsActive()))
991 obs
->OnScrollOffsetAnimated(scroll_offset
);
996 void LayerAnimationController::NotifyObserversAnimationWaitingForDeletion() {
997 FOR_EACH_OBSERVER(LayerAnimationValueObserver
,
999 OnAnimationWaitingForDeletion());
1002 bool LayerAnimationController::HasValueObserver() {
1003 if (value_observers_
.might_have_observers()) {
1004 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
1006 return it
.GetNext() != NULL
;
1011 bool LayerAnimationController::HasActiveValueObserver() {
1012 if (value_observers_
.might_have_observers()) {
1013 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
1015 LayerAnimationValueObserver
* obs
;
1016 while ((obs
= it
.GetNext()) != NULL
)
1017 if (obs
->IsActive())