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