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
))
152 animation
->TrimTimeToCurrentIteration(monotonic_time
).InSecondsF();
153 switch (animation
->target_property()) {
154 case Animation::Opacity
: {
155 AnimationEvent
event(AnimationEvent::PropertyUpdate
,
160 const FloatAnimationCurve
* float_animation_curve
=
161 animation
->curve()->ToFloatAnimationCurve();
162 event
.opacity
= float_animation_curve
->GetValue(trimmed
);
163 event
.is_impl_only
= true;
164 events
->push_back(event
);
168 case Animation::Transform
: {
169 AnimationEvent
event(AnimationEvent::PropertyUpdate
,
172 Animation::Transform
,
174 const TransformAnimationCurve
* transform_animation_curve
=
175 animation
->curve()->ToTransformAnimationCurve();
176 event
.transform
= transform_animation_curve
->GetValue(trimmed
);
177 event
.is_impl_only
= true;
178 events
->push_back(event
);
182 case Animation::Filter
: {
183 AnimationEvent
event(AnimationEvent::PropertyUpdate
,
188 const FilterAnimationCurve
* filter_animation_curve
=
189 animation
->curve()->ToFilterAnimationCurve();
190 event
.filters
= filter_animation_curve
->GetValue(trimmed
);
191 event
.is_impl_only
= true;
192 events
->push_back(event
);
196 case Animation::BackgroundColor
: { break; }
198 case Animation::ScrollOffset
: {
199 // Impl-side changes to scroll offset are already sent back to the
200 // main thread (e.g. for user-driven scrolling), so a PropertyUpdate
205 case Animation::TargetPropertyEnumSize
:
211 void LayerAnimationController::UpdateState(bool start_ready_animations
,
212 AnimationEventsVector
* events
) {
213 if (!HasActiveValueObserver())
216 // Animate hasn't been called, this happens if an observer has been added
217 // between the Commit and Draw phases.
218 if (last_tick_time_
== base::TimeTicks())
221 if (start_ready_animations
)
222 PromoteStartedAnimations(last_tick_time_
, events
);
224 MarkFinishedAnimations(last_tick_time_
);
225 MarkAnimationsForDeletion(last_tick_time_
, events
);
227 if (needs_to_start_animations_
&& start_ready_animations
) {
228 StartAnimations(last_tick_time_
);
229 PromoteStartedAnimations(last_tick_time_
, events
);
232 AccumulatePropertyUpdates(last_tick_time_
, events
);
234 UpdateActivation(NormalActivation
);
237 struct AffectsNoObservers
{
238 bool operator()(Animation
* animation
) const {
239 return !animation
->affects_active_observers() &&
240 !animation
->affects_pending_observers();
244 void LayerAnimationController::ActivateAnimations() {
245 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
246 animations_
[i
]->set_affects_active_observers(
247 animations_
[i
]->affects_pending_observers());
249 animations_
.erase(cc::remove_if(&animations_
,
252 AffectsNoObservers()),
254 UpdateActivation(NormalActivation
);
257 void LayerAnimationController::AddAnimation(scoped_ptr
<Animation
> animation
) {
258 animations_
.push_back(animation
.Pass());
259 needs_to_start_animations_
= true;
260 UpdateActivation(NormalActivation
);
263 Animation
* LayerAnimationController::GetAnimation(
265 Animation::TargetProperty target_property
) const {
266 for (size_t i
= 0; i
< animations_
.size(); ++i
)
267 if (animations_
[i
]->group() == group_id
&&
268 animations_
[i
]->target_property() == target_property
)
269 return animations_
[i
];
273 Animation
* LayerAnimationController::GetAnimation(
274 Animation::TargetProperty target_property
) const {
275 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
276 size_t index
= animations_
.size() - i
- 1;
277 if (animations_
[index
]->target_property() == target_property
)
278 return animations_
[index
];
283 bool LayerAnimationController::HasActiveAnimation() const {
284 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
285 if (!animations_
[i
]->is_finished())
291 bool LayerAnimationController::IsAnimatingProperty(
292 Animation::TargetProperty target_property
) const {
293 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
294 if (!animations_
[i
]->is_finished() &&
295 animations_
[i
]->InEffect(last_tick_time_
) &&
296 animations_
[i
]->target_property() == target_property
)
302 void LayerAnimationController::SetAnimationRegistrar(
303 AnimationRegistrar
* registrar
) {
304 if (registrar_
== registrar
)
308 registrar_
->UnregisterAnimationController(this);
310 registrar_
= registrar
;
312 registrar_
->RegisterAnimationController(this);
314 UpdateActivation(ForceActivation
);
317 void LayerAnimationController::NotifyAnimationStarted(
318 const AnimationEvent
& event
) {
319 if (event
.is_impl_only
) {
320 FOR_EACH_OBSERVER(LayerAnimationEventObserver
, event_observers_
,
321 OnAnimationStarted(event
));
322 if (layer_animation_delegate_
)
323 layer_animation_delegate_
->NotifyAnimationStarted(
324 event
.monotonic_time
, event
.target_property
, event
.group_id
);
328 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
329 if (animations_
[i
]->group() == event
.group_id
&&
330 animations_
[i
]->target_property() == event
.target_property
&&
331 animations_
[i
]->needs_synchronized_start_time()) {
332 animations_
[i
]->set_needs_synchronized_start_time(false);
333 if (!animations_
[i
]->has_set_start_time())
334 animations_
[i
]->set_start_time(event
.monotonic_time
);
336 FOR_EACH_OBSERVER(LayerAnimationEventObserver
, event_observers_
,
337 OnAnimationStarted(event
));
338 if (layer_animation_delegate_
)
339 layer_animation_delegate_
->NotifyAnimationStarted(
340 event
.monotonic_time
, event
.target_property
, event
.group_id
);
347 void LayerAnimationController::NotifyAnimationFinished(
348 const AnimationEvent
& event
) {
349 if (event
.is_impl_only
) {
350 if (layer_animation_delegate_
)
351 layer_animation_delegate_
->NotifyAnimationFinished(
352 event
.monotonic_time
, event
.target_property
, event
.group_id
);
356 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
357 if (animations_
[i
]->group() == event
.group_id
&&
358 animations_
[i
]->target_property() == event
.target_property
) {
359 animations_
[i
]->set_received_finished_event(true);
360 if (layer_animation_delegate_
)
361 layer_animation_delegate_
->NotifyAnimationFinished(
362 event
.monotonic_time
, event
.target_property
, event
.group_id
);
369 void LayerAnimationController::NotifyAnimationAborted(
370 const AnimationEvent
& event
) {
371 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
372 if (animations_
[i
]->group() == event
.group_id
&&
373 animations_
[i
]->target_property() == event
.target_property
) {
374 animations_
[i
]->SetRunState(Animation::Aborted
, event
.monotonic_time
);
379 void LayerAnimationController::NotifyAnimationPropertyUpdate(
380 const AnimationEvent
& event
) {
381 bool notify_active_observers
= true;
382 bool notify_pending_observers
= true;
383 switch (event
.target_property
) {
384 case Animation::Opacity
:
385 NotifyObserversOpacityAnimated(
386 event
.opacity
, notify_active_observers
, notify_pending_observers
);
388 case Animation::Transform
:
389 NotifyObserversTransformAnimated(
390 event
.transform
, notify_active_observers
, notify_pending_observers
);
397 void LayerAnimationController::AddValueObserver(
398 LayerAnimationValueObserver
* observer
) {
399 if (!value_observers_
.HasObserver(observer
))
400 value_observers_
.AddObserver(observer
);
403 void LayerAnimationController::RemoveValueObserver(
404 LayerAnimationValueObserver
* observer
) {
405 value_observers_
.RemoveObserver(observer
);
408 void LayerAnimationController::AddEventObserver(
409 LayerAnimationEventObserver
* observer
) {
410 if (!event_observers_
.HasObserver(observer
))
411 event_observers_
.AddObserver(observer
);
414 void LayerAnimationController::RemoveEventObserver(
415 LayerAnimationEventObserver
* observer
) {
416 event_observers_
.RemoveObserver(observer
);
419 bool LayerAnimationController::HasFilterAnimationThatInflatesBounds() const {
420 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
421 if (!animations_
[i
]->is_finished() &&
422 animations_
[i
]->target_property() == Animation::Filter
&&
425 ->ToFilterAnimationCurve()
426 ->HasFilterThatMovesPixels())
433 bool LayerAnimationController::HasTransformAnimationThatInflatesBounds() const {
434 return IsAnimatingProperty(Animation::Transform
);
437 bool LayerAnimationController::FilterAnimationBoundsForBox(
438 const gfx::BoxF
& box
, gfx::BoxF
* bounds
) const {
439 // TODO(avallee): Implement.
443 bool LayerAnimationController::TransformAnimationBoundsForBox(
444 const gfx::BoxF
& box
,
445 gfx::BoxF
* bounds
) const {
446 DCHECK(HasTransformAnimationThatInflatesBounds())
447 << "TransformAnimationBoundsForBox will give incorrect results if there "
448 << "are no transform animations affecting bounds, non-animated transform "
451 // Compute bounds based on animations for which is_finished() is false.
452 // Do nothing if there are no such animations; in this case, it is assumed
453 // that callers will take care of computing bounds based on the owning layer's
455 *bounds
= gfx::BoxF();
456 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
457 if (animations_
[i
]->is_finished() ||
458 animations_
[i
]->target_property() != Animation::Transform
)
461 const TransformAnimationCurve
* transform_animation_curve
=
462 animations_
[i
]->curve()->ToTransformAnimationCurve();
463 gfx::BoxF animation_bounds
;
465 transform_animation_curve
->AnimatedBoundsForBox(box
, &animation_bounds
);
468 bounds
->Union(animation_bounds
);
474 bool LayerAnimationController::HasAnimationThatAffectsScale() const {
475 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
476 if (animations_
[i
]->is_finished() ||
477 animations_
[i
]->target_property() != Animation::Transform
)
480 const TransformAnimationCurve
* transform_animation_curve
=
481 animations_
[i
]->curve()->ToTransformAnimationCurve();
482 if (transform_animation_curve
->AffectsScale())
489 bool LayerAnimationController::HasOnlyTranslationTransforms() const {
490 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
491 if (animations_
[i
]->is_finished() ||
492 animations_
[i
]->target_property() != Animation::Transform
)
495 const TransformAnimationCurve
* transform_animation_curve
=
496 animations_
[i
]->curve()->ToTransformAnimationCurve();
497 if (!transform_animation_curve
->IsTranslation())
504 bool LayerAnimationController::MaximumTargetScale(float* max_scale
) const {
506 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
507 if (animations_
[i
]->is_finished() ||
508 animations_
[i
]->target_property() != Animation::Transform
)
511 bool forward_direction
= true;
512 switch (animations_
[i
]->direction()) {
513 case Animation::Normal
:
514 case Animation::Alternate
:
515 forward_direction
= animations_
[i
]->playback_rate() >= 0.0;
517 case Animation::Reverse
:
518 case Animation::AlternateReverse
:
519 forward_direction
= animations_
[i
]->playback_rate() < 0.0;
523 const TransformAnimationCurve
* transform_animation_curve
=
524 animations_
[i
]->curve()->ToTransformAnimationCurve();
525 float animation_scale
= 0.f
;
526 if (!transform_animation_curve
->MaximumTargetScale(forward_direction
,
529 *max_scale
= std::max(*max_scale
, animation_scale
);
535 void LayerAnimationController::PushNewAnimationsToImplThread(
536 LayerAnimationController
* controller_impl
) const {
537 // Any new animations owned by the main thread's controller are cloned and
538 // add to the impl thread's controller.
539 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
540 // If the animation is already running on the impl thread, there is no
541 // need to copy it over.
542 if (controller_impl
->GetAnimation(animations_
[i
]->group(),
543 animations_
[i
]->target_property()))
546 // If the animation is not running on the impl thread, it does not
547 // necessarily mean that it needs to be copied over and started; it may
548 // have already finished. In this case, the impl thread animation will
549 // have already notified that it has started and the main thread animation
550 // will no longer need
551 // a synchronized start time.
552 if (!animations_
[i
]->needs_synchronized_start_time())
555 // Scroll animations always start at the current scroll offset.
556 if (animations_
[i
]->target_property() == Animation::ScrollOffset
) {
557 gfx::ScrollOffset current_scroll_offset
;
558 if (controller_impl
->value_provider_
) {
559 current_scroll_offset
=
560 controller_impl
->value_provider_
->ScrollOffsetForAnimation();
562 // The owning layer isn't yet in the active tree, so the main thread
563 // scroll offset will be up-to-date.
564 current_scroll_offset
= value_provider_
->ScrollOffsetForAnimation();
566 animations_
[i
]->curve()->ToScrollOffsetAnimationCurve()->SetInitialValue(
567 current_scroll_offset
);
570 // The new animation should be set to run as soon as possible.
571 Animation::RunState initial_run_state
=
572 Animation::WaitingForTargetAvailability
;
573 scoped_ptr
<Animation
> to_add(
574 animations_
[i
]->CloneAndInitialize(initial_run_state
));
575 DCHECK(!to_add
->needs_synchronized_start_time());
576 to_add
->set_affects_active_observers(false);
577 controller_impl
->AddAnimation(to_add
.Pass());
581 static bool IsCompleted(
582 Animation
* animation
,
583 const LayerAnimationController
* main_thread_controller
) {
584 if (animation
->is_impl_only()) {
585 return (animation
->run_state() == Animation::WaitingForDeletion
);
587 return !main_thread_controller
->GetAnimation(animation
->group(),
588 animation
->target_property());
592 static bool AffectsActiveOnlyAndIsWaitingForDeletion(Animation
* animation
) {
593 return animation
->run_state() == Animation::WaitingForDeletion
&&
594 !animation
->affects_pending_observers();
597 void LayerAnimationController::RemoveAnimationsCompletedOnMainThread(
598 LayerAnimationController
* controller_impl
) const {
599 // Animations removed on the main thread should no longer affect pending
600 // observers, and should stop affecting active observers after the next call
601 // to ActivateAnimations. If already WaitingForDeletion, they can be removed
603 ScopedPtrVector
<Animation
>& animations
= controller_impl
->animations_
;
604 for (size_t i
= 0; i
< animations
.size(); ++i
) {
605 if (IsCompleted(animations
[i
], this))
606 animations
[i
]->set_affects_pending_observers(false);
608 animations
.erase(cc::remove_if(&animations
,
611 AffectsActiveOnlyAndIsWaitingForDeletion
),
615 void LayerAnimationController::PushPropertiesToImplThread(
616 LayerAnimationController
* controller_impl
) const {
617 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
618 Animation
* current_impl
= controller_impl
->GetAnimation(
619 animations_
[i
]->group(), animations_
[i
]->target_property());
621 animations_
[i
]->PushPropertiesTo(current_impl
);
625 void LayerAnimationController::StartAnimations(base::TimeTicks monotonic_time
) {
626 DCHECK(needs_to_start_animations_
);
627 needs_to_start_animations_
= false;
628 // First collect running properties affecting each type of observer.
629 TargetProperties blocked_properties_for_active_observers
;
630 TargetProperties blocked_properties_for_pending_observers
;
631 std::vector
<size_t> animations_waiting_for_target
;
633 animations_waiting_for_target
.reserve(animations_
.size());
634 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
635 if (animations_
[i
]->run_state() == Animation::Starting
||
636 animations_
[i
]->run_state() == Animation::Running
) {
637 if (animations_
[i
]->affects_active_observers()) {
638 blocked_properties_for_active_observers
.insert(
639 animations_
[i
]->target_property());
641 if (animations_
[i
]->affects_pending_observers()) {
642 blocked_properties_for_pending_observers
.insert(
643 animations_
[i
]->target_property());
645 } else if (animations_
[i
]->run_state() ==
646 Animation::WaitingForTargetAvailability
) {
647 animations_waiting_for_target
.push_back(i
);
651 for (size_t i
= 0; i
< animations_waiting_for_target
.size(); ++i
) {
652 // Collect all properties for animations with the same group id (they
653 // should all also be in the list of animations).
654 size_t animation_index
= animations_waiting_for_target
[i
];
655 Animation
* animation_waiting_for_target
= animations_
[animation_index
];
656 // Check for the run state again even though the animation was waiting
657 // for target because it might have changed the run state while handling
658 // previous animation in this loop (if they belong to same group).
659 if (animation_waiting_for_target
->run_state() ==
660 Animation::WaitingForTargetAvailability
) {
661 TargetProperties enqueued_properties
;
662 bool affects_active_observers
=
663 animation_waiting_for_target
->affects_active_observers();
664 bool affects_pending_observers
=
665 animation_waiting_for_target
->affects_pending_observers();
666 enqueued_properties
.insert(
667 animation_waiting_for_target
->target_property());
668 for (size_t j
= animation_index
+ 1; j
< animations_
.size(); ++j
) {
669 if (animation_waiting_for_target
->group() == animations_
[j
]->group()) {
670 enqueued_properties
.insert(animations_
[j
]->target_property());
671 affects_active_observers
|=
672 animations_
[j
]->affects_active_observers();
673 affects_pending_observers
|=
674 animations_
[j
]->affects_pending_observers();
678 // Check to see if intersection of the list of properties affected by
679 // the group and the list of currently blocked properties is null, taking
680 // into account the type(s) of observers affected by the group. In any
681 // case, the group's target properties need to be added to the lists of
682 // blocked properties.
683 bool null_intersection
= true;
684 for (TargetProperties::iterator p_iter
= enqueued_properties
.begin();
685 p_iter
!= enqueued_properties
.end();
687 if (affects_active_observers
&&
688 !blocked_properties_for_active_observers
.insert(*p_iter
).second
)
689 null_intersection
= false;
690 if (affects_pending_observers
&&
691 !blocked_properties_for_pending_observers
.insert(*p_iter
).second
)
692 null_intersection
= false;
695 // If the intersection is null, then we are free to start the animations
697 if (null_intersection
) {
698 animation_waiting_for_target
->SetRunState(Animation::Starting
,
700 for (size_t j
= animation_index
+ 1; j
< animations_
.size(); ++j
) {
701 if (animation_waiting_for_target
->group() ==
702 animations_
[j
]->group()) {
703 animations_
[j
]->SetRunState(Animation::Starting
, monotonic_time
);
707 needs_to_start_animations_
= true;
713 void LayerAnimationController::PromoteStartedAnimations(
714 base::TimeTicks monotonic_time
,
715 AnimationEventsVector
* events
) {
716 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
717 if (animations_
[i
]->run_state() == Animation::Starting
&&
718 animations_
[i
]->affects_active_observers()) {
719 animations_
[i
]->SetRunState(Animation::Running
, monotonic_time
);
720 if (!animations_
[i
]->has_set_start_time() &&
721 !animations_
[i
]->needs_synchronized_start_time())
722 animations_
[i
]->set_start_time(monotonic_time
);
724 AnimationEvent
started_event(AnimationEvent::Started
,
726 animations_
[i
]->group(),
727 animations_
[i
]->target_property(),
729 started_event
.is_impl_only
= animations_
[i
]->is_impl_only();
730 if (started_event
.is_impl_only
)
731 NotifyAnimationStarted(started_event
);
733 events
->push_back(started_event
);
739 void LayerAnimationController::MarkFinishedAnimations(
740 base::TimeTicks monotonic_time
) {
741 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
742 if (animations_
[i
]->IsFinishedAt(monotonic_time
) &&
743 animations_
[i
]->run_state() != Animation::Aborted
&&
744 animations_
[i
]->run_state() != Animation::WaitingForDeletion
)
745 animations_
[i
]->SetRunState(Animation::Finished
, monotonic_time
);
749 void LayerAnimationController::MarkAnimationsForDeletion(
750 base::TimeTicks monotonic_time
,
751 AnimationEventsVector
* events
) {
752 bool marked_animations_for_deletions
= false;
753 std::vector
<size_t> animations_with_same_group_id
;
755 animations_with_same_group_id
.reserve(animations_
.size());
756 // Non-aborted animations are marked for deletion after a corresponding
757 // AnimationEvent::Finished event is sent or received. This means that if
758 // we don't have an events vector, we must ensure that non-aborted animations
759 // have received a finished event before marking them for deletion.
760 for (size_t i
= 0; i
< animations_
.size(); i
++) {
761 int group_id
= animations_
[i
]->group();
762 if (animations_
[i
]->run_state() == Animation::Aborted
) {
763 if (events
&& !animations_
[i
]->is_impl_only()) {
764 AnimationEvent
aborted_event(AnimationEvent::Aborted
,
767 animations_
[i
]->target_property(),
769 events
->push_back(aborted_event
);
771 animations_
[i
]->SetRunState(Animation::WaitingForDeletion
,
773 marked_animations_for_deletions
= true;
777 bool all_anims_with_same_id_are_finished
= false;
779 // Since deleting an animation on the main thread leads to its deletion
780 // on the impl thread, we only mark a Finished main thread animation for
781 // deletion once it has received a Finished event from the impl thread.
782 bool animation_i_will_send_or_has_received_finish_event
=
783 events
|| animations_
[i
]->received_finished_event();
784 // If an animation is finished, and not already marked for deletion,
785 // find out if all other animations in the same group are also finished.
786 if (animations_
[i
]->run_state() == Animation::Finished
&&
787 animation_i_will_send_or_has_received_finish_event
) {
788 // Clear the animations_with_same_group_id if it was added for
789 // the previous animation's iteration.
790 if (animations_with_same_group_id
.size() > 0)
791 animations_with_same_group_id
.clear();
792 all_anims_with_same_id_are_finished
= true;
793 for (size_t j
= 0; j
< animations_
.size(); ++j
) {
794 bool animation_j_will_send_or_has_received_finish_event
=
795 events
|| animations_
[j
]->received_finished_event();
796 if (group_id
== animations_
[j
]->group()) {
797 if (!animations_
[j
]->is_finished() ||
798 (animations_
[j
]->run_state() == Animation::Finished
&&
799 !animation_j_will_send_or_has_received_finish_event
)) {
800 all_anims_with_same_id_are_finished
= false;
803 animations_
[j
]->run_state() != Animation::Aborted
) {
804 // Mark down the animations which belong to the same group
805 // and is not yet aborted. If this current iteration finds that all
806 // animations with same ID are finished, then the marked
807 // animations below will be set to WaitingForDeletion in next
809 animations_with_same_group_id
.push_back(j
);
814 if (all_anims_with_same_id_are_finished
) {
815 // We now need to remove all animations with the same group id as
816 // group_id (and send along animation finished notifications, if
818 for (size_t j
= 0; j
< animations_with_same_group_id
.size(); j
++) {
819 size_t animation_index
= animations_with_same_group_id
[j
];
821 AnimationEvent
finished_event(
822 AnimationEvent::Finished
,
824 animations_
[animation_index
]->group(),
825 animations_
[animation_index
]->target_property(),
827 finished_event
.is_impl_only
=
828 animations_
[animation_index
]->is_impl_only();
829 if (finished_event
.is_impl_only
)
830 NotifyAnimationFinished(finished_event
);
832 events
->push_back(finished_event
);
834 animations_
[animation_index
]->SetRunState(
835 Animation::WaitingForDeletion
, monotonic_time
);
837 marked_animations_for_deletions
= true;
840 if (marked_animations_for_deletions
)
841 NotifyObserversAnimationWaitingForDeletion();
844 static bool IsWaitingForDeletion(Animation
* animation
) {
845 return animation
->run_state() == Animation::WaitingForDeletion
;
848 void LayerAnimationController::PurgeAnimationsMarkedForDeletion() {
849 animations_
.erase(cc::remove_if(&animations_
,
852 IsWaitingForDeletion
),
856 void LayerAnimationController::TickAnimations(base::TimeTicks monotonic_time
) {
857 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
858 if (animations_
[i
]->run_state() == Animation::Starting
||
859 animations_
[i
]->run_state() == Animation::Running
||
860 animations_
[i
]->run_state() == Animation::Paused
) {
861 if (!animations_
[i
]->InEffect(monotonic_time
))
864 double trimmed
= animations_
[i
]
865 ->TrimTimeToCurrentIteration(monotonic_time
)
868 switch (animations_
[i
]->target_property()) {
869 case Animation::Transform
: {
870 const TransformAnimationCurve
* transform_animation_curve
=
871 animations_
[i
]->curve()->ToTransformAnimationCurve();
872 const gfx::Transform transform
=
873 transform_animation_curve
->GetValue(trimmed
);
874 NotifyObserversTransformAnimated(
876 animations_
[i
]->affects_active_observers(),
877 animations_
[i
]->affects_pending_observers());
881 case Animation::Opacity
: {
882 const FloatAnimationCurve
* float_animation_curve
=
883 animations_
[i
]->curve()->ToFloatAnimationCurve();
884 const float opacity
= std::max(
885 std::min(float_animation_curve
->GetValue(trimmed
), 1.0f
), 0.f
);
886 NotifyObserversOpacityAnimated(
888 animations_
[i
]->affects_active_observers(),
889 animations_
[i
]->affects_pending_observers());
893 case Animation::Filter
: {
894 const FilterAnimationCurve
* filter_animation_curve
=
895 animations_
[i
]->curve()->ToFilterAnimationCurve();
896 const FilterOperations filter
=
897 filter_animation_curve
->GetValue(trimmed
);
898 NotifyObserversFilterAnimated(
900 animations_
[i
]->affects_active_observers(),
901 animations_
[i
]->affects_pending_observers());
905 case Animation::BackgroundColor
: {
906 // Not yet implemented.
910 case Animation::ScrollOffset
: {
911 const ScrollOffsetAnimationCurve
* scroll_offset_animation_curve
=
912 animations_
[i
]->curve()->ToScrollOffsetAnimationCurve();
913 const gfx::ScrollOffset scroll_offset
=
914 scroll_offset_animation_curve
->GetValue(trimmed
);
915 NotifyObserversScrollOffsetAnimated(
917 animations_
[i
]->affects_active_observers(),
918 animations_
[i
]->affects_pending_observers());
922 // Do nothing for sentinel value.
923 case Animation::TargetPropertyEnumSize
:
930 void LayerAnimationController::UpdateActivation(UpdateActivationType type
) {
931 bool force
= type
== ForceActivation
;
933 bool was_active
= is_active_
;
935 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
936 if (animations_
[i
]->run_state() != Animation::WaitingForDeletion
) {
942 if (is_active_
&& (!was_active
|| force
))
943 registrar_
->DidActivateAnimationController(this);
944 else if (!is_active_
&& (was_active
|| force
))
945 registrar_
->DidDeactivateAnimationController(this);
949 void LayerAnimationController::NotifyObserversOpacityAnimated(
951 bool notify_active_observers
,
952 bool notify_pending_observers
) {
953 if (value_observers_
.might_have_observers()) {
954 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
956 LayerAnimationValueObserver
* obs
;
957 while ((obs
= it
.GetNext()) != nullptr) {
958 if ((notify_active_observers
&& notify_pending_observers
) ||
959 (notify_active_observers
&& obs
->IsActive()) ||
960 (notify_pending_observers
&& !obs
->IsActive()))
961 obs
->OnOpacityAnimated(opacity
);
966 void LayerAnimationController::NotifyObserversTransformAnimated(
967 const gfx::Transform
& transform
,
968 bool notify_active_observers
,
969 bool notify_pending_observers
) {
970 if (value_observers_
.might_have_observers()) {
971 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
973 LayerAnimationValueObserver
* obs
;
974 while ((obs
= it
.GetNext()) != nullptr) {
975 if ((notify_active_observers
&& notify_pending_observers
) ||
976 (notify_active_observers
&& obs
->IsActive()) ||
977 (notify_pending_observers
&& !obs
->IsActive()))
978 obs
->OnTransformAnimated(transform
);
983 void LayerAnimationController::NotifyObserversFilterAnimated(
984 const FilterOperations
& filters
,
985 bool notify_active_observers
,
986 bool notify_pending_observers
) {
987 if (value_observers_
.might_have_observers()) {
988 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
990 LayerAnimationValueObserver
* obs
;
991 while ((obs
= it
.GetNext()) != nullptr) {
992 if ((notify_active_observers
&& notify_pending_observers
) ||
993 (notify_active_observers
&& obs
->IsActive()) ||
994 (notify_pending_observers
&& !obs
->IsActive()))
995 obs
->OnFilterAnimated(filters
);
1000 void LayerAnimationController::NotifyObserversScrollOffsetAnimated(
1001 const gfx::ScrollOffset
& scroll_offset
,
1002 bool notify_active_observers
,
1003 bool notify_pending_observers
) {
1004 if (value_observers_
.might_have_observers()) {
1005 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
1007 LayerAnimationValueObserver
* obs
;
1008 while ((obs
= it
.GetNext()) != nullptr) {
1009 if ((notify_active_observers
&& notify_pending_observers
) ||
1010 (notify_active_observers
&& obs
->IsActive()) ||
1011 (notify_pending_observers
&& !obs
->IsActive()))
1012 obs
->OnScrollOffsetAnimated(scroll_offset
);
1017 void LayerAnimationController::NotifyObserversAnimationWaitingForDeletion() {
1018 FOR_EACH_OBSERVER(LayerAnimationValueObserver
,
1020 OnAnimationWaitingForDeletion());
1023 bool LayerAnimationController::HasValueObserver() {
1024 if (value_observers_
.might_have_observers()) {
1025 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
1027 return it
.GetNext() != nullptr;
1032 bool LayerAnimationController::HasActiveValueObserver() {
1033 if (value_observers_
.might_have_observers()) {
1034 ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
1036 LayerAnimationValueObserver
* obs
;
1037 while ((obs
= it
.GetNext()) != nullptr)
1038 if (obs
->IsActive())