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_animation_sequence.h"
10 #include "base/debug/trace_event.h"
11 #include "cc/animation/animation_id_provider.h"
12 #include "ui/compositor/layer_animation_delegate.h"
13 #include "ui/compositor/layer_animation_element.h"
14 #include "ui/compositor/layer_animation_observer.h"
18 LayerAnimationSequence::LayerAnimationSequence()
19 : properties_(LayerAnimationElement::UNKNOWN
),
22 waiting_for_group_start_(false),
23 animation_group_id_(0),
24 last_progressed_fraction_(0.0),
25 weak_ptr_factory_(this) {
28 LayerAnimationSequence::LayerAnimationSequence(LayerAnimationElement
* element
)
29 : properties_(LayerAnimationElement::UNKNOWN
),
32 waiting_for_group_start_(false),
33 animation_group_id_(0),
34 last_progressed_fraction_(0.0),
35 weak_ptr_factory_(this) {
39 LayerAnimationSequence::~LayerAnimationSequence() {
40 FOR_EACH_OBSERVER(LayerAnimationObserver
,
42 DetachedFromSequence(this, true));
45 void LayerAnimationSequence::Start(LayerAnimationDelegate
* delegate
) {
46 DCHECK(start_time_
!= base::TimeTicks());
47 last_progressed_fraction_
= 0.0;
48 if (elements_
.empty())
51 elements_
[0]->set_requested_start_time(start_time_
);
52 elements_
[0]->Start(delegate
, animation_group_id_
);
55 void LayerAnimationSequence::Progress(base::TimeTicks now
,
56 LayerAnimationDelegate
* delegate
) {
57 DCHECK(start_time_
!= base::TimeTicks());
58 bool redraw_required
= false;
60 if (elements_
.empty())
63 if (last_element_
== 0)
64 last_start_
= start_time_
;
66 size_t current_index
= last_element_
% elements_
.size();
67 base::TimeDelta element_duration
;
68 while (is_cyclic_
|| last_element_
< elements_
.size()) {
69 elements_
[current_index
]->set_requested_start_time(last_start_
);
70 if (!elements_
[current_index
]->IsFinished(now
, &element_duration
))
73 // Let the element we're passing finish.
74 if (elements_
[current_index
]->ProgressToEnd(delegate
))
75 redraw_required
= true;
76 last_start_
+= element_duration
;
78 last_progressed_fraction_
=
79 elements_
[current_index
]->last_progressed_fraction();
80 current_index
= last_element_
% elements_
.size();
83 if (is_cyclic_
|| last_element_
< elements_
.size()) {
84 if (!elements_
[current_index
]->Started()) {
85 animation_group_id_
= cc::AnimationIdProvider::NextGroupId();
86 elements_
[current_index
]->Start(delegate
, animation_group_id_
);
88 base::WeakPtr
<LayerAnimationSequence
> alive(weak_ptr_factory_
.GetWeakPtr());
89 if (elements_
[current_index
]->Progress(now
, delegate
))
90 redraw_required
= true;
93 last_progressed_fraction_
=
94 elements_
[current_index
]->last_progressed_fraction();
97 // Since the delegate may be deleted due to the notifications below, it is
98 // important that we schedule a draw before sending them.
100 delegate
->ScheduleDrawForAnimation();
102 if (!is_cyclic_
&& last_element_
== elements_
.size()) {
104 waiting_for_group_start_
= false;
105 animation_group_id_
= 0;
110 bool LayerAnimationSequence::IsFinished(base::TimeTicks time
) {
111 if (is_cyclic_
|| waiting_for_group_start_
)
114 if (elements_
.empty())
117 if (last_element_
== 0)
118 last_start_
= start_time_
;
120 base::TimeTicks current_start
= last_start_
;
121 size_t current_index
= last_element_
;
122 base::TimeDelta element_duration
;
123 while (current_index
< elements_
.size()) {
124 elements_
[current_index
]->set_requested_start_time(current_start
);
125 if (!elements_
[current_index
]->IsFinished(time
, &element_duration
))
128 current_start
+= element_duration
;
132 return (current_index
== elements_
.size());
135 void LayerAnimationSequence::ProgressToEnd(LayerAnimationDelegate
* delegate
) {
136 bool redraw_required
= false;
138 if (elements_
.empty())
141 size_t current_index
= last_element_
% elements_
.size();
142 while (current_index
< elements_
.size()) {
143 if (elements_
[current_index
]->ProgressToEnd(delegate
))
144 redraw_required
= true;
145 last_progressed_fraction_
=
146 elements_
[current_index
]->last_progressed_fraction();
152 delegate
->ScheduleDrawForAnimation();
156 waiting_for_group_start_
= false;
157 animation_group_id_
= 0;
162 void LayerAnimationSequence::GetTargetValue(
163 LayerAnimationElement::TargetValue
* target
) const {
167 for (size_t i
= last_element_
; i
< elements_
.size(); ++i
)
168 elements_
[i
]->GetTargetValue(target
);
171 void LayerAnimationSequence::Abort(LayerAnimationDelegate
* delegate
) {
172 size_t current_index
= last_element_
% elements_
.size();
173 while (current_index
< elements_
.size()) {
174 elements_
[current_index
]->Abort(delegate
);
178 waiting_for_group_start_
= false;
182 void LayerAnimationSequence::AddElement(LayerAnimationElement
* element
) {
183 properties_
|= element
->properties();
184 elements_
.push_back(make_linked_ptr(element
));
187 bool LayerAnimationSequence::HasConflictingProperty(
188 LayerAnimationElement::AnimatableProperties other
) const {
189 return (properties_
& other
) != LayerAnimationElement::UNKNOWN
;
192 bool LayerAnimationSequence::IsFirstElementThreaded() const {
193 if (!elements_
.empty())
194 return elements_
[0]->IsThreaded();
199 void LayerAnimationSequence::AddObserver(LayerAnimationObserver
* observer
) {
200 if (!observers_
.HasObserver(observer
)) {
201 observers_
.AddObserver(observer
);
202 observer
->AttachedToSequence(this);
206 void LayerAnimationSequence::RemoveObserver(LayerAnimationObserver
* observer
) {
207 observers_
.RemoveObserver(observer
);
208 observer
->DetachedFromSequence(this, true);
211 void LayerAnimationSequence::OnThreadedAnimationStarted(
212 const cc::AnimationEvent
& event
) {
213 if (elements_
.empty() || event
.group_id
!= animation_group_id_
)
216 size_t current_index
= last_element_
% elements_
.size();
217 LayerAnimationElement::AnimatableProperties element_properties
=
218 elements_
[current_index
]->properties();
219 LayerAnimationElement::AnimatableProperty event_property
=
220 LayerAnimationElement::ToAnimatableProperty(event
.target_property
);
221 DCHECK(element_properties
& event_property
);
222 elements_
[current_index
]->set_effective_start_time(event
.monotonic_time
);
225 void LayerAnimationSequence::OnScheduled() {
229 void LayerAnimationSequence::OnAnimatorDestroyed() {
230 if (observers_
.might_have_observers()) {
231 ObserverListBase
<LayerAnimationObserver
>::Iterator
it(observers_
);
232 LayerAnimationObserver
* obs
;
233 while ((obs
= it
.GetNext()) != NULL
) {
234 if (!obs
->RequiresNotificationWhenAnimatorDestroyed()) {
235 // Remove the observer, but do not allow notifications to be sent.
236 observers_
.RemoveObserver(obs
);
237 obs
->DetachedFromSequence(this, false);
243 size_t LayerAnimationSequence::size() const {
244 return elements_
.size();
247 LayerAnimationElement
* LayerAnimationSequence::FirstElement() const {
248 if (elements_
.empty()) {
252 return elements_
[0].get();
255 void LayerAnimationSequence::NotifyScheduled() {
256 FOR_EACH_OBSERVER(LayerAnimationObserver
,
258 OnLayerAnimationScheduled(this));
261 void LayerAnimationSequence::NotifyEnded() {
262 FOR_EACH_OBSERVER(LayerAnimationObserver
,
264 OnLayerAnimationEnded(this));
267 void LayerAnimationSequence::NotifyAborted() {
268 FOR_EACH_OBSERVER(LayerAnimationObserver
,
270 OnLayerAnimationAborted(this));
273 LayerAnimationElement
* LayerAnimationSequence::CurrentElement() const {
274 if (elements_
.empty())
277 size_t current_index
= last_element_
% elements_
.size();
278 return elements_
[current_index
].get();