| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "ui/compositor/layer_animation_sequence.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 #include <iterator> | |
| 9 | |
| 10 #include "base/debug/trace_event.h" | |
| 11 #include "cc/animation/animation_id_provider.h" | |
| 12 #include "ui/compositor/layer_animation_delegate.h" | |
| 13 #include "ui/compositor/layer_animation_element.h" | |
| 14 #include "ui/compositor/layer_animation_observer.h" | |
| 15 | |
| 16 namespace ui { | |
| 17 | |
| 18 LayerAnimationSequence::LayerAnimationSequence() | |
| 19 : properties_(LayerAnimationElement::UNKNOWN), | |
| 20 is_cyclic_(false), | |
| 21 last_element_(0), | |
| 22 waiting_for_group_start_(false), | |
| 23 animation_group_id_(0), | |
| 24 last_progressed_fraction_(0.0), | |
| 25 weak_ptr_factory_(this) { | |
| 26 } | |
| 27 | |
| 28 LayerAnimationSequence::LayerAnimationSequence(LayerAnimationElement* element) | |
| 29 : properties_(LayerAnimationElement::UNKNOWN), | |
| 30 is_cyclic_(false), | |
| 31 last_element_(0), | |
| 32 waiting_for_group_start_(false), | |
| 33 animation_group_id_(0), | |
| 34 last_progressed_fraction_(0.0), | |
| 35 weak_ptr_factory_(this) { | |
| 36 AddElement(element); | |
| 37 } | |
| 38 | |
| 39 LayerAnimationSequence::~LayerAnimationSequence() { | |
| 40 FOR_EACH_OBSERVER(LayerAnimationObserver, | |
| 41 observers_, | |
| 42 DetachedFromSequence(this, true)); | |
| 43 } | |
| 44 | |
| 45 void LayerAnimationSequence::Start(LayerAnimationDelegate* delegate) { | |
| 46 DCHECK(start_time_ != base::TimeTicks()); | |
| 47 last_progressed_fraction_ = 0.0; | |
| 48 if (elements_.empty()) | |
| 49 return; | |
| 50 | |
| 51 elements_[0]->set_requested_start_time(start_time_); | |
| 52 elements_[0]->Start(delegate, animation_group_id_); | |
| 53 } | |
| 54 | |
| 55 void LayerAnimationSequence::Progress(base::TimeTicks now, | |
| 56 LayerAnimationDelegate* delegate) { | |
| 57 DCHECK(start_time_ != base::TimeTicks()); | |
| 58 bool redraw_required = false; | |
| 59 | |
| 60 if (elements_.empty()) | |
| 61 return; | |
| 62 | |
| 63 if (last_element_ == 0) | |
| 64 last_start_ = start_time_; | |
| 65 | |
| 66 size_t current_index = last_element_ % elements_.size(); | |
| 67 base::TimeDelta element_duration; | |
| 68 while (is_cyclic_ || last_element_ < elements_.size()) { | |
| 69 elements_[current_index]->set_requested_start_time(last_start_); | |
| 70 if (!elements_[current_index]->IsFinished(now, &element_duration)) | |
| 71 break; | |
| 72 | |
| 73 // Let the element we're passing finish. | |
| 74 if (elements_[current_index]->ProgressToEnd(delegate)) | |
| 75 redraw_required = true; | |
| 76 last_start_ += element_duration; | |
| 77 ++last_element_; | |
| 78 last_progressed_fraction_ = | |
| 79 elements_[current_index]->last_progressed_fraction(); | |
| 80 current_index = last_element_ % elements_.size(); | |
| 81 } | |
| 82 | |
| 83 if (is_cyclic_ || last_element_ < elements_.size()) { | |
| 84 if (!elements_[current_index]->Started()) { | |
| 85 animation_group_id_ = cc::AnimationIdProvider::NextGroupId(); | |
| 86 elements_[current_index]->Start(delegate, animation_group_id_); | |
| 87 } | |
| 88 base::WeakPtr<LayerAnimationSequence> alive(weak_ptr_factory_.GetWeakPtr()); | |
| 89 if (elements_[current_index]->Progress(now, delegate)) | |
| 90 redraw_required = true; | |
| 91 if (!alive) | |
| 92 return; | |
| 93 last_progressed_fraction_ = | |
| 94 elements_[current_index]->last_progressed_fraction(); | |
| 95 } | |
| 96 | |
| 97 // Since the delegate may be deleted due to the notifications below, it is | |
| 98 // important that we schedule a draw before sending them. | |
| 99 if (redraw_required) | |
| 100 delegate->ScheduleDrawForAnimation(); | |
| 101 | |
| 102 if (!is_cyclic_ && last_element_ == elements_.size()) { | |
| 103 last_element_ = 0; | |
| 104 waiting_for_group_start_ = false; | |
| 105 animation_group_id_ = 0; | |
| 106 NotifyEnded(); | |
| 107 } | |
| 108 } | |
| 109 | |
| 110 bool LayerAnimationSequence::IsFinished(base::TimeTicks time) { | |
| 111 if (is_cyclic_ || waiting_for_group_start_) | |
| 112 return false; | |
| 113 | |
| 114 if (elements_.empty()) | |
| 115 return true; | |
| 116 | |
| 117 if (last_element_ == 0) | |
| 118 last_start_ = start_time_; | |
| 119 | |
| 120 base::TimeTicks current_start = last_start_; | |
| 121 size_t current_index = last_element_; | |
| 122 base::TimeDelta element_duration; | |
| 123 while (current_index < elements_.size()) { | |
| 124 elements_[current_index]->set_requested_start_time(current_start); | |
| 125 if (!elements_[current_index]->IsFinished(time, &element_duration)) | |
| 126 break; | |
| 127 | |
| 128 current_start += element_duration; | |
| 129 ++current_index; | |
| 130 } | |
| 131 | |
| 132 return (current_index == elements_.size()); | |
| 133 } | |
| 134 | |
| 135 void LayerAnimationSequence::ProgressToEnd(LayerAnimationDelegate* delegate) { | |
| 136 bool redraw_required = false; | |
| 137 | |
| 138 if (elements_.empty()) | |
| 139 return; | |
| 140 | |
| 141 size_t current_index = last_element_ % elements_.size(); | |
| 142 while (current_index < elements_.size()) { | |
| 143 if (elements_[current_index]->ProgressToEnd(delegate)) | |
| 144 redraw_required = true; | |
| 145 last_progressed_fraction_ = | |
| 146 elements_[current_index]->last_progressed_fraction(); | |
| 147 ++current_index; | |
| 148 ++last_element_; | |
| 149 } | |
| 150 | |
| 151 if (redraw_required) | |
| 152 delegate->ScheduleDrawForAnimation(); | |
| 153 | |
| 154 if (!is_cyclic_) { | |
| 155 last_element_ = 0; | |
| 156 waiting_for_group_start_ = false; | |
| 157 animation_group_id_ = 0; | |
| 158 NotifyEnded(); | |
| 159 } | |
| 160 } | |
| 161 | |
| 162 void LayerAnimationSequence::GetTargetValue( | |
| 163 LayerAnimationElement::TargetValue* target) const { | |
| 164 if (is_cyclic_) | |
| 165 return; | |
| 166 | |
| 167 for (size_t i = last_element_; i < elements_.size(); ++i) | |
| 168 elements_[i]->GetTargetValue(target); | |
| 169 } | |
| 170 | |
| 171 void LayerAnimationSequence::Abort(LayerAnimationDelegate* delegate) { | |
| 172 size_t current_index = last_element_ % elements_.size(); | |
| 173 while (current_index < elements_.size()) { | |
| 174 elements_[current_index]->Abort(delegate); | |
| 175 ++current_index; | |
| 176 } | |
| 177 last_element_ = 0; | |
| 178 waiting_for_group_start_ = false; | |
| 179 NotifyAborted(); | |
| 180 } | |
| 181 | |
| 182 void LayerAnimationSequence::AddElement(LayerAnimationElement* element) { | |
| 183 properties_ |= element->properties(); | |
| 184 elements_.push_back(make_linked_ptr(element)); | |
| 185 } | |
| 186 | |
| 187 bool LayerAnimationSequence::HasConflictingProperty( | |
| 188 LayerAnimationElement::AnimatableProperties other) const { | |
| 189 return (properties_ & other) != LayerAnimationElement::UNKNOWN; | |
| 190 } | |
| 191 | |
| 192 bool LayerAnimationSequence::IsFirstElementThreaded() const { | |
| 193 if (!elements_.empty()) | |
| 194 return elements_[0]->IsThreaded(); | |
| 195 | |
| 196 return false; | |
| 197 } | |
| 198 | |
| 199 void LayerAnimationSequence::AddObserver(LayerAnimationObserver* observer) { | |
| 200 if (!observers_.HasObserver(observer)) { | |
| 201 observers_.AddObserver(observer); | |
| 202 observer->AttachedToSequence(this); | |
| 203 } | |
| 204 } | |
| 205 | |
| 206 void LayerAnimationSequence::RemoveObserver(LayerAnimationObserver* observer) { | |
| 207 observers_.RemoveObserver(observer); | |
| 208 observer->DetachedFromSequence(this, true); | |
| 209 } | |
| 210 | |
| 211 void LayerAnimationSequence::OnThreadedAnimationStarted( | |
| 212 const cc::AnimationEvent& event) { | |
| 213 if (elements_.empty() || event.group_id != animation_group_id_) | |
| 214 return; | |
| 215 | |
| 216 size_t current_index = last_element_ % elements_.size(); | |
| 217 LayerAnimationElement::AnimatableProperties element_properties = | |
| 218 elements_[current_index]->properties(); | |
| 219 LayerAnimationElement::AnimatableProperty event_property = | |
| 220 LayerAnimationElement::ToAnimatableProperty(event.target_property); | |
| 221 DCHECK(element_properties & event_property); | |
| 222 elements_[current_index]->set_effective_start_time(event.monotonic_time); | |
| 223 } | |
| 224 | |
| 225 void LayerAnimationSequence::OnScheduled() { | |
| 226 NotifyScheduled(); | |
| 227 } | |
| 228 | |
| 229 void LayerAnimationSequence::OnAnimatorDestroyed() { | |
| 230 if (observers_.might_have_observers()) { | |
| 231 ObserverListBase<LayerAnimationObserver>::Iterator it(observers_); | |
| 232 LayerAnimationObserver* obs; | |
| 233 while ((obs = it.GetNext()) != NULL) { | |
| 234 if (!obs->RequiresNotificationWhenAnimatorDestroyed()) { | |
| 235 // Remove the observer, but do not allow notifications to be sent. | |
| 236 observers_.RemoveObserver(obs); | |
| 237 obs->DetachedFromSequence(this, false); | |
| 238 } | |
| 239 } | |
| 240 } | |
| 241 } | |
| 242 | |
| 243 size_t LayerAnimationSequence::size() const { | |
| 244 return elements_.size(); | |
| 245 } | |
| 246 | |
| 247 LayerAnimationElement* LayerAnimationSequence::FirstElement() const { | |
| 248 if (elements_.empty()) { | |
| 249 return NULL; | |
| 250 } | |
| 251 | |
| 252 return elements_[0].get(); | |
| 253 } | |
| 254 | |
| 255 void LayerAnimationSequence::NotifyScheduled() { | |
| 256 FOR_EACH_OBSERVER(LayerAnimationObserver, | |
| 257 observers_, | |
| 258 OnLayerAnimationScheduled(this)); | |
| 259 } | |
| 260 | |
| 261 void LayerAnimationSequence::NotifyEnded() { | |
| 262 FOR_EACH_OBSERVER(LayerAnimationObserver, | |
| 263 observers_, | |
| 264 OnLayerAnimationEnded(this)); | |
| 265 } | |
| 266 | |
| 267 void LayerAnimationSequence::NotifyAborted() { | |
| 268 FOR_EACH_OBSERVER(LayerAnimationObserver, | |
| 269 observers_, | |
| 270 OnLayerAnimationAborted(this)); | |
| 271 } | |
| 272 | |
| 273 LayerAnimationElement* LayerAnimationSequence::CurrentElement() const { | |
| 274 if (elements_.empty()) | |
| 275 return NULL; | |
| 276 | |
| 277 size_t current_index = last_element_ % elements_.size(); | |
| 278 return elements_[current_index].get(); | |
| 279 } | |
| 280 | |
| 281 } // namespace ui | |
| OLD | NEW |