Index: ui/views/animation/ink_drop_animation.cc |
diff --git a/ui/views/animation/ink_drop_animation.cc b/ui/views/animation/ink_drop_animation.cc |
index d33eb43a0589a43d502ea2d666d1a04190f83901..b75672d340b7fff36c5707e771c04f465b93ef22 100644 |
--- a/ui/views/animation/ink_drop_animation.cc |
+++ b/ui/views/animation/ink_drop_animation.cc |
@@ -14,6 +14,10 @@ |
#include "ui/compositor/layer.h" |
#include "ui/compositor/layer_animation_sequence.h" |
#include "ui/compositor/scoped_layer_animation_settings.h" |
+#include "ui/gfx/geometry/point3_f.h" |
+#include "ui/gfx/geometry/point_conversions.h" |
+#include "ui/gfx/geometry/point_f.h" |
+#include "ui/gfx/geometry/vector3d_f.h" |
#include "ui/gfx/transform_util.h" |
#include "ui/views/animation/ink_drop_animation_observer.h" |
#include "ui/views/animation/ink_drop_painted_layer_delegates.h" |
@@ -37,14 +41,32 @@ const float kVisibleOpacity = 0.14f; |
// The opacity of the ink drop when it is not visible. |
const float kHiddenOpacity = 0.0f; |
-// Durations for the different InkDropState animations in milliseconds. |
-const int kHiddenStateAnimationDurationMs = 1; |
-const int kActionPendingStateAnimationDurationMs = 500; |
-const int kQuickActionStateAnimationDurationMs = 250; |
-const int kSlowActionPendingStateAnimationDurationMs = 500; |
-const int kSlowActionStateAnimationDurationMs = 250; |
-const int kActivatedStateAnimationDurationMs = 125; |
-const int kDeactivatedStateAnimationDurationMs = 250; |
+// The time taken to animate the ACTION_PENDING animation. |
+const int kActionPendingAnimationDurationMs = 500; |
+ |
+// The time taken to animate the visible portion of the QUICK_ACTION animation. |
+const int kQuickActionVisibleAnimationDurationMs = 200; |
+ |
+// The time taken to animate the fade out portion of the QUICK_ACTION animation. |
+const int kQuickActionFadeOutAnimationDurationMs = 100; |
+ |
+// The time taken to animate the SLOW_ACTION_PENDING animation. |
+const int kSlowActionPendingAnimationDurationMs = 100; |
+ |
+// The time taken to animate the visible portion of the SLOW_ACTION animation. |
+const int kSlowActionVisibleAnimationDurationMs = 150; |
+ |
+// The time taken to animate the fade out portion of the SLOW_ACTION animation. |
+const int kSlowActionFadeOutAnimationDurationMs = 100; |
+ |
+// The time taken to animate the ACTIVATED animation. |
+const int kActivatedAnimationDurationMs = 125; |
+ |
+// The time taken to animate the visible portion of the DEACTIVATED animation. |
+const int kDeactivatedVisibleAnimationDurationMs = 150; |
+ |
+// The time taken to animate the fade out portion of the SLOW_ACTION animation. |
varkha
2015/10/22 18:33:08
s/SLOW_ACTION/DEACTIVATED?
bruthig
2015/11/04 21:51:02
Done.
|
+const int kDeactivatedFadeOutAnimationDurationMs = 100; |
// A multiplicative factor used to slow down InkDropState animations. |
const int kSlowAnimationDurationFactor = 3; |
@@ -59,33 +81,85 @@ bool UseFastAnimations() { |
return fast; |
} |
-// Returns the InkDropState animation duration for the given |state|. |
-base::TimeDelta GetAnimationDuration(views::InkDropState state) { |
+// All the sub animations that are used to animate each of the InkDropStates. |
+enum InkDropSubAnimations { |
varkha
2015/10/22 18:33:07
Should this enum be above the time constants since
bruthig
2015/11/04 21:51:02
Done.
|
+ // The ACTION_PENDING animation has only one sub animation which animates to a |
+ // |large_size_| circle at visible opacity. |
+ ACTION_PENDING, |
+ |
+ // The QUICK_ACTION animation consists of the two sub animations: |
+ // QUICK_ACTION_VISIBLE, QUICK_ACTION_FADE_OUT. The final frame of the |
+ // animation is a |large_size_| circle at hidden opacity. |
+ |
+ // The portion of the QUICK_ACTION animation that is at visible opacity. |
+ QUICK_ACTION_VISIBLE, |
varkha
2015/10/22 18:33:08
nit: White space after this line for consistency.
bruthig
2015/11/04 21:51:02
Done.
|
+ // The portion of the QUICK_ACTION animation that is at fading out to a hidden |
+ // opacity. |
+ QUICK_ACTION_FADE_OUT, |
+ |
+ // The SLOW_ACTION_PENDING animation has only one sub animation which animates |
+ // to a |small_size_| rounded rectangle at visible opacity. |
+ SLOW_ACTION_PENDING, |
+ |
+ // The SLOW_ACTION animation consists of the two sub animations: |
+ // SLOW_ACTION_VISIBLE, SLOW_ACTION_FADE_OUT. The final frame of the |
+ // animation is a |large_size_| rounded rectangle at hidden opacity. |
+ |
+ // The portion of the SLOW_ACTION animation that is at visible opacity. |
+ SLOW_ACTION_VISIBLE, |
+ |
+ // The portion of the SLOW_ACTION animation that is fading out to a hidden |
+ // opacity. |
+ SLOW_ACTION_FADE_OUT, |
+ |
+ // The ACTIVATED animation has only one sub animation which animates to a |
+ // |small_size_| rounded rectangle at visible opacity. |
+ ACTIVATED, |
+ |
+ // The DEACTIVATED animation consists of the two sub animations: |
+ // DEACTIVATED_VISIBLE, DEACTIVATED_FADE_OUT. The final frame of the |
+ // animation is a |large_size_| rounded rectangle at hidden opacity. |
+ |
+ // The portion of the DEACTIVATED animation that is at visible opacity. |
+ DEACTIVATED_VISIBLE, |
+ |
+ // The portion of the DEACTIVATED animation that is fading out to a hidden |
+ // opacity. |
+ DEACTIVATED_FADE_OUT, |
+}; |
+ |
+// // Returns the InkDropState animation duration for the given |state|. |
varkha
2015/10/22 18:33:08
nit: extra //.
bruthig
2015/11/04 21:51:02
Done.
|
+base::TimeDelta GetAnimationDuration(InkDropSubAnimations state) { |
int duration = 0; |
switch (state) { |
- case views::InkDropState::HIDDEN: |
- duration = kHiddenStateAnimationDurationMs; |
+ case ACTION_PENDING: |
+ duration = kActionPendingAnimationDurationMs; |
+ break; |
+ case QUICK_ACTION_VISIBLE: |
+ duration = kQuickActionVisibleAnimationDurationMs; |
+ break; |
+ case QUICK_ACTION_FADE_OUT: |
+ duration = kQuickActionFadeOutAnimationDurationMs; |
break; |
- case views::InkDropState::ACTION_PENDING: |
- duration = kActionPendingStateAnimationDurationMs; |
+ case SLOW_ACTION_PENDING: |
+ duration = kSlowActionPendingAnimationDurationMs; |
break; |
- case views::InkDropState::QUICK_ACTION: |
- duration = kQuickActionStateAnimationDurationMs; |
+ case SLOW_ACTION_VISIBLE: |
+ duration = kSlowActionVisibleAnimationDurationMs; |
break; |
- case views::InkDropState::SLOW_ACTION_PENDING: |
- duration = kSlowActionPendingStateAnimationDurationMs; |
+ case SLOW_ACTION_FADE_OUT: |
+ duration = kSlowActionFadeOutAnimationDurationMs; |
break; |
- case views::InkDropState::SLOW_ACTION: |
- duration = kSlowActionStateAnimationDurationMs; |
+ case ACTIVATED: |
+ duration = kActivatedAnimationDurationMs; |
break; |
- case views::InkDropState::ACTIVATED: |
- duration = kActivatedStateAnimationDurationMs; |
+ case DEACTIVATED_VISIBLE: |
+ duration = kDeactivatedVisibleAnimationDurationMs; |
break; |
- case views::InkDropState::DEACTIVATED: |
- duration = kDeactivatedStateAnimationDurationMs; |
+ case DEACTIVATED_FADE_OUT: |
+ duration = kDeactivatedFadeOutAnimationDurationMs; |
break; |
} |
- |
return base::TimeDelta::FromMilliseconds( |
(UseFastAnimations() ? 1 : kSlowAnimationDurationFactor) * duration); |
} |
@@ -180,6 +254,7 @@ void InkDropAnimation::SetCenterPoint(const gfx::Point& center_point) { |
void InkDropAnimation::AnimateToStateInternal( |
InkDropState ink_drop_state, |
ui::LayerAnimationObserver* animation_observer) { |
+ const InkDropState previous_ink_drop_state_ = ink_drop_state_; |
ink_drop_state_ = ink_drop_state; |
if (ink_drop_state_ == InkDropState::HIDDEN) { |
@@ -189,7 +264,6 @@ void InkDropAnimation::AnimateToStateInternal( |
// running animation prior to receiving an InkDropAnimationStarted() event |
// for the HIDDEN 'animation'. |
AbortAllAnimations(); |
- root_layer_->SetVisible(false); |
SetStateToHidden(); |
return; |
} |
@@ -202,45 +276,99 @@ void InkDropAnimation::AnimateToStateInternal( |
// This case is handled above in a short circuit return. |
break; |
case InkDropState::ACTION_PENDING: |
varkha
2015/10/22 18:33:08
General comment in this method. The code seems lik
bruthig
2015/11/04 21:51:02
I'm not so sure how to reduce the amount of code h
|
+ AnimateToOpacity(kVisibleOpacity, GetAnimationDuration(ACTION_PENDING), |
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
+ animation_observer); |
CalculateCircleTransforms(large_size_, &transforms); |
- AnimateToTransforms(transforms, kVisibleOpacity, |
- GetAnimationDuration(InkDropState::ACTION_PENDING), |
+ AnimateToTransforms(transforms, GetAnimationDuration(ACTION_PENDING), |
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
animation_observer); |
break; |
- case InkDropState::QUICK_ACTION: |
+ case InkDropState::QUICK_ACTION: { |
+ float visible_duration_ratio = 1.0f; |
+ |
+ // If the previous state is ACTION_PENDING we don't want the QUICK_ACTION |
+ // to take the full duration because the expanding ripple noticably |
+ // changes speed. |
+ if (previous_ink_drop_state_ == InkDropState::ACTION_PENDING) { |
+ GetCurrentTransforms(&transforms); |
+ visible_duration_ratio = |
+ visible_duration_ratio - |
+ CalculateDistanceEstimateToQuickAction(transforms); |
+ } |
+ |
+ const base::TimeDelta visible_duration = |
+ GetAnimationDuration(QUICK_ACTION_VISIBLE) * visible_duration_ratio; |
+ |
+ ui::LayerAnimator::PreemptionStrategy fade_out_preemption_strategy = |
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET; |
+ |
+ base::TimeDelta total_effective_duration = |
+ GetAnimationDuration(QUICK_ACTION_FADE_OUT); |
+ |
+ if (visible_duration.InMilliseconds() > 0) { |
+ fade_out_preemption_strategy = ui::LayerAnimator::ENQUEUE_NEW_ANIMATION; |
+ total_effective_duration += visible_duration; |
+ AnimateToOpacity(kVisibleOpacity, visible_duration, |
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
+ animation_observer); |
+ } |
+ |
+ AnimateToOpacity(kHiddenOpacity, |
+ GetAnimationDuration(QUICK_ACTION_FADE_OUT), |
+ fade_out_preemption_strategy, animation_observer); |
CalculateCircleTransforms(large_size_, &transforms); |
- AnimateToTransforms(transforms, kHiddenOpacity, |
- GetAnimationDuration(InkDropState::QUICK_ACTION), |
+ AnimateToTransforms(transforms, total_effective_duration, |
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
animation_observer); |
break; |
+ } |
case InkDropState::SLOW_ACTION_PENDING: |
+ AnimateToOpacity(kVisibleOpacity, |
+ GetAnimationDuration(SLOW_ACTION_PENDING), |
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
+ animation_observer); |
CalculateRectTransforms(small_size_, small_corner_radius_, &transforms); |
- AnimateToTransforms( |
- transforms, kVisibleOpacity, |
- GetAnimationDuration(InkDropState::SLOW_ACTION_PENDING), |
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
- animation_observer); |
+ AnimateToTransforms(transforms, GetAnimationDuration(SLOW_ACTION_PENDING), |
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
+ animation_observer); |
break; |
case InkDropState::SLOW_ACTION: |
+ AnimateToOpacity(kVisibleOpacity, |
+ GetAnimationDuration(SLOW_ACTION_VISIBLE), |
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
+ animation_observer); |
+ AnimateToOpacity( |
+ kHiddenOpacity, GetAnimationDuration(SLOW_ACTION_FADE_OUT), |
+ ui::LayerAnimator::ENQUEUE_NEW_ANIMATION, animation_observer); |
CalculateRectTransforms(large_size_, large_corner_radius_, &transforms); |
- AnimateToTransforms(transforms, kHiddenOpacity, |
- GetAnimationDuration(InkDropState::SLOW_ACTION), |
+ AnimateToTransforms(transforms, |
+ GetAnimationDuration(SLOW_ACTION_VISIBLE) + |
+ GetAnimationDuration(SLOW_ACTION_FADE_OUT), |
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
animation_observer); |
break; |
case InkDropState::ACTIVATED: |
+ AnimateToOpacity(kVisibleOpacity, GetAnimationDuration(ACTIVATED), |
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
+ animation_observer); |
CalculateRectTransforms(small_size_, small_corner_radius_, &transforms); |
- AnimateToTransforms(transforms, kVisibleOpacity, |
- GetAnimationDuration(InkDropState::ACTIVATED), |
+ AnimateToTransforms(transforms, GetAnimationDuration(ACTIVATED), |
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
animation_observer); |
break; |
case InkDropState::DEACTIVATED: |
+ AnimateToOpacity(kVisibleOpacity, |
+ GetAnimationDuration(DEACTIVATED_VISIBLE), |
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
+ animation_observer); |
+ AnimateToOpacity( |
+ kHiddenOpacity, GetAnimationDuration(DEACTIVATED_FADE_OUT), |
+ ui::LayerAnimator::ENQUEUE_NEW_ANIMATION, animation_observer); |
CalculateRectTransforms(large_size_, large_corner_radius_, &transforms); |
- AnimateToTransforms(transforms, kHiddenOpacity, |
- GetAnimationDuration(InkDropState::DEACTIVATED), |
+ AnimateToTransforms(transforms, |
+ GetAnimationDuration(DEACTIVATED_VISIBLE) + |
+ GetAnimationDuration(DEACTIVATED_FADE_OUT), |
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, |
animation_observer); |
break; |
@@ -249,23 +377,9 @@ void InkDropAnimation::AnimateToStateInternal( |
void InkDropAnimation::AnimateToTransforms( |
const InkDropTransforms transforms, |
- float opacity, |
base::TimeDelta duration, |
ui::LayerAnimator::PreemptionStrategy preemption_strategy, |
ui::LayerAnimationObserver* animation_observer) { |
- ui::LayerAnimator* root_animator = root_layer_->GetAnimator(); |
- ui::ScopedLayerAnimationSettings root_animation(root_animator); |
- root_animation.SetPreemptionStrategy(preemption_strategy); |
- ui::LayerAnimationElement* root_element = |
- ui::LayerAnimationElement::CreateOpacityElement(opacity, duration); |
- ui::LayerAnimationSequence* root_sequence = |
- new ui::LayerAnimationSequence(root_element); |
- |
- if (animation_observer) |
- root_sequence->AddObserver(animation_observer); |
- |
- root_animator->StartAnimation(root_sequence); |
- |
for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i) { |
ui::LayerAnimator* animator = painted_layers_[i]->GetAnimator(); |
ui::ScopedLayerAnimationSettings animation(animator); |
@@ -289,6 +403,7 @@ void InkDropAnimation::SetStateToHidden() { |
CalculateCircleTransforms(gfx::Size(1, 1), &transforms); |
SetTransforms(transforms); |
SetOpacity(kHiddenOpacity); |
+ root_layer_->SetVisible(false); |
varkha
2015/10/22 18:33:07
Just a question: did it matter that this is now th
bruthig
2015/11/04 21:51:02
Nope
|
} |
void InkDropAnimation::SetTransforms(const InkDropTransforms transforms) { |
@@ -300,6 +415,25 @@ void InkDropAnimation::SetOpacity(float opacity) { |
root_layer_->SetOpacity(opacity); |
} |
+void InkDropAnimation::AnimateToOpacity( |
+ float opacity, |
+ base::TimeDelta duration, |
+ ui::LayerAnimator::PreemptionStrategy preemption_strategy, |
+ ui::LayerAnimationObserver* animation_observer) { |
+ ui::LayerAnimator* animator = root_layer_->GetAnimator(); |
+ ui::ScopedLayerAnimationSettings animation_settings(animator); |
+ animation_settings.SetPreemptionStrategy(preemption_strategy); |
+ ui::LayerAnimationElement* animation_element = |
+ ui::LayerAnimationElement::CreateOpacityElement(opacity, duration); |
+ ui::LayerAnimationSequence* animation_sequence = |
+ new ui::LayerAnimationSequence(animation_element); |
+ |
+ if (animation_observer) |
+ animation_sequence->AddObserver(animation_observer); |
+ |
+ animator->StartAnimation(animation_sequence); |
+} |
+ |
void InkDropAnimation::CalculateCircleTransforms( |
const gfx::Size& size, |
InkDropTransforms* transforms_out) const { |
@@ -328,19 +462,19 @@ void InkDropAnimation::CalculateRectTransforms( |
const float circle_target_y_offset = size.height() / 2.0f - corner_radius; |
(*transforms_out)[TOP_LEFT_CIRCLE] = CalculateCircleTransform( |
- painted_layers_[TOP_LEFT_CIRCLE]->bounds().CenterPoint(), circle_scale, |
+ ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale, |
-circle_target_x_offset, -circle_target_y_offset); |
(*transforms_out)[TOP_RIGHT_CIRCLE] = CalculateCircleTransform( |
- painted_layers_[TOP_RIGHT_CIRCLE]->bounds().CenterPoint(), circle_scale, |
+ ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale, |
circle_target_x_offset, -circle_target_y_offset); |
(*transforms_out)[BOTTOM_RIGHT_CIRCLE] = CalculateCircleTransform( |
- painted_layers_[BOTTOM_RIGHT_CIRCLE]->bounds().CenterPoint(), |
- circle_scale, circle_target_x_offset, circle_target_y_offset); |
+ ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale, |
+ circle_target_x_offset, circle_target_y_offset); |
(*transforms_out)[BOTTOM_LEFT_CIRCLE] = CalculateCircleTransform( |
- painted_layers_[BOTTOM_LEFT_CIRCLE]->bounds().CenterPoint(), circle_scale, |
+ ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale, |
-circle_target_x_offset, circle_target_y_offset); |
const float rect_delegate_width = |
@@ -349,22 +483,22 @@ void InkDropAnimation::CalculateRectTransforms( |
static_cast<float>(rect_layer_delegate_->size().height()); |
(*transforms_out)[HORIZONTAL_RECT] = CalculateRectTransform( |
- painted_layers_[HORIZONTAL_RECT]->bounds().CenterPoint(), |
+ ToRoundedPoint(rect_layer_delegate_->GetCenterPoint()), |
std::max(kMinimumRectScale, size.width() / rect_delegate_width), |
std::max(kMinimumRectScale, |
(size.height() - 2.0f * corner_radius) / rect_delegate_height)); |
(*transforms_out)[VERTICAL_RECT] = CalculateRectTransform( |
- painted_layers_[VERTICAL_RECT]->bounds().CenterPoint(), |
+ ToRoundedPoint(rect_layer_delegate_->GetCenterPoint()), |
std::max(kMinimumRectScale, |
(size.width() - 2.0f * corner_radius) / rect_delegate_width), |
std::max(kMinimumRectScale, size.height() / rect_delegate_height)); |
} |
-void InkDropAnimation::GetCurrentTansforms( |
+void InkDropAnimation::GetCurrentTransforms( |
InkDropTransforms* transforms_out) const { |
for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i) |
- (*transforms_out)[i] = painted_layers_[i]->GetTargetTransform(); |
+ (*transforms_out)[i] = painted_layers_[i]->transform(); |
} |
void InkDropAnimation::AddPaintLayer(PaintedShape painted_shape) { |
@@ -404,6 +538,37 @@ void InkDropAnimation::AbortAllAnimations() { |
painted_layers_[i]->GetAnimator()->AbortAllAnimations(); |
} |
+float InkDropAnimation::CalculateDistanceEstimateToQuickAction( |
+ const InkDropTransforms& transforms) const { |
+ gfx::Point3F circle_center_point = |
+ gfx::Point3F(circle_layer_delegate_->GetCenterPoint()); |
+ |
+ gfx::Point3F circle_top_point( |
+ circle_center_point.x(), |
+ circle_center_point.y() - circle_layer_delegate_->radius(), 0); |
+ |
+ transforms[TOP_LEFT_CIRCLE].TransformPoint(&circle_center_point); |
+ transforms[TOP_LEFT_CIRCLE].TransformPoint(&circle_top_point); |
+ |
+ // Calculate the ratio of how far the transformed circle's center point is |
+ // from the destination compared to how far it can be. |
+ const float center_point_distance_estimate = |
+ 1.0f - |
+ gfx::Vector3dF(circle_center_point.x(), circle_center_point.y(), 0) |
+ .Length() / |
varkha
2015/10/22 18:33:08
nit: indentation looks a bit odd here.
bruthig
2015/11/04 21:51:02
This is the result of 'git cl format'.
|
+ (gfx::Vector3dF(static_cast<float>(large_size_.width()), |
+ static_cast<float>(large_size_.height()), 0) |
+ .Length() / |
+ 2.0f); |
+ |
+ // Calculate the ratio of how far the transformed circle's top most point is |
varkha
2015/10/22 18:33:08
nit: topmost.
bruthig
2015/11/04 21:51:02
Done.
|
+ // from the destination compared to how far it can be. |
+ const float top_point_distance_estimate = fabs( |
varkha
2015/10/22 18:33:08
When is the argument of fabs ever negative?
bruthig
2015/11/04 21:51:02
circle_top_point.y() is expected to be negative si
|
+ circle_top_point.y() / static_cast<float>(large_size_.height()) / 2.0f); |
varkha
2015/10/22 18:33:07
Are the brackets correct here? Is it not y/(h/2) s
bruthig
2015/11/04 21:51:02
Done.
|
+ |
+ return std::min(center_point_distance_estimate, top_point_distance_estimate); |
+} |
+ |
void InkDropAnimation::AnimationStartedCallback( |
InkDropState ink_drop_state, |
const ui::CallbackLayerAnimationObserver& observer) { |