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"
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()) \
36 const int kDefaultTransitionDurationMs
= 120;
40 // LayerAnimator public --------------------------------------------------------
42 LayerAnimator::LayerAnimator(base::TimeDelta transition_duration
)
44 preemption_strategy_(IMMEDIATELY_SET_NEW_TARGET
),
45 is_transition_duration_locked_(false),
46 transition_duration_(transition_duration
),
47 tween_type_(gfx::Tween::LINEAR
),
49 disable_timer_for_test_(false),
50 adding_animations_(false) {
53 LayerAnimator::~LayerAnimator() {
54 for (size_t i
= 0; i
< running_animations_
.size(); ++i
) {
55 if (running_animations_
[i
].is_sequence_alive())
56 running_animations_
[i
].sequence()->OnAnimatorDestroyed();
58 ClearAnimationsInternal();
63 LayerAnimator
* LayerAnimator::CreateDefaultAnimator() {
64 return new LayerAnimator(base::TimeDelta::FromMilliseconds(0));
68 LayerAnimator
* LayerAnimator::CreateImplicitAnimator() {
69 return new LayerAnimator(
70 base::TimeDelta::FromMilliseconds(kDefaultTransitionDurationMs
));
73 // This macro provides the implementation for the setter and getter (well,
74 // the getter of the target value) for an animated property. For example,
75 // it is used for the implementations of SetTransform and GetTargetTransform.
76 // It is worth noting that SetFoo avoids invoking the usual animation machinery
77 // if the transition duration is zero -- in this case we just set the property
78 // on the layer animation delegate immediately.
79 #define ANIMATED_PROPERTY(type, property, name, member_type, member) \
80 void LayerAnimator::Set##name(type value) { \
81 base::TimeDelta duration = GetTransitionDuration(); \
82 if (duration == base::TimeDelta() && delegate() && \
83 (preemption_strategy_ != ENQUEUE_NEW_ANIMATION)) { \
84 StopAnimatingProperty(LayerAnimationElement::property); \
85 delegate()->Set##name##FromAnimation(value); \
88 scoped_ptr<LayerAnimationElement> element( \
89 LayerAnimationElement::Create##name##Element(value, duration)); \
90 element->set_tween_type(tween_type_); \
91 StartAnimation(new LayerAnimationSequence(element.release())); \
94 member_type LayerAnimator::GetTarget##name() const { \
95 LayerAnimationElement::TargetValue target(delegate()); \
96 GetTargetValue(&target); \
97 return target.member; \
101 const gfx::Transform
&, TRANSFORM
, Transform
, gfx::Transform
, transform
);
102 ANIMATED_PROPERTY(const gfx::Rect
&, BOUNDS
, Bounds
, gfx::Rect
, bounds
);
103 ANIMATED_PROPERTY(float, OPACITY
, Opacity
, float, opacity
);
104 ANIMATED_PROPERTY(bool, VISIBILITY
, Visibility
, bool, visibility
);
105 ANIMATED_PROPERTY(float, BRIGHTNESS
, Brightness
, float, brightness
);
106 ANIMATED_PROPERTY(float, GRAYSCALE
, Grayscale
, float, grayscale
);
107 ANIMATED_PROPERTY(SkColor
, COLOR
, Color
, SkColor
, color
);
109 base::TimeDelta
LayerAnimator::GetTransitionDuration() const {
110 return transition_duration_
;
113 void LayerAnimator::SetDelegate(LayerAnimationDelegate
* delegate
) {
114 if (delegate_
&& is_started_
) {
115 LayerAnimatorCollection
* collection
= GetLayerAnimatorCollection();
117 collection
->StopAnimator(this);
119 delegate_
= delegate
;
120 if (delegate_
&& is_started_
) {
121 LayerAnimatorCollection
* collection
= GetLayerAnimatorCollection();
123 collection
->StartAnimator(this);
127 void LayerAnimator::StartAnimation(LayerAnimationSequence
* animation
) {
128 scoped_refptr
<LayerAnimator
> retain(this);
129 OnScheduled(animation
);
130 if (!StartSequenceImmediately(animation
)) {
131 // Attempt to preempt a running animation.
132 switch (preemption_strategy_
) {
133 case IMMEDIATELY_SET_NEW_TARGET
:
134 ImmediatelySetNewTarget(animation
);
136 case IMMEDIATELY_ANIMATE_TO_NEW_TARGET
:
137 ImmediatelyAnimateToNewTarget(animation
);
139 case ENQUEUE_NEW_ANIMATION
:
140 EnqueueNewAnimation(animation
);
142 case REPLACE_QUEUED_ANIMATIONS
:
143 ReplaceQueuedAnimations(animation
);
145 case BLEND_WITH_CURRENT_ANIMATION
: {
146 // TODO(vollick) Add support for blended sequences and use them here.
152 FinishAnyAnimationWithZeroDuration();
153 UpdateAnimationState();
156 void LayerAnimator::ScheduleAnimation(LayerAnimationSequence
* animation
) {
157 scoped_refptr
<LayerAnimator
> retain(this);
158 OnScheduled(animation
);
159 if (is_animating()) {
160 animation_queue_
.push_back(make_linked_ptr(animation
));
163 StartSequenceImmediately(animation
);
165 UpdateAnimationState();
168 void LayerAnimator::StartTogether(
169 const std::vector
<LayerAnimationSequence
*>& animations
) {
170 scoped_refptr
<LayerAnimator
> retain(this);
171 if (preemption_strategy_
== IMMEDIATELY_SET_NEW_TARGET
) {
172 std::vector
<LayerAnimationSequence
*>::const_iterator iter
;
173 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
) {
174 StartAnimation(*iter
);
179 adding_animations_
= true;
180 if (!is_animating()) {
181 LayerAnimatorCollection
* collection
= GetLayerAnimatorCollection();
182 if (collection
&& collection
->HasActiveAnimators())
183 last_step_time_
= collection
->last_tick_time();
185 last_step_time_
= gfx::FrameTime::Now();
188 // Collect all the affected properties.
189 LayerAnimationElement::AnimatableProperties animated_properties
=
190 LayerAnimationElement::UNKNOWN
;
192 std::vector
<LayerAnimationSequence
*>::const_iterator iter
;
193 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
)
194 animated_properties
|= (*iter
)->properties();
196 // Starting a zero duration pause that affects all the animated properties
197 // will prevent any of the sequences from animating until there are no
198 // running animations that affect any of these properties, as well as
199 // handle preemption strategy.
200 StartAnimation(new LayerAnimationSequence(
201 LayerAnimationElement::CreatePauseElement(animated_properties
,
202 base::TimeDelta())));
204 bool wait_for_group_start
= false;
205 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
)
206 wait_for_group_start
|= (*iter
)->IsFirstElementThreaded();
208 int group_id
= cc::AnimationIdProvider::NextGroupId();
210 // These animations (provided they don't animate any common properties) will
211 // now animate together if trivially scheduled.
212 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
) {
213 (*iter
)->set_animation_group_id(group_id
);
214 (*iter
)->set_waiting_for_group_start(wait_for_group_start
);
215 ScheduleAnimation(*iter
);
218 adding_animations_
= false;
219 UpdateAnimationState();
223 void LayerAnimator::ScheduleTogether(
224 const std::vector
<LayerAnimationSequence
*>& animations
) {
225 scoped_refptr
<LayerAnimator
> retain(this);
227 // Collect all the affected properties.
228 LayerAnimationElement::AnimatableProperties animated_properties
=
229 LayerAnimationElement::UNKNOWN
;
231 std::vector
<LayerAnimationSequence
*>::const_iterator iter
;
232 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
)
233 animated_properties
|= (*iter
)->properties();
235 // Scheduling a zero duration pause that affects all the animated properties
236 // will prevent any of the sequences from animating until there are no
237 // running animations that affect any of these properties.
238 ScheduleAnimation(new LayerAnimationSequence(
239 LayerAnimationElement::CreatePauseElement(animated_properties
,
240 base::TimeDelta())));
242 bool wait_for_group_start
= false;
243 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
)
244 wait_for_group_start
|= (*iter
)->IsFirstElementThreaded();
246 int group_id
= cc::AnimationIdProvider::NextGroupId();
248 // These animations (provided they don't animate any common properties) will
249 // now animate together if trivially scheduled.
250 for (iter
= animations
.begin(); iter
!= animations
.end(); ++iter
) {
251 (*iter
)->set_animation_group_id(group_id
);
252 (*iter
)->set_waiting_for_group_start(wait_for_group_start
);
253 ScheduleAnimation(*iter
);
256 UpdateAnimationState();
259 void LayerAnimator::SchedulePauseForProperties(
260 base::TimeDelta duration
,
261 LayerAnimationElement::AnimatableProperties properties_to_pause
) {
262 ScheduleAnimation(new ui::LayerAnimationSequence(
263 ui::LayerAnimationElement::CreatePauseElement(
264 properties_to_pause
, duration
)));
267 bool LayerAnimator::IsAnimatingProperty(
268 LayerAnimationElement::AnimatableProperty property
) const {
269 for (AnimationQueue::const_iterator queue_iter
= animation_queue_
.begin();
270 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
271 if ((*queue_iter
)->properties() & property
)
277 void LayerAnimator::StopAnimatingProperty(
278 LayerAnimationElement::AnimatableProperty property
) {
279 scoped_refptr
<LayerAnimator
> retain(this);
281 // GetRunningAnimation purges deleted animations before searching, so we are
282 // guaranteed to find a live animation if any is returned at all.
283 RunningAnimation
* running
= GetRunningAnimation(property
);
286 // As was mentioned above, this sequence must be alive.
287 DCHECK(running
->is_sequence_alive());
288 FinishAnimation(running
->sequence(), false);
292 void LayerAnimator::AddObserver(LayerAnimationObserver
* observer
) {
293 if (!observers_
.HasObserver(observer
))
294 observers_
.AddObserver(observer
);
297 void LayerAnimator::RemoveObserver(LayerAnimationObserver
* observer
) {
298 observers_
.RemoveObserver(observer
);
299 // Remove the observer from all sequences as well.
300 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
301 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
302 (*queue_iter
)->RemoveObserver(observer
);
306 void LayerAnimator::OnThreadedAnimationStarted(
307 const cc::AnimationEvent
& event
) {
308 LayerAnimationElement::AnimatableProperty property
=
309 LayerAnimationElement::ToAnimatableProperty(event
.target_property
);
311 RunningAnimation
* running
= GetRunningAnimation(property
);
314 DCHECK(running
->is_sequence_alive());
316 if (running
->sequence()->animation_group_id() != event
.group_id
)
319 running
->sequence()->OnThreadedAnimationStarted(event
);
320 if (!running
->sequence()->waiting_for_group_start())
323 base::TimeTicks start_time
= event
.monotonic_time
;
325 running
->sequence()->set_waiting_for_group_start(false);
327 // The call to GetRunningAnimation made above already purged deleted
328 // animations, so we are guaranteed that all the animations we iterate
329 // over now are alive.
330 for (RunningAnimations::iterator iter
= running_animations_
.begin();
331 iter
!= running_animations_
.end(); ++iter
) {
332 // Ensure that each sequence is only Started once, regardless of the
333 // number of sequences in the group that have threaded first elements.
334 if (((*iter
).sequence()->animation_group_id() == event
.group_id
) &&
335 !(*iter
).sequence()->IsFirstElementThreaded() &&
336 (*iter
).sequence()->waiting_for_group_start()) {
337 (*iter
).sequence()->set_start_time(start_time
);
338 (*iter
).sequence()->set_waiting_for_group_start(false);
339 (*iter
).sequence()->Start(delegate());
344 void LayerAnimator::AddToCollection(LayerAnimatorCollection
* collection
) {
345 if (is_animating() && !is_started_
) {
346 collection
->StartAnimator(this);
351 void LayerAnimator::RemoveFromCollection(LayerAnimatorCollection
* collection
) {
352 if (is_animating() && is_started_
) {
353 collection
->StopAnimator(this);
358 // LayerAnimator protected -----------------------------------------------------
360 void LayerAnimator::ProgressAnimation(LayerAnimationSequence
* sequence
,
361 base::TimeTicks now
) {
362 if (!delegate() || sequence
->waiting_for_group_start())
365 sequence
->Progress(now
, delegate());
368 void LayerAnimator::ProgressAnimationToEnd(LayerAnimationSequence
* sequence
) {
372 sequence
->ProgressToEnd(delegate());
375 bool LayerAnimator::HasAnimation(LayerAnimationSequence
* sequence
) const {
376 for (AnimationQueue::const_iterator queue_iter
= animation_queue_
.begin();
377 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
378 if ((*queue_iter
).get() == sequence
)
384 // LayerAnimator private -------------------------------------------------------
386 void LayerAnimator::Step(base::TimeTicks now
) {
387 TRACE_EVENT0("ui", "LayerAnimator::Step");
388 scoped_refptr
<LayerAnimator
> retain(this);
390 last_step_time_
= now
;
392 PurgeDeletedAnimations();
394 // We need to make a copy of the running animations because progressing them
395 // and finishing them may indirectly affect the collection of running
397 RunningAnimations running_animations_copy
= running_animations_
;
398 for (size_t i
= 0; i
< running_animations_copy
.size(); ++i
) {
399 if (!SAFE_INVOKE_BOOL(HasAnimation
, running_animations_copy
[i
]))
402 if (running_animations_copy
[i
].sequence()->IsFinished(now
)) {
403 SAFE_INVOKE_VOID(FinishAnimation
, running_animations_copy
[i
], false);
405 SAFE_INVOKE_VOID(ProgressAnimation
, running_animations_copy
[i
], now
);
410 void LayerAnimator::StopAnimatingInternal(bool abort
) {
411 scoped_refptr
<LayerAnimator
> retain(this);
412 while (is_animating() && delegate()) {
413 // We're going to attempt to finish the first running animation. Let's
414 // ensure that it's valid.
415 PurgeDeletedAnimations();
417 // If we've purged all running animations, attempt to start one up.
418 if (running_animations_
.empty())
421 DCHECK(!running_animations_
.empty());
423 // Still no luck, let's just bail and clear all animations.
424 if (running_animations_
.empty()) {
425 ClearAnimationsInternal();
429 SAFE_INVOKE_VOID(FinishAnimation
, running_animations_
[0], abort
);
433 void LayerAnimator::UpdateAnimationState() {
434 if (disable_timer_for_test_
)
437 const bool should_start
= is_animating();
438 LayerAnimatorCollection
* collection
= GetLayerAnimatorCollection();
440 if (should_start
&& !is_started_
)
441 collection
->StartAnimator(this);
442 else if (!should_start
&& is_started_
)
443 collection
->StopAnimator(this);
444 is_started_
= should_start
;
450 LayerAnimationSequence
* LayerAnimator::RemoveAnimation(
451 LayerAnimationSequence
* sequence
) {
452 linked_ptr
<LayerAnimationSequence
> to_return
;
454 bool is_running
= false;
456 // First remove from running animations
457 for (RunningAnimations::iterator iter
= running_animations_
.begin();
458 iter
!= running_animations_
.end(); ++iter
) {
459 if ((*iter
).sequence() == sequence
) {
460 running_animations_
.erase(iter
);
466 // Then remove from the queue
467 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
468 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
469 if ((*queue_iter
) == sequence
) {
470 to_return
= *queue_iter
;
471 animation_queue_
.erase(queue_iter
);
476 if (!to_return
.get() ||
477 !to_return
->waiting_for_group_start() ||
478 !to_return
->IsFirstElementThreaded())
479 return to_return
.release();
481 // The removed sequence may have been responsible for making other sequences
482 // wait for a group start. If no other sequences in the group have a
483 // threaded first element, the group no longer needs the additional wait.
484 bool is_wait_still_needed
= false;
485 int group_id
= to_return
->animation_group_id();
486 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
487 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
488 if (((*queue_iter
)->animation_group_id() == group_id
) &&
489 (*queue_iter
)->IsFirstElementThreaded()) {
490 is_wait_still_needed
= true;
495 if (is_wait_still_needed
)
496 return to_return
.release();
498 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
499 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
500 if ((*queue_iter
)->animation_group_id() == group_id
&&
501 (*queue_iter
)->waiting_for_group_start()) {
502 (*queue_iter
)->set_waiting_for_group_start(false);
504 (*queue_iter
)->set_start_time(last_step_time_
);
505 (*queue_iter
)->Start(delegate());
509 return to_return
.release();
512 void LayerAnimator::FinishAnimation(
513 LayerAnimationSequence
* sequence
, bool abort
) {
514 scoped_refptr
<LayerAnimator
> retain(this);
515 scoped_ptr
<LayerAnimationSequence
> removed(RemoveAnimation(sequence
));
517 sequence
->Abort(delegate());
519 ProgressAnimationToEnd(sequence
);
523 UpdateAnimationState();
526 void LayerAnimator::FinishAnyAnimationWithZeroDuration() {
527 scoped_refptr
<LayerAnimator
> retain(this);
528 // Special case: if we've started a 0 duration animation, just finish it now
529 // and get rid of it. We need to make a copy because Progress may indirectly
530 // cause new animations to start running.
531 RunningAnimations running_animations_copy
= running_animations_
;
532 for (size_t i
= 0; i
< running_animations_copy
.size(); ++i
) {
533 if (!SAFE_INVOKE_BOOL(HasAnimation
, running_animations_copy
[i
]))
536 if (running_animations_copy
[i
].sequence()->IsFinished(
537 running_animations_copy
[i
].sequence()->start_time())) {
538 SAFE_INVOKE_VOID(ProgressAnimationToEnd
, running_animations_copy
[i
]);
539 scoped_ptr
<LayerAnimationSequence
> removed(
540 SAFE_INVOKE_PTR(RemoveAnimation
, running_animations_copy
[i
]));
544 UpdateAnimationState();
547 void LayerAnimator::ClearAnimations() {
548 scoped_refptr
<LayerAnimator
> retain(this);
549 ClearAnimationsInternal();
552 LayerAnimator::RunningAnimation
* LayerAnimator::GetRunningAnimation(
553 LayerAnimationElement::AnimatableProperty property
) {
554 PurgeDeletedAnimations();
555 for (RunningAnimations::iterator iter
= running_animations_
.begin();
556 iter
!= running_animations_
.end(); ++iter
) {
557 if ((*iter
).sequence()->properties() & property
)
563 void LayerAnimator::AddToQueueIfNotPresent(LayerAnimationSequence
* animation
) {
564 // If we don't have the animation in the queue yet, add it.
565 bool found_sequence
= false;
566 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
567 queue_iter
!= animation_queue_
.end(); ++queue_iter
) {
568 if ((*queue_iter
) == animation
) {
569 found_sequence
= true;
575 animation_queue_
.push_front(make_linked_ptr(animation
));
578 void LayerAnimator::RemoveAllAnimationsWithACommonProperty(
579 LayerAnimationSequence
* sequence
, bool abort
) {
580 // For all the running animations, if they animate the same property,
581 // progress them to the end and remove them. Note, Aborting or Progressing
582 // animations may affect the collection of running animations, so we need to
583 // operate on a copy.
584 RunningAnimations running_animations_copy
= running_animations_
;
585 for (size_t i
= 0; i
< running_animations_copy
.size(); ++i
) {
586 if (!SAFE_INVOKE_BOOL(HasAnimation
, running_animations_copy
[i
]))
589 if (running_animations_copy
[i
].sequence()->HasConflictingProperty(
590 sequence
->properties())) {
591 scoped_ptr
<LayerAnimationSequence
> removed(
592 SAFE_INVOKE_PTR(RemoveAnimation
, running_animations_copy
[i
]));
594 running_animations_copy
[i
].sequence()->Abort(delegate());
596 SAFE_INVOKE_VOID(ProgressAnimationToEnd
, running_animations_copy
[i
]);
600 // Same for the queued animations that haven't been started. Again, we'll
601 // need to operate on a copy.
602 std::vector
<base::WeakPtr
<LayerAnimationSequence
> > sequences
;
603 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
604 queue_iter
!= animation_queue_
.end(); ++queue_iter
)
605 sequences
.push_back((*queue_iter
)->AsWeakPtr());
607 for (size_t i
= 0; i
< sequences
.size(); ++i
) {
608 if (!sequences
[i
].get() || !HasAnimation(sequences
[i
].get()))
611 if (sequences
[i
]->HasConflictingProperty(sequence
->properties())) {
612 scoped_ptr
<LayerAnimationSequence
> removed(
613 RemoveAnimation(sequences
[i
].get()));
615 sequences
[i
]->Abort(delegate());
617 ProgressAnimationToEnd(sequences
[i
].get());
622 void LayerAnimator::ImmediatelySetNewTarget(LayerAnimationSequence
* sequence
) {
623 // Need to detect if our sequence gets destroyed.
624 base::WeakPtr
<LayerAnimationSequence
> weak_sequence_ptr
=
625 sequence
->AsWeakPtr();
627 const bool abort
= false;
628 RemoveAllAnimationsWithACommonProperty(sequence
, abort
);
629 if (!weak_sequence_ptr
.get())
632 LayerAnimationSequence
* removed
= RemoveAnimation(sequence
);
633 DCHECK(removed
== NULL
|| removed
== sequence
);
634 if (!weak_sequence_ptr
.get())
637 ProgressAnimationToEnd(sequence
);
638 if (!weak_sequence_ptr
.get())
644 void LayerAnimator::ImmediatelyAnimateToNewTarget(
645 LayerAnimationSequence
* sequence
) {
646 // Need to detect if our sequence gets destroyed.
647 base::WeakPtr
<LayerAnimationSequence
> weak_sequence_ptr
=
648 sequence
->AsWeakPtr();
650 const bool abort
= true;
651 RemoveAllAnimationsWithACommonProperty(sequence
, abort
);
652 if (!weak_sequence_ptr
.get())
655 AddToQueueIfNotPresent(sequence
);
656 if (!weak_sequence_ptr
.get())
659 StartSequenceImmediately(sequence
);
662 void LayerAnimator::EnqueueNewAnimation(LayerAnimationSequence
* sequence
) {
663 // It is assumed that if there was no conflicting animation, we would
664 // not have been called. No need to check for a collision; just
666 animation_queue_
.push_back(make_linked_ptr(sequence
));
670 void LayerAnimator::ReplaceQueuedAnimations(LayerAnimationSequence
* sequence
) {
671 // Need to detect if our sequence gets destroyed.
672 base::WeakPtr
<LayerAnimationSequence
> weak_sequence_ptr
=
673 sequence
->AsWeakPtr();
675 // Remove all animations that aren't running. Note: at each iteration i is
676 // incremented or an element is removed from the queue, so
677 // animation_queue_.size() - i is always decreasing and we are always making
678 // progress towards the loop terminating.
679 for (size_t i
= 0; i
< animation_queue_
.size();) {
680 if (!weak_sequence_ptr
.get())
683 PurgeDeletedAnimations();
685 bool is_running
= false;
686 for (RunningAnimations::const_iterator iter
= running_animations_
.begin();
687 iter
!= running_animations_
.end(); ++iter
) {
688 if ((*iter
).sequence() == animation_queue_
[i
].get()) {
695 delete RemoveAnimation(animation_queue_
[i
].get());
699 animation_queue_
.push_back(make_linked_ptr(sequence
));
703 void LayerAnimator::ProcessQueue() {
704 bool started_sequence
= false;
706 started_sequence
= false;
707 // Build a list of all currently animated properties.
708 LayerAnimationElement::AnimatableProperties animated
=
709 LayerAnimationElement::UNKNOWN
;
710 for (RunningAnimations::const_iterator iter
= running_animations_
.begin();
711 iter
!= running_animations_
.end(); ++iter
) {
712 if (!(*iter
).is_sequence_alive())
715 animated
|= (*iter
).sequence()->properties();
718 // Try to find an animation that doesn't conflict with an animated
719 // property or a property that will be animated before it. Note: starting
720 // the animation may indirectly cause more animations to be started, so we
721 // need to operate on a copy.
722 std::vector
<base::WeakPtr
<LayerAnimationSequence
> > sequences
;
723 for (AnimationQueue::iterator queue_iter
= animation_queue_
.begin();
724 queue_iter
!= animation_queue_
.end(); ++queue_iter
)
725 sequences
.push_back((*queue_iter
)->AsWeakPtr());
727 for (size_t i
= 0; i
< sequences
.size(); ++i
) {
728 if (!sequences
[i
].get() || !HasAnimation(sequences
[i
].get()))
731 if (!sequences
[i
]->HasConflictingProperty(animated
)) {
732 StartSequenceImmediately(sequences
[i
].get());
733 started_sequence
= true;
737 // Animation couldn't be started. Add its properties to the collection so
738 // that we don't start a conflicting animation. For example, if our queue
739 // has the elements { {T,B}, {B} } (that is, an element that animates both
740 // the transform and the bounds followed by an element that animates the
741 // bounds), and we're currently animating the transform, we can't start
742 // the first element because it animates the transform, too. We cannot
743 // start the second element, either, because the first element animates
744 // bounds too, and needs to go first.
745 animated
|= sequences
[i
]->properties();
748 // If we started a sequence, try again. We may be able to start several.
749 } while (started_sequence
);
752 bool LayerAnimator::StartSequenceImmediately(LayerAnimationSequence
* sequence
) {
753 PurgeDeletedAnimations();
755 // Ensure that no one is animating one of the sequence's properties already.
756 for (RunningAnimations::const_iterator iter
= running_animations_
.begin();
757 iter
!= running_animations_
.end(); ++iter
) {
758 if ((*iter
).sequence()->HasConflictingProperty(sequence
->properties()))
762 // All clear, actually start the sequence.
763 // All LayerAnimators share the same LayerAnimatorCollection. Use the
764 // last_tick_time() from there to ensure animations started during the same
765 // event complete at the same time.
766 base::TimeTicks start_time
;
767 LayerAnimatorCollection
* collection
= GetLayerAnimatorCollection();
768 if (is_animating() || adding_animations_
)
769 start_time
= last_step_time_
;
770 else if (collection
&& collection
->HasActiveAnimators())
771 start_time
= collection
->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 void LayerAnimator::SetTransitionDuration(base::TimeDelta duration
) {
814 if (is_transition_duration_locked_
)
816 transition_duration_
= duration
;
819 void LayerAnimator::ClearAnimationsInternal() {
820 PurgeDeletedAnimations();
822 // Abort should never affect the set of running animations, but just in case
823 // clients are badly behaved, we will use a copy of the running animations.
824 RunningAnimations running_animations_copy
= running_animations_
;
825 for (size_t i
= 0; i
< running_animations_copy
.size(); ++i
) {
826 if (!SAFE_INVOKE_BOOL(HasAnimation
, running_animations_copy
[i
]))
829 scoped_ptr
<LayerAnimationSequence
> removed(
830 RemoveAnimation(running_animations_copy
[i
].sequence()));
832 removed
->Abort(delegate());
834 // This *should* have cleared the list of running animations.
835 DCHECK(running_animations_
.empty());
836 running_animations_
.clear();
837 animation_queue_
.clear();
838 UpdateAnimationState();
841 void LayerAnimator::PurgeDeletedAnimations() {
842 for (size_t i
= 0; i
< running_animations_
.size();) {
843 if (!running_animations_
[i
].is_sequence_alive())
844 running_animations_
.erase(running_animations_
.begin() + i
);
850 LayerAnimatorCollection
* LayerAnimator::GetLayerAnimatorCollection() {
851 return delegate_
? delegate_
->GetLayerAnimatorCollection() : NULL
;
854 LayerAnimator::RunningAnimation::RunningAnimation(
855 const base::WeakPtr
<LayerAnimationSequence
>& sequence
)
856 : sequence_(sequence
) {
859 LayerAnimator::RunningAnimation::~RunningAnimation() { }