// 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 #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 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 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 transform); // Takes ownership of the passed transform. InterpolatedTransformAboutPivot( const gfx::Point& pivot, std::unique_ptr 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 transform); std::unique_ptr 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_