1 // Copyright (c) 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 "ui/compositor/layer_animator.h"
7 #include "base/debug/trace_event.h"
8 #include "base/logging.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "cc/animation/animation_id_provider.h"
11 #include "cc/output/begin_frame_args.h"
12 #include "ui/compositor/compositor.h"
13 #include "ui/compositor/layer.h"
14 #include "ui/compositor/layer_animation_delegate.h"
15 #include "ui/compositor/layer_animation_observer.h"
16 #include "ui/compositor/layer_animation_sequence.h"
17 #include "ui/gfx/animation/animation_container.h"
18 #include "ui/gfx/frame_time.h"
20 #define SAFE_INVOKE_VOID(function, running_anim, ...) \
21 if (running_anim.is_sequence_alive()) \
22 function(running_anim.sequence(), ##__VA_ARGS__)
23 #define SAFE_INVOKE_BOOL(function, running_anim) \
24 ((running_anim.is_sequence_alive()) \
25 ? function(running_anim.sequence()) \
27 #define SAFE_INVOKE_PTR(function, running_anim) \
28 ((running_anim.is_sequence_alive()) \
29 ? function(running_anim.sequence()) \
38 const int kDefaultTransitionDurationMs
= 120;
39 const int kTimerIntervalMs
= 10;
41 // Returns the AnimationContainer we're added to.
42 gfx::AnimationContainer
* GetAnimationContainer() {
43 static gfx::AnimationContainer
* container
= NULL
;
45 container
= new gfx::AnimationContainer();
53 // LayerAnimator public --------------------------------------------------------
55 LayerAnimator::LayerAnimator(base::TimeDelta transition_duration
)
57 preemption_strategy_(IMMEDIATELY_SET_NEW_TARGET
),
58 is_transition_duration_locked_(false),
59 transition_duration_(transition_duration
),
60 tween_type_(gfx::Tween::LINEAR
),
62 disable_timer_for_test_(false),
63 adding_animations_(false) {
66 LayerAnimator::~LayerAnimator() {
67 for (size_t i
= 0; i
< running_animations_
.size(); ++i
) {
68 if (running_animations_
[i
].is_sequence_alive())
69 running_animations_
[i
].sequence()->OnAnimatorDestroyed();
71 ClearAnimationsInternal();
76 LayerAnimator
* LayerAnimator::CreateDefaultAnimator() {
77 return new LayerAnimator(base::TimeDelta::FromMilliseconds(0));
81 LayerAnimator
* LayerAnimator::CreateImplicitAnimator() {
82 return new LayerAnimator(
83 base::TimeDelta::FromMilliseconds(kDefaultTransitionDurationMs
));
86 // This macro provides the implementation for the setter and getter (well,
87 // the getter of the target value) for an animated property. For example,
88 // it is used for the implementations of SetTransform and GetTargetTransform.
89 // It is worth noting that SetFoo avoids invoking the usual animation machinery
90 // if the transition duration is zero -- in this case we just set the property
91 // on the layer animation delegate immediately.
92 #define ANIMATED_PROPERTY(type, property, name, member_type, member) \
93 void LayerAnimator::Set##name(type value) { \
94 base::TimeDelta duration = GetTransitionDuration(); \
95 if (duration == base::TimeDelta() && delegate() && \
96 (preemption_strategy_ != ENQUEUE_NEW_ANIMATION)) { \
97 StopAnimatingProperty(LayerAnimationElement::property); \
98 delegate()->Set##name##FromAnimation(value); \
101 scoped_ptr<LayerAnimationElement> element( \
102 LayerAnimationElement::Create##name##Element(value, duration)); \
103 element->set_tween_type(tween_type_); \
104 StartAnimation(new LayerAnimationSequence(element.release())); \
107 member_type LayerAnimator::GetTarget##name() const { \
108 LayerAnimationElement::TargetValue target(delegate()); \
109 GetTargetValue(&target); \
110 return target.member; \
114 const gfx::Transform
&, TRANSFORM
, Transform
, gfx::Transform
, transform
);
115 ANIMATED_PROPERTY(const gfx::Rect
&, BOUNDS
, Bounds
, gfx::Rect
, bounds
);
116 ANIMATED_PROPERTY(float, OPACITY
, Opacity
, float, opacity
);
117 ANIMATED_PROPERTY(bool, VISIBILITY
, Visibility
, bool, visibility
);
118 ANIMATED_PROPERTY(float, BRIGHTNESS
, Brightness
, float, brightness
);
119 ANIMATED_PROPERTY(float, GRAYSCALE
, Grayscale
, float, grayscale
);
120 ANIMATED_PROPERTY(SkColor
, COLOR
, Color
, SkColor
, color
);
122 base::TimeDelta
LayerAnimator::GetTransitionDuration() const {
123 return transition_duration_
;
126 void LayerAnimator::SetDelegate(LayerAnimationDelegate
* delegate
) {
127 delegate_
= delegate
;
130 void LayerAnimator::StartAnimation(LayerAnimationSequence
* animation
) {
131 scoped_refptr
<LayerAnimator
> retain(this);
132 OnScheduled(animation
);
133 if (!StartSequenceImmediately(animation
)) {
134 // Attempt to preempt a running animation.
135 switch (preemption_strategy_
) {
136 case IMMEDIATELY_SET_NEW_TARGET
:
137 ImmediatelySetNewTarget(animation
);
139 case IMMEDIATELY_ANIMATE_TO_NEW_TARGET
:
140 ImmediatelyAnimateToNewTarget(animation
);
142 case ENQUEUE_NEW_ANIMATION
:
143 EnqueueNewAnimation(animation
);
145 case REPLACE_QUEUED_ANIMATIONS
:
146 ReplaceQueuedAnimations(animation
);
148 case BLEND_WITH_CURRENT_ANIMATION
: {
149 // TODO(vollick) Add support for blended sequences and use them here.
155 FinishAnyAnimationWithZeroDuration();
156 UpdateAnimationState();
159 void LayerAnimator::ScheduleAnimation(LayerAnimationSequence
* animation
) {
160 scoped_refptr
<LayerAnimator
> retain(this);
161 OnScheduled(animation
);
162 if (is_animating()) {
163 animation_queue_
.push_back(make_linked_ptr(animation
));
166 StartSequenceImmediately(animation
);
168 UpdateAnimationState();
171 void LayerAnimator::StartTogether(
172 const std::vector
<LayerAnimationSequence
*>& animations
) {
173 scoped_refptr
<LayerAnimator
> retain(this);
174 if (preemption_strategy_
== IMMEDIATELY_SET_NEW_TARGET
) {
175 std::vector
<LayerAnimationSequence
*>::const_iterator iter
;
176 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
) {
177 StartAnimation(*iter
);
182 adding_animations_
= true;
183 if (!is_animating()) {
184 if (GetAnimationContainer()->is_running())
185 last_step_time_
= GetAnimationContainer()->last_tick_time();
187 last_step_time_
= gfx::FrameTime::Now();
190 // Collect all the affected properties.
191 LayerAnimationElement::AnimatableProperties animated_properties
=
192 LayerAnimationElement::UNKNOWN
;
194 std::vector
<LayerAnimationSequence
*>::const_iterator iter
;
195 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
)
196 animated_properties
|= (*iter
)->properties();
198 // Starting a zero duration pause that affects all the animated properties
199 // will prevent any of the sequences from animating until there are no
200 // running animations that affect any of these properties, as well as
201 // handle preemption strategy.
202 StartAnimation(new LayerAnimationSequence(
203 LayerAnimationElement::CreatePauseElement(animated_properties
,
204 base::TimeDelta())));
206 bool wait_for_group_start
= false;
207 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
)
208 wait_for_group_start
|= (*iter
)->IsFirstElementThreaded();
210 int group_id
= cc::AnimationIdProvider::NextGroupId();
212 // These animations (provided they don't animate any common properties) will
213 // now animate together if trivially scheduled.
214 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
) {
215 (*iter
)->set_animation_group_id(group_id
);
216 (*iter
)->set_waiting_for_group_start(wait_for_group_start
);
217 ScheduleAnimation(*iter
);
220 adding_animations_
= false;
221 UpdateAnimationState();
225 void LayerAnimator::ScheduleTogether(
226 const std::vector
<LayerAnimationSequence
*>& animations
) {
227 scoped_refptr
<LayerAnimator
> retain(this);
229 // Collect all the affected properties.
230 LayerAnimationElement::AnimatableProperties animated_properties
=
231 LayerAnimationElement::UNKNOWN
;
233 std::vector
<LayerAnimationSequence
*>::const_iterator iter
;
234 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
)
235 animated_properties
|= (*iter
)->properties();
237 // Scheduling a zero duration pause that affects all the animated properties
238 // will prevent any of the sequences from animating until there are no
239 // running animations that affect any of these properties.
240 ScheduleAnimation(new LayerAnimationSequence(
241 LayerAnimationElement::CreatePauseElement(animated_properties
,
242 base::TimeDelta())));
244 bool wait_for_group_start
= false;
245 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
)
246 wait_for_group_start
|= (*iter
)->IsFirstElementThreaded();
248 int group_id
= cc::AnimationIdProvider::NextGroupId();
250 // These animations (provided they don't animate any common properties) will
251 // now animate together if trivially scheduled.
252 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
) {
253 (*iter
)->set_animation_group_id(group_id
);
254 (*iter
)->set_waiting_for_group_start(wait_for_group_start
);
255 ScheduleAnimation(*iter
);
258 UpdateAnimationState();
261 void LayerAnimator::SchedulePauseForProperties(
262 base::TimeDelta duration
,
263 LayerAnimationElement::AnimatableProperties properties_to_pause
) {
264 ScheduleAnimation(new ui::LayerAnimationSequence(
265 ui::LayerAnimationElement::CreatePauseElement(
266 properties_to_pause
, duration
)));
269 bool LayerAnimator::IsAnimatingProperty(
270 LayerAnimationElement::AnimatableProperty property
) const {
271 for (AnimationQueue::const_iterator queue_iter
= animation_queue_
.begin();
272 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
273 if ((*queue_iter
)->properties() & property
)
279 void LayerAnimator::StopAnimatingProperty(
280 LayerAnimationElement::AnimatableProperty property
) {
281 scoped_refptr
<LayerAnimator
> retain(this);
283 // GetRunningAnimation purges deleted animations before searching, so we are
284 // guaranteed to find a live animation if any is returned at all.
285 RunningAnimation
* running
= GetRunningAnimation(property
);
288 // As was mentioned above, this sequence must be alive.
289 DCHECK(running
->is_sequence_alive());
290 FinishAnimation(running
->sequence(), false);
294 void LayerAnimator::AddObserver(LayerAnimationObserver
* observer
) {
295 if (!observers_
.HasObserver(observer
))
296 observers_
.AddObserver(observer
);
299 void LayerAnimator::RemoveObserver(LayerAnimationObserver
* observer
) {
300 observers_
.RemoveObserver(observer
);
301 // Remove the observer from all sequences as well.
302 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
303 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
304 (*queue_iter
)->RemoveObserver(observer
);
308 void LayerAnimator::OnThreadedAnimationStarted(
309 const cc::AnimationEvent
& event
) {
310 LayerAnimationElement::AnimatableProperty property
=
311 LayerAnimationElement::ToAnimatableProperty(event
.target_property
);
313 RunningAnimation
* running
= GetRunningAnimation(property
);
316 DCHECK(running
->is_sequence_alive());
318 if (running
->sequence()->animation_group_id() != event
.group_id
)
321 running
->sequence()->OnThreadedAnimationStarted(event
);
322 if (!running
->sequence()->waiting_for_group_start())
325 base::TimeTicks start_time
= base::TimeTicks::FromInternalValue(
326 event
.monotonic_time
* base::Time::kMicrosecondsPerSecond
);
328 running
->sequence()->set_waiting_for_group_start(false);
330 // The call to GetRunningAnimation made above already purged deleted
331 // animations, so we are guaranteed that all the animations we iterate
332 // over now are alive.
333 for (RunningAnimations::iterator iter
= running_animations_
.begin();
334 iter
!= running_animations_
.end(); ++iter
) {
335 // Ensure that each sequence is only Started once, regardless of the
336 // number of sequences in the group that have threaded first elements.
337 if (((*iter
).sequence()->animation_group_id() == event
.group_id
) &&
338 !(*iter
).sequence()->IsFirstElementThreaded() &&
339 (*iter
).sequence()->waiting_for_group_start()) {
340 (*iter
).sequence()->set_start_time(start_time
);
341 (*iter
).sequence()->set_waiting_for_group_start(false);
342 (*iter
).sequence()->Start(delegate());
347 // LayerAnimator protected -----------------------------------------------------
349 void LayerAnimator::ProgressAnimation(LayerAnimationSequence
* sequence
,
350 base::TimeTicks now
) {
351 if (!delegate() || sequence
->waiting_for_group_start())
354 sequence
->Progress(now
, delegate());
357 void LayerAnimator::ProgressAnimationToEnd(LayerAnimationSequence
* sequence
) {
361 sequence
->ProgressToEnd(delegate());
364 bool LayerAnimator::HasAnimation(LayerAnimationSequence
* sequence
) const {
365 for (AnimationQueue::const_iterator queue_iter
= animation_queue_
.begin();
366 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
367 if ((*queue_iter
).get() == sequence
)
373 // LayerAnimator private -------------------------------------------------------
375 void LayerAnimator::Step(base::TimeTicks now
) {
376 TRACE_EVENT0("ui", "LayerAnimator::Step");
377 scoped_refptr
<LayerAnimator
> retain(this);
379 last_step_time_
= now
;
381 PurgeDeletedAnimations();
383 // We need to make a copy of the running animations because progressing them
384 // and finishing them may indirectly affect the collection of running
386 RunningAnimations running_animations_copy
= running_animations_
;
387 for (size_t i
= 0; i
< running_animations_copy
.size(); ++i
) {
388 if (!SAFE_INVOKE_BOOL(HasAnimation
, running_animations_copy
[i
]))
391 if (running_animations_copy
[i
].sequence()->IsFinished(now
)) {
392 SAFE_INVOKE_VOID(FinishAnimation
, running_animations_copy
[i
], false);
394 SAFE_INVOKE_VOID(ProgressAnimation
, running_animations_copy
[i
], now
);
399 void LayerAnimator::SetStartTime(base::TimeTicks start_time
) {
403 base::TimeDelta
LayerAnimator::GetTimerInterval() const {
404 return base::TimeDelta::FromMilliseconds(kTimerIntervalMs
);
407 void LayerAnimator::StopAnimatingInternal(bool abort
) {
408 scoped_refptr
<LayerAnimator
> retain(this);
409 while (is_animating()) {
410 // We're going to attempt to finish the first running animation. Let's
411 // ensure that it's valid.
412 PurgeDeletedAnimations();
414 // If we've purged all running animations, attempt to start one up.
415 if (running_animations_
.empty())
418 DCHECK(!running_animations_
.empty());
420 // Still no luck, let's just bail and clear all animations.
421 if (running_animations_
.empty()) {
422 ClearAnimationsInternal();
426 SAFE_INVOKE_VOID(FinishAnimation
, running_animations_
[0], abort
);
430 void LayerAnimator::UpdateAnimationState() {
431 if (disable_timer_for_test_
)
434 const bool should_start
= is_animating();
435 if (should_start
&& !is_started_
)
436 GetAnimationContainer()->Start(this);
437 else if (!should_start
&& is_started_
)
438 GetAnimationContainer()->Stop(this);
440 is_started_
= should_start
;
443 LayerAnimationSequence
* LayerAnimator::RemoveAnimation(
444 LayerAnimationSequence
* sequence
) {
445 linked_ptr
<LayerAnimationSequence
> to_return
;
447 bool is_running
= false;
449 // First remove from running animations
450 for (RunningAnimations::iterator iter
= running_animations_
.begin();
451 iter
!= running_animations_
.end(); ++iter
) {
452 if ((*iter
).sequence() == sequence
) {
453 running_animations_
.erase(iter
);
459 // Then remove from the queue
460 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
461 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
462 if ((*queue_iter
) == sequence
) {
463 to_return
= *queue_iter
;
464 animation_queue_
.erase(queue_iter
);
469 if (!to_return
.get() ||
470 !to_return
->waiting_for_group_start() ||
471 !to_return
->IsFirstElementThreaded())
472 return to_return
.release();
474 // The removed sequence may have been responsible for making other sequences
475 // wait for a group start. If no other sequences in the group have a
476 // threaded first element, the group no longer needs the additional wait.
477 bool is_wait_still_needed
= false;
478 int group_id
= to_return
->animation_group_id();
479 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
480 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
481 if (((*queue_iter
)->animation_group_id() == group_id
) &&
482 (*queue_iter
)->IsFirstElementThreaded()) {
483 is_wait_still_needed
= true;
488 if (is_wait_still_needed
)
489 return to_return
.release();
491 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
492 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
493 if ((*queue_iter
)->animation_group_id() == group_id
&&
494 (*queue_iter
)->waiting_for_group_start()) {
495 (*queue_iter
)->set_waiting_for_group_start(false);
497 (*queue_iter
)->set_start_time(last_step_time_
);
498 (*queue_iter
)->Start(delegate());
502 return to_return
.release();
505 void LayerAnimator::FinishAnimation(
506 LayerAnimationSequence
* sequence
, bool abort
) {
507 scoped_refptr
<LayerAnimator
> retain(this);
508 scoped_ptr
<LayerAnimationSequence
> removed(RemoveAnimation(sequence
));
510 sequence
->Abort(delegate());
512 ProgressAnimationToEnd(sequence
);
514 UpdateAnimationState();
517 void LayerAnimator::FinishAnyAnimationWithZeroDuration() {
518 scoped_refptr
<LayerAnimator
> retain(this);
519 // Special case: if we've started a 0 duration animation, just finish it now
520 // and get rid of it. We need to make a copy because Progress may indirectly
521 // cause new animations to start running.
522 RunningAnimations running_animations_copy
= running_animations_
;
523 for (size_t i
= 0; i
< running_animations_copy
.size(); ++i
) {
524 if (!SAFE_INVOKE_BOOL(HasAnimation
, running_animations_copy
[i
]))
527 if (running_animations_copy
[i
].sequence()->IsFinished(
528 running_animations_copy
[i
].sequence()->start_time())) {
529 SAFE_INVOKE_VOID(ProgressAnimationToEnd
, running_animations_copy
[i
]);
530 scoped_ptr
<LayerAnimationSequence
> removed(
531 SAFE_INVOKE_PTR(RemoveAnimation
, running_animations_copy
[i
]));
535 UpdateAnimationState();
538 void LayerAnimator::ClearAnimations() {
539 scoped_refptr
<LayerAnimator
> retain(this);
540 ClearAnimationsInternal();
543 LayerAnimator::RunningAnimation
* LayerAnimator::GetRunningAnimation(
544 LayerAnimationElement::AnimatableProperty property
) {
545 PurgeDeletedAnimations();
546 for (RunningAnimations::iterator iter
= running_animations_
.begin();
547 iter
!= running_animations_
.end(); ++iter
) {
548 if ((*iter
).sequence()->properties() & property
)
554 void LayerAnimator::AddToQueueIfNotPresent(LayerAnimationSequence
* animation
) {
555 // If we don't have the animation in the queue yet, add it.
556 bool found_sequence
= false;
557 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
558 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
559 if ((*queue_iter
) == animation
) {
560 found_sequence
= true;
566 animation_queue_
.push_front(make_linked_ptr(animation
));
569 void LayerAnimator::RemoveAllAnimationsWithACommonProperty(
570 LayerAnimationSequence
* sequence
, bool abort
) {
571 // For all the running animations, if they animate the same property,
572 // progress them to the end and remove them. Note, Aborting or Progressing
573 // animations may affect the collection of running animations, so we need to
574 // operate on a copy.
575 RunningAnimations running_animations_copy
= running_animations_
;
576 for (size_t i
= 0; i
< running_animations_copy
.size(); ++i
) {
577 if (!SAFE_INVOKE_BOOL(HasAnimation
, running_animations_copy
[i
]))
580 if (running_animations_copy
[i
].sequence()->HasConflictingProperty(
581 sequence
->properties())) {
582 scoped_ptr
<LayerAnimationSequence
> removed(
583 SAFE_INVOKE_PTR(RemoveAnimation
, running_animations_copy
[i
]));
585 running_animations_copy
[i
].sequence()->Abort(delegate());
587 SAFE_INVOKE_VOID(ProgressAnimationToEnd
, running_animations_copy
[i
]);
591 // Same for the queued animations that haven't been started. Again, we'll
592 // need to operate on a copy.
593 std::vector
<base::WeakPtr
<LayerAnimationSequence
> > sequences
;
594 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
595 queue_iter
!= animation_queue_
.end(); ++queue_iter
)
596 sequences
.push_back((*queue_iter
)->AsWeakPtr());
598 for (size_t i
= 0; i
< sequences
.size(); ++i
) {
599 if (!sequences
[i
].get() || !HasAnimation(sequences
[i
].get()))
602 if (sequences
[i
]->HasConflictingProperty(sequence
->properties())) {
603 scoped_ptr
<LayerAnimationSequence
> removed(
604 RemoveAnimation(sequences
[i
].get()));
606 sequences
[i
]->Abort(delegate());
608 ProgressAnimationToEnd(sequences
[i
].get());
613 void LayerAnimator::ImmediatelySetNewTarget(LayerAnimationSequence
* sequence
) {
614 // Need to detect if our sequence gets destroyed.
615 base::WeakPtr
<LayerAnimationSequence
> weak_sequence_ptr
=
616 sequence
->AsWeakPtr();
618 const bool abort
= false;
619 RemoveAllAnimationsWithACommonProperty(sequence
, abort
);
620 if (!weak_sequence_ptr
.get())
623 LayerAnimationSequence
* removed
= RemoveAnimation(sequence
);
624 DCHECK(removed
== NULL
|| removed
== sequence
);
625 if (!weak_sequence_ptr
.get())
628 ProgressAnimationToEnd(sequence
);
629 if (!weak_sequence_ptr
.get())
635 void LayerAnimator::ImmediatelyAnimateToNewTarget(
636 LayerAnimationSequence
* sequence
) {
637 // Need to detect if our sequence gets destroyed.
638 base::WeakPtr
<LayerAnimationSequence
> weak_sequence_ptr
=
639 sequence
->AsWeakPtr();
641 const bool abort
= true;
642 RemoveAllAnimationsWithACommonProperty(sequence
, abort
);
643 if (!weak_sequence_ptr
.get())
646 AddToQueueIfNotPresent(sequence
);
647 if (!weak_sequence_ptr
.get())
650 StartSequenceImmediately(sequence
);
653 void LayerAnimator::EnqueueNewAnimation(LayerAnimationSequence
* sequence
) {
654 // It is assumed that if there was no conflicting animation, we would
655 // not have been called. No need to check for a collision; just
657 animation_queue_
.push_back(make_linked_ptr(sequence
));
661 void LayerAnimator::ReplaceQueuedAnimations(LayerAnimationSequence
* sequence
) {
662 // Need to detect if our sequence gets destroyed.
663 base::WeakPtr
<LayerAnimationSequence
> weak_sequence_ptr
=
664 sequence
->AsWeakPtr();
666 // Remove all animations that aren't running. Note: at each iteration i is
667 // incremented or an element is removed from the queue, so
668 // animation_queue_.size() - i is always decreasing and we are always making
669 // progress towards the loop terminating.
670 for (size_t i
= 0; i
< animation_queue_
.size();) {
671 if (!weak_sequence_ptr
.get())
674 PurgeDeletedAnimations();
676 bool is_running
= false;
677 for (RunningAnimations::const_iterator iter
= running_animations_
.begin();
678 iter
!= running_animations_
.end(); ++iter
) {
679 if ((*iter
).sequence() == animation_queue_
[i
].get()) {
686 delete RemoveAnimation(animation_queue_
[i
].get());
690 animation_queue_
.push_back(make_linked_ptr(sequence
));
694 void LayerAnimator::ProcessQueue() {
695 bool started_sequence
= false;
697 started_sequence
= false;
698 // Build a list of all currently animated properties.
699 LayerAnimationElement::AnimatableProperties animated
=
700 LayerAnimationElement::UNKNOWN
;
701 for (RunningAnimations::const_iterator iter
= running_animations_
.begin();
702 iter
!= running_animations_
.end(); ++iter
) {
703 if (!(*iter
).is_sequence_alive())
706 animated
|= (*iter
).sequence()->properties();
709 // Try to find an animation that doesn't conflict with an animated
710 // property or a property that will be animated before it. Note: starting
711 // the animation may indirectly cause more animations to be started, so we
712 // need to operate on a copy.
713 std::vector
<base::WeakPtr
<LayerAnimationSequence
> > sequences
;
714 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
715 queue_iter
!= animation_queue_
.end(); ++queue_iter
)
716 sequences
.push_back((*queue_iter
)->AsWeakPtr());
718 for (size_t i
= 0; i
< sequences
.size(); ++i
) {
719 if (!sequences
[i
].get() || !HasAnimation(sequences
[i
].get()))
722 if (!sequences
[i
]->HasConflictingProperty(animated
)) {
723 StartSequenceImmediately(sequences
[i
].get());
724 started_sequence
= true;
728 // Animation couldn't be started. Add its properties to the collection so
729 // that we don't start a conflicting animation. For example, if our queue
730 // has the elements { {T,B}, {B} } (that is, an element that animates both
731 // the transform and the bounds followed by an element that animates the
732 // bounds), and we're currently animating the transform, we can't start
733 // the first element because it animates the transform, too. We cannot
734 // start the second element, either, because the first element animates
735 // bounds too, and needs to go first.
736 animated
|= sequences
[i
]->properties();
739 // If we started a sequence, try again. We may be able to start several.
740 } while (started_sequence
);
743 bool LayerAnimator::StartSequenceImmediately(LayerAnimationSequence
* sequence
) {
744 PurgeDeletedAnimations();
746 // Ensure that no one is animating one of the sequence's properties already.
747 for (RunningAnimations::const_iterator iter
= running_animations_
.begin();
748 iter
!= running_animations_
.end(); ++iter
) {
749 if ((*iter
).sequence()->HasConflictingProperty(sequence
->properties()))
753 // All clear, actually start the sequence. Note: base::TimeTicks::Now has
754 // a resolution that can be as bad as 15ms. If this causes glitches in the
755 // animations, this can be switched to HighResNow() (animation uses Now()
757 // All LayerAnimators share the same AnimationContainer. Use the
758 // last_tick_time() from there to ensure animations started during the same
759 // event complete at the same time.
760 base::TimeTicks start_time
;
761 if (is_animating() || adding_animations_
)
762 start_time
= last_step_time_
;
763 else if (GetAnimationContainer()->is_running())
764 start_time
= GetAnimationContainer()->last_tick_time();
766 start_time
= gfx::FrameTime::Now();
768 if (!sequence
->animation_group_id())
769 sequence
->set_animation_group_id(cc::AnimationIdProvider::NextGroupId());
770 if (!sequence
->waiting_for_group_start() ||
771 sequence
->IsFirstElementThreaded()) {
772 sequence
->set_start_time(start_time
);
773 sequence
->Start(delegate());
775 running_animations_
.push_back(
776 RunningAnimation(sequence
->AsWeakPtr()));
778 // Need to keep a reference to the animation.
779 AddToQueueIfNotPresent(sequence
);
781 // Ensure that animations get stepped at their start time.
787 void LayerAnimator::GetTargetValue(
788 LayerAnimationElement::TargetValue
* target
) const {
789 for (AnimationQueue::const_iterator iter
= animation_queue_
.begin();
790 iter
!= animation_queue_
.end(); ++iter
) {
791 (*iter
)->GetTargetValue(target
);
795 void LayerAnimator::OnScheduled(LayerAnimationSequence
* sequence
) {
796 if (observers_
.might_have_observers()) {
797 ObserverListBase
<LayerAnimationObserver
>::Iterator
it(observers_
);
798 LayerAnimationObserver
* obs
;
799 while ((obs
= it
.GetNext()) != NULL
) {
800 sequence
->AddObserver(obs
);
803 sequence
->OnScheduled();
806 void LayerAnimator::SetTransitionDuration(base::TimeDelta duration
) {
807 if (is_transition_duration_locked_
)
809 transition_duration_
= duration
;
812 void LayerAnimator::ClearAnimationsInternal() {
813 PurgeDeletedAnimations();
815 // Abort should never affect the set of running animations, but just in case
816 // clients are badly behaved, we will use a copy of the running animations.
817 RunningAnimations running_animations_copy
= running_animations_
;
818 for (size_t i
= 0; i
< running_animations_copy
.size(); ++i
) {
819 if (!SAFE_INVOKE_BOOL(HasAnimation
, running_animations_copy
[i
]))
822 scoped_ptr
<LayerAnimationSequence
> removed(
823 RemoveAnimation(running_animations_copy
[i
].sequence()));
825 removed
->Abort(delegate());
827 // This *should* have cleared the list of running animations.
828 DCHECK(running_animations_
.empty());
829 running_animations_
.clear();
830 animation_queue_
.clear();
831 UpdateAnimationState();
834 void LayerAnimator::PurgeDeletedAnimations() {
835 for (size_t i
= 0; i
< running_animations_
.size();) {
836 if (!running_animations_
[i
].is_sequence_alive())
837 running_animations_
.erase(running_animations_
.begin() + i
);
843 LayerAnimator::RunningAnimation::RunningAnimation(
844 const base::WeakPtr
<LayerAnimationSequence
>& sequence
)
845 : sequence_(sequence
) {
848 LayerAnimator::RunningAnimation::~RunningAnimation() { }