Revert 199284 "[Downloads] Clear current_path_ when deleting int..."
[chromium-blink-merge.git] / cc / animation / layer_animation_controller.cc
blob5e20dd5d6ee287e45b4264a34958e931d0478ecd
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.
5 #include "cc/animation/layer_animation_controller.h"
7 #include <algorithm>
9 #include "cc/animation/animation.h"
10 #include "cc/animation/animation_registrar.h"
11 #include "cc/animation/keyframed_animation_curve.h"
12 #include "cc/animation/layer_animation_value_observer.h"
13 #include "cc/base/scoped_ptr_algorithm.h"
14 #include "third_party/WebKit/Source/Platform/chromium/public/WebAnimationDelegate.h"
15 #include "ui/gfx/transform.h"
17 namespace cc {
19 LayerAnimationController::LayerAnimationController(int id)
20 : force_sync_(false),
21 registrar_(0),
22 id_(id),
23 is_active_(false),
24 last_tick_time_(0),
25 layer_animation_delegate_(NULL) {}
27 LayerAnimationController::~LayerAnimationController() {
28 if (registrar_)
29 registrar_->UnregisterAnimationController(this);
32 scoped_refptr<LayerAnimationController> LayerAnimationController::Create(
33 int id) {
34 return make_scoped_refptr(new LayerAnimationController(id));
37 void LayerAnimationController::PauseAnimation(int animation_id,
38 double time_offset) {
39 for (size_t i = 0; i < active_animations_.size(); ++i) {
40 if (active_animations_[i]->id() == animation_id) {
41 active_animations_[i]->SetRunState(
42 Animation::Paused, time_offset + active_animations_[i]->start_time());
47 struct HasAnimationId {
48 explicit HasAnimationId(int id) : id_(id) {}
49 bool operator()(Animation* animation) const {
50 return animation->id() == id_;
53 private:
54 int id_;
57 void LayerAnimationController::RemoveAnimation(int animation_id) {
58 ScopedPtrVector<Animation>& animations = active_animations_;
59 animations.erase(cc::remove_if(&animations,
60 animations.begin(),
61 animations.end(),
62 HasAnimationId(animation_id)),
63 animations.end());
64 UpdateActivation(NormalActivation);
67 struct HasAnimationIdAndProperty {
68 HasAnimationIdAndProperty(int id, Animation::TargetProperty target_property)
69 : id_(id), target_property_(target_property) {}
70 bool operator()(Animation* animation) const {
71 return animation->id() == id_ &&
72 animation->target_property() == target_property_;
75 private:
76 int id_;
77 Animation::TargetProperty target_property_;
80 void LayerAnimationController::RemoveAnimation(
81 int animation_id,
82 Animation::TargetProperty target_property) {
83 ScopedPtrVector<Animation>& animations = active_animations_;
84 animations.erase(cc::remove_if(&animations,
85 animations.begin(),
86 animations.end(),
87 HasAnimationIdAndProperty(animation_id,
88 target_property)),
89 animations.end());
90 UpdateActivation(NormalActivation);
93 // According to render layer backing, these are for testing only.
94 void LayerAnimationController::SuspendAnimations(double monotonic_time) {
95 for (size_t i = 0; i < active_animations_.size(); ++i) {
96 if (!active_animations_[i]->is_finished())
97 active_animations_[i]->SetRunState(Animation::Paused, monotonic_time);
101 // Looking at GraphicsLayerCA, this appears to be the analog to
102 // SuspendAnimations, which is for testing.
103 void LayerAnimationController::ResumeAnimations(double monotonic_time) {
104 for (size_t i = 0; i < active_animations_.size(); ++i) {
105 if (active_animations_[i]->run_state() == Animation::Paused)
106 active_animations_[i]->SetRunState(Animation::Running, monotonic_time);
110 // Ensures that the list of active animations on the main thread and the impl
111 // thread are kept in sync.
112 void LayerAnimationController::PushAnimationUpdatesTo(
113 LayerAnimationController* controller_impl) {
114 DCHECK(this != controller_impl);
115 if (force_sync_) {
116 ReplaceImplThreadAnimations(controller_impl);
117 force_sync_ = false;
118 } else {
119 PurgeAnimationsMarkedForDeletion();
120 PushNewAnimationsToImplThread(controller_impl);
122 // Remove finished impl side animations only after pushing,
123 // and only after the animations are deleted on the main thread
124 // this insures we will never push an animation twice.
125 RemoveAnimationsCompletedOnMainThread(controller_impl);
127 PushPropertiesToImplThread(controller_impl);
129 controller_impl->UpdateActivation(NormalActivation);
130 UpdateActivation(NormalActivation);
133 void LayerAnimationController::TransferAnimationsTo(
134 LayerAnimationController* other_controller) {
135 other_controller->active_animations_.clear();
136 active_animations_.swap(other_controller->active_animations_);
137 UpdateActivation(NormalActivation);
138 set_force_sync();
139 other_controller->UpdateActivation(NormalActivation);
140 other_controller->set_force_sync();
141 other_controller->SetAnimationRegistrar(registrar_);
144 void LayerAnimationController::Animate(double monotonic_time) {
145 if (!HasActiveValueObserver())
146 return;
148 StartAnimationsWaitingForNextTick(monotonic_time);
149 StartAnimationsWaitingForStartTime(monotonic_time);
150 StartAnimationsWaitingForTargetAvailability(monotonic_time);
151 ResolveConflicts(monotonic_time);
152 TickAnimations(monotonic_time);
153 last_tick_time_ = monotonic_time;
156 void LayerAnimationController::AccumulatePropertyUpdates(
157 double monotonic_time,
158 AnimationEventsVector* events) {
159 if (!events)
160 return;
162 for (size_t i = 0; i < active_animations_.size(); ++i) {
163 Animation* animation = active_animations_[i];
164 if (!animation->is_impl_only())
165 continue;
167 if (animation->target_property() == Animation::Opacity) {
168 AnimationEvent event(AnimationEvent::PropertyUpdate,
169 id_,
170 animation->group(),
171 Animation::Opacity,
172 monotonic_time);
173 event.opacity = animation->curve()->ToFloatAnimationCurve()->GetValue(
174 monotonic_time);
175 event.is_impl_only = true;
176 events->push_back(event);
177 } else if (animation->target_property() == Animation::Transform) {
178 AnimationEvent event(AnimationEvent::PropertyUpdate,
179 id_,
180 animation->group(),
181 Animation::Transform,
182 monotonic_time);
183 event.transform =
184 animation->curve()->ToTransformAnimationCurve()->GetValue(
185 monotonic_time);
186 event.is_impl_only = true;
187 events->push_back(event);
192 void LayerAnimationController::UpdateState(bool start_ready_animations,
193 AnimationEventsVector* events) {
194 if (!HasActiveValueObserver())
195 return;
197 if (start_ready_animations)
198 PromoteStartedAnimations(last_tick_time_, events);
200 MarkFinishedAnimations(last_tick_time_);
201 MarkAnimationsForDeletion(last_tick_time_, events);
203 if (start_ready_animations) {
204 StartAnimationsWaitingForTargetAvailability(last_tick_time_);
205 PromoteStartedAnimations(last_tick_time_, events);
208 AccumulatePropertyUpdates(last_tick_time_, events);
210 UpdateActivation(NormalActivation);
213 void LayerAnimationController::AddAnimation(scoped_ptr<Animation> animation) {
214 active_animations_.push_back(animation.Pass());
215 UpdateActivation(NormalActivation);
218 Animation* LayerAnimationController::GetAnimation(
219 int group_id,
220 Animation::TargetProperty target_property) const {
221 for (size_t i = 0; i < active_animations_.size(); ++i)
222 if (active_animations_[i]->group() == group_id &&
223 active_animations_[i]->target_property() == target_property)
224 return active_animations_[i];
225 return 0;
228 Animation* LayerAnimationController::GetAnimation(
229 Animation::TargetProperty target_property) const {
230 for (size_t i = 0; i < active_animations_.size(); ++i) {
231 size_t index = active_animations_.size() - i - 1;
232 if (active_animations_[index]->target_property() == target_property)
233 return active_animations_[index];
235 return 0;
238 bool LayerAnimationController::HasActiveAnimation() const {
239 for (size_t i = 0; i < active_animations_.size(); ++i) {
240 if (!active_animations_[i]->is_finished())
241 return true;
243 return false;
246 bool LayerAnimationController::IsAnimatingProperty(
247 Animation::TargetProperty target_property) const {
248 for (size_t i = 0; i < active_animations_.size(); ++i) {
249 if (!active_animations_[i]->is_finished() &&
250 active_animations_[i]->target_property() == target_property)
251 return true;
253 return false;
256 void LayerAnimationController::SetAnimationRegistrar(
257 AnimationRegistrar* registrar) {
258 if (registrar_ == registrar)
259 return;
261 if (registrar_)
262 registrar_->UnregisterAnimationController(this);
264 registrar_ = registrar;
265 if (registrar_)
266 registrar_->RegisterAnimationController(this);
268 UpdateActivation(ForceActivation);
271 void LayerAnimationController::NotifyAnimationStarted(
272 const AnimationEvent& event,
273 double wall_clock_time) {
274 if (event.is_impl_only) {
275 FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
276 OnAnimationStarted(event));
277 if (layer_animation_delegate_)
278 layer_animation_delegate_->notifyAnimationStarted(wall_clock_time);
280 return;
283 for (size_t i = 0; i < active_animations_.size(); ++i) {
284 if (active_animations_[i]->group() == event.group_id &&
285 active_animations_[i]->target_property() == event.target_property &&
286 active_animations_[i]->needs_synchronized_start_time()) {
287 active_animations_[i]->set_needs_synchronized_start_time(false);
288 active_animations_[i]->set_start_time(event.monotonic_time);
290 FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
291 OnAnimationStarted(event));
292 if (layer_animation_delegate_)
293 layer_animation_delegate_->notifyAnimationStarted(wall_clock_time);
295 return;
300 void LayerAnimationController::NotifyAnimationFinished(
301 const AnimationEvent& event,
302 double wall_clock_time) {
303 if (event.is_impl_only) {
304 if (layer_animation_delegate_)
305 layer_animation_delegate_->notifyAnimationFinished(wall_clock_time);
306 return;
309 for (size_t i = 0; i < active_animations_.size(); ++i) {
310 if (active_animations_[i]->group() == event.group_id &&
311 active_animations_[i]->target_property() == event.target_property) {
312 active_animations_[i]->set_received_finished_event(true);
313 if (layer_animation_delegate_)
314 layer_animation_delegate_->notifyAnimationFinished(wall_clock_time);
316 return;
321 void LayerAnimationController::NotifyAnimationPropertyUpdate(
322 const AnimationEvent& event) {
323 switch (event.target_property) {
324 case Animation::Opacity:
325 NotifyObserversOpacityAnimated(event.opacity);
326 break;
327 case Animation::Transform:
328 NotifyObserversTransformAnimated(event.transform);
329 break;
330 default:
331 NOTREACHED();
335 void LayerAnimationController::AddValueObserver(
336 LayerAnimationValueObserver* observer) {
337 if (!value_observers_.HasObserver(observer))
338 value_observers_.AddObserver(observer);
341 void LayerAnimationController::RemoveValueObserver(
342 LayerAnimationValueObserver* observer) {
343 value_observers_.RemoveObserver(observer);
346 void LayerAnimationController::AddEventObserver(
347 LayerAnimationEventObserver* observer) {
348 if (!event_observers_.HasObserver(observer))
349 event_observers_.AddObserver(observer);
352 void LayerAnimationController::RemoveEventObserver(
353 LayerAnimationEventObserver* observer) {
354 event_observers_.RemoveObserver(observer);
357 void LayerAnimationController::PushNewAnimationsToImplThread(
358 LayerAnimationController* controller_impl) const {
359 // Any new animations owned by the main thread's controller are cloned and
360 // add to the impl thread's controller.
361 for (size_t i = 0; i < active_animations_.size(); ++i) {
362 // If the animation is already running on the impl thread, there is no
363 // need to copy it over.
364 if (controller_impl->GetAnimation(active_animations_[i]->group(),
365 active_animations_[i]->target_property()))
366 continue;
368 // If the animation is not running on the impl thread, it does not
369 // necessarily mean that it needs to be copied over and started; it may
370 // have already finished. In this case, the impl thread animation will
371 // have already notified that it has started and the main thread animation
372 // will no longer need
373 // a synchronized start time.
374 if (!active_animations_[i]->needs_synchronized_start_time())
375 continue;
377 // The new animation should be set to run as soon as possible.
378 Animation::RunState initial_run_state =
379 Animation::WaitingForTargetAvailability;
380 double start_time = 0;
381 scoped_ptr<Animation> to_add(active_animations_[i]->CloneAndInitialize(
382 Animation::ControllingInstance, initial_run_state, start_time));
383 DCHECK(!to_add->needs_synchronized_start_time());
384 controller_impl->AddAnimation(to_add.Pass());
388 struct IsCompleted {
389 explicit IsCompleted(const LayerAnimationController& main_thread_controller)
390 : main_thread_controller_(main_thread_controller) {}
391 bool operator()(Animation* animation) const {
392 if (animation->is_impl_only()) {
393 return (animation->run_state() == Animation::WaitingForDeletion);
394 } else {
395 return !main_thread_controller_.GetAnimation(
396 animation->group(),
397 animation->target_property());
401 private:
402 const LayerAnimationController& main_thread_controller_;
405 void LayerAnimationController::RemoveAnimationsCompletedOnMainThread(
406 LayerAnimationController* controller_impl) const {
407 // Delete all impl thread animations for which there is no corresponding
408 // main thread animation. Each iteration,
409 // controller->active_animations_.size() is decremented or i is incremented
410 // guaranteeing progress towards loop termination.
411 ScopedPtrVector<Animation>& animations =
412 controller_impl->active_animations_;
413 animations.erase(cc::remove_if(&animations,
414 animations.begin(),
415 animations.end(),
416 IsCompleted(*this)),
417 animations.end());
420 void LayerAnimationController::PushPropertiesToImplThread(
421 LayerAnimationController* controller_impl) const {
422 for (size_t i = 0; i < active_animations_.size(); ++i) {
423 Animation* current_impl =
424 controller_impl->GetAnimation(
425 active_animations_[i]->group(),
426 active_animations_[i]->target_property());
427 if (current_impl)
428 active_animations_[i]->PushPropertiesTo(current_impl);
432 void LayerAnimationController::StartAnimationsWaitingForNextTick(
433 double monotonic_time) {
434 for (size_t i = 0; i < active_animations_.size(); ++i) {
435 if (active_animations_[i]->run_state() == Animation::WaitingForNextTick)
436 active_animations_[i]->SetRunState(Animation::Starting, monotonic_time);
440 void LayerAnimationController::StartAnimationsWaitingForStartTime(
441 double monotonic_time) {
442 for (size_t i = 0; i < active_animations_.size(); ++i) {
443 if (active_animations_[i]->run_state() == Animation::WaitingForStartTime &&
444 active_animations_[i]->start_time() <= monotonic_time)
445 active_animations_[i]->SetRunState(Animation::Starting, monotonic_time);
449 void LayerAnimationController::StartAnimationsWaitingForTargetAvailability(
450 double monotonic_time) {
451 // First collect running properties.
452 TargetProperties blocked_properties;
453 for (size_t i = 0; i < active_animations_.size(); ++i) {
454 if (active_animations_[i]->run_state() == Animation::Starting ||
455 active_animations_[i]->run_state() == Animation::Running)
456 blocked_properties.insert(active_animations_[i]->target_property());
459 for (size_t i = 0; i < active_animations_.size(); ++i) {
460 if (active_animations_[i]->run_state() ==
461 Animation::WaitingForTargetAvailability) {
462 // Collect all properties for animations with the same group id (they
463 // should all also be in the list of animations).
464 TargetProperties enqueued_properties;
465 enqueued_properties.insert(active_animations_[i]->target_property());
466 for (size_t j = i + 1; j < active_animations_.size(); ++j) {
467 if (active_animations_[i]->group() == active_animations_[j]->group())
468 enqueued_properties.insert(active_animations_[j]->target_property());
471 // Check to see if intersection of the list of properties affected by
472 // the group and the list of currently blocked properties is null. In
473 // any case, the group's target properties need to be added to the list
474 // of blocked properties.
475 bool null_intersection = true;
476 for (TargetProperties::iterator p_iter = enqueued_properties.begin();
477 p_iter != enqueued_properties.end();
478 ++p_iter) {
479 if (!blocked_properties.insert(*p_iter).second)
480 null_intersection = false;
483 // If the intersection is null, then we are free to start the animations
484 // in the group.
485 if (null_intersection) {
486 active_animations_[i]->SetRunState(
487 Animation::Starting, monotonic_time);
488 for (size_t j = i + 1; j < active_animations_.size(); ++j) {
489 if (active_animations_[i]->group() ==
490 active_animations_[j]->group()) {
491 active_animations_[j]->SetRunState(
492 Animation::Starting, monotonic_time);
500 void LayerAnimationController::PromoteStartedAnimations(
501 double monotonic_time,
502 AnimationEventsVector* events) {
503 for (size_t i = 0; i < active_animations_.size(); ++i) {
504 if (active_animations_[i]->run_state() == Animation::Starting) {
505 active_animations_[i]->SetRunState(Animation::Running, monotonic_time);
506 if (!active_animations_[i]->has_set_start_time())
507 active_animations_[i]->set_start_time(monotonic_time);
508 if (events) {
509 AnimationEvent started_event(
510 AnimationEvent::Started,
511 id_,
512 active_animations_[i]->group(),
513 active_animations_[i]->target_property(),
514 monotonic_time);
515 started_event.is_impl_only = active_animations_[i]->is_impl_only();
516 events->push_back(started_event);
522 void LayerAnimationController::MarkFinishedAnimations(double monotonic_time) {
523 for (size_t i = 0; i < active_animations_.size(); ++i) {
524 if (active_animations_[i]->IsFinishedAt(monotonic_time) &&
525 active_animations_[i]->run_state() != Animation::WaitingForDeletion)
526 active_animations_[i]->SetRunState(Animation::Finished, monotonic_time);
530 void LayerAnimationController::ResolveConflicts(double monotonic_time) {
531 // Find any animations that are animating the same property and resolve the
532 // confict. We could eventually blend, but for now we'll just abort the
533 // previous animation (where 'previous' means: (1) has a prior start time or
534 // (2) has an equal start time, but was added to the queue earlier, i.e.,
535 // has a lower index in active_animations_).
536 for (size_t i = 0; i < active_animations_.size(); ++i) {
537 if (active_animations_[i]->run_state() == Animation::Starting ||
538 active_animations_[i]->run_state() == Animation::Running) {
539 for (size_t j = i + 1; j < active_animations_.size(); ++j) {
540 if ((active_animations_[j]->run_state() == Animation::Starting ||
541 active_animations_[j]->run_state() == Animation::Running) &&
542 active_animations_[i]->target_property() ==
543 active_animations_[j]->target_property()) {
544 if (active_animations_[i]->start_time() >
545 active_animations_[j]->start_time()) {
546 active_animations_[j]->SetRunState(Animation::Aborted,
547 monotonic_time);
548 } else {
549 active_animations_[i]->SetRunState(Animation::Aborted,
550 monotonic_time);
558 void LayerAnimationController::MarkAnimationsForDeletion(
559 double monotonic_time, AnimationEventsVector* events) {
560 // Non-aborted animations are marked for deletion after a corresponding
561 // AnimationEvent::Finished event is sent or received. This means that if
562 // we don't have an events vector, we must ensure that non-aborted animations
563 // have received a finished event before marking them for deletion.
564 for (size_t i = 0; i < active_animations_.size(); i++) {
565 int group_id = active_animations_[i]->group();
566 bool all_anims_with_same_id_are_finished = false;
568 // Since deleting an animation on the main thread leads to its deletion
569 // on the impl thread, we only mark a Finished main thread animation for
570 // deletion once it has received a Finished event from the impl thread.
571 bool animation_i_will_send_or_has_received_finish_event =
572 events || active_animations_[i]->received_finished_event();
573 // If an animation is finished, and not already marked for deletion,
574 // find out if all other animations in the same group are also finished.
575 if (active_animations_[i]->run_state() == Animation::Aborted ||
576 (active_animations_[i]->run_state() == Animation::Finished &&
577 animation_i_will_send_or_has_received_finish_event)) {
578 all_anims_with_same_id_are_finished = true;
579 for (size_t j = 0; j < active_animations_.size(); ++j) {
580 bool animation_j_will_send_or_has_received_finish_event =
581 events || active_animations_[j]->received_finished_event();
582 if (group_id == active_animations_[j]->group() &&
583 (!active_animations_[j]->is_finished() ||
584 (active_animations_[j]->run_state() == Animation::Finished &&
585 !animation_j_will_send_or_has_received_finish_event))) {
586 all_anims_with_same_id_are_finished = false;
587 break;
591 if (all_anims_with_same_id_are_finished) {
592 // We now need to remove all animations with the same group id as
593 // group_id (and send along animation finished notifications, if
594 // necessary).
595 for (size_t j = i; j < active_animations_.size(); j++) {
596 if (group_id == active_animations_[j]->group()) {
597 if (events) {
598 AnimationEvent finished_event(
599 AnimationEvent::Finished,
600 id_,
601 active_animations_[j]->group(),
602 active_animations_[j]->target_property(),
603 monotonic_time);
604 finished_event.is_impl_only = active_animations_[j]->is_impl_only();
605 events->push_back(finished_event);
607 active_animations_[j]->SetRunState(Animation::WaitingForDeletion,
608 monotonic_time);
615 static bool IsWaitingForDeletion(Animation* animation) {
616 return animation->run_state() == Animation::WaitingForDeletion;
619 void LayerAnimationController::PurgeAnimationsMarkedForDeletion() {
620 ScopedPtrVector<Animation>& animations = active_animations_;
621 animations.erase(cc::remove_if(&animations,
622 animations.begin(),
623 animations.end(),
624 IsWaitingForDeletion),
625 animations.end());
628 void LayerAnimationController::ReplaceImplThreadAnimations(
629 LayerAnimationController* controller_impl) const {
630 controller_impl->active_animations_.clear();
631 for (size_t i = 0; i < active_animations_.size(); ++i) {
632 scoped_ptr<Animation> to_add;
633 if (active_animations_[i]->needs_synchronized_start_time()) {
634 // We haven't received an animation started notification yet, so it
635 // is important that we add it in a 'waiting' and not 'running' state.
636 Animation::RunState initial_run_state =
637 Animation::WaitingForTargetAvailability;
638 double start_time = 0;
639 to_add = active_animations_[i]->CloneAndInitialize(
640 Animation::ControllingInstance,
641 initial_run_state, start_time).Pass();
642 } else {
643 to_add = active_animations_[i]->Clone(
644 Animation::ControllingInstance).Pass();
647 controller_impl->AddAnimation(to_add.Pass());
651 void LayerAnimationController::TickAnimations(double monotonic_time) {
652 for (size_t i = 0; i < active_animations_.size(); ++i) {
653 if (active_animations_[i]->run_state() == Animation::Starting ||
654 active_animations_[i]->run_state() == Animation::Running ||
655 active_animations_[i]->run_state() == Animation::Paused) {
656 double trimmed =
657 active_animations_[i]->TrimTimeToCurrentIteration(monotonic_time);
659 // Animation assumes its initial value until it gets the synchronized
660 // start time from the impl thread and can start ticking.
661 if (active_animations_[i]->needs_synchronized_start_time())
662 trimmed = 0;
664 // A just-started animation assumes its initial value.
665 if (active_animations_[i]->run_state() == Animation::Starting &&
666 !active_animations_[i]->has_set_start_time())
667 trimmed = 0;
669 switch (active_animations_[i]->target_property()) {
670 case Animation::Transform: {
671 const TransformAnimationCurve* transform_animation_curve =
672 active_animations_[i]->curve()->ToTransformAnimationCurve();
673 const gfx::Transform transform =
674 transform_animation_curve->GetValue(trimmed);
675 NotifyObserversTransformAnimated(transform);
676 break;
679 case Animation::Opacity: {
680 const FloatAnimationCurve* float_animation_curve =
681 active_animations_[i]->curve()->ToFloatAnimationCurve();
682 const float opacity = float_animation_curve->GetValue(trimmed);
683 NotifyObserversOpacityAnimated(opacity);
684 break;
687 // Do nothing for sentinel value.
688 case Animation::TargetPropertyEnumSize:
689 NOTREACHED();
695 void LayerAnimationController::UpdateActivation(UpdateActivationType type) {
696 bool force = type == ForceActivation;
697 if (registrar_) {
698 if (!active_animations_.empty() && (!is_active_ || force))
699 registrar_->DidActivateAnimationController(this);
700 else if (active_animations_.empty() && (is_active_ || force))
701 registrar_->DidDeactivateAnimationController(this);
702 is_active_ = !active_animations_.empty();
706 void LayerAnimationController::NotifyObserversOpacityAnimated(float opacity) {
707 FOR_EACH_OBSERVER(LayerAnimationValueObserver,
708 value_observers_,
709 OnOpacityAnimated(opacity));
712 void LayerAnimationController::NotifyObserversTransformAnimated(
713 const gfx::Transform& transform) {
714 FOR_EACH_OBSERVER(LayerAnimationValueObserver,
715 value_observers_,
716 OnTransformAnimated(transform));
719 bool LayerAnimationController::HasActiveValueObserver() {
720 if (value_observers_.might_have_observers()) {
721 ObserverListBase<LayerAnimationValueObserver>::Iterator it(
722 value_observers_);
723 LayerAnimationValueObserver* obs;
724 while ((obs = it.GetNext()) != NULL)
725 if (obs->IsActive())
726 return true;
728 return false;
731 } // namespace cc