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 "ui/compositor/layer_animation_delegate.h"
12 #include "ui/compositor/layer_animation_element.h"
13 #include "ui/compositor/layer_animation_observer.h"
17 LayerAnimationSequence::LayerAnimationSequence()
20 waiting_for_group_start_(false),
21 animation_group_id_(0),
22 last_progressed_fraction_(0.0) {
25 LayerAnimationSequence::LayerAnimationSequence(LayerAnimationElement
* element
)
28 waiting_for_group_start_(false),
29 animation_group_id_(0),
30 last_progressed_fraction_(0.0) {
34 LayerAnimationSequence::~LayerAnimationSequence() {
35 FOR_EACH_OBSERVER(LayerAnimationObserver
,
37 DetachedFromSequence(this, true));
40 void LayerAnimationSequence::Start(LayerAnimationDelegate
* delegate
) {
41 DCHECK(start_time_
!= base::TimeTicks());
42 last_progressed_fraction_
= 0.0;
43 if (elements_
.empty())
46 elements_
[0]->set_requested_start_time(start_time_
);
47 elements_
[0]->Start(delegate
, animation_group_id_
);
50 void LayerAnimationSequence::Progress(base::TimeTicks now
,
51 LayerAnimationDelegate
* delegate
) {
52 DCHECK(start_time_
!= base::TimeTicks());
53 bool redraw_required
= false;
55 if (elements_
.empty())
58 if (last_element_
== 0)
59 last_start_
= start_time_
;
61 size_t current_index
= last_element_
% elements_
.size();
62 base::TimeDelta element_duration
;
63 while (is_cyclic_
|| last_element_
< elements_
.size()) {
64 elements_
[current_index
]->set_requested_start_time(last_start_
);
65 if (!elements_
[current_index
]->IsFinished(now
, &element_duration
))
68 // Let the element we're passing finish.
69 if (elements_
[current_index
]->ProgressToEnd(delegate
))
70 redraw_required
= true;
71 last_start_
+= element_duration
;
73 last_progressed_fraction_
=
74 elements_
[current_index
]->last_progressed_fraction();
75 current_index
= last_element_
% elements_
.size();
78 if (is_cyclic_
|| last_element_
< elements_
.size()) {
79 if (!elements_
[current_index
]->Started())
80 elements_
[current_index
]->Start(delegate
, animation_group_id_
);
81 if (elements_
[current_index
]->Progress(now
, delegate
))
82 redraw_required
= true;
83 last_progressed_fraction_
=
84 elements_
[current_index
]->last_progressed_fraction();
87 // Since the delegate may be deleted due to the notifications below, it is
88 // important that we schedule a draw before sending them.
90 delegate
->ScheduleDrawForAnimation();
92 if (!is_cyclic_
&& last_element_
== elements_
.size()) {
94 waiting_for_group_start_
= false;
95 animation_group_id_
= 0;
100 bool LayerAnimationSequence::IsFinished(base::TimeTicks time
) {
101 if (is_cyclic_
|| waiting_for_group_start_
)
104 if (elements_
.empty())
107 if (last_element_
== 0)
108 last_start_
= start_time_
;
110 base::TimeTicks current_start
= last_start_
;
111 size_t current_index
= last_element_
;
112 base::TimeDelta element_duration
;
113 while (current_index
< elements_
.size()) {
114 elements_
[current_index
]->set_requested_start_time(current_start
);
115 if (!elements_
[current_index
]->IsFinished(time
, &element_duration
))
118 current_start
+= element_duration
;
122 return (current_index
== elements_
.size());
125 void LayerAnimationSequence::ProgressToEnd(LayerAnimationDelegate
* delegate
) {
126 bool redraw_required
= false;
128 if (elements_
.empty())
131 size_t current_index
= last_element_
% elements_
.size();
132 while (current_index
< elements_
.size()) {
133 if (elements_
[current_index
]->ProgressToEnd(delegate
))
134 redraw_required
= true;
135 last_progressed_fraction_
=
136 elements_
[current_index
]->last_progressed_fraction();
142 delegate
->ScheduleDrawForAnimation();
146 waiting_for_group_start_
= false;
147 animation_group_id_
= 0;
152 void LayerAnimationSequence::GetTargetValue(
153 LayerAnimationElement::TargetValue
* target
) const {
157 for (size_t i
= last_element_
; i
< elements_
.size(); ++i
)
158 elements_
[i
]->GetTargetValue(target
);
161 void LayerAnimationSequence::Abort(LayerAnimationDelegate
* delegate
) {
162 size_t current_index
= last_element_
% elements_
.size();
163 while (current_index
< elements_
.size()) {
164 elements_
[current_index
]->Abort(delegate
);
168 waiting_for_group_start_
= false;
172 void LayerAnimationSequence::AddElement(LayerAnimationElement
* element
) {
173 properties_
.insert(element
->properties().begin(),
174 element
->properties().end());
175 elements_
.push_back(make_linked_ptr(element
));
178 bool LayerAnimationSequence::HasConflictingProperty(
179 const LayerAnimationElement::AnimatableProperties
& other
) const {
180 LayerAnimationElement::AnimatableProperties intersection
;
181 std::insert_iterator
<LayerAnimationElement::AnimatableProperties
> ii(
182 intersection
, intersection
.begin());
183 std::set_intersection(properties_
.begin(), properties_
.end(),
184 other
.begin(), other
.end(),
186 return (intersection
.size() > 0);
189 bool LayerAnimationSequence::IsFirstElementThreaded() const {
190 if (!elements_
.empty())
191 return elements_
[0]->IsThreaded();
196 void LayerAnimationSequence::AddObserver(LayerAnimationObserver
* observer
) {
197 if (!observers_
.HasObserver(observer
)) {
198 observers_
.AddObserver(observer
);
199 observer
->AttachedToSequence(this);
203 void LayerAnimationSequence::RemoveObserver(LayerAnimationObserver
* observer
) {
204 observers_
.RemoveObserver(observer
);
205 observer
->DetachedFromSequence(this, true);
208 void LayerAnimationSequence::OnThreadedAnimationStarted(
209 const cc::AnimationEvent
& event
) {
210 if (elements_
.empty() || event
.group_id
!= animation_group_id_
)
213 size_t current_index
= last_element_
% elements_
.size();
214 const LayerAnimationElement::AnimatableProperties
& element_properties
=
215 elements_
[current_index
]->properties();
216 LayerAnimationElement::AnimatableProperty event_property
=
217 LayerAnimationElement::ToAnimatableProperty(event
.target_property
);
218 DCHECK(element_properties
.find(event_property
) != element_properties
.end());
219 elements_
[current_index
]->set_effective_start_time(
220 base::TimeTicks::FromInternalValue(
221 event
.monotonic_time
* base::Time::kMicrosecondsPerSecond
));
224 void LayerAnimationSequence::OnScheduled() {
228 void LayerAnimationSequence::OnAnimatorDestroyed() {
229 if (observers_
.might_have_observers()) {
230 ObserverListBase
<LayerAnimationObserver
>::Iterator
it(observers_
);
231 LayerAnimationObserver
* obs
;
232 while ((obs
= it
.GetNext()) != NULL
) {
233 if (!obs
->RequiresNotificationWhenAnimatorDestroyed()) {
234 // Remove the observer, but do not allow notifications to be sent.
235 observers_
.RemoveObserver(obs
);
236 obs
->DetachedFromSequence(this, false);
242 void LayerAnimationSequence::NotifyScheduled() {
243 FOR_EACH_OBSERVER(LayerAnimationObserver
,
245 OnLayerAnimationScheduled(this));
248 void LayerAnimationSequence::NotifyEnded() {
249 FOR_EACH_OBSERVER(LayerAnimationObserver
,
251 OnLayerAnimationEnded(this));
254 void LayerAnimationSequence::NotifyAborted() {
255 FOR_EACH_OBSERVER(LayerAnimationObserver
,
257 OnLayerAnimationAborted(this));
260 LayerAnimationElement
* LayerAnimationSequence::CurrentElement() {
261 if (elements_
.empty())
264 size_t current_index
= last_element_
% elements_
.size();
265 return elements_
[current_index
].get();