Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/animation/scroll_offset_animation_curve.h" | 5 #include "cc/animation/scroll_offset_animation_curve.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 | 9 |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 34 | 34 |
| 35 namespace { | 35 namespace { |
| 36 | 36 |
| 37 const double kEpsilon = 0.01f; | 37 const double kEpsilon = 0.01f; |
| 38 | 38 |
| 39 static float MaximumDimension(const gfx::Vector2dF& delta) { | 39 static float MaximumDimension(const gfx::Vector2dF& delta) { |
| 40 return std::abs(delta.x()) > std::abs(delta.y()) ? delta.x() : delta.y(); | 40 return std::abs(delta.x()) > std::abs(delta.y()) ? delta.x() : delta.y(); |
| 41 } | 41 } |
| 42 | 42 |
| 43 static base::TimeDelta SegmentDuration(const gfx::Vector2dF& delta, | 43 static base::TimeDelta SegmentDuration(const gfx::Vector2dF& delta, |
| 44 DurationBehavior behavior) { | 44 DurationBehavior behavior, |
| 45 base::TimeDelta delayed_by) { | |
| 45 double duration = kConstantDuration; | 46 double duration = kConstantDuration; |
| 46 switch (behavior) { | 47 switch (behavior) { |
| 47 case DurationBehavior::CONSTANT: | 48 case DurationBehavior::CONSTANT: |
| 48 duration = kConstantDuration; | 49 duration = kConstantDuration; |
| 49 break; | 50 break; |
| 50 case DurationBehavior::DELTA_BASED: | 51 case DurationBehavior::DELTA_BASED: |
| 51 duration = std::sqrt(std::abs(MaximumDimension(delta))); | 52 duration = std::sqrt(std::abs(MaximumDimension(delta))); |
| 52 break; | 53 break; |
| 53 case DurationBehavior::INVERSE_DELTA: | 54 case DurationBehavior::INVERSE_DELTA: |
| 54 duration = std::min( | 55 duration = std::min( |
| 55 std::max(kInverseDeltaOffset + | 56 std::max(kInverseDeltaOffset + |
| 56 std::abs(MaximumDimension(delta)) * kInverseDeltaSlope, | 57 std::abs(MaximumDimension(delta)) * kInverseDeltaSlope, |
| 57 kInverseDeltaMinDuration), | 58 kInverseDeltaMinDuration), |
| 58 kInverseDeltaMaxDuration); | 59 kInverseDeltaMaxDuration); |
| 59 break; | 60 break; |
| 60 default: | 61 default: |
| 61 NOTREACHED(); | 62 NOTREACHED(); |
| 62 } | 63 } |
| 63 return base::TimeDelta::FromMicroseconds(duration / kDurationDivisor * | 64 |
| 64 base::Time::kMicrosecondsPerSecond); | 65 base::TimeDelta td = base::TimeDelta::FromMicroseconds( |
|
tdresser
2016/08/25 15:55:54
td -> time_delta
https://google.github.io/stylegu
ymalik
2016/08/29 14:52:05
Great, thanks!
| |
| 66 duration / kDurationDivisor * base::Time::kMicrosecondsPerSecond); | |
| 67 | |
| 68 td = td - delayed_by; | |
| 69 if (td >= base::TimeDelta()) | |
|
tdresser
2016/08/25 15:55:54
operator> is comparing unsigned integers, so this
tdresser
2016/08/29 14:31:33
Whoops, nevermind, this looks fine.
ymalik
2016/08/29 14:52:05
Acknowledged.
| |
| 70 return td; | |
| 71 return base::TimeDelta(); | |
| 65 } | 72 } |
| 66 | 73 |
| 67 static std::unique_ptr<TimingFunction> EaseOutWithInitialVelocity( | 74 static std::unique_ptr<TimingFunction> EaseOutWithInitialVelocity( |
| 68 double velocity) { | 75 double velocity) { |
| 69 // Clamp velocity to a sane value. | 76 // Clamp velocity to a sane value. |
| 70 velocity = std::min(std::max(velocity, -1000.0), 1000.0); | 77 velocity = std::min(std::max(velocity, -1000.0), 1000.0); |
| 71 | 78 |
| 72 // Based on CubicBezierTimingFunction::EaseType::EASE_IN_OUT preset | 79 // Based on CubicBezierTimingFunction::EaseType::EASE_IN_OUT preset |
| 73 // with first control point scaled. | 80 // with first control point scaled. |
| 74 const double x1 = 0.42; | 81 const double x1 = 0.42; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 91 std::unique_ptr<TimingFunction> timing_function, | 98 std::unique_ptr<TimingFunction> timing_function, |
| 92 DurationBehavior duration_behavior) | 99 DurationBehavior duration_behavior) |
| 93 : target_value_(target_value), | 100 : target_value_(target_value), |
| 94 timing_function_(std::move(timing_function)), | 101 timing_function_(std::move(timing_function)), |
| 95 duration_behavior_(duration_behavior), | 102 duration_behavior_(duration_behavior), |
| 96 has_set_initial_value_(false) {} | 103 has_set_initial_value_(false) {} |
| 97 | 104 |
| 98 ScrollOffsetAnimationCurve::~ScrollOffsetAnimationCurve() {} | 105 ScrollOffsetAnimationCurve::~ScrollOffsetAnimationCurve() {} |
| 99 | 106 |
| 100 void ScrollOffsetAnimationCurve::SetInitialValue( | 107 void ScrollOffsetAnimationCurve::SetInitialValue( |
| 101 const gfx::ScrollOffset& initial_value) { | 108 const gfx::ScrollOffset& initial_value, |
| 109 base::TimeDelta delayed_by) { | |
| 102 initial_value_ = initial_value; | 110 initial_value_ = initial_value; |
| 103 has_set_initial_value_ = true; | 111 has_set_initial_value_ = true; |
| 104 total_animation_duration_ = SegmentDuration( | 112 total_animation_duration_ = SegmentDuration( |
| 105 target_value_.DeltaFrom(initial_value_), duration_behavior_); | 113 target_value_.DeltaFrom(initial_value_), duration_behavior_, delayed_by); |
| 106 } | 114 } |
| 107 | 115 |
| 108 bool ScrollOffsetAnimationCurve::HasSetInitialValue() const { | 116 bool ScrollOffsetAnimationCurve::HasSetInitialValue() const { |
| 109 return has_set_initial_value_; | 117 return has_set_initial_value_; |
| 110 } | 118 } |
| 111 | 119 |
| 112 void ScrollOffsetAnimationCurve::ApplyAdjustment( | 120 void ScrollOffsetAnimationCurve::ApplyAdjustment( |
| 113 const gfx::Vector2dF& adjustment) { | 121 const gfx::Vector2dF& adjustment) { |
| 114 initial_value_ = ScrollOffsetWithDelta(initial_value_, adjustment); | 122 initial_value_ = ScrollOffsetWithDelta(initial_value_, adjustment); |
| 115 target_value_ = ScrollOffsetWithDelta(target_value_, adjustment); | 123 target_value_ = ScrollOffsetWithDelta(target_value_, adjustment); |
| 116 } | 124 } |
| 117 | 125 |
| 118 gfx::ScrollOffset ScrollOffsetAnimationCurve::GetValue( | 126 gfx::ScrollOffset ScrollOffsetAnimationCurve::GetValue( |
| 119 base::TimeDelta t) const { | 127 base::TimeDelta t) const { |
| 120 base::TimeDelta duration = total_animation_duration_ - last_retarget_; | 128 base::TimeDelta duration = total_animation_duration_ - last_retarget_; |
| 121 t -= last_retarget_; | 129 t -= last_retarget_; |
| 122 | 130 |
| 131 if (has_set_initial_value_ && duration == base::TimeDelta()) | |
|
tdresser
2016/08/25 15:55:54
duration_.is_zero()
ymalik
2016/08/29 14:52:05
Done.
| |
| 132 return target_value_; | |
| 133 | |
| 123 if (t <= base::TimeDelta()) | 134 if (t <= base::TimeDelta()) |
| 124 return initial_value_; | 135 return initial_value_; |
| 125 | 136 |
| 126 if (t >= duration) | 137 if (t >= duration) |
| 127 return target_value_; | 138 return target_value_; |
| 128 | 139 |
| 129 double progress = timing_function_->GetValue(TimeUtil::Divide(t, duration)); | 140 double progress = timing_function_->GetValue(TimeUtil::Divide(t, duration)); |
| 130 return gfx::ScrollOffset( | 141 return gfx::ScrollOffset( |
| 131 gfx::Tween::FloatValueBetween( | 142 gfx::Tween::FloatValueBetween( |
| 132 progress, initial_value_.x(), target_value_.x()), | 143 progress, initial_value_.x(), target_value_.x()), |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 187 } | 198 } |
| 188 | 199 |
| 189 void ScrollOffsetAnimationCurve::UpdateTarget( | 200 void ScrollOffsetAnimationCurve::UpdateTarget( |
| 190 double t, | 201 double t, |
| 191 const gfx::ScrollOffset& new_target) { | 202 const gfx::ScrollOffset& new_target) { |
| 192 if (std::abs(MaximumDimension(target_value_.DeltaFrom(new_target))) < | 203 if (std::abs(MaximumDimension(target_value_.DeltaFrom(new_target))) < |
| 193 kEpsilon) { | 204 kEpsilon) { |
| 194 target_value_ = new_target; | 205 target_value_ = new_target; |
| 195 return; | 206 return; |
| 196 } | 207 } |
| 208 | |
| 209 if (t == 0) { | |
|
tdresser
2016/08/25 15:55:54
Should this be combined with the clause above?
ymalik
2016/08/29 14:52:05
I think this is more clear in communicating that t
tdresser
2016/08/29 15:28:28
Acknowledged.
| |
| 210 // Just update the target since the animation hasn't started yet. | |
| 211 target_value_ = new_target; | |
| 212 return; | |
| 213 } | |
| 214 | |
| 197 gfx::ScrollOffset current_position = | 215 gfx::ScrollOffset current_position = |
| 198 GetValue(base::TimeDelta::FromSecondsD(t)); | 216 GetValue(base::TimeDelta::FromSecondsD(t)); |
| 199 gfx::Vector2dF old_delta = target_value_.DeltaFrom(initial_value_); | 217 gfx::Vector2dF old_delta = target_value_.DeltaFrom(initial_value_); |
| 200 gfx::Vector2dF new_delta = new_target.DeltaFrom(current_position); | 218 gfx::Vector2dF new_delta = new_target.DeltaFrom(current_position); |
| 201 | 219 |
| 202 double old_duration = | 220 double old_duration = |
| 203 (total_animation_duration_ - last_retarget_).InSecondsF(); | 221 (total_animation_duration_ - last_retarget_).InSecondsF(); |
| 204 double old_normalized_velocity = timing_function_->Velocity( | 222 double old_normalized_velocity = timing_function_->Velocity( |
| 205 (t - last_retarget_.InSecondsF()) / old_duration); | 223 (t - last_retarget_.InSecondsF()) / old_duration); |
| 206 | 224 |
| 207 // Use the velocity-based duration bound when it is less than the constant | 225 // Use the velocity-based duration bound when it is less than the constant |
| 208 // segment duration. This minimizes the "rubber-band" bouncing effect when | 226 // segment duration. This minimizes the "rubber-band" bouncing effect when |
| 209 // old_normalized_velocity is large and new_delta is small. | 227 // old_normalized_velocity is large and new_delta is small. |
| 210 double new_duration = | 228 double new_duration = |
| 211 std::min(SegmentDuration(new_delta, duration_behavior_).InSecondsF(), | 229 std::min(SegmentDuration(new_delta, duration_behavior_, base::TimeDelta()) |
| 230 .InSecondsF(), | |
| 212 VelocityBasedDurationBound(old_delta, old_normalized_velocity, | 231 VelocityBasedDurationBound(old_delta, old_normalized_velocity, |
| 213 old_duration, new_delta)); | 232 old_duration, new_delta)); |
| 214 | 233 |
| 215 if (new_duration < kEpsilon) { | 234 if (new_duration < kEpsilon) { |
| 216 // We are already at or very close to the new target. Stop animating. | 235 // We are already at or very close to the new target. Stop animating. |
| 217 target_value_ = new_target; | 236 target_value_ = new_target; |
| 218 total_animation_duration_ = base::TimeDelta::FromSecondsD(t); | 237 total_animation_duration_ = base::TimeDelta::FromSecondsD(t); |
| 219 return; | 238 return; |
| 220 } | 239 } |
| 221 | 240 |
| 222 // TimingFunction::Velocity gives the slope of the curve from 0 to 1. | 241 // TimingFunction::Velocity gives the slope of the curve from 0 to 1. |
| 223 // To match the "true" velocity in px/sec we must adjust this slope for | 242 // To match the "true" velocity in px/sec we must adjust this slope for |
| 224 // differences in duration and scroll delta between old and new curves. | 243 // differences in duration and scroll delta between old and new curves. |
| 225 double new_normalized_velocity = | 244 double new_normalized_velocity = |
| 226 old_normalized_velocity * (new_duration / old_duration) * | 245 old_normalized_velocity * (new_duration / old_duration) * |
| 227 (MaximumDimension(old_delta) / MaximumDimension(new_delta)); | 246 (MaximumDimension(old_delta) / MaximumDimension(new_delta)); |
| 228 | 247 |
| 229 initial_value_ = current_position; | 248 initial_value_ = current_position; |
| 230 target_value_ = new_target; | 249 target_value_ = new_target; |
| 231 total_animation_duration_ = base::TimeDelta::FromSecondsD(t + new_duration); | 250 total_animation_duration_ = base::TimeDelta::FromSecondsD(t + new_duration); |
| 232 last_retarget_ = base::TimeDelta::FromSecondsD(t); | 251 last_retarget_ = base::TimeDelta::FromSecondsD(t); |
| 233 timing_function_ = EaseOutWithInitialVelocity(new_normalized_velocity); | 252 timing_function_ = EaseOutWithInitialVelocity(new_normalized_velocity); |
| 234 } | 253 } |
| 235 | 254 |
| 236 } // namespace cc | 255 } // namespace cc |
| OLD | NEW |