diff --git a/src/layouts/QskStackBoxAnimator.cpp b/src/layouts/QskStackBoxAnimator.cpp index ba1fa84c..7e881171 100644 --- a/src/layouts/QskStackBoxAnimator.cpp +++ b/src/layouts/QskStackBoxAnimator.cpp @@ -67,14 +67,9 @@ namespace Q_OBJECT public: - RotationTransform( Qt::Axis axis, qreal dx1, qreal dy1, qreal dx2, - qreal dy2, qreal radians, QQuickItem* item ) + RotationTransform( Qt::Axis axis, qreal radians, QQuickItem* item ) : QQuickTransform( item ) , m_axis( axis ) - , m_dx1( dx1 ) - , m_dy1( dy1 ) - , m_dx2( dx2 ) - , m_dy2( dy2 ) , m_radians( radians ) { prependToItem( item ); @@ -89,34 +84,17 @@ namespace } } - void setPreTransform( qreal dx1, qreal dy1 ) - { - if( !qskFuzzyCompare( dx1, m_dx1 ) || !qskFuzzyCompare( dy1, m_dy1 ) ) - { - m_dx1 = dx1; - m_dy1 = dy1; - update(); - } - } - - void setPostTransform( qreal dx2, qreal dy2 ) - { - if( !qskFuzzyCompare( dx2, m_dx2 ) || !qskFuzzyCompare( dy2, m_dy2 ) ) - { - m_dx2 = dx2; - m_dy2 = dy2; - update(); - } - } - - void applyTo( QMatrix4x4* matrix ) const override + void applyTo( QMatrix4x4* matrix) const override { if ( const auto item = qobject_cast< QQuickItem* >( parent() ) ) { + const auto dx = 0.5 * item->width(); + const auto dy = 0.5 * item->height(); + QTransform transform; - transform.translate( m_dx1, m_dy1 ); + transform.translate( dx, dy ); transform.rotateRadians( m_radians, m_axis ); - transform.translate( m_dx2, m_dy2 ); + transform.translate( -dx, -dy ); *matrix *= transform; } @@ -124,19 +102,46 @@ namespace private: const Qt::Axis m_axis; - qreal m_dx1; - qreal m_dy1; - qreal m_dx2; - qreal m_dy2; qreal m_radians; }; - static RotationTransform* qskFindRotationTransform( const QQuickItem* item ) + class QuickTransform final : public QQuickTransform + { + Q_OBJECT + + public: + QuickTransform( QQuickItem* item ) + : QQuickTransform( item ) + { + prependToItem( item ); + } + + void setTransform( const QTransform& transform ) + { + if ( transform != m_transform ) + { + m_transform = transform; + update(); + } + } + + void applyTo( QMatrix4x4* matrix ) const override + { + if ( const auto item = qobject_cast< QQuickItem* >( parent() ) ) + *matrix *= m_transform; + } + + private: + QTransform m_transform; + }; + + template< typename Transform > + Transform* qskFindTransform( const QQuickItem* item ) { const auto& transforms = QQuickItemPrivate::get( item )->transforms; for ( const auto& t : transforms ) { - if ( auto transform = qobject_cast< RotationTransform* >( t ) ) + if ( auto transform = qobject_cast< Transform* >( t ) ) return transform; } @@ -402,19 +407,12 @@ void QskStackBoxAnimator2::setup() { const auto axis = ( m_orientation == Qt::Horizontal ) ? Qt::YAxis : Qt::XAxis; + if ( auto item = itemAt( 0 ) ) - { - const auto dx = 0.5 * item->width(); - const auto dy = 0.5 * item->height(); - ( void ) new RotationTransform( axis, dx, dy, -dx, -dy, 0.0, item ); - } + ( void ) new RotationTransform( axis, 0.0, item ); if ( auto item = itemAt( 1 ) ) - { - const auto dx = 0.5 * item->width(); - const auto dy = 0.5 * item->height(); - ( void ) new RotationTransform( axis, dx, dy, -dx, -dy, M_PI_2, item ); - } + ( void ) new RotationTransform( axis, M_PI_2, item ); } void QskStackBoxAnimator2::advanceIndex( qreal value ) @@ -428,7 +426,7 @@ void QskStackBoxAnimator2::advanceIndex( qreal value ) if ( !m_inverted ) radians = 2 * M_PI - radians; - auto rotation = qskFindRotationTransform( item ); + auto rotation = qskFindTransform< RotationTransform >( item ); rotation->setRadians( radians ); item->setVisible( true ); @@ -452,7 +450,7 @@ void QskStackBoxAnimator2::advanceIndex( qreal value ) if ( !m_inverted ) radians = 2 * M_PI - radians; - auto rotation = qskFindRotationTransform( item ); + auto rotation = qskFindTransform< RotationTransform >( item ); rotation->setRadians( radians ); item->setVisible( true ); @@ -466,7 +464,7 @@ void QskStackBoxAnimator2::done() { if ( auto item = itemAt( i ) ) { - delete qskFindRotationTransform( item ); + delete qskFindTransform< RotationTransform >( item ); item->setVisible( i == 1 ); } } @@ -552,18 +550,15 @@ bool QskStackBoxAnimator4::isInverted() const void QskStackBoxAnimator4::setup() { - const auto axis = ( m_orientation == Qt::Horizontal ) - ? Qt::YAxis : Qt::XAxis; - if ( auto item = itemAt( 0 ) ) { - ( void ) new RotationTransform( axis, 0.0, 0.0, 0.0, 0.0, 0.0, item ); + ( void ) new QuickTransform( item ); item->setVisible( true ); } if ( auto item = itemAt( 1 ) ) { - ( void ) new RotationTransform( axis, 0.0, 0.0, 0.0, 0.0, -M_PI_2, item ); + ( void ) new QuickTransform( item ); item->setVisible( true ); } } @@ -572,107 +567,76 @@ void QskStackBoxAnimator4::advanceIndex( qreal value ) { if ( auto item = itemAt( 0 ) ) { - auto rotation = qskFindRotationTransform( item ); + const auto transform = transformation( item, false, value ); - qreal dx1, dy1, radians, dx2, dy2; - - if( orientation() == Qt::Horizontal ) - { - const auto w = item->parentItem() ? item->parentItem()->width() : item->width(); - - if( isInverted() ) - { - dx1 = ( w - item->x() ) * value; - radians = -M_PI_2 * value; - dx2 = 0.0; - } - else - { - dx1 = w * ( 1 - value ) - item->x() * value; - radians = M_PI_2 * value; - dx2 = -w; - } - - dy1 = 0.5 * item->height(); - dy2 = -dy1; - } - else - { - const auto h = item->parentItem() ? item->parentItem()->height() : item->height(); - - dx1 = 0.5 * item->width(); - dx2 = -dx1; - - if( isInverted() ) - { - dy1 = ( h - item->y() ) * value; - radians = -M_PI_2 * value; - dy2 = 0.0; - } - else - { - dy1 = h * ( 1 - value ) - item->y() * value; - radians = M_PI_2 * value; - dy2 = -h; - } - } - - rotation->setPreTransform( dx1, dy1 ); - rotation->setRadians( radians ); - rotation->setPostTransform( dx2, dy2 ); + auto rotation = qskFindTransform< QuickTransform >( item ); + rotation->setTransform( transform ); } if ( auto item = itemAt( 1 ) ) { - auto rotation = qskFindRotationTransform( item ); + const auto transform = transformation( item, true, value ); - qreal dx1, dy1, radians, dx2, dy2; + auto rotation = qskFindTransform< QuickTransform >( item ); + rotation->setTransform( transform ); + } +} - if( orientation() == Qt::Horizontal ) +QTransform QskStackBoxAnimator4::transformation( + const QQuickItem* item, bool increasing, qreal value ) const +{ + const qreal v = increasing ? value : 1.0 - value; + + qreal radians = M_PI_2 * ( 1.0 - v ); + if ( increasing != isInverted() ) + radians = -radians; + + QTransform transform; + + if( orientation() == Qt::Horizontal ) + { + qreal dx1, dx2; + + if ( increasing == isInverted() ) { - const auto w = item->parentItem() ? item->parentItem()->width() : item->width(); - - if( isInverted() ) - { - dx1 = w * value - item->x() * ( 1 - value ); - radians = -M_PI_2 * ( value - 1 ); - dx2 = -w; - } - else - { - dx1 = ( item->width() + item->x() ) * ( 1 - value ); - radians = M_PI_2 * ( value - 1 ); - dx2 = 0.0; - } - - dy1 = 0.5 * item->height(); - dy2 = -dy1; + dx1 = item->width() * v - item->x() * ( 1.0 - v ); + dx2 = -item->width(); } else { - const auto h = item->parentItem() ? item->parentItem()->height() : item->height(); - - dx1 = 0.5 * item->width(); - dx2 = -dx1; - - if( isInverted() ) - { - dy1 = h * value - item->y() * ( 1 - value ); - radians = -M_PI_2 * ( value - 1 ); - dy2 = -h; - } - else - { - dy1 = ( item->height() + item->y() ) * ( 1 - value ); - radians = M_PI_2 * ( value - 1 ); - dy2 = 0.0; - } + dx1 = ( item->x() + item->width() ) * ( 1.0 - v ); + dx2 = 0.0; } - rotation->setPreTransform( dx1, dy1 ); - rotation->setRadians( radians ); - rotation->setPostTransform( dx2, dy2 ); + const qreal h2 = 0.5 * item->height(); + + transform.translate( dx1, h2 ); + transform.rotateRadians( radians, Qt::YAxis ); + transform.translate( dx2, -h2 ); } + else + { + qreal dy1, dy2; + + if ( increasing == isInverted() ) + { + dy1 = item->height() * v - item->y() * ( 1.0 - v ); + dy2 = -item->height(); + } + else + { + dy1 = ( item->y() + item->height() ) * ( 1.0 - v ); + dy2 = 0.0; + } + + const qreal w2 = 0.5 * item->width(); + + transform.translate( w2, dy1 ); + transform.rotateRadians( radians, Qt::XAxis ); + transform.translate( -w2, dy2 ); + } + + return transform; } void QskStackBoxAnimator4::done() @@ -681,7 +645,7 @@ void QskStackBoxAnimator4::done() { if ( auto item = itemAt( i ) ) { - delete qskFindRotationTransform( item ); + delete qskFindTransform< QuickTransform >( item ); item->setVisible( i == 1 ); } } diff --git a/src/layouts/QskStackBoxAnimator.h b/src/layouts/QskStackBoxAnimator.h index ce3b0131..880f2abc 100644 --- a/src/layouts/QskStackBoxAnimator.h +++ b/src/layouts/QskStackBoxAnimator.h @@ -13,6 +13,7 @@ class QskStackBox; class QQuickItem; +class QTransform; class QSK_EXPORT QskStackBoxAnimator : public QObject, public QskAnimator { @@ -137,6 +138,8 @@ class QSK_EXPORT QskStackBoxAnimator4 : public QskStackBoxAnimator void done() override; private: + QTransform transformation( const QQuickItem*, bool increasing, qreal value ) const; + Qt::Orientation m_orientation : 2; bool m_inverted : 1; };