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"
10 #include "cc/animation/animation.h"
11 #include "cc/animation/animation_delegate.h"
12 #include "cc/animation/animation_registrar.h"
13 #include "cc/animation/keyframed_animation_curve.h"
14 #include "cc/animation/layer_animation_value_observer.h"
15 #include "cc/animation/layer_animation_value_provider.h"
16 #include "cc/animation/scroll_offset_animation_curve.h"
17 #include "cc/base/scoped_ptr_algorithm.h"
18 #include "cc/output/filter_operations.h"
19 #include "ui/gfx/geometry/box_f.h"
20 #include "ui/gfx/transform.h"
24 LayerAnimationController::LayerAnimationController(int id
)
28 value_provider_(nullptr),
29 layer_animation_delegate_(nullptr),
30 needs_to_start_animations_(false) {
33 LayerAnimationController::~LayerAnimationController() {
35 registrar_
->UnregisterAnimationController(this);
38 scoped_refptr
<LayerAnimationController
> LayerAnimationController::Create(
40 return make_scoped_refptr(new LayerAnimationController(id
));
43 void LayerAnimationController::PauseAnimation(int animation_id
,
44 base::TimeDelta time_offset
) {
45 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
46 if (animations_
[i
]->id() == animation_id
) {
47 animations_
[i
]->SetRunState(Animation::Paused
,
48 time_offset
+ animations_
[i
]->start_time());
53 struct HasAnimationId
{
54 explicit HasAnimationId(int id
) : id_(id
) {}
55 bool operator()(Animation
* animation
) const {
56 return animation
->id() == id_
;
63 void LayerAnimationController::RemoveAnimation(int animation_id
) {
64 animations_
.erase(cc::remove_if(&animations_
,
67 HasAnimationId(animation_id
)),
69 UpdateActivation(NormalActivation
);
72 struct HasAnimationIdAndProperty
{
73 HasAnimationIdAndProperty(int id
, Animation::TargetProperty target_property
)
74 : id_(id
), target_property_(target_property
) {}
75 bool operator()(Animation
* animation
) const {
76 return animation
->id() == id_
&&
77 animation
->target_property() == target_property_
;
82 Animation::TargetProperty target_property_
;
85 void LayerAnimationController::RemoveAnimation(
87 Animation::TargetProperty target_property
) {
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
< animations_
.size(); ++i
) {
100 if (animations_
[i
]->target_property() == target_property
&&
101 !animations_
[i
]->is_finished())
102 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(base::TimeTicks monotonic_time
) {
127 DCHECK(!monotonic_time
.is_null());
128 if (!HasValueObserver())
131 if (needs_to_start_animations_
)
132 StartAnimations(monotonic_time
);
133 TickAnimations(monotonic_time
);
134 last_tick_time_
= monotonic_time
;
137 void LayerAnimationController::AccumulatePropertyUpdates(
138 base::TimeTicks monotonic_time
,
139 AnimationEventsVector
* events
) {
143 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
144 Animation
* animation
= animations_
[i
];
145 if (!animation
->is_impl_only())
148 if (!animation
->InEffect(monotonic_time
))
151 double trimmed
= animation
->TrimTimeToCurrentIteration(monotonic_time
);
152 switch (animation
->target_property()) {
153 case Animation::Opacity
: {
154 AnimationEvent
event(AnimationEvent::PropertyUpdate
,
159 const FloatAnimationCurve
* float_animation_curve
=
160 animation
->curve()->ToFloatAnimationCurve();
161 event
.opacity
= float_animation_curve
->GetValue(trimmed
);
162 event
.is_impl_only
= true;
163 events
->push_back(event
);
167 case Animation::Transform
: {
168 AnimationEvent
event(AnimationEvent::PropertyUpdate
,
171 Animation::Transform
,
173 const TransformAnimationCurve
* transform_animation_curve
=
174 animation
->curve()->ToTransformAnimationCurve();
175 event
.transform
= transform_animation_curve
->GetValue(trimmed
);
176 event
.is_impl_only
= true;
177 events
->push_back(event
);
181 case Animation::Filter
: {
182 AnimationEvent
event(AnimationEvent::PropertyUpdate
,
187 const FilterAnimationCurve
* filter_animation_curve
=
188 animation
->curve()->ToFilterAnimationCurve();
189 event
.filters
= filter_animation_curve
->GetValue(trimmed
);
190 event
.is_impl_only
= true;
191 events
->push_back(event
);
195 case Animation::BackgroundColor
: { break; }
197 case Animation::ScrollOffset
: {
198 // Impl-side changes to scroll offset are already sent back to the
199 // main thread (e.g. for user-driven scrolling), so a PropertyUpdate
204 case Animation::TargetPropertyEnumSize
:
210 void LayerAnimationController::UpdateState(bool start_ready_animations
,
211 AnimationEventsVector
* events
) {
212 if (!HasActiveValueObserver())
215 DCHECK(last_tick_time_
!= base::TimeTicks());
216 if (start_ready_animations
)
217 PromoteStartedAnimations(last_tick_time_
, events
);
219 MarkFinishedAnimations(last_tick_time_
);
220 MarkAnimationsForDeletion(last_tick_time_
, events
);
222 if (needs_to_start_animations_
&& start_ready_animations
) {
223 StartAnimations(last_tick_time_
);
224 PromoteStartedAnimations(last_tick_time_
, events
);
227 AccumulatePropertyUpdates(last_tick_time_
, events
);
229 UpdateActivation(NormalActivation
);
232 struct AffectsNoObservers
{
233 bool operator()(Animation
* animation
) const {
234 return !animation
->affects_active_observers() &&
235 !animation
->affects_pending_observers();
239 void LayerAnimationController::ActivateAnimations() {
240 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
241 animations_
[i
]->set_affects_active_observers(
242 animations_
[i
]->affects_pending_observers());
244 animations_
.erase(cc::remove_if(&animations_
,
247 AffectsNoObservers()),
249 UpdateActivation(NormalActivation
);
252 void LayerAnimationController::AddAnimation(scoped_ptr
<Animation
> animation
) {
253 animations_
.push_back(animation
.Pass());
254 needs_to_start_animations_
= true;
255 UpdateActivation(NormalActivation
);
258 Animation
* LayerAnimationController::GetAnimation(
260 Animation::TargetProperty target_property
) const {
261 for (size_t i
= 0; i
< animations_
.size(); ++i
)
262 if (animations_
[i
]->group() == group_id
&&
263 animations_
[i
]->target_property() == target_property
)
264 return animations_
[i
];
268 Animation
* LayerAnimationController::GetAnimation(
269 Animation::TargetProperty target_property
) const {
270 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
271 size_t index
= animations_
.size() - i
- 1;
272 if (animations_
[index
]->target_property() == target_property
)
273 return animations_
[index
];
278 bool LayerAnimationController::HasActiveAnimation() const {
279 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
280 if (!animations_
[i
]->is_finished())
286 bool LayerAnimationController::IsAnimatingProperty(
287 Animation::TargetProperty target_property
) const {
288 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
289 if (!animations_
[i
]->is_finished() &&
290 animations_
[i
]->InEffect(last_tick_time_
) &&
291 animations_
[i
]->target_property() == target_property
)
297 void LayerAnimationController::SetAnimationRegistrar(
298 AnimationRegistrar
* registrar
) {
299 if (registrar_
== registrar
)
303 registrar_
->UnregisterAnimationController(this);
305 registrar_
= registrar
;
307 registrar_
->RegisterAnimationController(this);
309 UpdateActivation(ForceActivation
);
312 void LayerAnimationController::NotifyAnimationStarted(
313 const AnimationEvent
& event
) {
314 if (event
.is_impl_only
) {
315 FOR_EACH_OBSERVER(LayerAnimationEventObserver
, event_observers_
,
316 OnAnimationStarted(event
));
317 if (layer_animation_delegate_
)
318 layer_animation_delegate_
->NotifyAnimationStarted(
319 event
.monotonic_time
, event
.target_property
, event
.group_id
);
323 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
324 if (animations_
[i
]->group() == event
.group_id
&&
325 animations_
[i
]->target_property() == event
.target_property
&&
326 animations_
[i
]->needs_synchronized_start_time()) {
327 animations_
[i
]->set_needs_synchronized_start_time(false);
328 if (!animations_
[i
]->has_set_start_time())
329 animations_
[i
]->set_start_time(event
.monotonic_time
);
331 FOR_EACH_OBSERVER(LayerAnimationEventObserver
, event_observers_
,
332 OnAnimationStarted(event
));
333 if (layer_animation_delegate_
)
334 layer_animation_delegate_
->NotifyAnimationStarted(
335 event
.monotonic_time
, event
.target_property
, event
.group_id
);
342 void LayerAnimationController::NotifyAnimationFinished(
343 const AnimationEvent
& event
) {
344 if (event
.is_impl_only
) {
345 if (layer_animation_delegate_
)
346 layer_animation_delegate_
->NotifyAnimationFinished(
347 event
.monotonic_time
, event
.target_property
, event
.group_id
);
351 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
352 if (animations_
[i
]->group() == event
.group_id
&&
353 animations_
[i
]->target_property() == event
.target_property
) {
354 animations_
[i
]->set_received_finished_event(true);
355 if (layer_animation_delegate_
)
356 layer_animation_delegate_
->NotifyAnimationFinished(
357 event
.monotonic_time
, event
.target_property
, event
.group_id
);
364 void LayerAnimationController::NotifyAnimationAborted(
365 const AnimationEvent
& event
) {
366 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
367 if (animations_
[i
]->group() == event
.group_id
&&
368 animations_
[i
]->target_property() == event
.target_property
) {
369 animations_
[i
]->SetRunState(Animation::Aborted
, event
.monotonic_time
);
374 void LayerAnimationController::NotifyAnimationPropertyUpdate(
375 const AnimationEvent
& event
) {
376 bool notify_active_observers
= true;
377 bool notify_pending_observers
= true;
378 switch (event
.target_property
) {
379 case Animation::Opacity
:
380 NotifyObserversOpacityAnimated(
381 event
.opacity
, notify_active_observers
, notify_pending_observers
);
383 case Animation::Transform
:
384 NotifyObserversTransformAnimated(
385 event
.transform
, notify_active_observers
, notify_pending_observers
);
392 void LayerAnimationController::AddValueObserver(
393 LayerAnimationValueObserver
* observer
) {
394 if (!value_observers_
.HasObserver(observer
))
395 value_observers_
.AddObserver(observer
);
398 void LayerAnimationController::RemoveValueObserver(
399 LayerAnimationValueObserver
* observer
) {
400 value_observers_
.RemoveObserver(observer
);
403 void LayerAnimationController::AddEventObserver(
404 LayerAnimationEventObserver
* observer
) {
405 if (!event_observers_
.HasObserver(observer
))
406 event_observers_
.AddObserver(observer
);
409 void LayerAnimationController::RemoveEventObserver(
410 LayerAnimationEventObserver
* observer
) {
411 event_observers_
.RemoveObserver(observer
);
414 bool LayerAnimationController::HasFilterAnimationThatInflatesBounds() const {
415 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
416 if (!animations_
[i
]->is_finished() &&
417 animations_
[i
]->target_property() == Animation::Filter
&&
420 ->ToFilterAnimationCurve()
421 ->HasFilterThatMovesPixels())
428 bool LayerAnimationController::HasTransformAnimationThatInflatesBounds() const {
429 return IsAnimatingProperty(Animation::Transform
);
432 bool LayerAnimationController::FilterAnimationBoundsForBox(
433 const gfx::BoxF
& box
, gfx::BoxF
* bounds
) const {
434 // TODO(avallee): Implement.
438 bool LayerAnimationController::TransformAnimationBoundsForBox(
439 const gfx::BoxF
& box
,
440 gfx::BoxF
* bounds
) const {
441 DCHECK(HasTransformAnimationThatInflatesBounds())
442 << "TransformAnimationBoundsForBox will give incorrect results if there "
443 << "are no transform animations affecting bounds, non-animated transform "
446 // Compute bounds based on animations for which is_finished() is false.
447 // Do nothing if there are no such animations; in this case, it is assumed
448 // that callers will take care of computing bounds based on the owning layer's
450 *bounds
= gfx::BoxF();
451 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
452 if (animations_
[i
]->is_finished() ||
453 animations_
[i
]->target_property() != Animation::Transform
)
456 const TransformAnimationCurve
* transform_animation_curve
=
457 animations_
[i
]->curve()->ToTransformAnimationCurve();
458 gfx::BoxF animation_bounds
;
460 transform_animation_curve
->AnimatedBoundsForBox(box
, &animation_bounds
);
463 bounds
->Union(animation_bounds
);
469 bool LayerAnimationController::HasAnimationThatAffectsScale() const {
470 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
471 if (animations_
[i
]->is_finished() ||
472 animations_
[i
]->target_property() != Animation::Transform
)
475 const TransformAnimationCurve
* transform_animation_curve
=
476 animations_
[i
]->curve()->ToTransformAnimationCurve();
477 if (transform_animation_curve
->AffectsScale())
484 bool LayerAnimationController::HasOnlyTranslationTransforms() const {
485 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
486 if (animations_
[i
]->is_finished() ||
487 animations_
[i
]->target_property() != Animation::Transform
)
490 const TransformAnimationCurve
* transform_animation_curve
=
491 animations_
[i
]->curve()->ToTransformAnimationCurve();
492 if (!transform_animation_curve
->IsTranslation())
499 bool LayerAnimationController::MaximumTargetScale(float* max_scale
) const {
501 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
502 if (animations_
[i
]->is_finished() ||
503 animations_
[i
]->target_property() != Animation::Transform
)
506 bool forward_direction
= true;
507 switch (animations_
[i
]->direction()) {
508 case Animation::Normal
:
509 case Animation::Alternate
:
510 forward_direction
= animations_
[i
]->playback_rate() >= 0.0;
512 case Animation::Reverse
:
513 case Animation::AlternateReverse
:
514 forward_direction
= animations_
[i
]->playback_rate() < 0.0;
518 const TransformAnimationCurve
* transform_animation_curve
=
519 animations_
[i
]->curve()->ToTransformAnimationCurve();
520 float animation_scale
= 0.f
;
521 if (!transform_animation_curve
->MaximumTargetScale(forward_direction
,
524 *max_scale
= std::max(*max_scale
, animation_scale
);
530 void LayerAnimationController::PushNewAnimationsToImplThread(
531 LayerAnimationController
* controller_impl
) const {
532 // Any new animations owned by the main thread's controller are cloned and
533 // add to the impl thread's controller.
534 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
535 // If the animation is already running on the impl thread, there is no
536 // need to copy it over.
537 if (controller_impl
->GetAnimation(animations_
[i
]->group(),
538 animations_
[i
]->target_property()))
541 // If the animation is not running on the impl thread, it does not
542 // necessarily mean that it needs to be copied over and started; it may
543 // have already finished. In this case, the impl thread animation will
544 // have already notified that it has started and the main thread animation
545 // will no longer need
546 // a synchronized start time.
547 if (!animations_
[i
]->needs_synchronized_start_time())
550 // Scroll animations always start at the current scroll offset.
551 if (animations_
[i
]->target_property() == Animation::ScrollOffset
) {
552 gfx::ScrollOffset current_scroll_offset
;
553 if (controller_impl
->value_provider_
) {
554 current_scroll_offset
=
555 controller_impl
->value_provider_
->ScrollOffsetForAnimation();
557 // The owning layer isn't yet in the active tree, so the main thread
558 // scroll offset will be up-to-date.
559 current_scroll_offset
= value_provider_
->ScrollOffsetForAnimation();
561 animations_
[i
]->curve()->ToScrollOffsetAnimationCurve()->SetInitialValue(
562 current_scroll_offset
);
565 // The new animation should be set to run as soon as possible.
566 Animation::RunState initial_run_state
=
567 Animation::WaitingForTargetAvailability
;
568 scoped_ptr
<Animation
> to_add(
569 animations_
[i
]->CloneAndInitialize(initial_run_state
));
570 DCHECK(!to_add
->needs_synchronized_start_time());
571 to_add
->set_affects_active_observers(false);
572 controller_impl
->AddAnimation(to_add
.Pass());
576 static bool IsCompleted(
577 Animation
* animation
,
578 const LayerAnimationController
* main_thread_controller
) {
579 if (animation
->is_impl_only()) {
580 return (animation
->run_state() == Animation::WaitingForDeletion
);
582 return !main_thread_controller
->GetAnimation(animation
->group(),
583 animation
->target_property());
587 static bool AffectsActiveOnlyAndIsWaitingForDeletion(Animation
* animation
) {
588 return animation
->run_state() == Animation::WaitingForDeletion
&&
589 !animation
->affects_pending_observers();
592 void LayerAnimationController::RemoveAnimationsCompletedOnMainThread(
593 LayerAnimationController
* controller_impl
) const {
594 // Animations removed on the main thread should no longer affect pending
595 // observers, and should stop affecting active observers after the next call
596 // to ActivateAnimations. If already WaitingForDeletion, they can be removed
598 ScopedPtrVector
<Animation
>& animations
= controller_impl
->animations_
;
599 for (size_t i
= 0; i
< animations
.size(); ++i
) {
600 if (IsCompleted(animations
[i
], this))
601 animations
[i
]->set_affects_pending_observers(false);
603 animations
.erase(cc::remove_if(&animations
,
606 AffectsActiveOnlyAndIsWaitingForDeletion
),
610 void LayerAnimationController::PushPropertiesToImplThread(
611 LayerAnimationController
* controller_impl
) const {
612 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
613 Animation
* current_impl
= controller_impl
->GetAnimation(
614 animations_
[i
]->group(), animations_
[i
]->target_property());
616 animations_
[i
]->PushPropertiesTo(current_impl
);
620 void LayerAnimationController::StartAnimations(base::TimeTicks monotonic_time
) {
621 DCHECK(needs_to_start_animations_
);
622 needs_to_start_animations_
= false;
623 // First collect running properties affecting each type of observer.
624 TargetProperties blocked_properties_for_active_observers
;
625 TargetProperties blocked_properties_for_pending_observers
;
626 std::vector
<size_t> animations_waiting_for_target
;
628 animations_waiting_for_target
.reserve(animations_
.size());
629 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
630 if (animations_
[i
]->run_state() == Animation::Starting
||
631 animations_
[i
]->run_state() == Animation::Running
) {
632 if (animations_
[i
]->affects_active_observers()) {
633 blocked_properties_for_active_observers
.insert(
634 animations_
[i
]->target_property());
636 if (animations_
[i
]->affects_pending_observers()) {
637 blocked_properties_for_pending_observers
.insert(
638 animations_
[i
]->target_property());
640 } else if (animations_
[i
]->run_state() ==
641 Animation::WaitingForTargetAvailability
) {
642 animations_waiting_for_target
.push_back(i
);
646 for (size_t i
= 0; i
< animations_waiting_for_target
.size(); ++i
) {
647 // Collect all properties for animations with the same group id (they
648 // should all also be in the list of animations).
649 size_t animation_index
= animations_waiting_for_target
[i
];
650 Animation
* animation_waiting_for_target
= animations_
[animation_index
];
651 // Check for the run state again even though the animation was waiting
652 // for target because it might have changed the run state while handling
653 // previous animation in this loop (if they belong to same group).
654 if (animation_waiting_for_target
->run_state() ==
655 Animation::WaitingForTargetAvailability
) {
656 TargetProperties enqueued_properties
;
657 bool affects_active_observers
=
658 animation_waiting_for_target
->affects_active_observers();
659 bool affects_pending_observers
=
660 animation_waiting_for_target
->affects_pending_observers();
661 enqueued_properties
.insert(
662 animation_waiting_for_target
->target_property());
663 for (size_t j
= animation_index
+ 1; j
< animations_
.size(); ++j
) {
664 if (animation_waiting_for_target
->group() == animations_
[j
]->group()) {
665 enqueued_properties
.insert(animations_
[j
]->target_property());
666 affects_active_observers
|=
667 animations_
[j
]->affects_active_observers();
668 affects_pending_observers
|=
669 animations_
[j
]->affects_pending_observers();
673 // Check to see if intersection of the list of properties affected by
674 // the group and the list of currently blocked properties is null, taking
675 // into account the type(s) of observers affected by the group. In any
676 // case, the group's target properties need to be added to the lists of
677 // blocked properties.
678 bool null_intersection
= true;
679 for (TargetProperties::iterator p_iter
= enqueued_properties
.begin();
680 p_iter
!= enqueued_properties
.end();
682 if (affects_active_observers
&&
683 !blocked_properties_for_active_observers
.insert(*p_iter
).second
)
684 null_intersection
= false;
685 if (affects_pending_observers
&&
686 !blocked_properties_for_pending_observers
.insert(*p_iter
).second
)
687 null_intersection
= false;
690 // If the intersection is null, then we are free to start the animations
692 if (null_intersection
) {
693 animation_waiting_for_target
->SetRunState(Animation::Starting
,
695 for (size_t j
= animation_index
+ 1; j
< animations_
.size(); ++j
) {
696 if (animation_waiting_for_target
->group() ==
697 animations_
[j
]->group()) {
698 animations_
[j
]->SetRunState(Animation::Starting
, monotonic_time
);
702 needs_to_start_animations_
= true;
708 void LayerAnimationController::PromoteStartedAnimations(
709 base::TimeTicks monotonic_time
,
710 AnimationEventsVector
* events
) {
711 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
712 if (animations_
[i
]->run_state() == Animation::Starting
&&
713 animations_
[i
]->affects_active_observers()) {
714 animations_
[i
]->SetRunState(Animation::Running
, monotonic_time
);
715 if (!animations_
[i
]->has_set_start_time() &&
716 !animations_
[i
]->needs_synchronized_start_time())
717 animations_
[i
]->set_start_time(monotonic_time
);
719 AnimationEvent
started_event(AnimationEvent::Started
,
721 animations_
[i
]->group(),
722 animations_
[i
]->target_property(),
724 started_event
.is_impl_only
= animations_
[i
]->is_impl_only();
725 if (started_event
.is_impl_only
)
726 NotifyAnimationStarted(started_event
);
728 events
->push_back(started_event
);
734 void LayerAnimationController::MarkFinishedAnimations(
735 base::TimeTicks monotonic_time
) {
736 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
737 if (animations_
[i
]->IsFinishedAt(monotonic_time
) &&
738 animations_
[i
]->run_state() != Animation::Aborted
&&
739 animations_
[i
]->run_state() != Animation::WaitingForDeletion
)
740 animations_
[i
]->SetRunState(Animation::Finished
, monotonic_time
);
744 void LayerAnimationController::MarkAnimationsForDeletion(
745 base::TimeTicks monotonic_time
,
746 AnimationEventsVector
* events
) {
747 bool marked_animations_for_deletions
= false;
748 std::vector
<size_t> animations_with_same_group_id
;
750 animations_with_same_group_id
.reserve(animations_
.size());
751 // Non-aborted animations are marked for deletion after a corresponding
752 // AnimationEvent::Finished event is sent or received. This means that if
753 // we don't have an events vector, we must ensure that non-aborted animations
754 // have received a finished event before marking them for deletion.
755 for (size_t i
= 0; i
< animations_
.size(); i
++) {
756 int group_id
= animations_
[i
]->group();
757 if (animations_
[i
]->run_state() == Animation::Aborted
) {
758 if (events
&& !animations_
[i
]->is_impl_only()) {
759 AnimationEvent
aborted_event(AnimationEvent::Aborted
,
762 animations_
[i
]->target_property(),
764 events
->push_back(aborted_event
);
766 animations_
[i
]->SetRunState(Animation::WaitingForDeletion
,
768 marked_animations_for_deletions
= true;
772 bool all_anims_with_same_id_are_finished
= false;
774 // Since deleting an animation on the main thread leads to its deletion
775 // on the impl thread, we only mark a Finished main thread animation for
776 // deletion once it has received a Finished event from the impl thread.
777 bool animation_i_will_send_or_has_received_finish_event
=
778 events
|| animations_
[i
]->received_finished_event();
779 // If an animation is finished, and not already marked for deletion,
780 // find out if all other animations in the same group are also finished.
781 if (animations_
[i
]->run_state() == Animation::Finished
&&
782 animation_i_will_send_or_has_received_finish_event
) {
783 // Clear the animations_with_same_group_id if it was added for
784 // the previous animation's iteration.
785 if (animations_with_same_group_id
.size() > 0)
786 animations_with_same_group_id
.clear();
787 all_anims_with_same_id_are_finished
= true;
788 for (size_t j
= 0; j
< animations_
.size(); ++j
) {
789 bool animation_j_will_send_or_has_received_finish_event
=
790 events
|| animations_
[j
]->received_finished_event();
791 if (group_id
== animations_
[j
]->group()) {
792 if (!animations_
[j
]->is_finished() ||
793 (animations_
[j
]->run_state() == Animation::Finished
&&
794 !animation_j_will_send_or_has_received_finish_event
)) {
795 all_anims_with_same_id_are_finished
= false;
798 animations_
[j
]->run_state() != Animation::Aborted
) {
799 // Mark down the animations which belong to the same group
800 // and is not yet aborted. If this current iteration finds that all
801 // animations with same ID are finished, then the marked
802 // animations below will be set to WaitingForDeletion in next
804 animations_with_same_group_id
.push_back(j
);
809 if (all_anims_with_same_id_are_finished
) {
810 // We now need to remove all animations with the same group id as
811 // group_id (and send along animation finished notifications, if
813 for (size_t j
= 0; j
< animations_with_same_group_id
.size(); j
++) {
814 size_t animation_index
= animations_with_same_group_id
[j
];
816 AnimationEvent
finished_event(
817 AnimationEvent::Finished
,
819 animations_
[animation_index
]->group(),
820 animations_
[animation_index
]->target_property(),
822 finished_event
.is_impl_only
=
823 animations_
[animation_index
]->is_impl_only();
824 if (finished_event
.is_impl_only
)
825 NotifyAnimationFinished(finished_event
);
827 events
->push_back(finished_event
);
829 animations_
[animation_index
]->SetRunState(
830 Animation::WaitingForDeletion
, monotonic_time
);
832 marked_animations_for_deletions
= true;
835 if (marked_animations_for_deletions
)
836 NotifyObserversAnimationWaitingForDeletion();
839 static bool IsWaitingForDeletion(Animation
* animation
) {
840 return animation
->run_state() == Animation::WaitingForDeletion
;
843 void LayerAnimationController::PurgeAnimationsMarkedForDeletion() {
844 animations_
.erase(cc::remove_if(&animations_
,
847 IsWaitingForDeletion
),
851 void LayerAnimationController::TickAnimations(base::TimeTicks monotonic_time
) {
852 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
853 if (animations_
[i
]->run_state() == Animation::Starting
||
854 animations_
[i
]->run_state() == Animation::Running
||
855 animations_
[i
]->run_state() == Animation::Paused
) {
856 if (!animations_
[i
]->InEffect(monotonic_time
))
860 animations_
[i
]->TrimTimeToCurrentIteration(monotonic_time
);
862 switch (animations_
[i
]->target_property()) {
863 case Animation::Transform
: {
864 const TransformAnimationCurve
* transform_animation_curve
=
865 animations_
[i
]->curve()->ToTransformAnimationCurve();
866 const gfx::Transform transform
=
867 transform_animation_curve
->GetValue(trimmed
);
868 NotifyObserversTransformAnimated(
870 animations_
[i
]->affects_active_observers(),
871 animations_
[i
]->affects_pending_observers());
875 case Animation::Opacity
: {
876 const FloatAnimationCurve
* float_animation_curve
=
877 animations_
[i
]->curve()->ToFloatAnimationCurve();
878 const float opacity
= std::max(
879 std::min(float_animation_curve
->GetValue(trimmed
), 1.0f
), 0.f
);
880 NotifyObserversOpacityAnimated(
882 animations_
[i
]->affects_active_observers(),
883 animations_
[i
]->affects_pending_observers());
887 case Animation::Filter
: {
888 const FilterAnimationCurve
* filter_animation_curve
=
889 animations_
[i
]->curve()->ToFilterAnimationCurve();
890 const FilterOperations filter
=
891 filter_animation_curve
->GetValue(trimmed
);
892 NotifyObserversFilterAnimated(
894 animations_
[i
]->affects_active_observers(),
895 animations_
[i
]->affects_pending_observers());
899 case Animation::BackgroundColor
: {
900 // Not yet implemented.
904 case Animation::ScrollOffset
: {
905 const ScrollOffsetAnimationCurve
* scroll_offset_animation_curve
=
906 animations_
[i
]->curve()->ToScrollOffsetAnimationCurve();
907 const gfx::ScrollOffset scroll_offset
=
908 scroll_offset_animation_curve
->GetValue(trimmed
);
909 NotifyObserversScrollOffsetAnimated(
911 animations_
[i
]->affects_active_observers(),
912 animations_
[i
]->affects_pending_observers());
916 // Do nothing for sentinel value.
917 case Animation::TargetPropertyEnumSize
:
924 void LayerAnimationController::UpdateActivation(UpdateActivationType type
) {
925 bool force
= type
== ForceActivation
;
927 bool was_active
= is_active_
;
929 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
930 if (animations_
[i
]->run_state() != Animation::WaitingForDeletion
) {
936 if (is_active_
&& (!was_active
|| force
))
937 registrar_
->DidActivateAnimationController(this);
938 else if (!is_active_
&& (was_active
|| force
))
939 registrar_
->DidDeactivateAnimationController(this);
943 void LayerAnimationController::NotifyObserversOpacityAnimated(
945 bool notify_active_observers
,
946 bool notify_pending_observers
) {
947 if (value_observers_
.might_have_observers()) {
948 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
950 LayerAnimationValueObserver
* obs
;
951 while ((obs
= it
.GetNext()) != nullptr) {
952 if ((notify_active_observers
&& notify_pending_observers
) ||
953 (notify_active_observers
&& obs
->IsActive()) ||
954 (notify_pending_observers
&& !obs
->IsActive()))
955 obs
->OnOpacityAnimated(opacity
);
960 void LayerAnimationController::NotifyObserversTransformAnimated(
961 const gfx::Transform
& transform
,
962 bool notify_active_observers
,
963 bool notify_pending_observers
) {
964 if (value_observers_
.might_have_observers()) {
965 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
967 LayerAnimationValueObserver
* obs
;
968 while ((obs
= it
.GetNext()) != nullptr) {
969 if ((notify_active_observers
&& notify_pending_observers
) ||
970 (notify_active_observers
&& obs
->IsActive()) ||
971 (notify_pending_observers
&& !obs
->IsActive()))
972 obs
->OnTransformAnimated(transform
);
977 void LayerAnimationController::NotifyObserversFilterAnimated(
978 const FilterOperations
& filters
,
979 bool notify_active_observers
,
980 bool notify_pending_observers
) {
981 if (value_observers_
.might_have_observers()) {
982 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
984 LayerAnimationValueObserver
* obs
;
985 while ((obs
= it
.GetNext()) != nullptr) {
986 if ((notify_active_observers
&& notify_pending_observers
) ||
987 (notify_active_observers
&& obs
->IsActive()) ||
988 (notify_pending_observers
&& !obs
->IsActive()))
989 obs
->OnFilterAnimated(filters
);
994 void LayerAnimationController::NotifyObserversScrollOffsetAnimated(
995 const gfx::ScrollOffset
& scroll_offset
,
996 bool notify_active_observers
,
997 bool notify_pending_observers
) {
998 if (value_observers_
.might_have_observers()) {
999 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
1001 LayerAnimationValueObserver
* obs
;
1002 while ((obs
= it
.GetNext()) != nullptr) {
1003 if ((notify_active_observers
&& notify_pending_observers
) ||
1004 (notify_active_observers
&& obs
->IsActive()) ||
1005 (notify_pending_observers
&& !obs
->IsActive()))
1006 obs
->OnScrollOffsetAnimated(scroll_offset
);
1011 void LayerAnimationController::NotifyObserversAnimationWaitingForDeletion() {
1012 FOR_EACH_OBSERVER(LayerAnimationValueObserver
,
1014 OnAnimationWaitingForDeletion());
1017 bool LayerAnimationController::HasValueObserver() {
1018 if (value_observers_
.might_have_observers()) {
1019 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
1021 return it
.GetNext() != nullptr;
1026 bool LayerAnimationController::HasActiveValueObserver() {
1027 if (value_observers_
.might_have_observers()) {
1028 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
1030 LayerAnimationValueObserver
* obs
;
1031 while ((obs
= it
.GetNext()) != nullptr)
1032 if (obs
->IsActive())