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),
31 scroll_offset_animation_was_interrupted_(false) {
34 LayerAnimationController::~LayerAnimationController() {
36 registrar_
->UnregisterAnimationController(this);
39 scoped_refptr
<LayerAnimationController
> LayerAnimationController::Create(
41 return make_scoped_refptr(new LayerAnimationController(id
));
44 void LayerAnimationController::PauseAnimation(int animation_id
,
45 base::TimeDelta time_offset
) {
46 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
47 if (animations_
[i
]->id() == animation_id
) {
48 animations_
[i
]->SetRunState(Animation::PAUSED
,
49 time_offset
+ animations_
[i
]->start_time() +
50 animations_
[i
]->time_offset());
55 struct HasAnimationId
{
56 explicit HasAnimationId(int id
) : id_(id
) {}
57 bool operator()(Animation
* animation
) const {
58 return animation
->id() == id_
;
65 void LayerAnimationController::RemoveAnimation(int animation_id
) {
66 auto animations_to_remove
=
67 animations_
.remove_if(HasAnimationId(animation_id
));
68 for (auto it
= animations_to_remove
; it
!= animations_
.end(); ++it
) {
69 if ((*it
)->target_property() == Animation::SCROLL_OFFSET
) {
70 scroll_offset_animation_was_interrupted_
= true;
74 animations_
.erase(animations_to_remove
, animations_
.end());
75 UpdateActivation(NORMAL_ACTIVATION
);
78 struct HasAnimationIdAndProperty
{
79 HasAnimationIdAndProperty(int id
, Animation::TargetProperty target_property
)
80 : id_(id
), target_property_(target_property
) {}
81 bool operator()(Animation
* animation
) const {
82 return animation
->id() == id_
&&
83 animation
->target_property() == target_property_
;
88 Animation::TargetProperty target_property_
;
91 void LayerAnimationController::RemoveAnimation(
93 Animation::TargetProperty target_property
) {
94 auto animations_to_remove
= animations_
.remove_if(
95 HasAnimationIdAndProperty(animation_id
, target_property
));
96 if (target_property
== Animation::SCROLL_OFFSET
&&
97 animations_to_remove
!= animations_
.end())
98 scroll_offset_animation_was_interrupted_
= true;
100 animations_
.erase(animations_to_remove
, animations_
.end());
101 UpdateActivation(NORMAL_ACTIVATION
);
104 void LayerAnimationController::AbortAnimations(
105 Animation::TargetProperty target_property
) {
106 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
107 if (animations_
[i
]->target_property() == target_property
&&
108 !animations_
[i
]->is_finished())
109 animations_
[i
]->SetRunState(Animation::ABORTED
, last_tick_time_
);
113 // Ensures that the list of active animations on the main thread and the impl
114 // thread are kept in sync.
115 void LayerAnimationController::PushAnimationUpdatesTo(
116 LayerAnimationController
* controller_impl
) {
117 DCHECK(this != controller_impl
);
118 if (!has_any_animation() && !controller_impl
->has_any_animation())
120 PurgeAnimationsMarkedForDeletion();
121 PushNewAnimationsToImplThread(controller_impl
);
123 // Remove finished impl side animations only after pushing,
124 // and only after the animations are deleted on the main thread
125 // this insures we will never push an animation twice.
126 RemoveAnimationsCompletedOnMainThread(controller_impl
);
128 PushPropertiesToImplThread(controller_impl
);
129 controller_impl
->UpdateActivation(NORMAL_ACTIVATION
);
130 UpdateActivation(NORMAL_ACTIVATION
);
133 void LayerAnimationController::Animate(base::TimeTicks monotonic_time
) {
134 DCHECK(!monotonic_time
.is_null());
135 if (!HasValueObserver())
138 if (needs_to_start_animations_
)
139 StartAnimations(monotonic_time
);
140 TickAnimations(monotonic_time
);
141 last_tick_time_
= monotonic_time
;
144 void LayerAnimationController::AccumulatePropertyUpdates(
145 base::TimeTicks monotonic_time
,
146 AnimationEventsVector
* events
) {
150 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
151 Animation
* animation
= animations_
[i
];
152 if (!animation
->is_impl_only())
155 if (!animation
->InEffect(monotonic_time
))
158 base::TimeDelta trimmed
=
159 animation
->TrimTimeToCurrentIteration(monotonic_time
);
160 switch (animation
->target_property()) {
161 case Animation::OPACITY
: {
162 AnimationEvent
event(AnimationEvent::PROPERTY_UPDATE
, id_
,
163 animation
->group(), Animation::OPACITY
,
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::PROPERTY_UPDATE
, id_
,
175 animation
->group(), Animation::TRANSFORM
,
177 const TransformAnimationCurve
* transform_animation_curve
=
178 animation
->curve()->ToTransformAnimationCurve();
179 event
.transform
= transform_animation_curve
->GetValue(trimmed
);
180 event
.is_impl_only
= true;
181 events
->push_back(event
);
185 case Animation::FILTER
: {
186 AnimationEvent
event(AnimationEvent::PROPERTY_UPDATE
, id_
,
187 animation
->group(), Animation::FILTER
,
189 const FilterAnimationCurve
* filter_animation_curve
=
190 animation
->curve()->ToFilterAnimationCurve();
191 event
.filters
= filter_animation_curve
->GetValue(trimmed
);
192 event
.is_impl_only
= true;
193 events
->push_back(event
);
197 case Animation::BACKGROUND_COLOR
: {
201 case Animation::SCROLL_OFFSET
: {
202 // Impl-side changes to scroll offset are already sent back to the
203 // main thread (e.g. for user-driven scrolling), so a PROPERTY_UPDATE
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(NORMAL_ACTIVATION
);
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 scroll_offset_animation_was_interrupted_
= false;
255 UpdateActivation(NORMAL_ACTIVATION
);
258 void LayerAnimationController::AddAnimation(scoped_ptr
<Animation
> animation
) {
259 animations_
.push_back(animation
.Pass());
260 needs_to_start_animations_
= true;
261 UpdateActivation(NORMAL_ACTIVATION
);
264 Animation
* LayerAnimationController::GetAnimation(
265 Animation::TargetProperty target_property
) const {
266 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
267 size_t index
= animations_
.size() - i
- 1;
268 if (animations_
[index
]->target_property() == target_property
)
269 return animations_
[index
];
274 Animation
* LayerAnimationController::GetAnimationById(int animation_id
) const {
275 for (size_t i
= 0; i
< animations_
.size(); ++i
)
276 if (animations_
[i
]->id() == animation_id
)
277 return animations_
[i
];
281 bool LayerAnimationController::HasActiveAnimation() const {
282 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
283 if (!animations_
[i
]->is_finished())
289 bool LayerAnimationController::IsPotentiallyAnimatingProperty(
290 Animation::TargetProperty target_property
,
291 ObserverType observer_type
) const {
292 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
293 if (!animations_
[i
]->is_finished() &&
294 animations_
[i
]->target_property() == target_property
) {
295 if ((observer_type
== ObserverType::ACTIVE
&&
296 animations_
[i
]->affects_active_observers()) ||
297 (observer_type
== ObserverType::PENDING
&&
298 animations_
[i
]->affects_pending_observers()))
305 bool LayerAnimationController::IsCurrentlyAnimatingProperty(
306 Animation::TargetProperty target_property
,
307 ObserverType observer_type
) const {
308 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
309 if (!animations_
[i
]->is_finished() &&
310 animations_
[i
]->InEffect(last_tick_time_
) &&
311 animations_
[i
]->target_property() == target_property
) {
312 if ((observer_type
== ObserverType::ACTIVE
&&
313 animations_
[i
]->affects_active_observers()) ||
314 (observer_type
== ObserverType::PENDING
&&
315 animations_
[i
]->affects_pending_observers()))
322 void LayerAnimationController::SetAnimationRegistrar(
323 AnimationRegistrar
* registrar
) {
324 if (registrar_
== registrar
)
328 registrar_
->UnregisterAnimationController(this);
330 registrar_
= registrar
;
332 registrar_
->RegisterAnimationController(this);
334 UpdateActivation(FORCE_ACTIVATION
);
337 void LayerAnimationController::NotifyAnimationStarted(
338 const AnimationEvent
& event
) {
339 if (event
.is_impl_only
) {
340 FOR_EACH_OBSERVER(LayerAnimationEventObserver
, event_observers_
,
341 OnAnimationStarted(event
));
342 if (layer_animation_delegate_
)
343 layer_animation_delegate_
->NotifyAnimationStarted(
344 event
.monotonic_time
, event
.target_property
, event
.group_id
);
348 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
349 if (animations_
[i
]->group() == event
.group_id
&&
350 animations_
[i
]->target_property() == event
.target_property
&&
351 animations_
[i
]->needs_synchronized_start_time()) {
352 animations_
[i
]->set_needs_synchronized_start_time(false);
353 if (!animations_
[i
]->has_set_start_time())
354 animations_
[i
]->set_start_time(event
.monotonic_time
);
356 FOR_EACH_OBSERVER(LayerAnimationEventObserver
, event_observers_
,
357 OnAnimationStarted(event
));
358 if (layer_animation_delegate_
)
359 layer_animation_delegate_
->NotifyAnimationStarted(
360 event
.monotonic_time
, event
.target_property
, event
.group_id
);
367 void LayerAnimationController::NotifyAnimationFinished(
368 const AnimationEvent
& event
) {
369 if (event
.is_impl_only
) {
370 if (layer_animation_delegate_
)
371 layer_animation_delegate_
->NotifyAnimationFinished(
372 event
.monotonic_time
, event
.target_property
, event
.group_id
);
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
]->set_received_finished_event(true);
380 if (layer_animation_delegate_
)
381 layer_animation_delegate_
->NotifyAnimationFinished(
382 event
.monotonic_time
, event
.target_property
, event
.group_id
);
389 void LayerAnimationController::NotifyAnimationAborted(
390 const AnimationEvent
& event
) {
391 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
392 if (animations_
[i
]->group() == event
.group_id
&&
393 animations_
[i
]->target_property() == event
.target_property
) {
394 animations_
[i
]->SetRunState(Animation::ABORTED
, event
.monotonic_time
);
399 void LayerAnimationController::NotifyAnimationPropertyUpdate(
400 const AnimationEvent
& event
) {
401 bool notify_active_observers
= true;
402 bool notify_pending_observers
= true;
403 switch (event
.target_property
) {
404 case Animation::OPACITY
:
405 NotifyObserversOpacityAnimated(
406 event
.opacity
, notify_active_observers
, notify_pending_observers
);
408 case Animation::TRANSFORM
:
409 NotifyObserversTransformAnimated(
410 event
.transform
, notify_active_observers
, notify_pending_observers
);
417 void LayerAnimationController::AddValueObserver(
418 LayerAnimationValueObserver
* observer
) {
419 if (!value_observers_
.HasObserver(observer
))
420 value_observers_
.AddObserver(observer
);
423 void LayerAnimationController::RemoveValueObserver(
424 LayerAnimationValueObserver
* observer
) {
425 value_observers_
.RemoveObserver(observer
);
428 void LayerAnimationController::AddEventObserver(
429 LayerAnimationEventObserver
* observer
) {
430 if (!event_observers_
.HasObserver(observer
))
431 event_observers_
.AddObserver(observer
);
434 void LayerAnimationController::RemoveEventObserver(
435 LayerAnimationEventObserver
* observer
) {
436 event_observers_
.RemoveObserver(observer
);
439 bool LayerAnimationController::HasFilterAnimationThatInflatesBounds() const {
440 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
441 if (!animations_
[i
]->is_finished() &&
442 animations_
[i
]->target_property() == Animation::FILTER
&&
445 ->ToFilterAnimationCurve()
446 ->HasFilterThatMovesPixels())
453 bool LayerAnimationController::HasTransformAnimationThatInflatesBounds() const {
454 return IsCurrentlyAnimatingProperty(Animation::TRANSFORM
,
455 ObserverType::ACTIVE
) ||
456 IsCurrentlyAnimatingProperty(Animation::TRANSFORM
,
457 ObserverType::PENDING
);
460 bool LayerAnimationController::FilterAnimationBoundsForBox(
461 const gfx::BoxF
& box
, gfx::BoxF
* bounds
) const {
462 // TODO(avallee): Implement.
466 bool LayerAnimationController::TransformAnimationBoundsForBox(
467 const gfx::BoxF
& box
,
468 gfx::BoxF
* bounds
) const {
469 DCHECK(HasTransformAnimationThatInflatesBounds())
470 << "TransformAnimationBoundsForBox will give incorrect results if there "
471 << "are no transform animations affecting bounds, non-animated transform "
474 // Compute bounds based on animations for which is_finished() is false.
475 // Do nothing if there are no such animations; in this case, it is assumed
476 // that callers will take care of computing bounds based on the owning layer's
478 *bounds
= gfx::BoxF();
479 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
480 if (animations_
[i
]->is_finished() ||
481 animations_
[i
]->target_property() != Animation::TRANSFORM
)
484 const TransformAnimationCurve
* transform_animation_curve
=
485 animations_
[i
]->curve()->ToTransformAnimationCurve();
486 gfx::BoxF animation_bounds
;
488 transform_animation_curve
->AnimatedBoundsForBox(box
, &animation_bounds
);
491 bounds
->Union(animation_bounds
);
497 bool LayerAnimationController::HasAnimationThatAffectsScale() const {
498 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
499 if (animations_
[i
]->is_finished() ||
500 animations_
[i
]->target_property() != Animation::TRANSFORM
)
503 const TransformAnimationCurve
* transform_animation_curve
=
504 animations_
[i
]->curve()->ToTransformAnimationCurve();
505 if (transform_animation_curve
->AffectsScale())
512 bool LayerAnimationController::HasOnlyTranslationTransforms() const {
513 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
514 if (animations_
[i
]->is_finished() ||
515 animations_
[i
]->target_property() != Animation::TRANSFORM
)
518 const TransformAnimationCurve
* transform_animation_curve
=
519 animations_
[i
]->curve()->ToTransformAnimationCurve();
520 if (!transform_animation_curve
->IsTranslation())
527 bool LayerAnimationController::AnimationsPreserveAxisAlignment() const {
528 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
529 if (animations_
[i
]->is_finished() ||
530 animations_
[i
]->target_property() != Animation::TRANSFORM
)
533 const TransformAnimationCurve
* transform_animation_curve
=
534 animations_
[i
]->curve()->ToTransformAnimationCurve();
535 if (!transform_animation_curve
->PreservesAxisAlignment())
542 bool LayerAnimationController::AnimationStartScale(float* start_scale
) const {
544 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
545 if (animations_
[i
]->is_finished() ||
546 animations_
[i
]->target_property() != Animation::TRANSFORM
)
549 bool forward_direction
= true;
550 switch (animations_
[i
]->direction()) {
551 case Animation::DIRECTION_NORMAL
:
552 case Animation::DIRECTION_ALTERNATE
:
553 forward_direction
= animations_
[i
]->playback_rate() >= 0.0;
555 case Animation::DIRECTION_REVERSE
:
556 case Animation::DIRECTION_ALTERNATE_REVERSE
:
557 forward_direction
= animations_
[i
]->playback_rate() < 0.0;
561 const TransformAnimationCurve
* transform_animation_curve
=
562 animations_
[i
]->curve()->ToTransformAnimationCurve();
563 float animation_start_scale
= 0.f
;
564 if (!transform_animation_curve
->AnimationStartScale(forward_direction
,
565 &animation_start_scale
))
567 *start_scale
= std::max(*start_scale
, animation_start_scale
);
572 bool LayerAnimationController::MaximumTargetScale(float* max_scale
) const {
574 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
575 if (animations_
[i
]->is_finished() ||
576 animations_
[i
]->target_property() != Animation::TRANSFORM
)
579 bool forward_direction
= true;
580 switch (animations_
[i
]->direction()) {
581 case Animation::DIRECTION_NORMAL
:
582 case Animation::DIRECTION_ALTERNATE
:
583 forward_direction
= animations_
[i
]->playback_rate() >= 0.0;
585 case Animation::DIRECTION_REVERSE
:
586 case Animation::DIRECTION_ALTERNATE_REVERSE
:
587 forward_direction
= animations_
[i
]->playback_rate() < 0.0;
591 const TransformAnimationCurve
* transform_animation_curve
=
592 animations_
[i
]->curve()->ToTransformAnimationCurve();
593 float animation_scale
= 0.f
;
594 if (!transform_animation_curve
->MaximumTargetScale(forward_direction
,
597 *max_scale
= std::max(*max_scale
, animation_scale
);
603 void LayerAnimationController::PushNewAnimationsToImplThread(
604 LayerAnimationController
* controller_impl
) const {
605 // Any new animations owned by the main thread's controller are cloned and
606 // add to the impl thread's controller.
607 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
608 // If the animation is already running on the impl thread, there is no
609 // need to copy it over.
610 if (controller_impl
->GetAnimationById(animations_
[i
]->id()))
613 // Scroll animations always start at the current scroll offset.
614 if (animations_
[i
]->target_property() == Animation::SCROLL_OFFSET
) {
615 gfx::ScrollOffset current_scroll_offset
;
616 if (controller_impl
->value_provider_
) {
617 current_scroll_offset
=
618 controller_impl
->value_provider_
->ScrollOffsetForAnimation();
620 // The owning layer isn't yet in the active tree, so the main thread
621 // scroll offset will be up-to-date.
622 current_scroll_offset
= value_provider_
->ScrollOffsetForAnimation();
624 animations_
[i
]->curve()->ToScrollOffsetAnimationCurve()->SetInitialValue(
625 current_scroll_offset
);
628 // The new animation should be set to run as soon as possible.
629 Animation::RunState initial_run_state
=
630 Animation::WAITING_FOR_TARGET_AVAILABILITY
;
631 scoped_ptr
<Animation
> to_add(
632 animations_
[i
]->CloneAndInitialize(initial_run_state
));
633 DCHECK(!to_add
->needs_synchronized_start_time());
634 to_add
->set_affects_active_observers(false);
635 controller_impl
->AddAnimation(to_add
.Pass());
639 static bool IsCompleted(
640 Animation
* animation
,
641 const LayerAnimationController
* main_thread_controller
) {
642 if (animation
->is_impl_only()) {
643 return (animation
->run_state() == Animation::WAITING_FOR_DELETION
);
645 return !main_thread_controller
->GetAnimationById(animation
->id());
649 static bool AffectsActiveOnlyAndIsWaitingForDeletion(Animation
* animation
) {
650 return animation
->run_state() == Animation::WAITING_FOR_DELETION
&&
651 !animation
->affects_pending_observers();
654 void LayerAnimationController::RemoveAnimationsCompletedOnMainThread(
655 LayerAnimationController
* controller_impl
) const {
656 // Animations removed on the main thread should no longer affect pending
657 // observers, and should stop affecting active observers after the next call
658 // to ActivateAnimations. If already WAITING_FOR_DELETION, they can be removed
660 ScopedPtrVector
<Animation
>& animations
= controller_impl
->animations_
;
661 for (size_t i
= 0; i
< animations
.size(); ++i
) {
662 if (IsCompleted(animations
[i
], this))
663 animations
[i
]->set_affects_pending_observers(false);
665 animations
.erase(cc::remove_if(&animations
,
668 AffectsActiveOnlyAndIsWaitingForDeletion
),
672 void LayerAnimationController::PushPropertiesToImplThread(
673 LayerAnimationController
* controller_impl
) {
674 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
675 Animation
* current_impl
=
676 controller_impl
->GetAnimationById(animations_
[i
]->id());
678 animations_
[i
]->PushPropertiesTo(current_impl
);
680 controller_impl
->scroll_offset_animation_was_interrupted_
=
681 scroll_offset_animation_was_interrupted_
;
682 scroll_offset_animation_was_interrupted_
= false;
685 void LayerAnimationController::StartAnimations(base::TimeTicks monotonic_time
) {
686 DCHECK(needs_to_start_animations_
);
687 needs_to_start_animations_
= false;
688 // First collect running properties affecting each type of observer.
689 TargetProperties blocked_properties_for_active_observers
;
690 TargetProperties blocked_properties_for_pending_observers
;
691 std::vector
<size_t> animations_waiting_for_target
;
693 animations_waiting_for_target
.reserve(animations_
.size());
694 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
695 if (animations_
[i
]->run_state() == Animation::STARTING
||
696 animations_
[i
]->run_state() == Animation::RUNNING
) {
697 if (animations_
[i
]->affects_active_observers()) {
698 blocked_properties_for_active_observers
.insert(
699 animations_
[i
]->target_property());
701 if (animations_
[i
]->affects_pending_observers()) {
702 blocked_properties_for_pending_observers
.insert(
703 animations_
[i
]->target_property());
705 } else if (animations_
[i
]->run_state() ==
706 Animation::WAITING_FOR_TARGET_AVAILABILITY
) {
707 animations_waiting_for_target
.push_back(i
);
711 for (size_t i
= 0; i
< animations_waiting_for_target
.size(); ++i
) {
712 // Collect all properties for animations with the same group id (they
713 // should all also be in the list of animations).
714 size_t animation_index
= animations_waiting_for_target
[i
];
715 Animation
* animation_waiting_for_target
= animations_
[animation_index
];
716 // Check for the run state again even though the animation was waiting
717 // for target because it might have changed the run state while handling
718 // previous animation in this loop (if they belong to same group).
719 if (animation_waiting_for_target
->run_state() ==
720 Animation::WAITING_FOR_TARGET_AVAILABILITY
) {
721 TargetProperties enqueued_properties
;
722 bool affects_active_observers
=
723 animation_waiting_for_target
->affects_active_observers();
724 bool affects_pending_observers
=
725 animation_waiting_for_target
->affects_pending_observers();
726 enqueued_properties
.insert(
727 animation_waiting_for_target
->target_property());
728 for (size_t j
= animation_index
+ 1; j
< animations_
.size(); ++j
) {
729 if (animation_waiting_for_target
->group() == animations_
[j
]->group()) {
730 enqueued_properties
.insert(animations_
[j
]->target_property());
731 affects_active_observers
|=
732 animations_
[j
]->affects_active_observers();
733 affects_pending_observers
|=
734 animations_
[j
]->affects_pending_observers();
738 // Check to see if intersection of the list of properties affected by
739 // the group and the list of currently blocked properties is null, taking
740 // into account the type(s) of observers affected by the group. In any
741 // case, the group's target properties need to be added to the lists of
742 // blocked properties.
743 bool null_intersection
= true;
744 for (TargetProperties::iterator p_iter
= enqueued_properties
.begin();
745 p_iter
!= enqueued_properties
.end();
747 if (affects_active_observers
&&
748 !blocked_properties_for_active_observers
.insert(*p_iter
).second
)
749 null_intersection
= false;
750 if (affects_pending_observers
&&
751 !blocked_properties_for_pending_observers
.insert(*p_iter
).second
)
752 null_intersection
= false;
755 // If the intersection is null, then we are free to start the animations
757 if (null_intersection
) {
758 animation_waiting_for_target
->SetRunState(Animation::STARTING
,
760 for (size_t j
= animation_index
+ 1; j
< animations_
.size(); ++j
) {
761 if (animation_waiting_for_target
->group() ==
762 animations_
[j
]->group()) {
763 animations_
[j
]->SetRunState(Animation::STARTING
, monotonic_time
);
767 needs_to_start_animations_
= true;
773 void LayerAnimationController::PromoteStartedAnimations(
774 base::TimeTicks monotonic_time
,
775 AnimationEventsVector
* events
) {
776 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
777 if (animations_
[i
]->run_state() == Animation::STARTING
&&
778 animations_
[i
]->affects_active_observers()) {
779 animations_
[i
]->SetRunState(Animation::RUNNING
, monotonic_time
);
780 if (!animations_
[i
]->has_set_start_time() &&
781 !animations_
[i
]->needs_synchronized_start_time())
782 animations_
[i
]->set_start_time(monotonic_time
);
784 base::TimeTicks start_time
;
785 if (animations_
[i
]->has_set_start_time())
786 start_time
= animations_
[i
]->start_time();
788 start_time
= monotonic_time
;
789 AnimationEvent
started_event(
790 AnimationEvent::STARTED
, id_
, animations_
[i
]->group(),
791 animations_
[i
]->target_property(), start_time
);
792 started_event
.is_impl_only
= animations_
[i
]->is_impl_only();
793 if (started_event
.is_impl_only
)
794 NotifyAnimationStarted(started_event
);
796 events
->push_back(started_event
);
802 void LayerAnimationController::MarkFinishedAnimations(
803 base::TimeTicks monotonic_time
) {
804 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
805 if (animations_
[i
]->IsFinishedAt(monotonic_time
) &&
806 animations_
[i
]->run_state() != Animation::ABORTED
&&
807 animations_
[i
]->run_state() != Animation::WAITING_FOR_DELETION
)
808 animations_
[i
]->SetRunState(Animation::FINISHED
, monotonic_time
);
812 void LayerAnimationController::MarkAnimationsForDeletion(
813 base::TimeTicks monotonic_time
,
814 AnimationEventsVector
* events
) {
815 bool marked_animations_for_deletions
= false;
816 std::vector
<size_t> animations_with_same_group_id
;
818 animations_with_same_group_id
.reserve(animations_
.size());
819 // Non-aborted animations are marked for deletion after a corresponding
820 // AnimationEvent::FINISHED event is sent or received. This means that if
821 // we don't have an events vector, we must ensure that non-aborted animations
822 // have received a finished event before marking them for deletion.
823 for (size_t i
= 0; i
< animations_
.size(); i
++) {
824 int group_id
= animations_
[i
]->group();
825 if (animations_
[i
]->run_state() == Animation::ABORTED
) {
826 if (events
&& !animations_
[i
]->is_impl_only()) {
827 AnimationEvent
aborted_event(AnimationEvent::ABORTED
, id_
, group_id
,
828 animations_
[i
]->target_property(),
830 events
->push_back(aborted_event
);
832 animations_
[i
]->SetRunState(Animation::WAITING_FOR_DELETION
,
834 marked_animations_for_deletions
= true;
838 bool all_anims_with_same_id_are_finished
= false;
840 // Since deleting an animation on the main thread leads to its deletion
841 // on the impl thread, we only mark a FINISHED main thread animation for
842 // deletion once it has received a FINISHED event from the impl thread.
843 bool animation_i_will_send_or_has_received_finish_event
=
844 animations_
[i
]->is_controlling_instance() ||
845 animations_
[i
]->is_impl_only() ||
846 animations_
[i
]->received_finished_event();
847 // If an animation is finished, and not already marked for deletion,
848 // find out if all other animations in the same group are also finished.
849 if (animations_
[i
]->run_state() == Animation::FINISHED
&&
850 animation_i_will_send_or_has_received_finish_event
) {
851 // Clear the animations_with_same_group_id if it was added for
852 // the previous animation's iteration.
853 if (animations_with_same_group_id
.size() > 0)
854 animations_with_same_group_id
.clear();
855 all_anims_with_same_id_are_finished
= true;
856 for (size_t j
= 0; j
< animations_
.size(); ++j
) {
857 bool animation_j_will_send_or_has_received_finish_event
=
858 animations_
[j
]->is_controlling_instance() ||
859 animations_
[j
]->is_impl_only() ||
860 animations_
[j
]->received_finished_event();
861 if (group_id
== animations_
[j
]->group()) {
862 if (!animations_
[j
]->is_finished() ||
863 (animations_
[j
]->run_state() == Animation::FINISHED
&&
864 !animation_j_will_send_or_has_received_finish_event
)) {
865 all_anims_with_same_id_are_finished
= false;
868 animations_
[j
]->run_state() != Animation::ABORTED
) {
869 // Mark down the animations which belong to the same group
870 // and is not yet aborted. If this current iteration finds that all
871 // animations with same ID are finished, then the marked
872 // animations below will be set to WAITING_FOR_DELETION in next
874 animations_with_same_group_id
.push_back(j
);
879 if (all_anims_with_same_id_are_finished
) {
880 // We now need to remove all animations with the same group id as
881 // group_id (and send along animation finished notifications, if
883 for (size_t j
= 0; j
< animations_with_same_group_id
.size(); j
++) {
884 size_t animation_index
= animations_with_same_group_id
[j
];
886 AnimationEvent
finished_event(
887 AnimationEvent::FINISHED
, id_
,
888 animations_
[animation_index
]->group(),
889 animations_
[animation_index
]->target_property(),
891 finished_event
.is_impl_only
=
892 animations_
[animation_index
]->is_impl_only();
893 if (finished_event
.is_impl_only
)
894 NotifyAnimationFinished(finished_event
);
896 events
->push_back(finished_event
);
898 animations_
[animation_index
]->SetRunState(
899 Animation::WAITING_FOR_DELETION
, monotonic_time
);
901 marked_animations_for_deletions
= true;
904 if (marked_animations_for_deletions
)
905 NotifyObserversAnimationWaitingForDeletion();
908 static bool IsWaitingForDeletion(Animation
* animation
) {
909 return animation
->run_state() == Animation::WAITING_FOR_DELETION
;
912 void LayerAnimationController::PurgeAnimationsMarkedForDeletion() {
913 animations_
.erase(cc::remove_if(&animations_
,
916 IsWaitingForDeletion
),
920 void LayerAnimationController::TickAnimations(base::TimeTicks monotonic_time
) {
921 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
922 if (animations_
[i
]->run_state() == Animation::STARTING
||
923 animations_
[i
]->run_state() == Animation::RUNNING
||
924 animations_
[i
]->run_state() == Animation::PAUSED
) {
925 if (!animations_
[i
]->InEffect(monotonic_time
))
928 base::TimeDelta trimmed
=
929 animations_
[i
]->TrimTimeToCurrentIteration(monotonic_time
);
931 switch (animations_
[i
]->target_property()) {
932 case Animation::TRANSFORM
: {
933 const TransformAnimationCurve
* transform_animation_curve
=
934 animations_
[i
]->curve()->ToTransformAnimationCurve();
935 const gfx::Transform transform
=
936 transform_animation_curve
->GetValue(trimmed
);
937 NotifyObserversTransformAnimated(
939 animations_
[i
]->affects_active_observers(),
940 animations_
[i
]->affects_pending_observers());
944 case Animation::OPACITY
: {
945 const FloatAnimationCurve
* float_animation_curve
=
946 animations_
[i
]->curve()->ToFloatAnimationCurve();
947 const float opacity
= std::max(
948 std::min(float_animation_curve
->GetValue(trimmed
), 1.0f
), 0.f
);
949 NotifyObserversOpacityAnimated(
951 animations_
[i
]->affects_active_observers(),
952 animations_
[i
]->affects_pending_observers());
956 case Animation::FILTER
: {
957 const FilterAnimationCurve
* filter_animation_curve
=
958 animations_
[i
]->curve()->ToFilterAnimationCurve();
959 const FilterOperations filter
=
960 filter_animation_curve
->GetValue(trimmed
);
961 NotifyObserversFilterAnimated(
963 animations_
[i
]->affects_active_observers(),
964 animations_
[i
]->affects_pending_observers());
968 case Animation::BACKGROUND_COLOR
: {
969 // Not yet implemented.
973 case Animation::SCROLL_OFFSET
: {
974 const ScrollOffsetAnimationCurve
* scroll_offset_animation_curve
=
975 animations_
[i
]->curve()->ToScrollOffsetAnimationCurve();
976 const gfx::ScrollOffset scroll_offset
=
977 scroll_offset_animation_curve
->GetValue(trimmed
);
978 NotifyObserversScrollOffsetAnimated(
980 animations_
[i
]->affects_active_observers(),
981 animations_
[i
]->affects_pending_observers());
989 void LayerAnimationController::UpdateActivation(UpdateActivationType type
) {
990 bool force
= type
== FORCE_ACTIVATION
;
992 bool was_active
= is_active_
;
994 for (size_t i
= 0; i
< animations_
.size(); ++i
) {
995 if (animations_
[i
]->run_state() != Animation::WAITING_FOR_DELETION
) {
1001 if (is_active_
&& (!was_active
|| force
))
1002 registrar_
->DidActivateAnimationController(this);
1003 else if (!is_active_
&& (was_active
|| force
))
1004 registrar_
->DidDeactivateAnimationController(this);
1008 void LayerAnimationController::NotifyObserversOpacityAnimated(
1010 bool notify_active_observers
,
1011 bool notify_pending_observers
) {
1012 if (value_observers_
.might_have_observers()) {
1013 base::ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
1015 LayerAnimationValueObserver
* obs
;
1016 while ((obs
= it
.GetNext()) != nullptr) {
1017 if ((notify_active_observers
&& notify_pending_observers
) ||
1018 (notify_active_observers
&& obs
->IsActive()) ||
1019 (notify_pending_observers
&& !obs
->IsActive()))
1020 obs
->OnOpacityAnimated(opacity
);
1025 void LayerAnimationController::NotifyObserversTransformAnimated(
1026 const gfx::Transform
& transform
,
1027 bool notify_active_observers
,
1028 bool notify_pending_observers
) {
1029 if (value_observers_
.might_have_observers()) {
1030 base::ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
1032 LayerAnimationValueObserver
* obs
;
1033 while ((obs
= it
.GetNext()) != nullptr) {
1034 if ((notify_active_observers
&& notify_pending_observers
) ||
1035 (notify_active_observers
&& obs
->IsActive()) ||
1036 (notify_pending_observers
&& !obs
->IsActive()))
1037 obs
->OnTransformAnimated(transform
);
1042 void LayerAnimationController::NotifyObserversFilterAnimated(
1043 const FilterOperations
& filters
,
1044 bool notify_active_observers
,
1045 bool notify_pending_observers
) {
1046 if (value_observers_
.might_have_observers()) {
1047 base::ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
1049 LayerAnimationValueObserver
* obs
;
1050 while ((obs
= it
.GetNext()) != nullptr) {
1051 if ((notify_active_observers
&& notify_pending_observers
) ||
1052 (notify_active_observers
&& obs
->IsActive()) ||
1053 (notify_pending_observers
&& !obs
->IsActive()))
1054 obs
->OnFilterAnimated(filters
);
1059 void LayerAnimationController::NotifyObserversScrollOffsetAnimated(
1060 const gfx::ScrollOffset
& scroll_offset
,
1061 bool notify_active_observers
,
1062 bool notify_pending_observers
) {
1063 if (value_observers_
.might_have_observers()) {
1064 base::ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
1066 LayerAnimationValueObserver
* obs
;
1067 while ((obs
= it
.GetNext()) != nullptr) {
1068 if ((notify_active_observers
&& notify_pending_observers
) ||
1069 (notify_active_observers
&& obs
->IsActive()) ||
1070 (notify_pending_observers
&& !obs
->IsActive()))
1071 obs
->OnScrollOffsetAnimated(scroll_offset
);
1076 void LayerAnimationController::NotifyObserversAnimationWaitingForDeletion() {
1077 FOR_EACH_OBSERVER(LayerAnimationValueObserver
,
1079 OnAnimationWaitingForDeletion());
1082 bool LayerAnimationController::HasValueObserver() {
1083 if (value_observers_
.might_have_observers()) {
1084 base::ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
1086 return it
.GetNext() != nullptr;
1091 bool LayerAnimationController::HasActiveValueObserver() {
1092 if (value_observers_
.might_have_observers()) {
1093 base::ObserverListBase
<LayerAnimationValueObserver
>::Iterator
it(
1095 LayerAnimationValueObserver
* obs
;
1096 while ((obs
= it
.GetNext()) != nullptr)
1097 if (obs
->IsActive())