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/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/trace_event/trace_event.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/compositor/layer_animator_collection.h"
19 #define SAFE_INVOKE_VOID(function, running_anim, ...) \
20 if (running_anim.is_sequence_alive()) \
21 function(running_anim.sequence(), ##__VA_ARGS__)
22 #define SAFE_INVOKE_BOOL(function, running_anim) \
23 ((running_anim.is_sequence_alive()) \
24 ? function(running_anim.sequence()) \
26 #define SAFE_INVOKE_PTR(function, running_anim) \
27 ((running_anim.is_sequence_alive()) \
28 ? function(running_anim.sequence()) \
35 const int kDefaultTransitionDurationMs
= 120;
39 // LayerAnimator public --------------------------------------------------------
41 LayerAnimator::LayerAnimator(base::TimeDelta transition_duration
)
43 preemption_strategy_(IMMEDIATELY_SET_NEW_TARGET
),
44 is_transition_duration_locked_(false),
45 transition_duration_(transition_duration
),
46 tween_type_(gfx::Tween::LINEAR
),
48 disable_timer_for_test_(false),
49 adding_animations_(false) {
52 LayerAnimator::~LayerAnimator() {
53 for (size_t i
= 0; i
< running_animations_
.size(); ++i
) {
54 if (running_animations_
[i
].is_sequence_alive())
55 running_animations_
[i
].sequence()->OnAnimatorDestroyed();
57 ClearAnimationsInternal();
62 LayerAnimator
* LayerAnimator::CreateDefaultAnimator() {
63 return new LayerAnimator(base::TimeDelta::FromMilliseconds(0));
67 LayerAnimator
* LayerAnimator::CreateImplicitAnimator() {
68 return new LayerAnimator(
69 base::TimeDelta::FromMilliseconds(kDefaultTransitionDurationMs
));
72 // This macro provides the implementation for the setter and getter (well,
73 // the getter of the target value) for an animated property. For example,
74 // it is used for the implementations of SetTransform and GetTargetTransform.
75 // It is worth noting that SetFoo avoids invoking the usual animation machinery
76 // if the transition duration is zero -- in this case we just set the property
77 // on the layer animation delegate immediately.
78 #define ANIMATED_PROPERTY(type, property, name, member_type, member) \
79 void LayerAnimator::Set##name(type value) { \
80 base::TimeDelta duration = GetTransitionDuration(); \
81 if (duration == base::TimeDelta() && delegate() && \
82 (preemption_strategy_ != ENQUEUE_NEW_ANIMATION)) { \
83 StopAnimatingProperty(LayerAnimationElement::property); \
84 delegate()->Set##name##FromAnimation(value); \
87 scoped_ptr<LayerAnimationElement> element( \
88 LayerAnimationElement::Create##name##Element(value, duration)); \
89 element->set_tween_type(tween_type_); \
90 StartAnimation(new LayerAnimationSequence(element.release())); \
93 member_type LayerAnimator::GetTarget##name() const { \
94 LayerAnimationElement::TargetValue target(delegate()); \
95 GetTargetValue(&target); \
96 return target.member; \
100 const gfx::Transform
&, TRANSFORM
, Transform
, gfx::Transform
, transform
);
101 ANIMATED_PROPERTY(const gfx::Rect
&, BOUNDS
, Bounds
, gfx::Rect
, bounds
);
102 ANIMATED_PROPERTY(float, OPACITY
, Opacity
, float, opacity
);
103 ANIMATED_PROPERTY(bool, VISIBILITY
, Visibility
, bool, visibility
);
104 ANIMATED_PROPERTY(float, BRIGHTNESS
, Brightness
, float, brightness
);
105 ANIMATED_PROPERTY(float, GRAYSCALE
, Grayscale
, float, grayscale
);
106 ANIMATED_PROPERTY(SkColor
, COLOR
, Color
, SkColor
, color
);
108 base::TimeDelta
LayerAnimator::GetTransitionDuration() const {
109 return transition_duration_
;
112 void LayerAnimator::SetDelegate(LayerAnimationDelegate
* delegate
) {
113 if (delegate_
&& is_started_
) {
114 LayerAnimatorCollection
* collection
= GetLayerAnimatorCollection();
116 collection
->StopAnimator(this);
118 delegate_
= delegate
;
119 if (delegate_
&& is_started_
) {
120 LayerAnimatorCollection
* collection
= GetLayerAnimatorCollection();
122 collection
->StartAnimator(this);
126 void LayerAnimator::StartAnimation(LayerAnimationSequence
* animation
) {
127 scoped_refptr
<LayerAnimator
> retain(this);
128 OnScheduled(animation
);
129 if (!StartSequenceImmediately(animation
)) {
130 // Attempt to preempt a running animation.
131 switch (preemption_strategy_
) {
132 case IMMEDIATELY_SET_NEW_TARGET
:
133 ImmediatelySetNewTarget(animation
);
135 case IMMEDIATELY_ANIMATE_TO_NEW_TARGET
:
136 ImmediatelyAnimateToNewTarget(animation
);
138 case ENQUEUE_NEW_ANIMATION
:
139 EnqueueNewAnimation(animation
);
141 case REPLACE_QUEUED_ANIMATIONS
:
142 ReplaceQueuedAnimations(animation
);
144 case BLEND_WITH_CURRENT_ANIMATION
: {
145 // TODO(vollick) Add support for blended sequences and use them here.
151 FinishAnyAnimationWithZeroDuration();
152 UpdateAnimationState();
155 void LayerAnimator::ScheduleAnimation(LayerAnimationSequence
* animation
) {
156 scoped_refptr
<LayerAnimator
> retain(this);
157 OnScheduled(animation
);
158 if (is_animating()) {
159 animation_queue_
.push_back(make_linked_ptr(animation
));
162 StartSequenceImmediately(animation
);
164 UpdateAnimationState();
167 void LayerAnimator::StartTogether(
168 const std::vector
<LayerAnimationSequence
*>& animations
) {
169 scoped_refptr
<LayerAnimator
> retain(this);
170 if (preemption_strategy_
== IMMEDIATELY_SET_NEW_TARGET
) {
171 std::vector
<LayerAnimationSequence
*>::const_iterator iter
;
172 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
) {
173 StartAnimation(*iter
);
178 adding_animations_
= true;
179 if (!is_animating()) {
180 LayerAnimatorCollection
* collection
= GetLayerAnimatorCollection();
181 if (collection
&& collection
->HasActiveAnimators())
182 last_step_time_
= collection
->last_tick_time();
184 last_step_time_
= base::TimeTicks::Now();
187 // Collect all the affected properties.
188 LayerAnimationElement::AnimatableProperties animated_properties
=
189 LayerAnimationElement::UNKNOWN
;
191 std::vector
<LayerAnimationSequence
*>::const_iterator iter
;
192 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
)
193 animated_properties
|= (*iter
)->properties();
195 // Starting a zero duration pause that affects all the animated properties
196 // will prevent any of the sequences from animating until there are no
197 // running animations that affect any of these properties, as well as
198 // handle preemption strategy.
199 StartAnimation(new LayerAnimationSequence(
200 LayerAnimationElement::CreatePauseElement(animated_properties
,
201 base::TimeDelta())));
203 bool wait_for_group_start
= false;
204 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
)
205 wait_for_group_start
|= (*iter
)->IsFirstElementThreaded();
207 int group_id
= cc::AnimationIdProvider::NextGroupId();
209 // These animations (provided they don't animate any common properties) will
210 // now animate together if trivially scheduled.
211 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
) {
212 (*iter
)->set_animation_group_id(group_id
);
213 (*iter
)->set_waiting_for_group_start(wait_for_group_start
);
214 ScheduleAnimation(*iter
);
217 adding_animations_
= false;
218 UpdateAnimationState();
222 void LayerAnimator::ScheduleTogether(
223 const std::vector
<LayerAnimationSequence
*>& animations
) {
224 scoped_refptr
<LayerAnimator
> retain(this);
226 // Collect all the affected properties.
227 LayerAnimationElement::AnimatableProperties animated_properties
=
228 LayerAnimationElement::UNKNOWN
;
230 std::vector
<LayerAnimationSequence
*>::const_iterator iter
;
231 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
)
232 animated_properties
|= (*iter
)->properties();
234 // Scheduling a zero duration pause that affects all the animated properties
235 // will prevent any of the sequences from animating until there are no
236 // running animations that affect any of these properties.
237 ScheduleAnimation(new LayerAnimationSequence(
238 LayerAnimationElement::CreatePauseElement(animated_properties
,
239 base::TimeDelta())));
241 bool wait_for_group_start
= false;
242 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
)
243 wait_for_group_start
|= (*iter
)->IsFirstElementThreaded();
245 int group_id
= cc::AnimationIdProvider::NextGroupId();
247 // These animations (provided they don't animate any common properties) will
248 // now animate together if trivially scheduled.
249 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
) {
250 (*iter
)->set_animation_group_id(group_id
);
251 (*iter
)->set_waiting_for_group_start(wait_for_group_start
);
252 ScheduleAnimation(*iter
);
255 UpdateAnimationState();
258 void LayerAnimator::SchedulePauseForProperties(
259 base::TimeDelta duration
,
260 LayerAnimationElement::AnimatableProperties properties_to_pause
) {
261 ScheduleAnimation(new ui::LayerAnimationSequence(
262 ui::LayerAnimationElement::CreatePauseElement(
263 properties_to_pause
, duration
)));
266 bool LayerAnimator::IsAnimatingProperty(
267 LayerAnimationElement::AnimatableProperty property
) const {
268 for (AnimationQueue::const_iterator queue_iter
= animation_queue_
.begin();
269 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
270 if ((*queue_iter
)->properties() & property
)
276 void LayerAnimator::StopAnimatingProperty(
277 LayerAnimationElement::AnimatableProperty property
) {
278 scoped_refptr
<LayerAnimator
> retain(this);
280 // GetRunningAnimation purges deleted animations before searching, so we are
281 // guaranteed to find a live animation if any is returned at all.
282 RunningAnimation
* running
= GetRunningAnimation(property
);
285 // As was mentioned above, this sequence must be alive.
286 DCHECK(running
->is_sequence_alive());
287 FinishAnimation(running
->sequence(), false);
291 void LayerAnimator::AddObserver(LayerAnimationObserver
* observer
) {
292 if (!observers_
.HasObserver(observer
))
293 observers_
.AddObserver(observer
);
296 void LayerAnimator::RemoveObserver(LayerAnimationObserver
* observer
) {
297 observers_
.RemoveObserver(observer
);
298 // Remove the observer from all sequences as well.
299 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
300 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
301 (*queue_iter
)->RemoveObserver(observer
);
305 void LayerAnimator::OnThreadedAnimationStarted(
306 const cc::AnimationEvent
& event
) {
307 LayerAnimationElement::AnimatableProperty property
=
308 LayerAnimationElement::ToAnimatableProperty(event
.target_property
);
310 RunningAnimation
* running
= GetRunningAnimation(property
);
313 DCHECK(running
->is_sequence_alive());
315 if (running
->sequence()->animation_group_id() != event
.group_id
)
318 running
->sequence()->OnThreadedAnimationStarted(event
);
319 if (!running
->sequence()->waiting_for_group_start())
322 base::TimeTicks start_time
= event
.monotonic_time
;
324 running
->sequence()->set_waiting_for_group_start(false);
326 // The call to GetRunningAnimation made above already purged deleted
327 // animations, so we are guaranteed that all the animations we iterate
328 // over now are alive.
329 for (RunningAnimations::iterator iter
= running_animations_
.begin();
330 iter
!= running_animations_
.end(); ++iter
) {
331 // Ensure that each sequence is only Started once, regardless of the
332 // number of sequences in the group that have threaded first elements.
333 if (((*iter
).sequence()->animation_group_id() == event
.group_id
) &&
334 !(*iter
).sequence()->IsFirstElementThreaded() &&
335 (*iter
).sequence()->waiting_for_group_start()) {
336 (*iter
).sequence()->set_start_time(start_time
);
337 (*iter
).sequence()->set_waiting_for_group_start(false);
338 (*iter
).sequence()->Start(delegate());
343 void LayerAnimator::AddToCollection(LayerAnimatorCollection
* collection
) {
344 if (is_animating() && !is_started_
) {
345 collection
->StartAnimator(this);
350 void LayerAnimator::RemoveFromCollection(LayerAnimatorCollection
* collection
) {
351 if (is_animating() && is_started_
) {
352 collection
->StopAnimator(this);
357 // LayerAnimator protected -----------------------------------------------------
359 void LayerAnimator::ProgressAnimation(LayerAnimationSequence
* sequence
,
360 base::TimeTicks now
) {
361 if (!delegate() || sequence
->waiting_for_group_start())
364 sequence
->Progress(now
, delegate());
367 void LayerAnimator::ProgressAnimationToEnd(LayerAnimationSequence
* sequence
) {
371 sequence
->ProgressToEnd(delegate());
374 bool LayerAnimator::HasAnimation(LayerAnimationSequence
* sequence
) const {
375 for (AnimationQueue::const_iterator queue_iter
= animation_queue_
.begin();
376 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
377 if ((*queue_iter
).get() == sequence
)
383 // LayerAnimator private -------------------------------------------------------
385 void LayerAnimator::Step(base::TimeTicks now
) {
386 TRACE_EVENT0("ui", "LayerAnimator::Step");
387 scoped_refptr
<LayerAnimator
> retain(this);
389 last_step_time_
= now
;
391 PurgeDeletedAnimations();
393 // We need to make a copy of the running animations because progressing them
394 // and finishing them may indirectly affect the collection of running
396 RunningAnimations running_animations_copy
= running_animations_
;
397 for (size_t i
= 0; i
< running_animations_copy
.size(); ++i
) {
398 if (!SAFE_INVOKE_BOOL(HasAnimation
, running_animations_copy
[i
]))
401 if (running_animations_copy
[i
].sequence()->IsFinished(now
)) {
402 SAFE_INVOKE_VOID(FinishAnimation
, running_animations_copy
[i
], false);
404 SAFE_INVOKE_VOID(ProgressAnimation
, running_animations_copy
[i
], now
);
409 void LayerAnimator::StopAnimatingInternal(bool abort
) {
410 scoped_refptr
<LayerAnimator
> retain(this);
411 while (is_animating() && delegate()) {
412 // We're going to attempt to finish the first running animation. Let's
413 // ensure that it's valid.
414 PurgeDeletedAnimations();
416 // If we've purged all running animations, attempt to start one up.
417 if (running_animations_
.empty())
420 DCHECK(!running_animations_
.empty());
422 // Still no luck, let's just bail and clear all animations.
423 if (running_animations_
.empty()) {
424 ClearAnimationsInternal();
428 SAFE_INVOKE_VOID(FinishAnimation
, running_animations_
[0], abort
);
432 void LayerAnimator::UpdateAnimationState() {
433 if (disable_timer_for_test_
)
436 const bool should_start
= is_animating();
437 LayerAnimatorCollection
* collection
= GetLayerAnimatorCollection();
439 if (should_start
&& !is_started_
)
440 collection
->StartAnimator(this);
441 else if (!should_start
&& is_started_
)
442 collection
->StopAnimator(this);
443 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
);
522 UpdateAnimationState();
525 void LayerAnimator::FinishAnyAnimationWithZeroDuration() {
526 scoped_refptr
<LayerAnimator
> retain(this);
527 // Special case: if we've started a 0 duration animation, just finish it now
528 // and get rid of it. We need to make a copy because Progress may indirectly
529 // cause new animations to start running.
530 RunningAnimations running_animations_copy
= running_animations_
;
531 for (size_t i
= 0; i
< running_animations_copy
.size(); ++i
) {
532 if (!SAFE_INVOKE_BOOL(HasAnimation
, running_animations_copy
[i
]))
535 if (running_animations_copy
[i
].sequence()->IsFinished(
536 running_animations_copy
[i
].sequence()->start_time())) {
537 SAFE_INVOKE_VOID(ProgressAnimationToEnd
, running_animations_copy
[i
]);
538 scoped_ptr
<LayerAnimationSequence
> removed(
539 SAFE_INVOKE_PTR(RemoveAnimation
, running_animations_copy
[i
]));
543 UpdateAnimationState();
546 void LayerAnimator::ClearAnimations() {
547 scoped_refptr
<LayerAnimator
> retain(this);
548 ClearAnimationsInternal();
551 LayerAnimator::RunningAnimation
* LayerAnimator::GetRunningAnimation(
552 LayerAnimationElement::AnimatableProperty property
) {
553 PurgeDeletedAnimations();
554 for (RunningAnimations::iterator iter
= running_animations_
.begin();
555 iter
!= running_animations_
.end(); ++iter
) {
556 if ((*iter
).sequence()->properties() & property
)
562 void LayerAnimator::AddToQueueIfNotPresent(LayerAnimationSequence
* animation
) {
563 // If we don't have the animation in the queue yet, add it.
564 bool found_sequence
= false;
565 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
566 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
567 if ((*queue_iter
) == animation
) {
568 found_sequence
= true;
574 animation_queue_
.push_front(make_linked_ptr(animation
));
577 void LayerAnimator::RemoveAllAnimationsWithACommonProperty(
578 LayerAnimationSequence
* sequence
, bool abort
) {
579 // For all the running animations, if they animate the same property,
580 // progress them to the end and remove them. Note, Aborting or Progressing
581 // animations may affect the collection of running animations, so we need to
582 // operate on a copy.
583 RunningAnimations running_animations_copy
= running_animations_
;
584 for (size_t i
= 0; i
< running_animations_copy
.size(); ++i
) {
585 if (!SAFE_INVOKE_BOOL(HasAnimation
, running_animations_copy
[i
]))
588 if (running_animations_copy
[i
].sequence()->HasConflictingProperty(
589 sequence
->properties())) {
590 scoped_ptr
<LayerAnimationSequence
> removed(
591 SAFE_INVOKE_PTR(RemoveAnimation
, running_animations_copy
[i
]));
593 running_animations_copy
[i
].sequence()->Abort(delegate());
595 SAFE_INVOKE_VOID(ProgressAnimationToEnd
, running_animations_copy
[i
]);
599 // Same for the queued animations that haven't been started. Again, we'll
600 // need to operate on a copy.
601 std::vector
<base::WeakPtr
<LayerAnimationSequence
> > sequences
;
602 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
603 queue_iter
!= animation_queue_
.end(); ++queue_iter
)
604 sequences
.push_back((*queue_iter
)->AsWeakPtr());
606 for (size_t i
= 0; i
< sequences
.size(); ++i
) {
607 if (!sequences
[i
].get() || !HasAnimation(sequences
[i
].get()))
610 if (sequences
[i
]->HasConflictingProperty(sequence
->properties())) {
611 scoped_ptr
<LayerAnimationSequence
> removed(
612 RemoveAnimation(sequences
[i
].get()));
614 sequences
[i
]->Abort(delegate());
616 ProgressAnimationToEnd(sequences
[i
].get());
621 void LayerAnimator::ImmediatelySetNewTarget(LayerAnimationSequence
* sequence
) {
622 // Need to detect if our sequence gets destroyed.
623 base::WeakPtr
<LayerAnimationSequence
> weak_sequence_ptr
=
624 sequence
->AsWeakPtr();
626 const bool abort
= false;
627 RemoveAllAnimationsWithACommonProperty(sequence
, abort
);
628 if (!weak_sequence_ptr
.get())
631 LayerAnimationSequence
* removed
= RemoveAnimation(sequence
);
632 DCHECK(removed
== NULL
|| removed
== sequence
);
633 if (!weak_sequence_ptr
.get())
636 ProgressAnimationToEnd(sequence
);
637 if (!weak_sequence_ptr
.get())
643 void LayerAnimator::ImmediatelyAnimateToNewTarget(
644 LayerAnimationSequence
* sequence
) {
645 // Need to detect if our sequence gets destroyed.
646 base::WeakPtr
<LayerAnimationSequence
> weak_sequence_ptr
=
647 sequence
->AsWeakPtr();
649 const bool abort
= true;
650 RemoveAllAnimationsWithACommonProperty(sequence
, abort
);
651 if (!weak_sequence_ptr
.get())
654 AddToQueueIfNotPresent(sequence
);
655 if (!weak_sequence_ptr
.get())
658 StartSequenceImmediately(sequence
);
661 void LayerAnimator::EnqueueNewAnimation(LayerAnimationSequence
* sequence
) {
662 // It is assumed that if there was no conflicting animation, we would
663 // not have been called. No need to check for a collision; just
665 animation_queue_
.push_back(make_linked_ptr(sequence
));
669 void LayerAnimator::ReplaceQueuedAnimations(LayerAnimationSequence
* sequence
) {
670 // Need to detect if our sequence gets destroyed.
671 base::WeakPtr
<LayerAnimationSequence
> weak_sequence_ptr
=
672 sequence
->AsWeakPtr();
674 // Remove all animations that aren't running. Note: at each iteration i is
675 // incremented or an element is removed from the queue, so
676 // animation_queue_.size() - i is always decreasing and we are always making
677 // progress towards the loop terminating.
678 for (size_t i
= 0; i
< animation_queue_
.size();) {
679 if (!weak_sequence_ptr
.get())
682 PurgeDeletedAnimations();
684 bool is_running
= false;
685 for (RunningAnimations::const_iterator iter
= running_animations_
.begin();
686 iter
!= running_animations_
.end(); ++iter
) {
687 if ((*iter
).sequence() == animation_queue_
[i
].get()) {
694 delete RemoveAnimation(animation_queue_
[i
].get());
698 animation_queue_
.push_back(make_linked_ptr(sequence
));
702 void LayerAnimator::ProcessQueue() {
703 bool started_sequence
= false;
705 started_sequence
= false;
706 // Build a list of all currently animated properties.
707 LayerAnimationElement::AnimatableProperties animated
=
708 LayerAnimationElement::UNKNOWN
;
709 for (RunningAnimations::const_iterator iter
= running_animations_
.begin();
710 iter
!= running_animations_
.end(); ++iter
) {
711 if (!(*iter
).is_sequence_alive())
714 animated
|= (*iter
).sequence()->properties();
717 // Try to find an animation that doesn't conflict with an animated
718 // property or a property that will be animated before it. Note: starting
719 // the animation may indirectly cause more animations to be started, so we
720 // need to operate on a copy.
721 std::vector
<base::WeakPtr
<LayerAnimationSequence
> > sequences
;
722 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
723 queue_iter
!= animation_queue_
.end(); ++queue_iter
)
724 sequences
.push_back((*queue_iter
)->AsWeakPtr());
726 for (size_t i
= 0; i
< sequences
.size(); ++i
) {
727 if (!sequences
[i
].get() || !HasAnimation(sequences
[i
].get()))
730 if (!sequences
[i
]->HasConflictingProperty(animated
)) {
731 StartSequenceImmediately(sequences
[i
].get());
732 started_sequence
= true;
736 // Animation couldn't be started. Add its properties to the collection so
737 // that we don't start a conflicting animation. For example, if our queue
738 // has the elements { {T,B}, {B} } (that is, an element that animates both
739 // the transform and the bounds followed by an element that animates the
740 // bounds), and we're currently animating the transform, we can't start
741 // the first element because it animates the transform, too. We cannot
742 // start the second element, either, because the first element animates
743 // bounds too, and needs to go first.
744 animated
|= sequences
[i
]->properties();
747 // If we started a sequence, try again. We may be able to start several.
748 } while (started_sequence
);
751 bool LayerAnimator::StartSequenceImmediately(LayerAnimationSequence
* sequence
) {
752 PurgeDeletedAnimations();
754 // Ensure that no one is animating one of the sequence's properties already.
755 for (RunningAnimations::const_iterator iter
= running_animations_
.begin();
756 iter
!= running_animations_
.end(); ++iter
) {
757 if ((*iter
).sequence()->HasConflictingProperty(sequence
->properties()))
761 // All clear, actually start the sequence.
762 // All LayerAnimators share the same LayerAnimatorCollection. Use the
763 // last_tick_time() from there to ensure animations started during the same
764 // event complete at the same time.
765 base::TimeTicks start_time
;
766 LayerAnimatorCollection
* collection
= GetLayerAnimatorCollection();
767 if (is_animating() || adding_animations_
)
768 start_time
= last_step_time_
;
769 else if (collection
&& collection
->HasActiveAnimators())
770 start_time
= collection
->last_tick_time();
772 start_time
= base::TimeTicks::Now();
774 if (!sequence
->animation_group_id())
775 sequence
->set_animation_group_id(cc::AnimationIdProvider::NextGroupId());
776 if (!sequence
->waiting_for_group_start() ||
777 sequence
->IsFirstElementThreaded()) {
778 sequence
->set_start_time(start_time
);
779 sequence
->Start(delegate());
781 running_animations_
.push_back(
782 RunningAnimation(sequence
->AsWeakPtr()));
784 // Need to keep a reference to the animation.
785 AddToQueueIfNotPresent(sequence
);
787 // Ensure that animations get stepped at their start time.
793 void LayerAnimator::GetTargetValue(
794 LayerAnimationElement::TargetValue
* target
) const {
795 for (AnimationQueue::const_iterator iter
= animation_queue_
.begin();
796 iter
!= animation_queue_
.end(); ++iter
) {
797 (*iter
)->GetTargetValue(target
);
801 void LayerAnimator::OnScheduled(LayerAnimationSequence
* sequence
) {
802 if (observers_
.might_have_observers()) {
803 base::ObserverListBase
<LayerAnimationObserver
>::Iterator
it(&observers_
);
804 LayerAnimationObserver
* obs
;
805 while ((obs
= it
.GetNext()) != NULL
) {
806 sequence
->AddObserver(obs
);
809 sequence
->OnScheduled();
812 void LayerAnimator::SetTransitionDuration(base::TimeDelta duration
) {
813 if (is_transition_duration_locked_
)
815 transition_duration_
= duration
;
818 void LayerAnimator::ClearAnimationsInternal() {
819 PurgeDeletedAnimations();
821 // Abort should never affect the set of running animations, but just in case
822 // clients are badly behaved, we will use a copy of the running animations.
823 RunningAnimations running_animations_copy
= running_animations_
;
824 for (size_t i
= 0; i
< running_animations_copy
.size(); ++i
) {
825 if (!SAFE_INVOKE_BOOL(HasAnimation
, running_animations_copy
[i
]))
828 scoped_ptr
<LayerAnimationSequence
> removed(
829 RemoveAnimation(running_animations_copy
[i
].sequence()));
831 removed
->Abort(delegate());
833 // This *should* have cleared the list of running animations.
834 DCHECK(running_animations_
.empty());
835 running_animations_
.clear();
836 animation_queue_
.clear();
837 UpdateAnimationState();
840 void LayerAnimator::PurgeDeletedAnimations() {
841 for (size_t i
= 0; i
< running_animations_
.size();) {
842 if (!running_animations_
[i
].is_sequence_alive())
843 running_animations_
.erase(running_animations_
.begin() + i
);
849 LayerAnimatorCollection
* LayerAnimator::GetLayerAnimatorCollection() {
850 return delegate_
? delegate_
->GetLayerAnimatorCollection() : NULL
;
853 LayerAnimator::RunningAnimation::RunningAnimation(
854 const base::WeakPtr
<LayerAnimationSequence
>& sequence
)
855 : sequence_(sequence
) {
858 LayerAnimator::RunningAnimation::~RunningAnimation() { }