blob: b836e24fb4d79f8efecc64123da92292bf9b616f [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_GFX_INTERPOLATED_TRANSFORM_H_
#define UI_GFX_INTERPOLATED_TRANSFORM_H_
#include <memory>
#include "base/macros.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/point3_f.h"
#include "ui/gfx/geometry/transform.h"
#include "ui/gfx/geometry/transform_util.h"
#include "ui/gfx/geometry/vector3d_f.h"
#include "ui/gfx/gfx_export.h"
namespace ui {
///////////////////////////////////////////////////////////////////////////////
// class InterpolatedTransform
//
// Abstract base class for transforms that animate over time. These
// interpolated transforms can be combined to allow for more sophisticated
// animations. For example, you might combine a rotation of 90 degrees between
// times 0 and 1, with a scale from 1 to 0.3 between times 0 and 0.25 and a
// scale from 0.3 to 1 from between times 0.75 and 1.
//
///////////////////////////////////////////////////////////////////////////////
class GFX_EXPORT InterpolatedTransform {
public:
InterpolatedTransform();
// The interpolated transform varies only when t in (start_time, end_time).
// If t <= start_time, Interpolate(t) will return the initial transform, and
// if t >= end_time, Interpolate(t) will return the final transform.
InterpolatedTransform(float start_time, float end_time);
InterpolatedTransform(const InterpolatedTransform&) = delete;
InterpolatedTransform& operator=(const InterpolatedTransform&) = delete;
virtual ~InterpolatedTransform();
// Returns the interpolated transform at time t. Note: not virtual.
gfx::Transform Interpolate(float t) const;
// The Intepolate ultimately returns the product of our transform at time t
// and our child's transform at time t (if we have one).
//
// This function takes ownership of the passed InterpolatedTransform.
void SetChild(std::unique_ptr<InterpolatedTransform> child);
// If the interpolated transform is reversed, Interpolate(t) will return
// Interpolate(1 - t)
void SetReversed(bool reversed) { reversed_ = reversed; }
bool Reversed() const { return reversed_; }
protected:
// Calculates the interpolated transform without considering our child.
virtual gfx::Transform InterpolateButDoNotCompose(float t) const = 0;
// If time in (start_time_, end_time_], this function linearly interpolates
// between start_value and end_value. More precisely it returns
// (1 - t) * start_value + t * end_value where
// t = (start_time_ - time) / (end_time_ - start_time_).
// If time < start_time_ it returns start_value, and if time >= end_time_
// it returns end_value.
float ValueBetween(float time, float start_value, float end_value) const;
float start_time() const { return start_time_; }
float end_time() const { return end_time_; }
private:
const float start_time_;
const float end_time_;
// The child transform. If you consider an interpolated transform as a
// function of t. If, without a child, we are f(t), and our child is
// g(t), then with a child we become f'(t) = f(t) * g(t). Using a child
// transform, we can chain collections of transforms together.
std::unique_ptr<InterpolatedTransform> child_;
bool reversed_;
};
///////////////////////////////////////////////////////////////////////////////
// class InterpolatedRotation
//
// Represents an animated rotation.
//
///////////////////////////////////////////////////////////////////////////////
class GFX_EXPORT InterpolatedRotation : public InterpolatedTransform {
public:
InterpolatedRotation(float start_degrees, float end_degrees);
InterpolatedRotation(float start_degrees,
float end_degrees,
float start_time,
float end_time);
InterpolatedRotation(const InterpolatedRotation&) = delete;
InterpolatedRotation& operator=(const InterpolatedRotation&) = delete;
~InterpolatedRotation() override;
protected:
gfx::Transform InterpolateButDoNotCompose(float t) const override;
private:
const float start_degrees_;
const float end_degrees_;
};
///////////////////////////////////////////////////////////////////////////////
// class InterpolatedAxisAngleRotation
//
// Represents an animated rotation.
//
///////////////////////////////////////////////////////////////////////////////
class GFX_EXPORT InterpolatedAxisAngleRotation : public InterpolatedTransform {
public:
InterpolatedAxisAngleRotation(const gfx::Vector3dF& axis,
float start_degrees,
float end_degrees);
InterpolatedAxisAngleRotation(const gfx::Vector3dF& axis,
float start_degrees,
float end_degrees,
float start_time,
float end_time);
InterpolatedAxisAngleRotation(const InterpolatedAxisAngleRotation&) = delete;
InterpolatedAxisAngleRotation& operator=(
const InterpolatedAxisAngleRotation&) = delete;
~InterpolatedAxisAngleRotation() override;
protected:
gfx::Transform InterpolateButDoNotCompose(float t) const override;
private:
gfx::Vector3dF axis_;
const float start_degrees_;
const float end_degrees_;
};
///////////////////////////////////////////////////////////////////////////////
// class InterpolatedScale
//
// Represents an animated scale.
//
///////////////////////////////////////////////////////////////////////////////
class GFX_EXPORT InterpolatedScale : public InterpolatedTransform {
public:
InterpolatedScale(float start_scale, float end_scale);
InterpolatedScale(float start_scale, float end_scale,
float start_time, float end_time);
InterpolatedScale(const gfx::Point3F& start_scale,
const gfx::Point3F& end_scale);
InterpolatedScale(const gfx::Point3F& start_scale,
const gfx::Point3F& end_scale,
float start_time,
float end_time);
InterpolatedScale(const InterpolatedScale&) = delete;
InterpolatedScale& operator=(const InterpolatedScale&) = delete;
~InterpolatedScale() override;
protected:
gfx::Transform InterpolateButDoNotCompose(float t) const override;
private:
const gfx::Point3F start_scale_;
const gfx::Point3F end_scale_;
};
class GFX_EXPORT InterpolatedTranslation : public InterpolatedTransform {
public:
InterpolatedTranslation(const gfx::PointF& start_pos,
const gfx::PointF& end_pos);
InterpolatedTranslation(const gfx::PointF& start_pos,
const gfx::PointF& end_pos,
float start_time,
float end_time);
InterpolatedTranslation(const gfx::Point3F& start_pos,
const gfx::Point3F& end_pos);
InterpolatedTranslation(const gfx::Point3F& start_pos,
const gfx::Point3F& end_pos,
float start_time,
float end_time);
InterpolatedTranslation(const InterpolatedTranslation&) = delete;
InterpolatedTranslation& operator=(const InterpolatedTranslation&) = delete;
~InterpolatedTranslation() override;
protected:
gfx::Transform InterpolateButDoNotCompose(float t) const override;
private:
const gfx::Point3F start_pos_;
const gfx::Point3F end_pos_;
};
///////////////////////////////////////////////////////////////////////////////
// class InterpolatedConstantTransform
//
// Represents a transform that is constant over time. This is only useful when
// composed with other interpolated transforms.
//
// See InterpolatedTransformAboutPivot for an example of its usage.
//
///////////////////////////////////////////////////////////////////////////////
class GFX_EXPORT InterpolatedConstantTransform : public InterpolatedTransform {
public:
explicit InterpolatedConstantTransform(const gfx::Transform& transform);
InterpolatedConstantTransform(const InterpolatedConstantTransform&) = delete;
InterpolatedConstantTransform& operator=(
const InterpolatedConstantTransform&) = delete;
~InterpolatedConstantTransform() override;
protected:
gfx::Transform InterpolateButDoNotCompose(float t) const override;
private:
const gfx::Transform transform_;
};
///////////////////////////////////////////////////////////////////////////////
// class InterpolatedTransformAboutPivot
//
// Represents an animated transform with a transformed origin. Essentially,
// at each time, t, the interpolated transform is created by composing
// P * T * P^-1 where P is a constant transform to the new origin.
//
///////////////////////////////////////////////////////////////////////////////
class GFX_EXPORT InterpolatedTransformAboutPivot
: public InterpolatedTransform {
public:
// Takes ownership of the passed transform.
InterpolatedTransformAboutPivot(
const gfx::Point& pivot,
std::unique_ptr<InterpolatedTransform> transform);
// Takes ownership of the passed transform.
InterpolatedTransformAboutPivot(
const gfx::Point& pivot,
std::unique_ptr<InterpolatedTransform> transform,
float start_time,
float end_time);
InterpolatedTransformAboutPivot(const InterpolatedTransformAboutPivot&) =
delete;
InterpolatedTransformAboutPivot& operator=(
const InterpolatedTransformAboutPivot&) = delete;
~InterpolatedTransformAboutPivot() override;
protected:
gfx::Transform InterpolateButDoNotCompose(float t) const override;
private:
void Init(const gfx::Point& pivot,
std::unique_ptr<InterpolatedTransform> transform);
std::unique_ptr<InterpolatedTransform> transform_;
};
class GFX_EXPORT InterpolatedMatrixTransform : public InterpolatedTransform {
public:
InterpolatedMatrixTransform(const gfx::Transform& start_transform,
const gfx::Transform& end_transform);
InterpolatedMatrixTransform(const gfx::Transform& start_transform,
const gfx::Transform& end_transform,
float start_time,
float end_time);
~InterpolatedMatrixTransform() override;
protected:
gfx::Transform InterpolateButDoNotCompose(float t) const override;
private:
void Init(const gfx::Transform& start_transform,
const gfx::Transform& end_transform);
gfx::DecomposedTransform start_decomp_;
gfx::DecomposedTransform end_decomp_;
};
} // namespace ui
#endif // UI_GFX_INTERPOLATED_TRANSFORM_H_