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 auto animations_to_remove
=
65 animations_
.remove_if(HasAnimationId(animation_id
));
66 for (auto it
= animations_to_remove
; it
!= animations_
.end(); ++it
) {
67 if ((*it
)->target_property() == Animation::ScrollOffset
) {
68 NotifyObserversScrollOffsetAnimationRemoved();
72 animations_
.erase(animations_to_remove
, animations_
.end());
73 UpdateActivation(NormalActivation
);
76 struct HasAnimationIdAndProperty
{
77 HasAnimationIdAndProperty(int id
, Animation::TargetProperty target_property
)
78 : id_(id
), target_property_(target_property
) {}
79 bool operator()(Animation
* animation
) const {
80 return animation
->id() == id_
&&
81 animation
->target_property() == target_property_
;
86 Animation::TargetProperty target_property_
;
89 void LayerAnimationController::RemoveAnimation(
91 Animation::TargetProperty target_property
) {
92 auto animations_to_remove
= animations_
.remove_if(
93 HasAnimationIdAndProperty(animation_id
, target_property
));
94 if (target_property
== Animation::ScrollOffset
&&
95 animations_to_remove
!= animations_
.end())
96 NotifyObserversScrollOffsetAnimationRemoved();
98 animations_
.erase(animations_to_remove
, animations_
.end());
99 UpdateActivation(NormalActivation
);
102 void LayerAnimationController::AbortAnimations(
103 Animation::TargetProperty target_property
) {
104 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
105 if (animations_
[i
]->target_property() == target_property
&&
106 !animations_
[i
]->is_finished())
107 animations_
[i
]->SetRunState(Animation::Aborted
, last_tick_time_
);
111 // Ensures that the list of active animations on the main thread and the impl
112 // thread are kept in sync.
113 void LayerAnimationController::PushAnimationUpdatesTo(
114 LayerAnimationController
* controller_impl
) {
115 DCHECK(this != controller_impl
);
116 if (!has_any_animation() && !controller_impl
->has_any_animation())
118 PurgeAnimationsMarkedForDeletion();
119 PushNewAnimationsToImplThread(controller_impl
);
121 // Remove finished impl side animations only after pushing,
122 // and only after the animations are deleted on the main thread
123 // this insures we will never push an animation twice.
124 RemoveAnimationsCompletedOnMainThread(controller_impl
);
126 PushPropertiesToImplThread(controller_impl
);
127 controller_impl
->UpdateActivation(NormalActivation
);
128 UpdateActivation(NormalActivation
);
131 void LayerAnimationController::Animate(base::TimeTicks monotonic_time
) {
132 DCHECK(!monotonic_time
.is_null());
133 if (!HasValueObserver())
136 if (needs_to_start_animations_
)
137 StartAnimations(monotonic_time
);
138 TickAnimations(monotonic_time
);
139 last_tick_time_
= monotonic_time
;
142 void LayerAnimationController::AccumulatePropertyUpdates(
143 base::TimeTicks monotonic_time
,
144 AnimationEventsVector
* events
) {
148 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
149 Animation
* animation
= animations_
[i
];
150 if (!animation
->is_impl_only())
153 if (!animation
->InEffect(monotonic_time
))
156 base::TimeDelta trimmed
=
157 animation
->TrimTimeToCurrentIteration(monotonic_time
);
158 switch (animation
->target_property()) {
159 case Animation::Opacity
: {
160 AnimationEvent
event(AnimationEvent::PropertyUpdate
,
165 const FloatAnimationCurve
* float_animation_curve
=
166 animation
->curve()->ToFloatAnimationCurve();
167 event
.opacity
= float_animation_curve
->GetValue(trimmed
);
168 event
.is_impl_only
= true;
169 events
->push_back(event
);
173 case Animation::Transform
: {
174 AnimationEvent
event(AnimationEvent::PropertyUpdate
,
177 Animation::Transform
,
179 const TransformAnimationCurve
* transform_animation_curve
=
180 animation
->curve()->ToTransformAnimationCurve();
181 event
.transform
= transform_animation_curve
->GetValue(trimmed
);
182 event
.is_impl_only
= true;
183 events
->push_back(event
);
187 case Animation::Filter
: {
188 AnimationEvent
event(AnimationEvent::PropertyUpdate
,
193 const FilterAnimationCurve
* filter_animation_curve
=
194 animation
->curve()->ToFilterAnimationCurve();
195 event
.filters
= filter_animation_curve
->GetValue(trimmed
);
196 event
.is_impl_only
= true;
197 events
->push_back(event
);
201 case Animation::BackgroundColor
: { break; }
203 case Animation::ScrollOffset
: {
204 // Impl-side changes to scroll offset are already sent back to the
205 // main thread (e.g. for user-driven scrolling), so a PropertyUpdate
210 case Animation::TargetPropertyEnumSize
:
216 void LayerAnimationController::UpdateState(bool start_ready_animations
,
217 AnimationEventsVector
* events
) {
218 if (!HasActiveValueObserver())
221 // Animate hasn't been called, this happens if an observer has been added
222 // between the Commit and Draw phases.
223 if (last_tick_time_
== base::TimeTicks())
226 if (start_ready_animations
)
227 PromoteStartedAnimations(last_tick_time_
, events
);
229 MarkFinishedAnimations(last_tick_time_
);
230 MarkAnimationsForDeletion(last_tick_time_
, events
);
232 if (needs_to_start_animations_
&& start_ready_animations
) {
233 StartAnimations(last_tick_time_
);
234 PromoteStartedAnimations(last_tick_time_
, events
);
237 AccumulatePropertyUpdates(last_tick_time_
, events
);
239 UpdateActivation(NormalActivation
);
242 struct AffectsNoObservers
{
243 bool operator()(Animation
* animation
) const {
244 return !animation
->affects_active_observers() &&
245 !animation
->affects_pending_observers();
249 void LayerAnimationController::ActivateAnimations() {
250 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
251 animations_
[i
]->set_affects_active_observers(
252 animations_
[i
]->affects_pending_observers());
254 animations_
.erase(cc::remove_if(&animations_
,
257 AffectsNoObservers()),
259 UpdateActivation(NormalActivation
);
262 void LayerAnimationController::AddAnimation(scoped_ptr
<Animation
> animation
) {
263 animations_
.push_back(animation
.Pass());
264 needs_to_start_animations_
= true;
265 UpdateActivation(NormalActivation
);
268 Animation
* LayerAnimationController::GetAnimation(
270 Animation::TargetProperty target_property
) const {
271 for (size_t i
= 0; i
< animations_
.size(); ++i
)
272 if (animations_
[i
]->group() == group_id
&&
273 animations_
[i
]->target_property() == target_property
)
274 return animations_
[i
];
278 Animation
* LayerAnimationController::GetAnimation(
279 Animation::TargetProperty target_property
) const {
280 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
281 size_t index
= animations_
.size() - i
- 1;
282 if (animations_
[index
]->target_property() == target_property
)
283 return animations_
[index
];
288 bool LayerAnimationController::HasActiveAnimation() const {
289 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
290 if (!animations_
[i
]->is_finished())
296 bool LayerAnimationController::IsAnimatingProperty(
297 Animation::TargetProperty target_property
) const {
298 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
299 if (!animations_
[i
]->is_finished() &&
300 animations_
[i
]->InEffect(last_tick_time_
) &&
301 animations_
[i
]->target_property() == target_property
)
307 void LayerAnimationController::SetAnimationRegistrar(
308 AnimationRegistrar
* registrar
) {
309 if (registrar_
== registrar
)
313 registrar_
->UnregisterAnimationController(this);
315 registrar_
= registrar
;
317 registrar_
->RegisterAnimationController(this);
319 UpdateActivation(ForceActivation
);
322 void LayerAnimationController::NotifyAnimationStarted(
323 const AnimationEvent
& event
) {
324 if (event
.is_impl_only
) {
325 FOR_EACH_OBSERVER(LayerAnimationEventObserver
, event_observers_
,
326 OnAnimationStarted(event
));
327 if (layer_animation_delegate_
)
328 layer_animation_delegate_
->NotifyAnimationStarted(
329 event
.monotonic_time
, event
.target_property
, event
.group_id
);
333 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
334 if (animations_
[i
]->group() == event
.group_id
&&
335 animations_
[i
]->target_property() == event
.target_property
&&
336 animations_
[i
]->needs_synchronized_start_time()) {
337 animations_
[i
]->set_needs_synchronized_start_time(false);
338 if (!animations_
[i
]->has_set_start_time())
339 animations_
[i
]->set_start_time(event
.monotonic_time
);
341 FOR_EACH_OBSERVER(LayerAnimationEventObserver
, event_observers_
,
342 OnAnimationStarted(event
));
343 if (layer_animation_delegate_
)
344 layer_animation_delegate_
->NotifyAnimationStarted(
345 event
.monotonic_time
, event
.target_property
, event
.group_id
);
352 void LayerAnimationController::NotifyAnimationFinished(
353 const AnimationEvent
& event
) {
354 if (event
.is_impl_only
) {
355 if (layer_animation_delegate_
)
356 layer_animation_delegate_
->NotifyAnimationFinished(
357 event
.monotonic_time
, event
.target_property
, event
.group_id
);
361 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
362 if (animations_
[i
]->group() == event
.group_id
&&
363 animations_
[i
]->target_property() == event
.target_property
) {
364 animations_
[i
]->set_received_finished_event(true);
365 if (layer_animation_delegate_
)
366 layer_animation_delegate_
->NotifyAnimationFinished(
367 event
.monotonic_time
, event
.target_property
, event
.group_id
);
374 void LayerAnimationController::NotifyAnimationAborted(
375 const AnimationEvent
& event
) {
376 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
377 if (animations_
[i
]->group() == event
.group_id
&&
378 animations_
[i
]->target_property() == event
.target_property
) {
379 animations_
[i
]->SetRunState(Animation::Aborted
, event
.monotonic_time
);
384 void LayerAnimationController::NotifyAnimationPropertyUpdate(
385 const AnimationEvent
& event
) {
386 bool notify_active_observers
= true;
387 bool notify_pending_observers
= true;
388 switch (event
.target_property
) {
389 case Animation::Opacity
:
390 NotifyObserversOpacityAnimated(
391 event
.opacity
, notify_active_observers
, notify_pending_observers
);
393 case Animation::Transform
:
394 NotifyObserversTransformAnimated(
395 event
.transform
, notify_active_observers
, notify_pending_observers
);
402 void LayerAnimationController::AddValueObserver(
403 LayerAnimationValueObserver
* observer
) {
404 if (!value_observers_
.HasObserver(observer
))
405 value_observers_
.AddObserver(observer
);
408 void LayerAnimationController::RemoveValueObserver(
409 LayerAnimationValueObserver
* observer
) {
410 value_observers_
.RemoveObserver(observer
);
413 void LayerAnimationController::AddEventObserver(
414 LayerAnimationEventObserver
* observer
) {
415 if (!event_observers_
.HasObserver(observer
))
416 event_observers_
.AddObserver(observer
);
419 void LayerAnimationController::RemoveEventObserver(
420 LayerAnimationEventObserver
* observer
) {
421 event_observers_
.RemoveObserver(observer
);
424 bool LayerAnimationController::HasFilterAnimationThatInflatesBounds() const {
425 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
426 if (!animations_
[i
]->is_finished() &&
427 animations_
[i
]->target_property() == Animation::Filter
&&
430 ->ToFilterAnimationCurve()
431 ->HasFilterThatMovesPixels())
438 bool LayerAnimationController::HasTransformAnimationThatInflatesBounds() const {
439 return IsAnimatingProperty(Animation::Transform
);
442 bool LayerAnimationController::FilterAnimationBoundsForBox(
443 const gfx::BoxF
& box
, gfx::BoxF
* bounds
) const {
444 // TODO(avallee): Implement.
448 bool LayerAnimationController::TransformAnimationBoundsForBox(
449 const gfx::BoxF
& box
,
450 gfx::BoxF
* bounds
) const {
451 DCHECK(HasTransformAnimationThatInflatesBounds())
452 << "TransformAnimationBoundsForBox will give incorrect results if there "
453 << "are no transform animations affecting bounds, non-animated transform "
456 // Compute bounds based on animations for which is_finished() is false.
457 // Do nothing if there are no such animations; in this case, it is assumed
458 // that callers will take care of computing bounds based on the owning layer's
460 *bounds
= gfx::BoxF();
461 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
462 if (animations_
[i
]->is_finished() ||
463 animations_
[i
]->target_property() != Animation::Transform
)
466 const TransformAnimationCurve
* transform_animation_curve
=
467 animations_
[i
]->curve()->ToTransformAnimationCurve();
468 gfx::BoxF animation_bounds
;
470 transform_animation_curve
->AnimatedBoundsForBox(box
, &animation_bounds
);
473 bounds
->Union(animation_bounds
);
479 bool LayerAnimationController::HasAnimationThatAffectsScale() const {
480 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
481 if (animations_
[i
]->is_finished() ||
482 animations_
[i
]->target_property() != Animation::Transform
)
485 const TransformAnimationCurve
* transform_animation_curve
=
486 animations_
[i
]->curve()->ToTransformAnimationCurve();
487 if (transform_animation_curve
->AffectsScale())
494 bool LayerAnimationController::HasOnlyTranslationTransforms() const {
495 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
496 if (animations_
[i
]->is_finished() ||
497 animations_
[i
]->target_property() != Animation::Transform
)
500 const TransformAnimationCurve
* transform_animation_curve
=
501 animations_
[i
]->curve()->ToTransformAnimationCurve();
502 if (!transform_animation_curve
->IsTranslation())
509 bool LayerAnimationController::AnimationsPreserveAxisAlignment() const {
510 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
511 if (animations_
[i
]->is_finished() ||
512 animations_
[i
]->target_property() != Animation::Transform
)
515 const TransformAnimationCurve
* transform_animation_curve
=
516 animations_
[i
]->curve()->ToTransformAnimationCurve();
517 if (!transform_animation_curve
->PreservesAxisAlignment())
524 bool LayerAnimationController::MaximumTargetScale(float* max_scale
) const {
526 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
527 if (animations_
[i
]->is_finished() ||
528 animations_
[i
]->target_property() != Animation::Transform
)
531 bool forward_direction
= true;
532 switch (animations_
[i
]->direction()) {
533 case Animation::Normal
:
534 case Animation::Alternate
:
535 forward_direction
= animations_
[i
]->playback_rate() >= 0.0;
537 case Animation::Reverse
:
538 case Animation::AlternateReverse
:
539 forward_direction
= animations_
[i
]->playback_rate() < 0.0;
543 const TransformAnimationCurve
* transform_animation_curve
=
544 animations_
[i
]->curve()->ToTransformAnimationCurve();
545 float animation_scale
= 0.f
;
546 if (!transform_animation_curve
->MaximumTargetScale(forward_direction
,
549 *max_scale
= std::max(*max_scale
, animation_scale
);
555 void LayerAnimationController::PushNewAnimationsToImplThread(
556 LayerAnimationController
* controller_impl
) const {
557 // Any new animations owned by the main thread's controller are cloned and
558 // add to the impl thread's controller.
559 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
560 // If the animation is already running on the impl thread, there is no
561 // need to copy it over.
562 if (controller_impl
->GetAnimation(animations_
[i
]->group(),
563 animations_
[i
]->target_property()))
566 // If the animation is not running on the impl thread, it does not
567 // necessarily mean that it needs to be copied over and started; it may
568 // have already finished. In this case, the impl thread animation will
569 // have already notified that it has started and the main thread animation
570 // will no longer need
571 // a synchronized start time.
572 if (!animations_
[i
]->needs_synchronized_start_time())
575 // Scroll animations always start at the current scroll offset.
576 if (animations_
[i
]->target_property() == Animation::ScrollOffset
) {
577 gfx::ScrollOffset current_scroll_offset
;
578 if (controller_impl
->value_provider_
) {
579 current_scroll_offset
=
580 controller_impl
->value_provider_
->ScrollOffsetForAnimation();
582 // The owning layer isn't yet in the active tree, so the main thread
583 // scroll offset will be up-to-date.
584 current_scroll_offset
= value_provider_
->ScrollOffsetForAnimation();
586 animations_
[i
]->curve()->ToScrollOffsetAnimationCurve()->SetInitialValue(
587 current_scroll_offset
);
590 // The new animation should be set to run as soon as possible.
591 Animation::RunState initial_run_state
=
592 Animation::WaitingForTargetAvailability
;
593 scoped_ptr
<Animation
> to_add(
594 animations_
[i
]->CloneAndInitialize(initial_run_state
));
595 DCHECK(!to_add
->needs_synchronized_start_time());
596 to_add
->set_affects_active_observers(false);
597 controller_impl
->AddAnimation(to_add
.Pass());
601 static bool IsCompleted(
602 Animation
* animation
,
603 const LayerAnimationController
* main_thread_controller
) {
604 if (animation
->is_impl_only()) {
605 return (animation
->run_state() == Animation::WaitingForDeletion
);
607 return !main_thread_controller
->GetAnimation(animation
->group(),
608 animation
->target_property());
612 static bool AffectsActiveOnlyAndIsWaitingForDeletion(Animation
* animation
) {
613 return animation
->run_state() == Animation::WaitingForDeletion
&&
614 !animation
->affects_pending_observers();
617 void LayerAnimationController::RemoveAnimationsCompletedOnMainThread(
618 LayerAnimationController
* controller_impl
) const {
619 // Animations removed on the main thread should no longer affect pending
620 // observers, and should stop affecting active observers after the next call
621 // to ActivateAnimations. If already WaitingForDeletion, they can be removed
623 ScopedPtrVector
<Animation
>& animations
= controller_impl
->animations_
;
624 for (size_t i
= 0; i
< animations
.size(); ++i
) {
625 if (IsCompleted(animations
[i
], this))
626 animations
[i
]->set_affects_pending_observers(false);
628 animations
.erase(cc::remove_if(&animations
,
631 AffectsActiveOnlyAndIsWaitingForDeletion
),
635 void LayerAnimationController::PushPropertiesToImplThread(
636 LayerAnimationController
* controller_impl
) const {
637 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
638 Animation
* current_impl
= controller_impl
->GetAnimation(
639 animations_
[i
]->group(), animations_
[i
]->target_property());
641 animations_
[i
]->PushPropertiesTo(current_impl
);
645 void LayerAnimationController::StartAnimations(base::TimeTicks monotonic_time
) {
646 DCHECK(needs_to_start_animations_
);
647 needs_to_start_animations_
= false;
648 // First collect running properties affecting each type of observer.
649 TargetProperties blocked_properties_for_active_observers
;
650 TargetProperties blocked_properties_for_pending_observers
;
651 std::vector
<size_t> animations_waiting_for_target
;
653 animations_waiting_for_target
.reserve(animations_
.size());
654 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
655 if (animations_
[i
]->run_state() == Animation::Starting
||
656 animations_
[i
]->run_state() == Animation::Running
) {
657 if (animations_
[i
]->affects_active_observers()) {
658 blocked_properties_for_active_observers
.insert(
659 animations_
[i
]->target_property());
661 if (animations_
[i
]->affects_pending_observers()) {
662 blocked_properties_for_pending_observers
.insert(
663 animations_
[i
]->target_property());
665 } else if (animations_
[i
]->run_state() ==
666 Animation::WaitingForTargetAvailability
) {
667 animations_waiting_for_target
.push_back(i
);
671 for (size_t i
= 0; i
< animations_waiting_for_target
.size(); ++i
) {
672 // Collect all properties for animations with the same group id (they
673 // should all also be in the list of animations).
674 size_t animation_index
= animations_waiting_for_target
[i
];
675 Animation
* animation_waiting_for_target
= animations_
[animation_index
];
676 // Check for the run state again even though the animation was waiting
677 // for target because it might have changed the run state while handling
678 // previous animation in this loop (if they belong to same group).
679 if (animation_waiting_for_target
->run_state() ==
680 Animation::WaitingForTargetAvailability
) {
681 TargetProperties enqueued_properties
;
682 bool affects_active_observers
=
683 animation_waiting_for_target
->affects_active_observers();
684 bool affects_pending_observers
=
685 animation_waiting_for_target
->affects_pending_observers();
686 enqueued_properties
.insert(
687 animation_waiting_for_target
->target_property());
688 for (size_t j
= animation_index
+ 1; j
< animations_
.size(); ++j
) {
689 if (animation_waiting_for_target
->group() == animations_
[j
]->group()) {
690 enqueued_properties
.insert(animations_
[j
]->target_property());
691 affects_active_observers
|=
692 animations_
[j
]->affects_active_observers();
693 affects_pending_observers
|=
694 animations_
[j
]->affects_pending_observers();
698 // Check to see if intersection of the list of properties affected by
699 // the group and the list of currently blocked properties is null, taking
700 // into account the type(s) of observers affected by the group. In any
701 // case, the group's target properties need to be added to the lists of
702 // blocked properties.
703 bool null_intersection
= true;
704 for (TargetProperties::iterator p_iter
= enqueued_properties
.begin();
705 p_iter
!= enqueued_properties
.end();
707 if (affects_active_observers
&&
708 !blocked_properties_for_active_observers
.insert(*p_iter
).second
)
709 null_intersection
= false;
710 if (affects_pending_observers
&&
711 !blocked_properties_for_pending_observers
.insert(*p_iter
).second
)
712 null_intersection
= false;
715 // If the intersection is null, then we are free to start the animations
717 if (null_intersection
) {
718 animation_waiting_for_target
->SetRunState(Animation::Starting
,
720 for (size_t j
= animation_index
+ 1; j
< animations_
.size(); ++j
) {
721 if (animation_waiting_for_target
->group() ==
722 animations_
[j
]->group()) {
723 animations_
[j
]->SetRunState(Animation::Starting
, monotonic_time
);
727 needs_to_start_animations_
= true;
733 void LayerAnimationController::PromoteStartedAnimations(
734 base::TimeTicks monotonic_time
,
735 AnimationEventsVector
* events
) {
736 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
737 if (animations_
[i
]->run_state() == Animation::Starting
&&
738 animations_
[i
]->affects_active_observers()) {
739 animations_
[i
]->SetRunState(Animation::Running
, monotonic_time
);
740 if (!animations_
[i
]->has_set_start_time() &&
741 !animations_
[i
]->needs_synchronized_start_time())
742 animations_
[i
]->set_start_time(monotonic_time
);
744 AnimationEvent
started_event(AnimationEvent::Started
,
746 animations_
[i
]->group(),
747 animations_
[i
]->target_property(),
749 started_event
.is_impl_only
= animations_
[i
]->is_impl_only();
750 if (started_event
.is_impl_only
)
751 NotifyAnimationStarted(started_event
);
753 events
->push_back(started_event
);
759 void LayerAnimationController::MarkFinishedAnimations(
760 base::TimeTicks monotonic_time
) {
761 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
762 if (animations_
[i
]->IsFinishedAt(monotonic_time
) &&
763 animations_
[i
]->run_state() != Animation::Aborted
&&
764 animations_
[i
]->run_state() != Animation::WaitingForDeletion
)
765 animations_
[i
]->SetRunState(Animation::Finished
, monotonic_time
);
769 void LayerAnimationController::MarkAnimationsForDeletion(
770 base::TimeTicks monotonic_time
,
771 AnimationEventsVector
* events
) {
772 bool marked_animations_for_deletions
= false;
773 std::vector
<size_t> animations_with_same_group_id
;
775 animations_with_same_group_id
.reserve(animations_
.size());
776 // Non-aborted animations are marked for deletion after a corresponding
777 // AnimationEvent::Finished event is sent or received. This means that if
778 // we don't have an events vector, we must ensure that non-aborted animations
779 // have received a finished event before marking them for deletion.
780 for (size_t i
= 0; i
< animations_
.size(); i
++) {
781 int group_id
= animations_
[i
]->group();
782 if (animations_
[i
]->run_state() == Animation::Aborted
) {
783 if (events
&& !animations_
[i
]->is_impl_only()) {
784 AnimationEvent
aborted_event(AnimationEvent::Aborted
,
787 animations_
[i
]->target_property(),
789 events
->push_back(aborted_event
);
791 animations_
[i
]->SetRunState(Animation::WaitingForDeletion
,
793 marked_animations_for_deletions
= true;
797 bool all_anims_with_same_id_are_finished
= false;
799 // Since deleting an animation on the main thread leads to its deletion
800 // on the impl thread, we only mark a Finished main thread animation for
801 // deletion once it has received a Finished event from the impl thread.
802 bool animation_i_will_send_or_has_received_finish_event
=
803 events
|| animations_
[i
]->received_finished_event();
804 // If an animation is finished, and not already marked for deletion,
805 // find out if all other animations in the same group are also finished.
806 if (animations_
[i
]->run_state() == Animation::Finished
&&
807 animation_i_will_send_or_has_received_finish_event
) {
808 // Clear the animations_with_same_group_id if it was added for
809 // the previous animation's iteration.
810 if (animations_with_same_group_id
.size() > 0)
811 animations_with_same_group_id
.clear();
812 all_anims_with_same_id_are_finished
= true;
813 for (size_t j
= 0; j
< animations_
.size(); ++j
) {
814 bool animation_j_will_send_or_has_received_finish_event
=
815 events
|| animations_
[j
]->received_finished_event();
816 if (group_id
== animations_
[j
]->group()) {
817 if (!animations_
[j
]->is_finished() ||
818 (animations_
[j
]->run_state() == Animation::Finished
&&
819 !animation_j_will_send_or_has_received_finish_event
)) {
820 all_anims_with_same_id_are_finished
= false;
823 animations_
[j
]->run_state() != Animation::Aborted
) {
824 // Mark down the animations which belong to the same group
825 // and is not yet aborted. If this current iteration finds that all
826 // animations with same ID are finished, then the marked
827 // animations below will be set to WaitingForDeletion in next
829 animations_with_same_group_id
.push_back(j
);
834 if (all_anims_with_same_id_are_finished
) {
835 // We now need to remove all animations with the same group id as
836 // group_id (and send along animation finished notifications, if
838 for (size_t j
= 0; j
< animations_with_same_group_id
.size(); j
++) {
839 size_t animation_index
= animations_with_same_group_id
[j
];
841 AnimationEvent
finished_event(
842 AnimationEvent::Finished
,
844 animations_
[animation_index
]->group(),
845 animations_
[animation_index
]->target_property(),
847 finished_event
.is_impl_only
=
848 animations_
[animation_index
]->is_impl_only();
849 if (finished_event
.is_impl_only
)
850 NotifyAnimationFinished(finished_event
);
852 events
->push_back(finished_event
);
854 animations_
[animation_index
]->SetRunState(
855 Animation::WaitingForDeletion
, monotonic_time
);
857 marked_animations_for_deletions
= true;
860 if (marked_animations_for_deletions
)
861 NotifyObserversAnimationWaitingForDeletion();
864 static bool IsWaitingForDeletion(Animation
* animation
) {
865 return animation
->run_state() == Animation::WaitingForDeletion
;
868 void LayerAnimationController::PurgeAnimationsMarkedForDeletion() {
869 animations_
.erase(cc::remove_if(&animations_
,
872 IsWaitingForDeletion
),
876 void LayerAnimationController::TickAnimations(base::TimeTicks monotonic_time
) {
877 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
878 if (animations_
[i
]->run_state() == Animation::Starting
||
879 animations_
[i
]->run_state() == Animation::Running
||
880 animations_
[i
]->run_state() == Animation::Paused
) {
881 if (!animations_
[i
]->InEffect(monotonic_time
))
884 base::TimeDelta trimmed
=
885 animations_
[i
]->TrimTimeToCurrentIteration(monotonic_time
);
887 switch (animations_
[i
]->target_property()) {
888 case Animation::Transform
: {
889 const TransformAnimationCurve
* transform_animation_curve
=
890 animations_
[i
]->curve()->ToTransformAnimationCurve();
891 const gfx::Transform transform
=
892 transform_animation_curve
->GetValue(trimmed
);
893 NotifyObserversTransformAnimated(
895 animations_
[i
]->affects_active_observers(),
896 animations_
[i
]->affects_pending_observers());
900 case Animation::Opacity
: {
901 const FloatAnimationCurve
* float_animation_curve
=
902 animations_
[i
]->curve()->ToFloatAnimationCurve();
903 const float opacity
= std::max(
904 std::min(float_animation_curve
->GetValue(trimmed
), 1.0f
), 0.f
);
905 NotifyObserversOpacityAnimated(
907 animations_
[i
]->affects_active_observers(),
908 animations_
[i
]->affects_pending_observers());
912 case Animation::Filter
: {
913 const FilterAnimationCurve
* filter_animation_curve
=
914 animations_
[i
]->curve()->ToFilterAnimationCurve();
915 const FilterOperations filter
=
916 filter_animation_curve
->GetValue(trimmed
);
917 NotifyObserversFilterAnimated(
919 animations_
[i
]->affects_active_observers(),
920 animations_
[i
]->affects_pending_observers());
924 case Animation::BackgroundColor
: {
925 // Not yet implemented.
929 case Animation::ScrollOffset
: {
930 const ScrollOffsetAnimationCurve
* scroll_offset_animation_curve
=
931 animations_
[i
]->curve()->ToScrollOffsetAnimationCurve();
932 const gfx::ScrollOffset scroll_offset
=
933 scroll_offset_animation_curve
->GetValue(trimmed
);
934 NotifyObserversScrollOffsetAnimated(
936 animations_
[i
]->affects_active_observers(),
937 animations_
[i
]->affects_pending_observers());
941 // Do nothing for sentinel value.
942 case Animation::TargetPropertyEnumSize
:
949 void LayerAnimationController::UpdateActivation(UpdateActivationType type
) {
950 bool force
= type
== ForceActivation
;
952 bool was_active
= is_active_
;
954 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
955 if (animations_
[i
]->run_state() != Animation::WaitingForDeletion
) {
961 if (is_active_
&& (!was_active
|| force
))
962 registrar_
->DidActivateAnimationController(this);
963 else if (!is_active_
&& (was_active
|| force
))
964 registrar_
->DidDeactivateAnimationController(this);
968 void LayerAnimationController::NotifyObserversOpacityAnimated(
970 bool notify_active_observers
,
971 bool notify_pending_observers
) {
972 if (value_observers_
.might_have_observers()) {
973 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
975 LayerAnimationValueObserver
* obs
;
976 while ((obs
= it
.GetNext()) != nullptr) {
977 if ((notify_active_observers
&& notify_pending_observers
) ||
978 (notify_active_observers
&& obs
->IsActive()) ||
979 (notify_pending_observers
&& !obs
->IsActive()))
980 obs
->OnOpacityAnimated(opacity
);
985 void LayerAnimationController::NotifyObserversTransformAnimated(
986 const gfx::Transform
& transform
,
987 bool notify_active_observers
,
988 bool notify_pending_observers
) {
989 if (value_observers_
.might_have_observers()) {
990 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
992 LayerAnimationValueObserver
* obs
;
993 while ((obs
= it
.GetNext()) != nullptr) {
994 if ((notify_active_observers
&& notify_pending_observers
) ||
995 (notify_active_observers
&& obs
->IsActive()) ||
996 (notify_pending_observers
&& !obs
->IsActive()))
997 obs
->OnTransformAnimated(transform
);
1002 void LayerAnimationController::NotifyObserversFilterAnimated(
1003 const FilterOperations
& filters
,
1004 bool notify_active_observers
,
1005 bool notify_pending_observers
) {
1006 if (value_observers_
.might_have_observers()) {
1007 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
1009 LayerAnimationValueObserver
* obs
;
1010 while ((obs
= it
.GetNext()) != nullptr) {
1011 if ((notify_active_observers
&& notify_pending_observers
) ||
1012 (notify_active_observers
&& obs
->IsActive()) ||
1013 (notify_pending_observers
&& !obs
->IsActive()))
1014 obs
->OnFilterAnimated(filters
);
1019 void LayerAnimationController::NotifyObserversScrollOffsetAnimated(
1020 const gfx::ScrollOffset
& scroll_offset
,
1021 bool notify_active_observers
,
1022 bool notify_pending_observers
) {
1023 if (value_observers_
.might_have_observers()) {
1024 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
1026 LayerAnimationValueObserver
* obs
;
1027 while ((obs
= it
.GetNext()) != nullptr) {
1028 if ((notify_active_observers
&& notify_pending_observers
) ||
1029 (notify_active_observers
&& obs
->IsActive()) ||
1030 (notify_pending_observers
&& !obs
->IsActive()))
1031 obs
->OnScrollOffsetAnimated(scroll_offset
);
1036 void LayerAnimationController::NotifyObserversAnimationWaitingForDeletion() {
1037 FOR_EACH_OBSERVER(LayerAnimationValueObserver
,
1039 OnAnimationWaitingForDeletion());
1042 void LayerAnimationController::NotifyObserversScrollOffsetAnimationRemoved() {
1043 FOR_EACH_OBSERVER(LayerAnimationValueObserver
, value_observers_
,
1044 OnScrollOffsetAnimationRemoved());
1047 bool LayerAnimationController::HasValueObserver() {
1048 if (value_observers_
.might_have_observers()) {
1049 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
1051 return it
.GetNext() != nullptr;
1056 bool LayerAnimationController::HasActiveValueObserver() {
1057 if (value_observers_
.might_have_observers()) {
1058 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
1060 LayerAnimationValueObserver
* obs
;
1061 while ((obs
= it
.GetNext()) != nullptr)
1062 if (obs
->IsActive())