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