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 transition_duration_(transition_duration
),
59 tween_type_(gfx::Tween::LINEAR
),
61 disable_timer_for_test_(false),
62 adding_animations_(false) {
65 LayerAnimator::~LayerAnimator() {
66 for (size_t i
= 0; i
< running_animations_
.size(); ++i
) {
67 if (running_animations_
[i
].is_sequence_alive())
68 running_animations_
[i
].sequence()->OnAnimatorDestroyed();
70 ClearAnimationsInternal();
75 LayerAnimator
* LayerAnimator::CreateDefaultAnimator() {
76 return new LayerAnimator(base::TimeDelta::FromMilliseconds(0));
80 LayerAnimator
* LayerAnimator::CreateImplicitAnimator() {
81 return new LayerAnimator(
82 base::TimeDelta::FromMilliseconds(kDefaultTransitionDurationMs
));
85 // This macro provides the implementation for the setter and getter (well,
86 // the getter of the target value) for an animated property. For example,
87 // it is used for the implementations of SetTransform and GetTargetTransform.
88 // It is worth noting that SetFoo avoids invoking the usual animation machinery
89 // if the transition duration is zero -- in this case we just set the property
90 // on the layer animation delegate immediately.
91 #define ANIMATED_PROPERTY(type, property, name, member_type, member) \
92 void LayerAnimator::Set##name(type value) { \
93 base::TimeDelta duration = GetTransitionDuration(); \
94 if (duration == base::TimeDelta() && delegate() && \
95 (preemption_strategy_ != ENQUEUE_NEW_ANIMATION)) { \
96 StopAnimatingProperty(LayerAnimationElement::property); \
97 delegate()->Set##name##FromAnimation(value); \
100 scoped_ptr<LayerAnimationElement> element( \
101 LayerAnimationElement::Create##name##Element(value, duration)); \
102 element->set_tween_type(tween_type_); \
103 StartAnimation(new LayerAnimationSequence(element.release())); \
106 member_type LayerAnimator::GetTarget##name() const { \
107 LayerAnimationElement::TargetValue target(delegate()); \
108 GetTargetValue(&target); \
109 return target.member; \
113 const gfx::Transform
&, TRANSFORM
, Transform
, gfx::Transform
, transform
);
114 ANIMATED_PROPERTY(const gfx::Rect
&, BOUNDS
, Bounds
, gfx::Rect
, bounds
);
115 ANIMATED_PROPERTY(float, OPACITY
, Opacity
, float, opacity
);
116 ANIMATED_PROPERTY(bool, VISIBILITY
, Visibility
, bool, visibility
);
117 ANIMATED_PROPERTY(float, BRIGHTNESS
, Brightness
, float, brightness
);
118 ANIMATED_PROPERTY(float, GRAYSCALE
, Grayscale
, float, grayscale
);
119 ANIMATED_PROPERTY(SkColor
, COLOR
, Color
, SkColor
, color
);
121 void LayerAnimator::SetDelegate(LayerAnimationDelegate
* delegate
) {
122 delegate_
= delegate
;
125 void LayerAnimator::StartAnimation(LayerAnimationSequence
* animation
) {
126 scoped_refptr
<LayerAnimator
> retain(this);
127 OnScheduled(animation
);
128 if (!StartSequenceImmediately(animation
)) {
129 // Attempt to preempt a running animation.
130 switch (preemption_strategy_
) {
131 case IMMEDIATELY_SET_NEW_TARGET
:
132 ImmediatelySetNewTarget(animation
);
134 case IMMEDIATELY_ANIMATE_TO_NEW_TARGET
:
135 ImmediatelyAnimateToNewTarget(animation
);
137 case ENQUEUE_NEW_ANIMATION
:
138 EnqueueNewAnimation(animation
);
140 case REPLACE_QUEUED_ANIMATIONS
:
141 ReplaceQueuedAnimations(animation
);
143 case BLEND_WITH_CURRENT_ANIMATION
: {
144 // TODO(vollick) Add support for blended sequences and use them here.
150 FinishAnyAnimationWithZeroDuration();
151 UpdateAnimationState();
154 void LayerAnimator::ScheduleAnimation(LayerAnimationSequence
* animation
) {
155 scoped_refptr
<LayerAnimator
> retain(this);
156 OnScheduled(animation
);
157 if (is_animating()) {
158 animation_queue_
.push_back(make_linked_ptr(animation
));
161 StartSequenceImmediately(animation
);
163 UpdateAnimationState();
166 void LayerAnimator::StartTogether(
167 const std::vector
<LayerAnimationSequence
*>& animations
) {
168 scoped_refptr
<LayerAnimator
> retain(this);
169 if (preemption_strategy_
== IMMEDIATELY_SET_NEW_TARGET
) {
170 std::vector
<LayerAnimationSequence
*>::const_iterator iter
;
171 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
) {
172 StartAnimation(*iter
);
177 adding_animations_
= true;
178 if (!is_animating()) {
179 if (GetAnimationContainer()->is_running())
180 last_step_time_
= GetAnimationContainer()->last_tick_time();
182 last_step_time_
= gfx::FrameTime::Now();
185 // Collect all the affected properties.
186 LayerAnimationElement::AnimatableProperties animated_properties
;
187 std::vector
<LayerAnimationSequence
*>::const_iterator iter
;
188 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
) {
189 animated_properties
.insert((*iter
)->properties().begin(),
190 (*iter
)->properties().end());
193 // Starting a zero duration pause that affects all the animated properties
194 // will prevent any of the sequences from animating until there are no
195 // running animations that affect any of these properties, as well as
196 // handle preemption strategy.
197 StartAnimation(new LayerAnimationSequence(
198 LayerAnimationElement::CreatePauseElement(animated_properties
,
199 base::TimeDelta())));
201 bool wait_for_group_start
= false;
202 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
)
203 wait_for_group_start
|= (*iter
)->IsFirstElementThreaded();
205 int group_id
= cc::AnimationIdProvider::NextGroupId();
207 // These animations (provided they don't animate any common properties) will
208 // now animate together if trivially scheduled.
209 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
) {
210 (*iter
)->set_animation_group_id(group_id
);
211 (*iter
)->set_waiting_for_group_start(wait_for_group_start
);
212 ScheduleAnimation(*iter
);
215 adding_animations_
= false;
216 UpdateAnimationState();
220 void LayerAnimator::ScheduleTogether(
221 const std::vector
<LayerAnimationSequence
*>& animations
) {
222 scoped_refptr
<LayerAnimator
> retain(this);
224 // Collect all the affected properties.
225 LayerAnimationElement::AnimatableProperties animated_properties
;
226 std::vector
<LayerAnimationSequence
*>::const_iterator iter
;
227 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
) {
228 animated_properties
.insert((*iter
)->properties().begin(),
229 (*iter
)->properties().end());
232 // Scheduling a zero duration pause that affects all the animated properties
233 // will prevent any of the sequences from animating until there are no
234 // running animations that affect any of these properties.
235 ScheduleAnimation(new LayerAnimationSequence(
236 LayerAnimationElement::CreatePauseElement(animated_properties
,
237 base::TimeDelta())));
239 bool wait_for_group_start
= false;
240 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
)
241 wait_for_group_start
|= (*iter
)->IsFirstElementThreaded();
243 int group_id
= cc::AnimationIdProvider::NextGroupId();
245 // These animations (provided they don't animate any common properties) will
246 // now animate together if trivially scheduled.
247 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
) {
248 (*iter
)->set_animation_group_id(group_id
);
249 (*iter
)->set_waiting_for_group_start(wait_for_group_start
);
250 ScheduleAnimation(*iter
);
253 UpdateAnimationState();
256 void LayerAnimator::SchedulePauseForProperties(
257 base::TimeDelta duration
,
258 LayerAnimationElement::AnimatableProperty property
,
260 ui::LayerAnimationElement::AnimatableProperties properties_to_pause
;
262 va_start(marker
, property
);
263 for (int p
= static_cast<int>(property
); p
!= -1; p
= va_arg(marker
, int)) {
264 properties_to_pause
.insert(
265 static_cast<LayerAnimationElement::AnimatableProperty
>(p
));
268 ScheduleAnimation(new ui::LayerAnimationSequence(
269 ui::LayerAnimationElement::CreatePauseElement(
270 properties_to_pause
, duration
)));
273 bool LayerAnimator::IsAnimatingProperty(
274 LayerAnimationElement::AnimatableProperty property
) const {
275 for (AnimationQueue::const_iterator queue_iter
= animation_queue_
.begin();
276 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
277 if ((*queue_iter
)->properties().find(property
) !=
278 (*queue_iter
)->properties().end()) {
285 void LayerAnimator::StopAnimatingProperty(
286 LayerAnimationElement::AnimatableProperty property
) {
287 scoped_refptr
<LayerAnimator
> retain(this);
289 // GetRunningAnimation purges deleted animations before searching, so we are
290 // guaranteed to find a live animation if any is returned at all.
291 RunningAnimation
* running
= GetRunningAnimation(property
);
294 // As was mentioned above, this sequence must be alive.
295 DCHECK(running
->is_sequence_alive());
296 FinishAnimation(running
->sequence(), false);
300 void LayerAnimator::AddObserver(LayerAnimationObserver
* observer
) {
301 if (!observers_
.HasObserver(observer
))
302 observers_
.AddObserver(observer
);
305 void LayerAnimator::RemoveObserver(LayerAnimationObserver
* observer
) {
306 observers_
.RemoveObserver(observer
);
307 // Remove the observer from all sequences as well.
308 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
309 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
310 (*queue_iter
)->RemoveObserver(observer
);
314 void LayerAnimator::OnThreadedAnimationStarted(
315 const cc::AnimationEvent
& event
) {
316 LayerAnimationElement::AnimatableProperty property
=
317 LayerAnimationElement::ToAnimatableProperty(event
.target_property
);
319 RunningAnimation
* running
= GetRunningAnimation(property
);
322 DCHECK(running
->is_sequence_alive());
324 if (running
->sequence()->animation_group_id() != event
.group_id
)
327 running
->sequence()->OnThreadedAnimationStarted(event
);
328 if (!running
->sequence()->waiting_for_group_start())
331 base::TimeTicks start_time
= base::TimeTicks::FromInternalValue(
332 event
.monotonic_time
* base::Time::kMicrosecondsPerSecond
);
334 running
->sequence()->set_waiting_for_group_start(false);
336 // The call to GetRunningAnimation made above already purged deleted
337 // animations, so we are guaranteed that all the animations we iterate
338 // over now are alive.
339 for (RunningAnimations::iterator iter
= running_animations_
.begin();
340 iter
!= running_animations_
.end(); ++iter
) {
341 // Ensure that each sequence is only Started once, regardless of the
342 // number of sequences in the group that have threaded first elements.
343 if (((*iter
).sequence()->animation_group_id() == event
.group_id
) &&
344 !(*iter
).sequence()->IsFirstElementThreaded() &&
345 (*iter
).sequence()->waiting_for_group_start()) {
346 (*iter
).sequence()->set_start_time(start_time
);
347 (*iter
).sequence()->set_waiting_for_group_start(false);
348 (*iter
).sequence()->Start(delegate());
353 // LayerAnimator protected -----------------------------------------------------
355 void LayerAnimator::ProgressAnimation(LayerAnimationSequence
* sequence
,
356 base::TimeTicks now
) {
357 if (!delegate() || sequence
->waiting_for_group_start())
360 sequence
->Progress(now
, delegate());
363 void LayerAnimator::ProgressAnimationToEnd(LayerAnimationSequence
* sequence
) {
367 sequence
->ProgressToEnd(delegate());
370 bool LayerAnimator::HasAnimation(LayerAnimationSequence
* sequence
) const {
371 for (AnimationQueue::const_iterator queue_iter
= animation_queue_
.begin();
372 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
373 if ((*queue_iter
).get() == sequence
)
379 // LayerAnimator private -------------------------------------------------------
381 void LayerAnimator::Step(base::TimeTicks now
) {
382 TRACE_EVENT0("ui", "LayerAnimator::Step");
383 scoped_refptr
<LayerAnimator
> retain(this);
385 last_step_time_
= now
;
387 PurgeDeletedAnimations();
389 // We need to make a copy of the running animations because progressing them
390 // and finishing them may indirectly affect the collection of running
392 RunningAnimations running_animations_copy
= running_animations_
;
393 for (size_t i
= 0; i
< running_animations_copy
.size(); ++i
) {
394 if (!SAFE_INVOKE_BOOL(HasAnimation
, running_animations_copy
[i
]))
397 if (running_animations_copy
[i
].sequence()->IsFinished(now
)) {
398 SAFE_INVOKE_VOID(FinishAnimation
, running_animations_copy
[i
], false);
400 SAFE_INVOKE_VOID(ProgressAnimation
, running_animations_copy
[i
], now
);
405 void LayerAnimator::SetStartTime(base::TimeTicks start_time
) {
409 base::TimeDelta
LayerAnimator::GetTimerInterval() const {
410 return base::TimeDelta::FromMilliseconds(kTimerIntervalMs
);
413 void LayerAnimator::StopAnimatingInternal(bool abort
) {
414 scoped_refptr
<LayerAnimator
> retain(this);
415 while (is_animating()) {
416 // We're going to attempt to finish the first running animation. Let's
417 // ensure that it's valid.
418 PurgeDeletedAnimations();
420 // If we've purged all running animations, attempt to start one up.
421 if (running_animations_
.empty())
424 DCHECK(!running_animations_
.empty());
426 // Still no luck, let's just bail and clear all animations.
427 if (running_animations_
.empty()) {
428 ClearAnimationsInternal();
432 SAFE_INVOKE_VOID(FinishAnimation
, running_animations_
[0], abort
);
436 void LayerAnimator::UpdateAnimationState() {
437 if (disable_timer_for_test_
)
440 const bool should_start
= is_animating();
441 if (should_start
&& !is_started_
)
442 GetAnimationContainer()->Start(this);
443 else if (!should_start
&& is_started_
)
444 GetAnimationContainer()->Stop(this);
446 is_started_
= should_start
;
449 LayerAnimationSequence
* LayerAnimator::RemoveAnimation(
450 LayerAnimationSequence
* sequence
) {
451 linked_ptr
<LayerAnimationSequence
> to_return
;
453 bool is_running
= false;
455 // First remove from running animations
456 for (RunningAnimations::iterator iter
= running_animations_
.begin();
457 iter
!= running_animations_
.end(); ++iter
) {
458 if ((*iter
).sequence() == sequence
) {
459 running_animations_
.erase(iter
);
465 // Then remove from the queue
466 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
467 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
468 if ((*queue_iter
) == sequence
) {
469 to_return
= *queue_iter
;
470 animation_queue_
.erase(queue_iter
);
475 if (!to_return
.get() ||
476 !to_return
->waiting_for_group_start() ||
477 !to_return
->IsFirstElementThreaded())
478 return to_return
.release();
480 // The removed sequence may have been responsible for making other sequences
481 // wait for a group start. If no other sequences in the group have a
482 // threaded first element, the group no longer needs the additional wait.
483 bool is_wait_still_needed
= false;
484 int group_id
= to_return
->animation_group_id();
485 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
486 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
487 if (((*queue_iter
)->animation_group_id() == group_id
) &&
488 (*queue_iter
)->IsFirstElementThreaded()) {
489 is_wait_still_needed
= true;
494 if (is_wait_still_needed
)
495 return to_return
.release();
497 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
498 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
499 if ((*queue_iter
)->animation_group_id() == group_id
&&
500 (*queue_iter
)->waiting_for_group_start()) {
501 (*queue_iter
)->set_waiting_for_group_start(false);
503 (*queue_iter
)->set_start_time(last_step_time_
);
504 (*queue_iter
)->Start(delegate());
508 return to_return
.release();
511 void LayerAnimator::FinishAnimation(
512 LayerAnimationSequence
* sequence
, bool abort
) {
513 scoped_refptr
<LayerAnimator
> retain(this);
514 scoped_ptr
<LayerAnimationSequence
> removed(RemoveAnimation(sequence
));
516 sequence
->Abort(delegate());
518 ProgressAnimationToEnd(sequence
);
520 UpdateAnimationState();
523 void LayerAnimator::FinishAnyAnimationWithZeroDuration() {
524 scoped_refptr
<LayerAnimator
> retain(this);
525 // Special case: if we've started a 0 duration animation, just finish it now
526 // and get rid of it. We need to make a copy because Progress may indirectly
527 // cause new animations to start running.
528 RunningAnimations running_animations_copy
= running_animations_
;
529 for (size_t i
= 0; i
< running_animations_copy
.size(); ++i
) {
530 if (!SAFE_INVOKE_BOOL(HasAnimation
, running_animations_copy
[i
]))
533 if (running_animations_copy
[i
].sequence()->IsFinished(
534 running_animations_copy
[i
].sequence()->start_time())) {
535 SAFE_INVOKE_VOID(ProgressAnimationToEnd
, running_animations_copy
[i
]);
536 scoped_ptr
<LayerAnimationSequence
> removed(
537 SAFE_INVOKE_PTR(RemoveAnimation
, running_animations_copy
[i
]));
541 UpdateAnimationState();
544 void LayerAnimator::ClearAnimations() {
545 scoped_refptr
<LayerAnimator
> retain(this);
546 ClearAnimationsInternal();
549 LayerAnimator::RunningAnimation
* LayerAnimator::GetRunningAnimation(
550 LayerAnimationElement::AnimatableProperty property
) {
551 PurgeDeletedAnimations();
552 for (RunningAnimations::iterator iter
= running_animations_
.begin();
553 iter
!= running_animations_
.end(); ++iter
) {
554 if ((*iter
).sequence()->properties().find(property
) !=
555 (*iter
).sequence()->properties().end())
561 void LayerAnimator::AddToQueueIfNotPresent(LayerAnimationSequence
* animation
) {
562 // If we don't have the animation in the queue yet, add it.
563 bool found_sequence
= false;
564 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
565 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
566 if ((*queue_iter
) == animation
) {
567 found_sequence
= true;
573 animation_queue_
.push_front(make_linked_ptr(animation
));
576 void LayerAnimator::RemoveAllAnimationsWithACommonProperty(
577 LayerAnimationSequence
* sequence
, bool abort
) {
578 // For all the running animations, if they animate the same property,
579 // progress them to the end and remove them. Note, Aborting or Progressing
580 // animations may affect the collection of running animations, so we need to
581 // operate on a copy.
582 RunningAnimations running_animations_copy
= running_animations_
;
583 for (size_t i
= 0; i
< running_animations_copy
.size(); ++i
) {
584 if (!SAFE_INVOKE_BOOL(HasAnimation
, running_animations_copy
[i
]))
587 if (running_animations_copy
[i
].sequence()->HasConflictingProperty(
588 sequence
->properties())) {
589 scoped_ptr
<LayerAnimationSequence
> removed(
590 SAFE_INVOKE_PTR(RemoveAnimation
, running_animations_copy
[i
]));
592 running_animations_copy
[i
].sequence()->Abort(delegate());
594 SAFE_INVOKE_VOID(ProgressAnimationToEnd
, running_animations_copy
[i
]);
598 // Same for the queued animations that haven't been started. Again, we'll
599 // need to operate on a copy.
600 std::vector
<base::WeakPtr
<LayerAnimationSequence
> > sequences
;
601 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
602 queue_iter
!= animation_queue_
.end(); ++queue_iter
)
603 sequences
.push_back((*queue_iter
)->AsWeakPtr());
605 for (size_t i
= 0; i
< sequences
.size(); ++i
) {
606 if (!sequences
[i
].get() || !HasAnimation(sequences
[i
].get()))
609 if (sequences
[i
]->HasConflictingProperty(sequence
->properties())) {
610 scoped_ptr
<LayerAnimationSequence
> removed(
611 RemoveAnimation(sequences
[i
].get()));
613 sequences
[i
]->Abort(delegate());
615 ProgressAnimationToEnd(sequences
[i
].get());
620 void LayerAnimator::ImmediatelySetNewTarget(LayerAnimationSequence
* sequence
) {
621 // Need to detect if our sequence gets destroyed.
622 base::WeakPtr
<LayerAnimationSequence
> weak_sequence_ptr
=
623 sequence
->AsWeakPtr();
625 const bool abort
= false;
626 RemoveAllAnimationsWithACommonProperty(sequence
, abort
);
627 if (!weak_sequence_ptr
.get())
630 LayerAnimationSequence
* removed
= RemoveAnimation(sequence
);
631 DCHECK(removed
== NULL
|| removed
== sequence
);
632 if (!weak_sequence_ptr
.get())
635 ProgressAnimationToEnd(sequence
);
636 if (!weak_sequence_ptr
.get())
642 void LayerAnimator::ImmediatelyAnimateToNewTarget(
643 LayerAnimationSequence
* sequence
) {
644 // Need to detect if our sequence gets destroyed.
645 base::WeakPtr
<LayerAnimationSequence
> weak_sequence_ptr
=
646 sequence
->AsWeakPtr();
648 const bool abort
= true;
649 RemoveAllAnimationsWithACommonProperty(sequence
, abort
);
650 if (!weak_sequence_ptr
.get())
653 AddToQueueIfNotPresent(sequence
);
654 if (!weak_sequence_ptr
.get())
657 StartSequenceImmediately(sequence
);
660 void LayerAnimator::EnqueueNewAnimation(LayerAnimationSequence
* sequence
) {
661 // It is assumed that if there was no conflicting animation, we would
662 // not have been called. No need to check for a collision; just
664 animation_queue_
.push_back(make_linked_ptr(sequence
));
668 void LayerAnimator::ReplaceQueuedAnimations(LayerAnimationSequence
* sequence
) {
669 // Need to detect if our sequence gets destroyed.
670 base::WeakPtr
<LayerAnimationSequence
> weak_sequence_ptr
=
671 sequence
->AsWeakPtr();
673 // Remove all animations that aren't running. Note: at each iteration i is
674 // incremented or an element is removed from the queue, so
675 // animation_queue_.size() - i is always decreasing and we are always making
676 // progress towards the loop terminating.
677 for (size_t i
= 0; i
< animation_queue_
.size();) {
678 if (!weak_sequence_ptr
.get())
681 PurgeDeletedAnimations();
683 bool is_running
= false;
684 for (RunningAnimations::const_iterator iter
= running_animations_
.begin();
685 iter
!= running_animations_
.end(); ++iter
) {
686 if ((*iter
).sequence() == animation_queue_
[i
].get()) {
693 delete RemoveAnimation(animation_queue_
[i
].get());
697 animation_queue_
.push_back(make_linked_ptr(sequence
));
701 void LayerAnimator::ProcessQueue() {
702 bool started_sequence
= false;
704 started_sequence
= false;
705 // Build a list of all currently animated properties.
706 LayerAnimationElement::AnimatableProperties animated
;
707 for (RunningAnimations::const_iterator iter
= running_animations_
.begin();
708 iter
!= running_animations_
.end(); ++iter
) {
709 if (!(*iter
).is_sequence_alive())
711 animated
.insert((*iter
).sequence()->properties().begin(),
712 (*iter
).sequence()->properties().end());
715 // Try to find an animation that doesn't conflict with an animated
716 // property or a property that will be animated before it. Note: starting
717 // the animation may indirectly cause more animations to be started, so we
718 // need to operate on a copy.
719 std::vector
<base::WeakPtr
<LayerAnimationSequence
> > sequences
;
720 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
721 queue_iter
!= animation_queue_
.end(); ++queue_iter
)
722 sequences
.push_back((*queue_iter
)->AsWeakPtr());
724 for (size_t i
= 0; i
< sequences
.size(); ++i
) {
725 if (!sequences
[i
].get() || !HasAnimation(sequences
[i
].get()))
728 if (!sequences
[i
]->HasConflictingProperty(animated
)) {
729 StartSequenceImmediately(sequences
[i
].get());
730 started_sequence
= true;
734 // Animation couldn't be started. Add its properties to the collection so
735 // that we don't start a conflicting animation. For example, if our queue
736 // has the elements { {T,B}, {B} } (that is, an element that animates both
737 // the transform and the bounds followed by an element that animates the
738 // bounds), and we're currently animating the transform, we can't start
739 // the first element because it animates the transform, too. We cannot
740 // start the second element, either, because the first element animates
741 // bounds too, and needs to go first.
742 animated
.insert(sequences
[i
]->properties().begin(),
743 sequences
[i
]->properties().end());
746 // If we started a sequence, try again. We may be able to start several.
747 } while (started_sequence
);
750 bool LayerAnimator::StartSequenceImmediately(LayerAnimationSequence
* sequence
) {
751 PurgeDeletedAnimations();
753 // Ensure that no one is animating one of the sequence's properties already.
754 for (RunningAnimations::const_iterator iter
= running_animations_
.begin();
755 iter
!= running_animations_
.end(); ++iter
) {
756 if ((*iter
).sequence()->HasConflictingProperty(sequence
->properties()))
760 // All clear, actually start the sequence. Note: base::TimeTicks::Now has
761 // a resolution that can be as bad as 15ms. If this causes glitches in the
762 // animations, this can be switched to HighResNow() (animation uses Now()
764 // All LayerAnimators share the same AnimationContainer. Use the
765 // last_tick_time() from there to ensure animations started during the same
766 // event complete at the same time.
767 base::TimeTicks start_time
;
768 if (is_animating() || adding_animations_
)
769 start_time
= last_step_time_
;
770 else if (GetAnimationContainer()->is_running())
771 start_time
= GetAnimationContainer()->last_tick_time();
773 start_time
= gfx::FrameTime::Now();
775 if (!sequence
->animation_group_id())
776 sequence
->set_animation_group_id(cc::AnimationIdProvider::NextGroupId());
777 if (!sequence
->waiting_for_group_start() ||
778 sequence
->IsFirstElementThreaded()) {
779 sequence
->set_start_time(start_time
);
780 sequence
->Start(delegate());
782 running_animations_
.push_back(
783 RunningAnimation(sequence
->AsWeakPtr()));
785 // Need to keep a reference to the animation.
786 AddToQueueIfNotPresent(sequence
);
788 // Ensure that animations get stepped at their start time.
794 void LayerAnimator::GetTargetValue(
795 LayerAnimationElement::TargetValue
* target
) const {
796 for (AnimationQueue::const_iterator iter
= animation_queue_
.begin();
797 iter
!= animation_queue_
.end(); ++iter
) {
798 (*iter
)->GetTargetValue(target
);
802 void LayerAnimator::OnScheduled(LayerAnimationSequence
* sequence
) {
803 if (observers_
.might_have_observers()) {
804 ObserverListBase
<LayerAnimationObserver
>::Iterator
it(observers_
);
805 LayerAnimationObserver
* obs
;
806 while ((obs
= it
.GetNext()) != NULL
) {
807 sequence
->AddObserver(obs
);
810 sequence
->OnScheduled();
813 base::TimeDelta
LayerAnimator::GetTransitionDuration() const {
814 return transition_duration_
;
817 void LayerAnimator::ClearAnimationsInternal() {
818 PurgeDeletedAnimations();
820 // Abort should never affect the set of running animations, but just in case
821 // clients are badly behaved, we will use a copy of the running animations.
822 RunningAnimations running_animations_copy
= running_animations_
;
823 for (size_t i
= 0; i
< running_animations_copy
.size(); ++i
) {
824 if (!SAFE_INVOKE_BOOL(HasAnimation
, running_animations_copy
[i
]))
827 scoped_ptr
<LayerAnimationSequence
> removed(
828 RemoveAnimation(running_animations_copy
[i
].sequence()));
830 removed
->Abort(delegate());
832 // This *should* have cleared the list of running animations.
833 DCHECK(running_animations_
.empty());
834 running_animations_
.clear();
835 animation_queue_
.clear();
836 UpdateAnimationState();
839 void LayerAnimator::PurgeDeletedAnimations() {
840 for (size_t i
= 0; i
< running_animations_
.size();) {
841 if (!running_animations_
[i
].is_sequence_alive())
842 running_animations_
.erase(running_animations_
.begin() + i
);
848 LayerAnimator::RunningAnimation::RunningAnimation(
849 const base::WeakPtr
<LayerAnimationSequence
>& sequence
)
850 : sequence_(sequence
) {
853 LayerAnimator::RunningAnimation::~RunningAnimation() { }