Commit 0cd6d059 authored by Xiaoqian Dai's avatar Xiaoqian Dai Committed by Commit Bot

capture_mode: implement animation for countdown UI animation.

Please refer to https://carbon.googleplex.com/cros-ux/pages/screen-capture/motion#647b61a3-343c-448d-8c9b-f289d357c615
for the spec (search for "Screen record countdown").

Not covered in this CL:
- stop-recording shelf item animation

Bug: 1126669
Change-Id: I747f7df5f51677ef263921f5f00aa56f540b023b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2463646Reviewed-by: default avatarAhmed Fakhry <afakhry@chromium.org>
Reviewed-by: default avatarRobert Flack <flackr@chromium.org>
Commit-Queue: Xiaoqian Dai <xdai@chromium.org>
Cr-Commit-Position: refs/heads/master@{#818529}
parent 04b305f9
...@@ -11,9 +11,16 @@ ...@@ -11,9 +11,16 @@
#include "ash/style/ash_color_provider.h" #include "ash/style/ash_color_provider.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "base/i18n/number_formatting.h" #include "base/i18n/number_formatting.h"
#include "base/task_runner.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
#include "ui/compositor/callback_layer_animation_observer.h"
#include "ui/compositor/layer_animation_element.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/paint_vector_icon.h" #include "ui/gfx/paint_vector_icon.h"
#include "ui/gfx/text_constants.h" #include "ui/gfx/text_constants.h"
#include "ui/gfx/transform.h"
#include "ui/gfx/transform_util.h"
#include "ui/views/background.h" #include "ui/views/background.h"
#include "ui/views/controls/button/label_button.h" #include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/label.h" #include "ui/views/controls/label.h"
...@@ -23,19 +30,109 @@ namespace ash { ...@@ -23,19 +30,109 @@ namespace ash {
namespace { namespace {
bool g_use_delay_for_testing = false;
// Capture label button rounded corner radius. // Capture label button rounded corner radius.
constexpr int kCaptureLabelRadius = 18; constexpr int kCaptureLabelRadius = 18;
constexpr base::TimeDelta kCountDownDuration = base::TimeDelta::FromSeconds(1); constexpr int kCountDownStartSeconds = 3;
constexpr base::TimeDelta kCountDownDurationForTesting = constexpr int kCountDownEndSeconds = 1;
base::TimeDelta::FromMilliseconds(10);
constexpr base::TimeDelta kCaptureLabelOpacityFadeoutDuration =
base::TimeDelta::FromMilliseconds(33);
// Opacity fade in animation duration and scale up animation duration when the
// timeout label enters 3.
constexpr base::TimeDelta kCountDownEnter3Duration =
base::TimeDelta::FromMilliseconds(267);
// Opacity fade out animation duration and scale down animation duration when
// the timeout label exits 1.
constexpr base::TimeDelta kCountDownExit1Duration =
base::TimeDelta::FromMilliseconds(333);
// For other number enter/exit fade in/out, scale up/down animation duration.
constexpr base::TimeDelta kCountDownEnterExitDuration =
base::TimeDelta::FromMilliseconds(167);
// Delay to enter number 3 to start count down.
constexpr base::TimeDelta kStartCountDownDelay =
base::TimeDelta::FromMilliseconds(233);
// Delay to exit a number after entering animation is completed.
constexpr base::TimeDelta kCountDownExitDelay =
base::TimeDelta::FromMilliseconds(667);
// Different scales for enter/exiting countdown numbers.
constexpr float kEnterLabelScaleDown = 0.8f;
constexpr float kExitLabelScaleUp = 1.2f;
// Scale when exiting the number 1, unlike the other numbers, it will shrink
// down a bit and fade out.
constexpr float kExitLabel1ScaleDown = 0.8f;
void GetOpacityCountDownAnimationSetting(int count_down_number,
bool enter,
base::TimeDelta* duration,
gfx::Tween::Type* tween_type) {
if (count_down_number == kCountDownStartSeconds && enter) {
*duration = kCountDownEnter3Duration;
*tween_type = gfx::Tween::LINEAR_OUT_SLOW_IN;
} else if (count_down_number == kCountDownEndSeconds && !enter) {
*duration = kCountDownExit1Duration;
*tween_type = gfx::Tween::EASE_OUT_3;
} else {
*duration = kCountDownEnterExitDuration;
*tween_type = gfx::Tween::LINEAR;
}
}
void GetTransformCountDownAnimationSetting(int count_down_number,
bool enter,
base::TimeDelta* duration,
gfx::Tween::Type* tween_type) {
if (count_down_number == kCountDownStartSeconds && enter) {
*duration = kCountDownEnter3Duration;
*tween_type = gfx::Tween::LINEAR_OUT_SLOW_IN;
} else if (count_down_number == kCountDownEndSeconds && !enter) {
*duration = kCountDownExit1Duration;
*tween_type = gfx::Tween::EASE_OUT_3;
} else if (enter) {
*duration = kCountDownEnterExitDuration;
*tween_type = gfx::Tween::LINEAR_OUT_SLOW_IN;
} else {
*duration = kCountDownEnterExitDuration;
*tween_type = gfx::Tween::FAST_OUT_LINEAR_IN;
}
}
std::unique_ptr<ui::LayerAnimationElement> CreateOpacityLayerAnimationElement(
float target_opacity,
base::TimeDelta duration,
gfx::Tween::Type tween_type) {
std::unique_ptr<ui::LayerAnimationElement> opacity_element =
ui::LayerAnimationElement::CreateOpacityElement(target_opacity, duration);
opacity_element->set_tween_type(tween_type);
return opacity_element;
}
std::unique_ptr<ui::LayerAnimationElement> CreateTransformLayerAnimationElement(
const gfx::Transform& target_transform,
base::TimeDelta duration,
gfx::Tween::Type tween_type) {
std::unique_ptr<ui::LayerAnimationElement> transform_element =
ui::LayerAnimationElement::CreateTransformElement(target_transform,
duration);
transform_element->set_tween_type(tween_type);
return transform_element;
}
// Returns the transform that can scale |bounds| around its center point.
gfx::Transform GetScaleTransform(const gfx::Rect& bounds, float scale) {
const gfx::Point center_point = bounds.CenterPoint();
return gfx::GetScaleTransform(
gfx::Point(center_point.x() - bounds.x(), center_point.y() - bounds.y()),
scale);
}
} // namespace } // namespace
CaptureLabelView::CaptureLabelView(CaptureModeSession* capture_mode_session) CaptureLabelView::CaptureLabelView(CaptureModeSession* capture_mode_session)
: capture_mode_session_(capture_mode_session) { : timeout_count_down_(kCountDownStartSeconds),
capture_mode_session_(capture_mode_session) {
SetPaintToLayer(); SetPaintToLayer();
layer()->SetFillsBoundsOpaquely(false); layer()->SetFillsBoundsOpaquely(false);
...@@ -74,11 +171,6 @@ CaptureLabelView::CaptureLabelView(CaptureModeSession* capture_mode_session) ...@@ -74,11 +171,6 @@ CaptureLabelView::CaptureLabelView(CaptureModeSession* capture_mode_session)
CaptureLabelView::~CaptureLabelView() = default; CaptureLabelView::~CaptureLabelView() = default;
// static
void CaptureLabelView::SetUseDelayForTesting(bool use_delay) {
g_use_delay_for_testing = true;
}
void CaptureLabelView::UpdateIconAndText() { void CaptureLabelView::UpdateIconAndText() {
CaptureModeController* controller = CaptureModeController::Get(); CaptureModeController* controller = CaptureModeController::Get();
const CaptureModeSource source = controller->source(); const CaptureModeSource source = controller->source();
...@@ -155,15 +247,30 @@ bool CaptureLabelView::ShouldHandleEvent() { ...@@ -155,15 +247,30 @@ bool CaptureLabelView::ShouldHandleEvent() {
void CaptureLabelView::StartCountDown( void CaptureLabelView::StartCountDown(
base::OnceClosure countdown_finished_callback) { base::OnceClosure countdown_finished_callback) {
countdown_finished_callback_ = std::move(countdown_finished_callback); countdown_finished_callback_ = std::move(countdown_finished_callback);
label_button_->SetVisible(false);
label_->SetVisible(true);
CountDown(); // Depending on the visibility of |label_button_| and |label_|, decide which
base::TimeDelta duration = g_use_delay_for_testing // view needs to fade out.
? kCountDownDurationForTesting ui::Layer* animation_layer = nullptr;
: kCountDownDuration; if (label_button_->GetVisible())
count_down_timer_.Start(FROM_HERE, duration, this, animation_layer = label_button_->layer();
&CaptureLabelView::CountDown); if (label_->GetVisible())
animation_layer = label_->layer();
if (animation_layer) {
// Fade out the opacity.
animation_layer->SetOpacity(1.f);
ui::ScopedLayerAnimationSettings settings(animation_layer->GetAnimator());
settings.SetTweenType(gfx::Tween::LINEAR);
settings.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
settings.SetTransitionDuration(kCaptureLabelOpacityFadeoutDuration);
animation_layer->SetOpacity(0.f);
}
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&CaptureLabelView::ScheduleCountDownAnimation,
weak_factory_.GetWeakPtr()),
kStartCountDownDelay);
} }
bool CaptureLabelView::IsInCountDownAnimation() const { bool CaptureLabelView::IsInCountDownAnimation() const {
...@@ -179,7 +286,7 @@ void CaptureLabelView::Layout() { ...@@ -179,7 +286,7 @@ void CaptureLabelView::Layout() {
} }
gfx::Size CaptureLabelView::CalculatePreferredSize() const { gfx::Size CaptureLabelView::CalculatePreferredSize() const {
if (count_down_timer_.IsRunning()) if (countdown_finished_callback_)
return gfx::Size(kCaptureLabelRadius * 2, kCaptureLabelRadius * 2); return gfx::Size(kCaptureLabelRadius * 2, kCaptureLabelRadius * 2);
const bool is_label_button_visible = label_button_->GetVisible(); const bool is_label_button_visible = label_button_->GetVisible();
...@@ -206,13 +313,129 @@ void CaptureLabelView::ButtonPressed(views::Button* sender, ...@@ -206,13 +313,129 @@ void CaptureLabelView::ButtonPressed(views::Button* sender,
CaptureModeController::Get()->PerformCapture(); CaptureModeController::Get()->PerformCapture();
} }
void CaptureLabelView::CountDown() { void CaptureLabelView::ScheduleCountDownAnimation() {
if (timeout_count_down_ == 0) { label_->SetVisible(true);
label_->SetText(base::FormatNumber(timeout_count_down_));
// Initial setup for entering |timeout_count_down_|:
ui::Layer* label_layer = label_->layer();
label_layer->SetOpacity(0.f);
// Use target bounds as when this function is called, we're still in bounds
// change animation, Widget::GetBoundsInScreen() won't return correct value.
gfx::Rect bounds = GetWidget()->GetLayer()->GetTargetBounds();
bounds.ClampToCenteredSize(label_->GetPreferredSize());
label_layer->SetTransform(GetScaleTransform(bounds, kEnterLabelScaleDown));
if (!animation_observer_) {
animation_observer_ = std::make_unique<ui::CallbackLayerAnimationObserver>(
base::BindRepeating(&CaptureLabelView::OnCountDownAnimationCompleted,
base::Unretained(this)));
}
StartLabelLayerAnimationSequences();
StartWidgetLayerAnimationSequences();
animation_observer_->SetActive();
}
bool CaptureLabelView::OnCountDownAnimationCompleted(
const ui::CallbackLayerAnimationObserver& observer) {
if (timeout_count_down_ == kCountDownEndSeconds) {
std::move(countdown_finished_callback_).Run(); // |this| is destroyed here. std::move(countdown_finished_callback_).Run(); // |this| is destroyed here.
return; } else {
timeout_count_down_--;
ScheduleCountDownAnimation();
}
// Return false to prevent the observer from destroying itself.
return false;
}
void CaptureLabelView::StartLabelLayerAnimationSequences() {
// Create |label_opacity_sequence|. Note we don't need the exit animation for
// the last countdown number 1, since when exiting number 1, we'll fade out
// the entire widget, not just the label.
std::unique_ptr<ui::LayerAnimationSequence> label_opacity_sequence =
std::make_unique<ui::LayerAnimationSequence>();
base::TimeDelta enter_duration, exit_duration;
gfx::Tween::Type enter_type, exit_type;
GetOpacityCountDownAnimationSetting(timeout_count_down_, /*enter=*/true,
&enter_duration, &enter_type);
GetOpacityCountDownAnimationSetting(timeout_count_down_, /*enter=*/false,
&exit_duration, &exit_type);
label_opacity_sequence->AddElement(
CreateOpacityLayerAnimationElement(1.f, enter_duration, enter_type));
label_opacity_sequence->AddElement(
ui::LayerAnimationElement::CreatePauseElement(
ui::LayerAnimationElement::OPACITY, kCountDownExitDelay));
const bool is_final_second = timeout_count_down_ == kCountDownEndSeconds;
if (!is_final_second) {
label_opacity_sequence->AddElement(
CreateOpacityLayerAnimationElement(0.f, exit_duration, exit_type));
}
// Construct |label_transfrom_sequence|. Same reason above, we don't need
// the exit animation for the last countdown number 1.
std::unique_ptr<ui::LayerAnimationSequence> label_transfrom_sequence =
std::make_unique<ui::LayerAnimationSequence>();
GetTransformCountDownAnimationSetting(timeout_count_down_, /*enter=*/true,
&enter_duration, &enter_type);
GetTransformCountDownAnimationSetting(timeout_count_down_, /*enter=*/false,
&exit_duration, &exit_type);
label_transfrom_sequence->AddElement(CreateTransformLayerAnimationElement(
gfx::Transform(), enter_duration, enter_type));
label_transfrom_sequence->AddElement(
ui::LayerAnimationElement::CreatePauseElement(
ui::LayerAnimationElement::TRANSFORM, kCountDownExitDelay));
if (!is_final_second) {
gfx::Rect bounds = GetWidget()->GetLayer()->GetTargetBounds();
bounds.ClampToCenteredSize(label_->GetPreferredSize());
label_transfrom_sequence->AddElement(CreateTransformLayerAnimationElement(
GetScaleTransform(bounds, kExitLabelScaleUp), exit_duration,
exit_type));
} }
label_->SetText(base::FormatNumber(timeout_count_down_--)); label_opacity_sequence->AddObserver(animation_observer_.get());
label_transfrom_sequence->AddObserver(animation_observer_.get());
label_->layer()->GetAnimator()->StartTogether(
{label_opacity_sequence.release(), label_transfrom_sequence.release()});
}
void CaptureLabelView::StartWidgetLayerAnimationSequences() {
// Only need animate the widget layer when exiting the last countdown number.
if (timeout_count_down_ != kCountDownEndSeconds)
return;
std::unique_ptr<ui::LayerAnimationSequence> widget_opacity_sequence =
std::make_unique<ui::LayerAnimationSequence>();
base::TimeDelta exit_duration;
gfx::Tween::Type exit_type;
GetOpacityCountDownAnimationSetting(timeout_count_down_, /*enter=*/false,
&exit_duration, &exit_type);
widget_opacity_sequence->AddElement(
ui::LayerAnimationElement::CreatePauseElement(
ui::LayerAnimationElement::OPACITY,
kCountDownEnterExitDuration + kCountDownExitDelay));
widget_opacity_sequence->AddElement(
CreateOpacityLayerAnimationElement(0.f, exit_duration, exit_type));
std::unique_ptr<ui::LayerAnimationSequence> widget_transform_sequence =
std::make_unique<ui::LayerAnimationSequence>();
GetTransformCountDownAnimationSetting(timeout_count_down_, /*enter=*/false,
&exit_duration, &exit_type);
widget_transform_sequence->AddElement(
ui::LayerAnimationElement::CreatePauseElement(
ui::LayerAnimationElement::TRANSFORM,
kCountDownEnterExitDuration + kCountDownExitDelay));
const gfx::Rect bounds = GetWidget()->GetLayer()->GetTargetBounds();
widget_transform_sequence->AddElement(CreateTransformLayerAnimationElement(
GetScaleTransform(bounds, kExitLabel1ScaleDown), exit_duration,
exit_type));
widget_opacity_sequence->AddObserver(animation_observer_.get());
widget_transform_sequence->AddObserver(animation_observer_.get());
GetWidget()->GetLayer()->GetAnimator()->StartTogether(
{widget_opacity_sequence.release(), widget_transform_sequence.release()});
} }
BEGIN_METADATA(CaptureLabelView, views::View) BEGIN_METADATA(CaptureLabelView, views::View)
......
...@@ -5,7 +5,10 @@ ...@@ -5,7 +5,10 @@
#ifndef ASH_CAPTURE_MODE_CAPTURE_LABEL_VIEW_H_ #ifndef ASH_CAPTURE_MODE_CAPTURE_LABEL_VIEW_H_
#define ASH_CAPTURE_MODE_CAPTURE_LABEL_VIEW_H_ #define ASH_CAPTURE_MODE_CAPTURE_LABEL_VIEW_H_
#include <vector>
#include "ash/ash_export.h" #include "ash/ash_export.h"
#include "base/memory/weak_ptr.h"
#include "ui/views/controls/button/button.h" #include "ui/views/controls/button/button.h"
#include "ui/views/view.h" #include "ui/views/view.h"
...@@ -14,6 +17,10 @@ class LabelButton; ...@@ -14,6 +17,10 @@ class LabelButton;
class Label; class Label;
} // namespace views } // namespace views
namespace ui {
class CallbackLayerAnimationObserver;
}
namespace ash { namespace ash {
class CaptureModeSession; class CaptureModeSession;
...@@ -31,10 +38,6 @@ class ASH_EXPORT CaptureLabelView : public views::View, ...@@ -31,10 +38,6 @@ class ASH_EXPORT CaptureLabelView : public views::View,
CaptureLabelView& operator=(const CaptureLabelView&) = delete; CaptureLabelView& operator=(const CaptureLabelView&) = delete;
~CaptureLabelView() override; ~CaptureLabelView() override;
// Function to be called to set a short time interval for countdown in tests
// so that we don't have to wait over 3 seconds to start video recording.
static void SetUseDelayForTesting(bool use_delay);
// Update icon and text according to current capture source and type. // Update icon and text according to current capture source and type.
void UpdateIconAndText(); void UpdateIconAndText();
...@@ -57,9 +60,16 @@ class ASH_EXPORT CaptureLabelView : public views::View, ...@@ -57,9 +60,16 @@ class ASH_EXPORT CaptureLabelView : public views::View,
void ButtonPressed(views::Button* sender, const ui::Event& event) override; void ButtonPressed(views::Button* sender, const ui::Event& event) override;
private: private:
static constexpr int kCountDownSeconds = 3; // Start performing countdown to number |timout_count_down_| animation.
void ScheduleCountDownAnimation();
// Called when each number's countdown animation is completed.
bool OnCountDownAnimationCompleted(
const ui::CallbackLayerAnimationObserver& observer);
void CountDown(); // Starts the layer animation sequences for the countdown label.
void StartLabelLayerAnimationSequences();
// Starts the layer animation sequences for the entire widget if applicable.
void StartWidgetLayerAnimationSequences();
// The label button that displays an icon and a text message. Can be user // The label button that displays an icon and a text message. Can be user
// interactable. When clicking/tapping on the button, start perform image or // interactable. When clicking/tapping on the button, start perform image or
...@@ -69,16 +79,18 @@ class ASH_EXPORT CaptureLabelView : public views::View, ...@@ -69,16 +79,18 @@ class ASH_EXPORT CaptureLabelView : public views::View,
// The label that displays a text message. Not user interactable. // The label that displays a text message. Not user interactable.
views::Label* label_ = nullptr; views::Label* label_ = nullptr;
// Count down timer. int timeout_count_down_;
base::RepeatingTimer count_down_timer_;
int timeout_count_down_ = kCountDownSeconds;
// Callback function to be called after countdown if finished. // Callback function to be called after countdown if finished.
base::OnceClosure countdown_finished_callback_; base::OnceClosure countdown_finished_callback_;
// Observe the countdown animation.
std::unique_ptr<ui::CallbackLayerAnimationObserver> animation_observer_;
// Pointer to the current capture mode session. Not nullptr during this // Pointer to the current capture mode session. Not nullptr during this
// lifecycle. // lifecycle.
CaptureModeSession* capture_mode_session_; CaptureModeSession* capture_mode_session_;
base::WeakPtrFactory<CaptureLabelView> weak_factory_{this};
}; };
} // namespace ash } // namespace ash
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
#include <memory> #include <memory>
#include "ash/capture_mode/capture_label_view.h"
#include "ash/capture_mode/capture_mode_bar_view.h" #include "ash/capture_mode/capture_mode_bar_view.h"
#include "ash/capture_mode/capture_mode_close_button.h" #include "ash/capture_mode/capture_mode_close_button.h"
#include "ash/capture_mode/capture_mode_controller.h" #include "ash/capture_mode/capture_mode_controller.h"
...@@ -26,6 +25,7 @@ ...@@ -26,6 +25,7 @@
#include "ash/wm/window_state.h" #include "ash/wm/window_state.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/test/scoped_feature_list.h" #include "base/test/scoped_feature_list.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/events/keycodes/keyboard_codes_posix.h" #include "ui/events/keycodes/keyboard_codes_posix.h"
#include "ui/events/test/event_generator.h" #include "ui/events/test/event_generator.h"
#include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/insets.h"
...@@ -262,6 +262,10 @@ TEST_F(CaptureModeTest, ChangeTypeAndSourceFromUI) { ...@@ -262,6 +262,10 @@ TEST_F(CaptureModeTest, ChangeTypeAndSourceFromUI) {
} }
TEST_F(CaptureModeTest, VideoRecordingUiBehavior) { TEST_F(CaptureModeTest, VideoRecordingUiBehavior) {
// We need a non-zero duration to avoid infinite loop on countdown.
ui::ScopedAnimationDurationScaleMode animatin_scale(
ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
auto* controller = CaptureModeController::Get(); auto* controller = CaptureModeController::Get();
// Start Capture Mode in a fullscreen video recording mode. // Start Capture Mode in a fullscreen video recording mode.
controller->SetSource(CaptureModeSource::kFullscreen); controller->SetSource(CaptureModeSource::kFullscreen);
...@@ -270,7 +274,6 @@ TEST_F(CaptureModeTest, VideoRecordingUiBehavior) { ...@@ -270,7 +274,6 @@ TEST_F(CaptureModeTest, VideoRecordingUiBehavior) {
EXPECT_TRUE(controller->IsActive()); EXPECT_TRUE(controller->IsActive());
EXPECT_FALSE(controller->is_recording_in_progress()); EXPECT_FALSE(controller->is_recording_in_progress());
EXPECT_FALSE(IsCursorCompositingEnabled()); EXPECT_FALSE(IsCursorCompositingEnabled());
CaptureLabelView::SetUseDelayForTesting(true);
// Hit Enter to begin recording. // Hit Enter to begin recording.
auto* event_generator = GetEventGenerator(); auto* event_generator = GetEventGenerator();
......
...@@ -42,6 +42,9 @@ double Tween::CalculateValue(Tween::Type type, double state) { ...@@ -42,6 +42,9 @@ double Tween::CalculateValue(Tween::Type type, double state) {
case EASE_IN_OUT_2: case EASE_IN_OUT_2:
return gfx::CubicBezier(0.33, 0, 0.67, 1).Solve(state); return gfx::CubicBezier(0.33, 0, 0.67, 1).Solve(state);
case EASE_OUT_3:
return gfx::CubicBezier(0.6, 0, 0, 1).Solve(state);
case LINEAR: case LINEAR:
return state; return state;
......
...@@ -22,18 +22,19 @@ namespace gfx { ...@@ -22,18 +22,19 @@ namespace gfx {
class ANIMATION_EXPORT Tween { class ANIMATION_EXPORT Tween {
public: public:
enum Type { enum Type {
LINEAR, // Linear. LINEAR, // Linear.
EASE_OUT, // Fast in, slow out (default). EASE_OUT, // Fast in, slow out (default).
EASE_OUT_2, // Variant of EASE_OUT that ends slower than EASE_OUT. EASE_OUT_2, // Variant of EASE_OUT that ends slower than EASE_OUT.
EASE_IN, // Slow in, fast out. EASE_OUT_3, // Variant of EASE_OUT that ends slower than EASE_OUT_2.
EASE_IN_2, // Variant of EASE_IN that starts out slower than EASE_IN, // Slow in, fast out.
// EASE_IN. EASE_IN_2, // Variant of EASE_IN that starts out slower than
EASE_IN_OUT, // Slow in and out, fast in the middle. // EASE_IN.
EASE_IN_OUT_2, // Variant of EASE_IN_OUT that starts and ends slower EASE_IN_OUT, // Slow in and out, fast in the middle.
// than EASE_IN_OUT. EASE_IN_OUT_2, // Variant of EASE_IN_OUT that starts and ends slower
SMOOTH_IN_OUT, // Smooth, consistent speeds in and out (sine wave). // than EASE_IN_OUT.
FAST_OUT_SLOW_IN, // Variant of EASE_IN_OUT which should be used in most SMOOTH_IN_OUT, // Smooth, consistent speeds in and out (sine wave).
// cases. FAST_OUT_SLOW_IN, // Variant of EASE_IN_OUT which should be used in most
// cases.
FAST_OUT_SLOW_IN_2, // Variant of FAST_OUT_SLOW_IN that starts out quicker. FAST_OUT_SLOW_IN_2, // Variant of FAST_OUT_SLOW_IN that starts out quicker.
LINEAR_OUT_SLOW_IN, // Variant of EASE_OUT which should be used for LINEAR_OUT_SLOW_IN, // Variant of EASE_OUT which should be used for
// fading in from 0% or motion when entering a scene. // fading in from 0% or motion when entering a scene.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment