File indexing completed on 2025-02-02 04:11:03

0001 /*
0002  * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best>
0003  *
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  */
0006 
0007 #pragma once
0008 
0009 #include"math/bezier/solver.hpp"
0010 
0011 #include <QObject>
0012 #include <QPointF>
0013 
0014 
0015 namespace glaxnimate::model {
0016 
0017 /**
0018  * \brief Describes the easing between two keyframes
0019  */
0020 class KeyframeTransition
0021 {
0022     Q_GADGET
0023 
0024 public:
0025     enum Descriptive
0026     {
0027         Hold,
0028         Linear,
0029         Ease,
0030         Fast,
0031         Overshoot,
0032         Custom,
0033     };
0034 
0035     Q_ENUM(Descriptive)
0036 
0037     KeyframeTransition() = default;
0038     KeyframeTransition(const QPointF& before_handle, const QPointF& after_handle, bool hold = false);
0039     explicit KeyframeTransition(Descriptive before, Descriptive after);
0040     explicit KeyframeTransition(Descriptive descriptive);
0041 
0042     const math::bezier::CubicBezierSolver<QPointF>& bezier() const { return bezier_; }
0043     bool hold() const { return hold_; }
0044 
0045     Descriptive before_descriptive() const;
0046     Descriptive after_descriptive() const;
0047     QPointF before() const { return bezier_.points()[1]; }
0048     QPointF after() const  { return bezier_.points()[2]; }
0049 
0050     /**
0051      * \brief Get interpolation factor
0052      * \param ratio in [0, 1]. Determines the time ratio (0 = before, 1 = after)
0053      * \return A value in [0, 1]: the corresponding interpolation factor
0054      *
0055      * If the bezier is defined as B(t) = (x,y). This gives y given x.
0056      */
0057     double lerp_factor(double ratio) const;
0058 
0059     /**
0060      * \brief Get the bezier parameter at the given time
0061      * \param ratio in [0, 1]. Determines the time ratio (0 = before, 1 = after)
0062      * \return A value in [0, 1]: the corresponding bezier parameter
0063      *
0064      * If the bezier is defined as B(t) = (x,y). This gives t given x.
0065      */
0066     double bezier_parameter(double ratio) const;
0067 
0068     void set_hold(bool hold);
0069     void set_before_descriptive(Descriptive d);
0070     void set_after_descriptive(Descriptive d);
0071     void set_handles(const QPointF& before, const QPointF& after);
0072     void set_before(const QPointF& before);
0073     void set_after(const QPointF& after);
0074 
0075     /**
0076      * \brief Split the transition at \p x
0077      * \return The transitions before/after the split
0078      */
0079     std::pair<KeyframeTransition, KeyframeTransition> split(double x) const;
0080 
0081 
0082     std::pair<KeyframeTransition, KeyframeTransition> split_t(double t) const;
0083 
0084 private:
0085     math::bezier::CubicBezierSolver<QPointF> bezier_ { QPointF(0, 0), QPointF(0, 0), QPointF(1, 1), QPointF(1, 1) };
0086     bool hold_ = false;
0087 };
0088 
0089 } // namespace glaxnimate::model