OLD | NEW |
---|---|
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/layer_animation_controller.h" | 5 #include "cc/layer_animation_controller.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "cc/animation.h" | 9 #include "cc/animation.h" |
10 #include "cc/animation_registrar.h" | 10 #include "cc/animation_registrar.h" |
11 #include "cc/keyframed_animation_curve.h" | 11 #include "cc/keyframed_animation_curve.h" |
12 #include "cc/layer_animation_value_observer.h" | 12 #include "cc/layer_animation_value_observer.h" |
13 #include "cc/scoped_ptr_algorithm.h" | 13 #include "cc/scoped_ptr_algorithm.h" |
14 #include "ui/gfx/transform.h" | 14 #include "ui/gfx/transform.h" |
15 | 15 |
16 namespace cc { | 16 namespace cc { LayerAnimationController::LayerAnimationController(int id) |
jamesr
2013/03/09 02:44:56
this one's on the same line too
danakj
2013/03/09 03:01:11
Done.
| |
17 | 17 : force_sync_(false), |
18 LayerAnimationController::LayerAnimationController(int id) | 18 id_(id), |
19 : m_forceSync(false) | 19 registrar_(0), |
20 , m_id(id) | 20 is_active_(false), |
21 , m_registrar(0) | 21 last_tick_time_(0) {} |
22 , m_isActive(false) | 22 |
23 , m_lastTickTime(0) | 23 LayerAnimationController::~LayerAnimationController() { |
24 { | 24 if (registrar_) |
25 } | 25 registrar_->UnregisterAnimationController(this); |
26 | 26 } |
27 LayerAnimationController::~LayerAnimationController() | 27 |
28 { | 28 scoped_refptr<LayerAnimationController> LayerAnimationController::Create( |
29 if (m_registrar) | 29 int id) { |
30 m_registrar->UnregisterAnimationController(this); | 30 return make_scoped_refptr(new LayerAnimationController(id)); |
31 } | 31 } |
32 | 32 |
33 scoped_refptr<LayerAnimationController> LayerAnimationController::create(int id) | 33 void LayerAnimationController::PauseAnimation(int animation_id, |
34 { | 34 double time_offset) { |
35 return make_scoped_refptr(new LayerAnimationController(id)); | 35 for (size_t i = 0; i < active_animations_.size(); ++i) { |
36 } | 36 if (active_animations_[i]->id() == animation_id) { |
37 | 37 active_animations_[i]->SetRunState( |
38 void LayerAnimationController::pauseAnimation(int animationId, double timeOffset ) | 38 Animation::Paused, time_offset + active_animations_[i]->start_time()); |
39 { | 39 } |
40 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { | 40 } |
41 if (m_activeAnimations[i]->id() == animationId) | |
42 m_activeAnimations[i]->setRunState(Animation::Paused, timeOffset + m _activeAnimations[i]->startTime()); | |
43 } | |
44 } | 41 } |
45 | 42 |
46 struct HasAnimationId { | 43 struct HasAnimationId { |
47 HasAnimationId(int id) : m_id(id) { } | 44 HasAnimationId(int id) : id_(id) {} |
48 bool operator()(Animation* animation) const { return animation->id() == m_id ; } | 45 bool operator()(Animation* animation) const { |
49 private: | 46 return animation->id() == id_; |
50 int m_id; | 47 } |
48 | |
49 private: | |
50 int id_; | |
51 }; | 51 }; |
52 | 52 |
53 void LayerAnimationController::removeAnimation(int animationId) | 53 void LayerAnimationController::RemoveAnimation(int animation_id) { |
54 { | 54 ScopedPtrVector<Animation>& animations = active_animations_; |
55 ScopedPtrVector<Animation>& animations = m_activeAnimations; | 55 animations.erase(cc::remove_if(animations, |
56 animations.erase(cc::remove_if(animations, animations.begin(), animations.en d(), HasAnimationId(animationId)), animations.end()); | 56 animations.begin(), |
57 updateActivation(); | 57 animations.end(), |
58 HasAnimationId(animation_id)), | |
59 animations.end()); | |
60 UpdateActivation(NormalActivation); | |
58 } | 61 } |
59 | 62 |
60 struct HasAnimationIdAndProperty { | 63 struct HasAnimationIdAndProperty { |
61 HasAnimationIdAndProperty(int id, Animation::TargetProperty targetProperty) : m_id(id), m_targetProperty(targetProperty) { } | 64 HasAnimationIdAndProperty(int id, Animation::TargetProperty target_property) |
62 bool operator()(Animation* animation) const { return animation->id() == m_id && animation->targetProperty() == m_targetProperty; } | 65 : id_(id), target_property_(target_property) {} |
63 private: | 66 bool operator()(Animation* animation) const { |
64 int m_id; | 67 return animation->id() == id_ && |
65 Animation::TargetProperty m_targetProperty; | 68 animation->target_property() == target_property_; |
69 } | |
70 | |
71 private: | |
72 int id_; | |
73 Animation::TargetProperty target_property_; | |
66 }; | 74 }; |
67 | 75 |
68 void LayerAnimationController::removeAnimation(int animationId, Animation::Targe tProperty targetProperty) | 76 void LayerAnimationController::RemoveAnimation( |
69 { | 77 int animation_id, |
70 ScopedPtrVector<Animation>& animations = m_activeAnimations; | 78 Animation::TargetProperty target_property) { |
71 animations.erase(cc::remove_if(animations, animations.begin(), animations.en d(), HasAnimationIdAndProperty(animationId, targetProperty)), animations.end()); | 79 ScopedPtrVector<Animation>& animations = active_animations_; |
72 updateActivation(); | 80 animations.erase(cc::remove_if(animations, |
81 animations.begin(), | |
82 animations.end(), | |
83 HasAnimationIdAndProperty(animation_id, | |
84 target_property)), | |
85 animations.end()); | |
86 UpdateActivation(NormalActivation); | |
73 } | 87 } |
74 | 88 |
75 // According to render layer backing, these are for testing only. | 89 // According to render layer backing, these are for testing only. |
76 void LayerAnimationController::suspendAnimations(double monotonicTime) | 90 void LayerAnimationController::SuspendAnimations(double monotonic_time) { |
77 { | 91 for (size_t i = 0; i < active_animations_.size(); ++i) { |
78 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { | 92 if (!active_animations_[i]->is_finished()) |
79 if (!m_activeAnimations[i]->isFinished()) | 93 active_animations_[i]->SetRunState(Animation::Paused, monotonic_time); |
80 m_activeAnimations[i]->setRunState(Animation::Paused, monotonicTime) ; | 94 } |
81 } | 95 } |
82 } | 96 |
83 | 97 // Looking at GraphicsLayerCA, this appears to be the analog to |
84 // Looking at GraphicsLayerCA, this appears to be the analog to suspendAnimation s, which is for testing. | 98 // suspendAnimations, which is for testing. |
85 void LayerAnimationController::resumeAnimations(double monotonicTime) | 99 void LayerAnimationController::ResumeAnimations(double monotonic_time) { |
86 { | 100 for (size_t i = 0; i < active_animations_.size(); ++i) { |
87 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { | 101 if (active_animations_[i]->run_state() == Animation::Paused) |
88 if (m_activeAnimations[i]->runState() == Animation::Paused) | 102 active_animations_[i]->SetRunState(Animation::Running, monotonic_time); |
89 m_activeAnimations[i]->setRunState(Animation::Running, monotonicTime ); | 103 } |
90 } | 104 } |
91 } | 105 |
92 | 106 // Ensures that the list of active animations on the main thread and the impl |
93 // Ensures that the list of active animations on the main thread and the impl th read | 107 // thread are kept in sync. |
94 // are kept in sync. | 108 void LayerAnimationController::PushAnimationUpdatesTo( |
95 void LayerAnimationController::pushAnimationUpdatesTo(LayerAnimationController* controllerImpl) | 109 LayerAnimationController* controller_impl) { |
96 { | 110 if (force_sync_) { |
97 if (m_forceSync) { | 111 ReplaceImplThreadAnimations(controller_impl); |
98 replaceImplThreadAnimations(controllerImpl); | 112 force_sync_ = false; |
99 m_forceSync = false; | 113 } else { |
114 PurgeAnimationsMarkedForDeletion(); | |
115 PushNewAnimationsToImplThread(controller_impl); | |
116 | |
117 // Remove finished impl side animations only after pushing, | |
118 // and only after the animations are deleted on the main thread | |
119 // this insures we will never push an animation twice. | |
120 RemoveAnimationsCompletedOnMainThread(controller_impl); | |
121 | |
122 PushPropertiesToImplThread(controller_impl); | |
123 } | |
124 controller_impl->UpdateActivation(NormalActivation); | |
125 UpdateActivation(NormalActivation); | |
126 } | |
127 | |
128 void LayerAnimationController::Animate(double monotonic_time) { | |
129 if (!HasActiveObserver()) | |
130 return; | |
131 | |
132 StartAnimationsWaitingForNextTick(monotonic_time); | |
133 StartAnimationsWaitingForStartTime(monotonic_time); | |
134 StartAnimationsWaitingForTargetAvailability(monotonic_time); | |
135 ResolveConflicts(monotonic_time); | |
136 TickAnimations(monotonic_time); | |
137 last_tick_time_ = monotonic_time; | |
138 } | |
139 | |
140 void LayerAnimationController::AccumulatePropertyUpdates( | |
141 double monotonic_time, | |
142 AnimationEventsVector* events) { | |
143 if (!events) | |
144 return; | |
145 | |
146 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
147 Animation* animation = active_animations_[i]; | |
148 if (!animation->is_impl_only()) | |
149 continue; | |
150 | |
151 if (animation->target_property() == Animation::Opacity) { | |
152 AnimationEvent event(AnimationEvent::PropertyUpdate, | |
153 id_, | |
154 animation->group(), | |
155 Animation::Opacity, | |
156 monotonic_time); | |
157 event.opacity = animation->curve()->ToFloatAnimationCurve()->GetValue( | |
158 monotonic_time); | |
159 | |
160 events->push_back(event); | |
161 } | |
162 else if (animation->target_property() == Animation::Transform) { | |
163 AnimationEvent event(AnimationEvent::PropertyUpdate, | |
164 id_, | |
165 animation->group(), | |
166 Animation::Transform, | |
167 monotonic_time); | |
168 event.transform = | |
169 animation->curve()->ToTransformAnimationCurve()->GetValue( | |
170 monotonic_time); | |
171 events->push_back(event); | |
172 } | |
173 } | |
174 } | |
175 | |
176 void LayerAnimationController::UpdateState(AnimationEventsVector* events) { | |
177 if (!HasActiveObserver()) | |
178 return; | |
179 | |
180 PromoteStartedAnimations(last_tick_time_, events); | |
181 MarkFinishedAnimations(last_tick_time_); | |
182 MarkAnimationsForDeletion(last_tick_time_, events); | |
183 StartAnimationsWaitingForTargetAvailability(last_tick_time_); | |
184 PromoteStartedAnimations(last_tick_time_, events); | |
185 | |
186 AccumulatePropertyUpdates(last_tick_time_, events); | |
187 | |
188 UpdateActivation(NormalActivation); | |
189 } | |
190 | |
191 void LayerAnimationController::AddAnimation(scoped_ptr<Animation> animation) { | |
192 active_animations_.push_back(animation.Pass()); | |
193 UpdateActivation(NormalActivation); | |
194 } | |
195 | |
196 Animation* LayerAnimationController::GetAnimation( | |
197 int group_id, | |
198 Animation::TargetProperty target_property) const { | |
199 for (size_t i = 0; i < active_animations_.size(); ++i) | |
200 if (active_animations_[i]->group() == group_id && | |
201 active_animations_[i]->target_property() == target_property) | |
202 return active_animations_[i]; | |
203 return 0; | |
204 } | |
205 | |
206 Animation* LayerAnimationController::GetAnimation( | |
207 Animation::TargetProperty target_property) const { | |
208 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
209 size_t index = active_animations_.size() - i - 1; | |
210 if (active_animations_[index]->target_property() == target_property) | |
211 return active_animations_[index]; | |
212 } | |
213 return 0; | |
214 } | |
215 | |
216 bool LayerAnimationController::HasActiveAnimation() const { | |
217 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
218 if (!active_animations_[i]->is_finished()) | |
219 return true; | |
220 } | |
221 return false; | |
222 } | |
223 | |
224 bool LayerAnimationController::IsAnimatingProperty( | |
225 Animation::TargetProperty target_property) const { | |
226 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
227 if (active_animations_[i]->run_state() != Animation::Finished && | |
228 active_animations_[i]->run_state() != Animation::Aborted && | |
229 active_animations_[i]->target_property() == target_property) | |
230 return true; | |
231 } | |
232 return false; | |
233 } | |
234 | |
235 void LayerAnimationController::OnAnimationStarted( | |
236 const AnimationEvent& event) { | |
237 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
238 if (active_animations_[i]->group() == event.group_id && | |
239 active_animations_[i]->target_property() == event.target_property && | |
240 active_animations_[i]->needs_synchronized_start_time()) { | |
241 active_animations_[i]->set_needs_synchronized_start_time(false); | |
242 active_animations_[i]->set_start_time(event.monotonic_time); | |
243 return; | |
244 } | |
245 } | |
246 } | |
247 | |
248 void LayerAnimationController::SetAnimationRegistrar( | |
249 AnimationRegistrar* registrar) { | |
250 if (registrar_ == registrar) | |
251 return; | |
252 | |
253 if (registrar_) | |
254 registrar_->UnregisterAnimationController(this); | |
255 | |
256 registrar_ = registrar; | |
257 if (registrar_) | |
258 registrar_->RegisterAnimationController(this); | |
259 | |
260 bool force = true; | |
261 UpdateActivation(ForceActivation); | |
262 } | |
263 | |
264 void LayerAnimationController::AddObserver( | |
265 LayerAnimationValueObserver* observer) { | |
266 if (!observers_.HasObserver(observer)) | |
267 observers_.AddObserver(observer); | |
268 } | |
269 | |
270 void LayerAnimationController::RemoveObserver( | |
271 LayerAnimationValueObserver* observer) { | |
272 observers_.RemoveObserver(observer); | |
273 } | |
274 | |
275 void LayerAnimationController::PushNewAnimationsToImplThread( | |
276 LayerAnimationController* controller_impl) const { | |
277 // Any new animations owned by the main thread's controller are cloned and | |
278 // add to the impl thread's controller. | |
279 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
280 // If the animation is already running on the impl thread, there is no | |
281 // need to copy it over. | |
282 if (controller_impl->GetAnimation(active_animations_[i]->group(), | |
283 active_animations_[i]->target_property())) | |
284 continue; | |
285 | |
286 // If the animation is not running on the impl thread, it does not | |
287 // necessarily mean that it needs to be copied over and started; it may | |
288 // have already finished. In this case, the impl thread animation will | |
289 // have already notified that it has started and the main thread animation | |
290 // will no longer need | |
291 // a synchronized start time. | |
292 if (!active_animations_[i]->needs_synchronized_start_time()) | |
293 continue; | |
294 | |
295 // The new animation should be set to run as soon as possible. | |
296 Animation::RunState initial_run_state = | |
297 Animation::WaitingForTargetAvailability; | |
298 double start_time = 0; | |
299 scoped_ptr<Animation> to_add(active_animations_[i]->CloneAndInitialize( | |
300 Animation::ControllingInstance, initial_run_state, start_time)); | |
301 DCHECK(!to_add->needs_synchronized_start_time()); | |
302 controller_impl->AddAnimation(to_add.Pass()); | |
303 } | |
304 } | |
305 | |
306 struct IsCompleted { | |
307 IsCompleted(const LayerAnimationController& main_thread_controller) | |
308 : main_thread_controller_(main_thread_controller) {} | |
309 bool operator()(Animation* animation) const { | |
310 if (animation->is_impl_only()) | |
311 return false; | |
312 return !main_thread_controller_.GetAnimation(animation->group(), | |
313 animation->target_property()); | |
314 } | |
315 | |
316 private: | |
317 const LayerAnimationController& main_thread_controller_; | |
318 }; | |
319 | |
320 void LayerAnimationController::RemoveAnimationsCompletedOnMainThread( | |
321 LayerAnimationController* controller_impl) const { | |
322 // Delete all impl thread animations for which there is no corresponding | |
323 // main thread animation. Each iteration, | |
324 // controller->active_animations_.size() is decremented or i is incremented | |
325 // guaranteeing progress towards loop termination. | |
326 ScopedPtrVector<Animation>& animations = | |
327 controller_impl->active_animations_; | |
328 animations.erase(cc::remove_if(animations, | |
329 animations.begin(), | |
330 animations.end(), | |
331 IsCompleted(*this)), | |
332 animations.end()); | |
333 } | |
334 | |
335 void LayerAnimationController::PushPropertiesToImplThread( | |
336 LayerAnimationController* controller_impl) const { | |
337 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
338 Animation* current_impl = | |
339 controller_impl->GetAnimation( | |
340 active_animations_[i]->group(), | |
341 active_animations_[i]->target_property()); | |
342 if (current_impl) | |
343 active_animations_[i]->PushPropertiesTo(current_impl); | |
344 } | |
345 } | |
346 | |
347 void LayerAnimationController::StartAnimationsWaitingForNextTick( | |
348 double monotonic_time) { | |
349 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
350 if (active_animations_[i]->run_state() == Animation::WaitingForNextTick) | |
351 active_animations_[i]->SetRunState(Animation::Starting, monotonic_time); | |
352 } | |
353 } | |
354 | |
355 void LayerAnimationController::StartAnimationsWaitingForStartTime( | |
356 double monotonic_time) { | |
357 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
358 if (active_animations_[i]->run_state() == Animation::WaitingForStartTime && | |
359 active_animations_[i]->start_time() <= monotonic_time) | |
360 active_animations_[i]->SetRunState(Animation::Starting, monotonic_time); | |
361 } | |
362 } | |
363 | |
364 void LayerAnimationController::StartAnimationsWaitingForTargetAvailability( | |
365 double monotonic_time) { | |
366 // First collect running properties. | |
367 TargetProperties blocked_properties; | |
368 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
369 if (active_animations_[i]->run_state() == Animation::Starting || | |
370 active_animations_[i]->run_state() == Animation::Running || | |
371 active_animations_[i]->run_state() == Animation::Finished) | |
372 blocked_properties.insert(active_animations_[i]->target_property()); | |
373 } | |
374 | |
375 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
376 if (active_animations_[i]->run_state() == | |
377 Animation::WaitingForTargetAvailability) { | |
378 // Collect all properties for animations with the same group id (they | |
379 // should all also be in the list of animations). | |
380 TargetProperties enqueued_properties; | |
381 enqueued_properties.insert(active_animations_[i]->target_property()); | |
382 for (size_t j = i + 1; j < active_animations_.size(); ++j) { | |
383 if (active_animations_[i]->group() == active_animations_[j]->group()) | |
384 enqueued_properties.insert(active_animations_[j]->target_property()); | |
385 } | |
386 | |
387 // Check to see if intersection of the list of properties affected by | |
388 // the group and the list of currently blocked properties is null. In | |
389 // any case, the group's target properties need to be added to the list | |
390 // of blocked properties. | |
391 bool null_intersection = true; | |
392 for (TargetProperties::iterator p_iter = enqueued_properties.begin(); | |
393 p_iter != enqueued_properties.end(); | |
394 ++p_iter) { | |
395 if (!blocked_properties.insert(*p_iter).second) | |
396 null_intersection = false; | |
397 } | |
398 | |
399 // If the intersection is null, then we are free to start the animations | |
400 // in the group. | |
401 if (null_intersection) { | |
402 active_animations_[i]->SetRunState( | |
403 Animation::Starting, monotonic_time); | |
404 for (size_t j = i + 1; j < active_animations_.size(); ++j) { | |
405 if (active_animations_[i]->group() == | |
406 active_animations_[j]->group()) { | |
407 active_animations_[j]->SetRunState( | |
408 Animation::Starting, monotonic_time); | |
409 } | |
410 } | |
411 } | |
412 } | |
413 } | |
414 } | |
415 | |
416 void LayerAnimationController::PromoteStartedAnimations( | |
417 double monotonic_time, | |
418 AnimationEventsVector* events) { | |
419 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
420 if (active_animations_[i]->run_state() == Animation::Starting) { | |
421 active_animations_[i]->SetRunState(Animation::Running, monotonic_time); | |
422 if (!active_animations_[i]->has_set_start_time()) | |
423 active_animations_[i]->set_start_time(monotonic_time); | |
424 if (events) { | |
425 events->push_back(AnimationEvent( | |
426 AnimationEvent::Started, | |
427 id_, | |
428 active_animations_[i]->group(), | |
429 active_animations_[i]->target_property(), | |
430 monotonic_time)); | |
431 } | |
432 } | |
433 } | |
434 } | |
435 | |
436 void LayerAnimationController::MarkFinishedAnimations(double monotonic_time) { | |
437 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
438 if (active_animations_[i]->IsFinishedAt(monotonic_time)) | |
439 active_animations_[i]->SetRunState(Animation::Finished, monotonic_time); | |
440 } | |
441 } | |
442 | |
443 void LayerAnimationController::ResolveConflicts(double monotonic_time) { | |
444 // Find any animations that are animating the same property and resolve the | |
445 // confict. We could eventually blend, but for now we'll just abort the | |
446 // previous animation (where 'previous' means: (1) has a prior start time or | |
447 // (2) has an equal start time, but was added to the queue earlier, i.e., | |
448 // has a lower index in active_animations_). | |
449 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
450 if (active_animations_[i]->run_state() == Animation::Starting || | |
451 active_animations_[i]->run_state() == Animation::Running) { | |
452 for (size_t j = i + 1; j < active_animations_.size(); ++j) { | |
453 if ((active_animations_[j]->run_state() == Animation::Starting || | |
454 active_animations_[j]->run_state() == Animation::Running) && | |
455 active_animations_[i]->target_property() == | |
456 active_animations_[j]->target_property()) { | |
457 if (active_animations_[i]->start_time() > | |
458 active_animations_[j]->start_time()) { | |
459 active_animations_[j]->SetRunState(Animation::Aborted, | |
460 monotonic_time); | |
461 } else { | |
462 active_animations_[i]->SetRunState(Animation::Aborted, | |
463 monotonic_time); | |
464 } | |
465 } | |
466 } | |
467 } | |
468 } | |
469 } | |
470 | |
471 void LayerAnimationController::MarkAnimationsForDeletion( | |
472 double monotonic_time, AnimationEventsVector* events) { | |
473 for (size_t i = 0; i < active_animations_.size(); i++) { | |
474 int group_id = active_animations_[i]->group(); | |
475 bool all_anims_with_same_id_are_finished = false; | |
476 // If an animation is finished, and not already marked for deletion, | |
477 // Find out if all other animations in the same group are also finished. | |
478 if (active_animations_[i]->is_finished() && | |
479 active_animations_[i]->run_state() != Animation::WaitingForDeletion) { | |
480 all_anims_with_same_id_are_finished = true; | |
481 for (size_t j = 0; j < active_animations_.size(); ++j) { | |
482 if (group_id == active_animations_[j]->group() && | |
483 !active_animations_[j]->is_finished()) { | |
484 all_anims_with_same_id_are_finished = false; | |
485 break; | |
486 } | |
487 } | |
488 } | |
489 if (all_anims_with_same_id_are_finished) { | |
490 // We now need to remove all animations with the same group id as | |
491 // group_id (and send along animation finished notifications, if | |
492 // necessary). | |
493 for (size_t j = i; j < active_animations_.size(); j++) { | |
494 if (group_id == active_animations_[j]->group()) { | |
495 if (events) { | |
496 events->push_back(AnimationEvent( | |
497 AnimationEvent::Finished, | |
498 id_, | |
499 active_animations_[j]->group(), | |
500 active_animations_[j]->target_property(), | |
501 monotonic_time)); | |
502 } | |
503 active_animations_[j]->SetRunState(Animation::WaitingForDeletion, | |
504 monotonic_time); | |
505 } | |
506 } | |
507 } | |
508 } | |
509 } | |
510 | |
511 static bool IsWaitingForDeletion(Animation* animation) { | |
512 return animation->run_state() == Animation::WaitingForDeletion; | |
513 } | |
514 | |
515 void LayerAnimationController::PurgeAnimationsMarkedForDeletion() { | |
516 ScopedPtrVector<Animation>& animations = active_animations_; | |
517 animations.erase(cc::remove_if(animations, | |
518 animations.begin(), | |
519 animations.end(), | |
520 IsWaitingForDeletion), | |
521 animations.end()); | |
522 } | |
523 | |
524 void LayerAnimationController::ReplaceImplThreadAnimations( | |
525 LayerAnimationController* controller_impl) const { | |
526 controller_impl->active_animations_.clear(); | |
527 for (size_t i = 0; i < active_animations_.size(); ++i) { | |
528 scoped_ptr<Animation> to_add; | |
529 if (active_animations_[i]->needs_synchronized_start_time()) { | |
530 // We haven't received an animation started notification yet, so it | |
531 // is important that we add it in a 'waiting' and not 'running' state. | |
532 Animation::RunState initial_run_state = | |
533 Animation::WaitingForTargetAvailability; | |
534 double start_time = 0; | |
535 to_add = active_animations_[i]->CloneAndInitialize( | |
536 Animation::ControllingInstance, | |
537 initial_run_state, start_time).Pass(); | |
100 } else { | 538 } else { |
101 purgeAnimationsMarkedForDeletion(); | 539 to_add = active_animations_[i]->Clone( |
102 pushNewAnimationsToImplThread(controllerImpl); | 540 Animation::ControllingInstance).Pass(); |
103 | 541 } |
104 // Remove finished impl side animations only after pushing, | 542 |
105 // and only after the animations are deleted on the main thread | 543 controller_impl->AddAnimation(to_add.Pass()); |
106 // this insures we will never push an animation twice. | 544 } |
107 removeAnimationsCompletedOnMainThread(controllerImpl); | 545 } |
108 | 546 |
109 pushPropertiesToImplThread(controllerImpl); | 547 void LayerAnimationController::TickAnimations(double monotonic_time) { |
110 } | 548 for (size_t i = 0; i < active_animations_.size(); ++i) { |
111 controllerImpl->updateActivation(); | 549 if (active_animations_[i]->run_state() == Animation::Starting || |
112 updateActivation(); | 550 active_animations_[i]->run_state() == Animation::Running || |
113 } | 551 active_animations_[i]->run_state() == Animation::Paused) { |
114 | 552 double trimmed = |
115 void LayerAnimationController::animate(double monotonicTime) | 553 active_animations_[i]->TrimTimeToCurrentIteration(monotonic_time); |
116 { | 554 |
117 if (!hasActiveObserver()) | 555 // Animation assumes its initial value until it gets the synchronized |
118 return; | 556 // start time from the impl thread and can start ticking. |
119 | 557 if (active_animations_[i]->needs_synchronized_start_time()) |
120 startAnimationsWaitingForNextTick(monotonicTime); | 558 trimmed = 0; |
121 startAnimationsWaitingForStartTime(monotonicTime); | 559 |
122 startAnimationsWaitingForTargetAvailability(monotonicTime); | 560 // A just-started animation assumes its initial value. |
123 resolveConflicts(monotonicTime); | 561 if (active_animations_[i]->run_state() == Animation::Starting && |
124 tickAnimations(monotonicTime); | 562 !active_animations_[i]->has_set_start_time()) |
125 m_lastTickTime = monotonicTime; | 563 trimmed = 0; |
126 } | 564 |
127 | 565 switch (active_animations_[i]->target_property()) { |
128 void LayerAnimationController::accumulatePropertyUpdates(double monotonicTime, | 566 |
129 AnimationEventsVector* events) | 567 case Animation::Transform: { |
130 { | 568 const TransformAnimationCurve* transform_animation_curve = |
131 if (!events) | 569 active_animations_[i]->curve()->ToTransformAnimationCurve(); |
132 return; | 570 const gfx::Transform transform = |
133 | 571 transform_animation_curve->GetValue(trimmed); |
134 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { | 572 NotifyObserversTransformAnimated(transform); |
135 Animation* animation = m_activeAnimations[i]; | 573 break; |
136 if (!animation->isImplOnly()) | |
137 continue; | |
138 | |
139 if (animation->targetProperty() == Animation::Opacity) { | |
140 AnimationEvent event(AnimationEvent::PropertyUpdate, | |
141 m_id, animation->group(), | |
142 Animation::Opacity, monotonicTime); | |
143 event.opacity = animation->curve()->toFloatAnimationCurve()->getValu e(monotonicTime); | |
144 | |
145 events->push_back(event); | |
146 } | 574 } |
147 else if (animation->targetProperty() == Animation::Transform) { | 575 |
148 AnimationEvent event(AnimationEvent::PropertyUpdate, | 576 case Animation::Opacity: { |
149 m_id, animation->group(), | 577 const FloatAnimationCurve* float_animation_curve = |
150 Animation::Transform, monotonicTime); | 578 active_animations_[i]->curve()->ToFloatAnimationCurve(); |
151 event.transform = animation->curve()->toTransformAnimationCurve()->g etValue(monotonicTime); | 579 const float opacity = float_animation_curve->GetValue(trimmed); |
152 events->push_back(event); | 580 NotifyObserversOpacityAnimated(opacity); |
581 break; | |
153 } | 582 } |
154 } | 583 |
155 } | 584 // Do nothing for sentinel value. |
156 | 585 case Animation::TargetPropertyEnumSize: |
157 void LayerAnimationController::updateState(AnimationEventsVector* events) | 586 NOTREACHED(); |
158 { | 587 } |
159 if (!hasActiveObserver()) | 588 } |
160 return; | 589 } |
161 | 590 } |
162 promoteStartedAnimations(m_lastTickTime, events); | 591 |
163 markFinishedAnimations(m_lastTickTime); | 592 void LayerAnimationController::UpdateActivation(UpdateActivationType type) { |
164 markAnimationsForDeletion(m_lastTickTime, events); | 593 bool force = type == ForceActivation; |
165 startAnimationsWaitingForTargetAvailability(m_lastTickTime); | 594 if (registrar_) { |
166 promoteStartedAnimations(m_lastTickTime, events); | 595 if (!active_animations_.empty() && (!is_active_ || force)) |
167 | 596 registrar_->DidActivateAnimationController(this); |
168 accumulatePropertyUpdates(m_lastTickTime, events); | 597 else if (active_animations_.empty() && (is_active_ || force)) |
169 | 598 registrar_->DidDeactivateAnimationController(this); |
170 updateActivation(); | 599 is_active_ = !active_animations_.empty(); |
171 } | 600 } |
172 | 601 } |
173 void LayerAnimationController::addAnimation(scoped_ptr<Animation> animation) | 602 |
174 { | 603 void LayerAnimationController::NotifyObserversOpacityAnimated(float opacity) { |
175 m_activeAnimations.push_back(animation.Pass()); | 604 FOR_EACH_OBSERVER(LayerAnimationValueObserver, |
176 updateActivation(); | 605 observers_, |
177 } | 606 OnOpacityAnimated(opacity)); |
178 | 607 } |
179 Animation* LayerAnimationController::getAnimation(int groupId, Animation::Target Property targetProperty) const | 608 |
180 { | 609 void LayerAnimationController::NotifyObserversTransformAnimated( |
181 for (size_t i = 0; i < m_activeAnimations.size(); ++i) | 610 const gfx::Transform& transform) { |
182 if (m_activeAnimations[i]->group() == groupId && m_activeAnimations[i]-> targetProperty() == targetProperty) | 611 FOR_EACH_OBSERVER(LayerAnimationValueObserver, |
183 return m_activeAnimations[i]; | 612 observers_, |
184 return 0; | 613 OnTransformAnimated(transform)); |
185 } | 614 } |
186 | 615 |
187 Animation* LayerAnimationController::getAnimation(Animation::TargetProperty targ etProperty) const | 616 bool LayerAnimationController::HasActiveObserver() { |
188 { | 617 if (observers_.might_have_observers()) { |
189 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { | 618 ObserverListBase<LayerAnimationValueObserver>::Iterator it(observers_); |
190 size_t index = m_activeAnimations.size() - i - 1; | 619 LayerAnimationValueObserver* obs; |
191 if (m_activeAnimations[index]->targetProperty() == targetProperty) | 620 while ((obs = it.GetNext()) != NULL) |
192 return m_activeAnimations[index]; | 621 if (obs->IsActive()) |
193 } | 622 return true; |
194 return 0; | 623 } |
195 } | 624 return false; |
196 | |
197 bool LayerAnimationController::hasActiveAnimation() const | |
198 { | |
199 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { | |
200 if (!m_activeAnimations[i]->isFinished()) | |
201 return true; | |
202 } | |
203 return false; | |
204 } | |
205 | |
206 bool LayerAnimationController::isAnimatingProperty(Animation::TargetProperty tar getProperty) const | |
207 { | |
208 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { | |
209 if (m_activeAnimations[i]->runState() != Animation::Finished && m_active Animations[i]->runState() != Animation::Aborted && m_activeAnimations[i]->target Property() == targetProperty) | |
210 return true; | |
211 } | |
212 return false; | |
213 } | |
214 | |
215 void LayerAnimationController::OnAnimationStarted(const AnimationEvent& event) | |
216 { | |
217 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { | |
218 if (m_activeAnimations[i]->group() == event.groupId && m_activeAnimation s[i]->targetProperty() == event.targetProperty && m_activeAnimations[i]->needsSy nchronizedStartTime()) { | |
219 m_activeAnimations[i]->setNeedsSynchronizedStartTime(false); | |
220 m_activeAnimations[i]->setStartTime(event.monotonicTime); | |
221 return; | |
222 } | |
223 } | |
224 } | |
225 | |
226 void LayerAnimationController::setAnimationRegistrar(AnimationRegistrar* registr ar) | |
227 { | |
228 if (m_registrar == registrar) | |
229 return; | |
230 | |
231 if (m_registrar) | |
232 m_registrar->UnregisterAnimationController(this); | |
233 | |
234 m_registrar = registrar; | |
235 if (m_registrar) | |
236 m_registrar->RegisterAnimationController(this); | |
237 | |
238 bool force = true; | |
239 updateActivation(force); | |
240 } | |
241 | |
242 void LayerAnimationController::addObserver(LayerAnimationValueObserver* observer ) | |
243 { | |
244 if (!m_observers.HasObserver(observer)) | |
245 m_observers.AddObserver(observer); | |
246 } | |
247 | |
248 void LayerAnimationController::removeObserver(LayerAnimationValueObserver* obser ver) | |
249 { | |
250 m_observers.RemoveObserver(observer); | |
251 } | |
252 | |
253 void LayerAnimationController::pushNewAnimationsToImplThread(LayerAnimationContr oller* controllerImpl) const | |
254 { | |
255 // Any new animations owned by the main thread's controller are cloned and a dde to the impl thread's controller. | |
256 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { | |
257 // If the animation is already running on the impl thread, there is no n eed to copy it over. | |
258 if (controllerImpl->getAnimation(m_activeAnimations[i]->group(), m_activ eAnimations[i]->targetProperty())) | |
259 continue; | |
260 | |
261 // If the animation is not running on the impl thread, it does not neces sarily mean that it needs | |
262 // to be copied over and started; it may have already finished. In this case, the impl thread animation | |
263 // will have already notified that it has started and the main thread an imation will no longer need | |
264 // a synchronized start time. | |
265 if (!m_activeAnimations[i]->needsSynchronizedStartTime()) | |
266 continue; | |
267 | |
268 // The new animation should be set to run as soon as possible. | |
269 Animation::RunState initialRunState = Animation::WaitingForTargetAvailab ility; | |
270 double startTime = 0; | |
271 scoped_ptr<Animation> toAdd(m_activeAnimations[i]->cloneAndInitialize(An imation::ControllingInstance, initialRunState, startTime)); | |
272 DCHECK(!toAdd->needsSynchronizedStartTime()); | |
273 controllerImpl->addAnimation(toAdd.Pass()); | |
274 } | |
275 } | |
276 | |
277 struct IsCompleted { | |
278 IsCompleted(const LayerAnimationController& mainThreadController) : m_mainTh readController(mainThreadController) { } | |
279 bool operator()(Animation* animation) const { | |
280 if (animation->isImplOnly()) | |
281 return false; | |
282 return !m_mainThreadController.getAnimation(animation->group(), animatio n->targetProperty()); } | |
283 private: | |
284 const LayerAnimationController& m_mainThreadController; | |
285 }; | |
286 | |
287 void LayerAnimationController::removeAnimationsCompletedOnMainThread(LayerAnimat ionController* controllerImpl) const | |
288 { | |
289 // Delete all impl thread animations for which there is no corresponding mai n thread animation. | |
290 // Each iteration, controller->m_activeAnimations.size() is decremented or i is incremented | |
291 // guaranteeing progress towards loop termination. | |
292 ScopedPtrVector<Animation>& animations = controllerImpl->m_activeAnimations; | |
293 animations.erase(cc::remove_if(animations, animations.begin(), animations.en d(), IsCompleted(*this)), animations.end()); | |
294 } | |
295 | |
296 void LayerAnimationController::pushPropertiesToImplThread(LayerAnimationControll er* controllerImpl) const | |
297 { | |
298 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { | |
299 Animation* currentImpl = controllerImpl->getAnimation(m_activeAnimations [i]->group(), m_activeAnimations[i]->targetProperty()); | |
300 if (currentImpl) | |
301 m_activeAnimations[i]->pushPropertiesTo(currentImpl); | |
302 } | |
303 } | |
304 | |
305 void LayerAnimationController::startAnimationsWaitingForNextTick(double monotoni cTime) | |
306 { | |
307 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { | |
308 if (m_activeAnimations[i]->runState() == Animation::WaitingForNextTick) | |
309 m_activeAnimations[i]->setRunState(Animation::Starting, monotonicTim e); | |
310 } | |
311 } | |
312 | |
313 void LayerAnimationController::startAnimationsWaitingForStartTime(double monoton icTime) | |
314 { | |
315 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { | |
316 if (m_activeAnimations[i]->runState() == Animation::WaitingForStartTime && m_activeAnimations[i]->startTime() <= monotonicTime) | |
317 m_activeAnimations[i]->setRunState(Animation::Starting, monotonicTim e); | |
318 } | |
319 } | |
320 | |
321 void LayerAnimationController::startAnimationsWaitingForTargetAvailability(doubl e monotonicTime) | |
322 { | |
323 // First collect running properties. | |
324 TargetProperties blockedProperties; | |
325 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { | |
326 if (m_activeAnimations[i]->runState() == Animation::Starting || m_active Animations[i]->runState() == Animation::Running || m_activeAnimations[i]->runSta te() == Animation::Finished) | |
327 blockedProperties.insert(m_activeAnimations[i]->targetProperty()); | |
328 } | |
329 | |
330 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { | |
331 if (m_activeAnimations[i]->runState() == Animation::WaitingForTargetAvai lability) { | |
332 // Collect all properties for animations with the same group id (the y should all also be in the list of animations). | |
333 TargetProperties enqueuedProperties; | |
334 enqueuedProperties.insert(m_activeAnimations[i]->targetProperty()); | |
335 for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) { | |
336 if (m_activeAnimations[i]->group() == m_activeAnimations[j]->gro up()) | |
337 enqueuedProperties.insert(m_activeAnimations[j]->targetPrope rty()); | |
338 } | |
339 | |
340 // Check to see if intersection of the list of properties affected b y the group and the list of currently | |
341 // blocked properties is null. In any case, the group's target prope rties need to be added to the list | |
342 // of blocked properties. | |
343 bool nullIntersection = true; | |
344 for (TargetProperties::iterator pIter = enqueuedProperties.begin(); pIter != enqueuedProperties.end(); ++pIter) { | |
345 if (!blockedProperties.insert(*pIter).second) | |
346 nullIntersection = false; | |
347 } | |
348 | |
349 // If the intersection is null, then we are free to start the animat ions in the group. | |
350 if (nullIntersection) { | |
351 m_activeAnimations[i]->setRunState(Animation::Starting, monotoni cTime); | |
352 for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) { | |
353 if (m_activeAnimations[i]->group() == m_activeAnimations[j]- >group()) | |
354 m_activeAnimations[j]->setRunState(Animation::Starting, monotonicTime); | |
355 } | |
356 } | |
357 } | |
358 } | |
359 } | |
360 | |
361 void LayerAnimationController::promoteStartedAnimations(double monotonicTime, An imationEventsVector* events) | |
362 { | |
363 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { | |
364 if (m_activeAnimations[i]->runState() == Animation::Starting) { | |
365 m_activeAnimations[i]->setRunState(Animation::Running, monotonicTime ); | |
366 if (!m_activeAnimations[i]->hasSetStartTime()) | |
367 m_activeAnimations[i]->setStartTime(monotonicTime); | |
368 if (events) | |
369 events->push_back(AnimationEvent(AnimationEvent::Started, m_id, m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty(), monoton icTime)); | |
370 } | |
371 } | |
372 } | |
373 | |
374 void LayerAnimationController::markFinishedAnimations(double monotonicTime) | |
375 { | |
376 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { | |
377 if (m_activeAnimations[i]->isFinishedAt(monotonicTime)) | |
378 m_activeAnimations[i]->setRunState(Animation::Finished, monotonicTim e); | |
379 } | |
380 } | |
381 | |
382 void LayerAnimationController::resolveConflicts(double monotonicTime) | |
383 { | |
384 // Find any animations that are animating the same property and resolve the | |
385 // confict. We could eventually blend, but for now we'll just abort the | |
386 // previous animation (where 'previous' means: (1) has a prior start time or | |
387 // (2) has an equal start time, but was added to the queue earlier, i.e., | |
388 // has a lower index in m_activeAnimations). | |
389 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { | |
390 if (m_activeAnimations[i]->runState() == Animation::Starting || m_active Animations[i]->runState() == Animation::Running) { | |
391 for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) { | |
392 if ((m_activeAnimations[j]->runState() == Animation::Starting || | |
393 m_activeAnimations[j]->runState() == Animation::Running) && | |
394 m_activeAnimations[i]->targetProperty() == m_activeAnimation s[j]->targetProperty()) { | |
395 if (m_activeAnimations[i]->startTime() > m_activeAnimations[ j]->startTime()) | |
396 m_activeAnimations[j]->setRunState(Animation::Aborted, m onotonicTime); | |
397 else | |
398 m_activeAnimations[i]->setRunState(Animation::Aborted, m onotonicTime); | |
399 } | |
400 } | |
401 } | |
402 } | |
403 } | |
404 | |
405 void LayerAnimationController::markAnimationsForDeletion(double monotonicTime, A nimationEventsVector* events) | |
406 { | |
407 for (size_t i = 0; i < m_activeAnimations.size(); i++) { | |
408 int groupId = m_activeAnimations[i]->group(); | |
409 bool allAnimsWithSameIdAreFinished = false; | |
410 // If an animation is finished, and not already marked for deletion, | |
411 // Find out if all other animations in the same group are also finished. | |
412 if (m_activeAnimations[i]->isFinished() && m_activeAnimations[i]->runSta te() != Animation::WaitingForDeletion) { | |
413 allAnimsWithSameIdAreFinished = true; | |
414 for (size_t j = 0; j < m_activeAnimations.size(); ++j) { | |
415 if (groupId == m_activeAnimations[j]->group() && !m_activeAnimat ions[j]->isFinished()) { | |
416 allAnimsWithSameIdAreFinished = false; | |
417 break; | |
418 } | |
419 } | |
420 } | |
421 if (allAnimsWithSameIdAreFinished) { | |
422 // We now need to remove all animations with the same group id as gr oupId | |
423 // (and send along animation finished notifications, if necessary). | |
424 for (size_t j = i; j < m_activeAnimations.size(); j++) { | |
425 if (groupId == m_activeAnimations[j]->group()) { | |
426 if (events) | |
427 events->push_back(AnimationEvent(AnimationEvent::Finishe d, m_id, m_activeAnimations[j]->group(), m_activeAnimations[j]->targetProperty() , monotonicTime)); | |
428 m_activeAnimations[j]->setRunState(Animation::WaitingForDele tion, monotonicTime); | |
429 } | |
430 } | |
431 } | |
432 } | |
433 } | |
434 | |
435 static bool isWaitingForDeletion(Animation* animation) { return animation->runSt ate() == Animation::WaitingForDeletion; } | |
436 | |
437 void LayerAnimationController::purgeAnimationsMarkedForDeletion() | |
438 { | |
439 ScopedPtrVector<Animation>& animations = m_activeAnimations; | |
440 animations.erase(cc::remove_if(animations, animations.begin(), animations.en d(), isWaitingForDeletion), animations.end()); | |
441 } | |
442 | |
443 void LayerAnimationController::replaceImplThreadAnimations(LayerAnimationControl ler* controllerImpl) const | |
444 { | |
445 controllerImpl->m_activeAnimations.clear(); | |
446 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { | |
447 scoped_ptr<Animation> toAdd; | |
448 if (m_activeAnimations[i]->needsSynchronizedStartTime()) { | |
449 // We haven't received an animation started notification yet, so it | |
450 // is important that we add it in a 'waiting' and not 'running' stat e. | |
451 Animation::RunState initialRunState = Animation::WaitingForTargetAva ilability; | |
452 double startTime = 0; | |
453 toAdd = m_activeAnimations[i]->cloneAndInitialize(Animation::Control lingInstance, initialRunState, startTime).Pass(); | |
454 } else | |
455 toAdd = m_activeAnimations[i]->clone(Animation::ControllingInstance) .Pass(); | |
456 | |
457 controllerImpl->addAnimation(toAdd.Pass()); | |
458 } | |
459 } | |
460 | |
461 void LayerAnimationController::tickAnimations(double monotonicTime) | |
462 { | |
463 for (size_t i = 0; i < m_activeAnimations.size(); ++i) { | |
464 if (m_activeAnimations[i]->runState() == Animation::Starting || | |
465 m_activeAnimations[i]->runState() == Animation::Running || | |
466 m_activeAnimations[i]->runState() == Animation::Paused) { | |
467 double trimmed = m_activeAnimations[i]->trimTimeToCurrentIteration(m onotonicTime); | |
468 | |
469 // Animation assumes its initial value until it gets the synchronize d start time | |
470 // from the impl thread and can start ticking. | |
471 if (m_activeAnimations[i]->needsSynchronizedStartTime()) | |
472 trimmed = 0; | |
473 | |
474 // A just-started animation assumes its initial value. | |
475 if (m_activeAnimations[i]->runState() == Animation::Starting && !m_a ctiveAnimations[i]->hasSetStartTime()) | |
476 trimmed = 0; | |
477 | |
478 switch (m_activeAnimations[i]->targetProperty()) { | |
479 | |
480 case Animation::Transform: { | |
481 const TransformAnimationCurve* transformAnimationCurve = m_activ eAnimations[i]->curve()->toTransformAnimationCurve(); | |
482 const gfx::Transform transform = transformAnimationCurve->getVal ue(trimmed); | |
483 notifyObserversTransformAnimated(transform); | |
484 break; | |
485 } | |
486 | |
487 case Animation::Opacity: { | |
488 const FloatAnimationCurve* floatAnimationCurve = m_activeAnimati ons[i]->curve()->toFloatAnimationCurve(); | |
489 const float opacity = floatAnimationCurve->getValue(trimmed); | |
490 notifyObserversOpacityAnimated(opacity); | |
491 break; | |
492 } | |
493 | |
494 // Do nothing for sentinel value. | |
495 case Animation::TargetPropertyEnumSize: | |
496 NOTREACHED(); | |
497 } | |
498 } | |
499 } | |
500 } | |
501 | |
502 void LayerAnimationController::updateActivation(bool force) | |
503 { | |
504 if (m_registrar) { | |
505 if (!m_activeAnimations.empty() && (!m_isActive || force)) | |
506 m_registrar->DidActivateAnimationController(this); | |
507 else if (m_activeAnimations.empty() && (m_isActive || force)) | |
508 m_registrar->DidDeactivateAnimationController(this); | |
509 m_isActive = !m_activeAnimations.empty(); | |
510 } | |
511 } | |
512 | |
513 void LayerAnimationController::notifyObserversOpacityAnimated(float opacity) | |
514 { | |
515 FOR_EACH_OBSERVER(LayerAnimationValueObserver, | |
516 m_observers, | |
517 OnOpacityAnimated(opacity)); | |
518 } | |
519 | |
520 void LayerAnimationController::notifyObserversTransformAnimated(const gfx::Trans form& transform) | |
521 { | |
522 FOR_EACH_OBSERVER(LayerAnimationValueObserver, | |
523 m_observers, | |
524 OnTransformAnimated(transform)); | |
525 } | |
526 | |
527 bool LayerAnimationController::hasActiveObserver() | |
528 { | |
529 if (m_observers.might_have_observers()) { | |
530 ObserverListBase<LayerAnimationValueObserver>::Iterator it(m_observers); | |
531 LayerAnimationValueObserver* obs; | |
532 while ((obs = it.GetNext()) != NULL) | |
533 if (obs->IsActive()) | |
534 return true; | |
535 } | |
536 return false; | |
537 } | 625 } |
538 | 626 |
539 } // namespace cc | 627 } // namespace cc |
OLD | NEW |