| /**************************************************************************** |
| ** |
| ** Copyright (C) 2020 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of Qt Quick 3D. |
| ** |
| ** $QT_BEGIN_LICENSE:GPL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 3 or (at your option) any later version |
| ** approved by the KDE Free Qt Foundation. The licenses are as published by |
| ** the Free Software Foundation and appearing in the file LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qquick3dquaternionanimation_p.h" |
| #include <QtQuick/private/qquickanimation_p_p.h> |
| |
| QT_BEGIN_NAMESPACE |
| |
| /*! |
| \qmltype QuaternionAnimation |
| \inherits PropertyAnimation |
| \inqmlmodule QtQuick3D |
| \since 5.15 |
| |
| \brief A PropertyAnimation for quaternions. |
| |
| A specialized \l{PropertyAnimation} that defines an animation between two |
| \l{QQuaternion}{quaternions}. |
| |
| By default spherical linear interpolation is used. This can be changed to |
| the faster but less accurate normalized linear interpolation by setting the |
| \a type property. |
| |
| Instead of specifying quaternions directly in the \a from and \a to |
| properties, it is also possible to provide euler angles in degrees in the |
| \a fromXRotation, \a toXRotation, \a fromYRotation, \a toYRotation, |
| \a fromZRotation, \a toZRotation properties. |
| |
| \note Avoid mixing the quaternion and euler angle-based properties. The |
| from and to values are expected to be fully specified either via a |
| quaternion or the three euler angles. |
| |
| \sa {Animation and Transitions in Qt Quick} QQuaternion QQuaternion::slerp() QQuaternion::nlerp() |
| */ |
| |
| class QQuick3DQuaternionAnimationPrivate : public QQuickPropertyAnimationPrivate |
| { |
| Q_DECLARE_PUBLIC(QQuick3DQuaternionAnimation) |
| |
| public: |
| QQuick3DQuaternionAnimationPrivate() : |
| type(QQuick3DQuaternionAnimation::Slerp) |
| { } |
| |
| QQuick3DQuaternionAnimation::Type type; |
| QVector3D anglesFrom; |
| QVector3D anglesTo; |
| }; |
| |
| |
| QVariant q_quaternionInterpolator(const QQuaternion &from, const QQuaternion &to, qreal progress) |
| { |
| return QVariant::fromValue(QQuaternion::slerp(from, to, progress)); |
| } |
| |
| QVariant q_quaternionNlerpInterpolator(const QQuaternion &from, const QQuaternion &to, qreal progress) |
| { |
| return QVariant::fromValue(QQuaternion::nlerp(from, to, progress)); |
| } |
| |
| QQuick3DQuaternionAnimation::QQuick3DQuaternionAnimation(QObject *parent) |
| : QQuickPropertyAnimation(*(new QQuick3DQuaternionAnimationPrivate), parent) |
| { |
| Q_D(QQuick3DQuaternionAnimation); |
| d->interpolatorType = qMetaTypeId<QQuaternion>(); |
| d->defaultToInterpolatorType = true; |
| d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType); |
| } |
| |
| /*! |
| \qmlproperty quaternion QtQuick3D::QuaternionAnimation::from |
| |
| This property holds the starting value for the animation. |
| |
| */ |
| |
| QQuaternion QQuick3DQuaternionAnimation::from() const |
| { |
| Q_D(const QQuick3DQuaternionAnimation); |
| return d->from.value<QQuaternion>(); |
| } |
| |
| void QQuick3DQuaternionAnimation::setFrom(const QQuaternion &f) |
| { |
| QQuickPropertyAnimation::setFrom(QVariant::fromValue(f)); |
| } |
| |
| /*! |
| \qmlproperty quaternion QtQuick3D::QuaternionAnimation::to |
| |
| This property holds the ending value for the animation. |
| |
| */ |
| |
| QQuaternion QQuick3DQuaternionAnimation::to() const |
| { |
| Q_D(const QQuick3DQuaternionAnimation); |
| return d->to.value<QQuaternion>(); |
| } |
| |
| void QQuick3DQuaternionAnimation::setTo(const QQuaternion &t) |
| { |
| QQuickPropertyAnimation::setTo(QVariant::fromValue(t)); |
| } |
| |
| /*! |
| \qmlproperty enumeration QtQuick3D::QuaternionAnimation::type |
| |
| This property defines the interpolation mode. |
| |
| \value QuaternionAnimation.Slerp Spherical linear interpolation. |
| \value QuaternionAnimation.Nlerp Normalized linear interpolation. |
| |
| */ |
| |
| QQuick3DQuaternionAnimation::Type QQuick3DQuaternionAnimation::type() const |
| { |
| Q_D(const QQuick3DQuaternionAnimation); |
| return d->type; |
| } |
| |
| void QQuick3DQuaternionAnimation::setType(Type type) |
| { |
| Q_D(QQuick3DQuaternionAnimation); |
| if (d->type == type) |
| return; |
| |
| d->type = type; |
| switch (type) { |
| case Nlerp: |
| d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(reinterpret_cast<void(*)()>(&q_quaternionNlerpInterpolator)); |
| break; |
| case Slerp: |
| default: |
| d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType); |
| break; |
| } |
| |
| emit typeChanged(type); |
| } |
| |
| /*! |
| \qmlproperty float QtQuick3D::QuaternionAnimation::fromXRotation |
| |
| This property holds the starting value of the animation for the X axis as |
| an euler angle in degrees. |
| |
| */ |
| |
| float QQuick3DQuaternionAnimation::fromXRotation() const |
| { |
| Q_D(const QQuick3DQuaternionAnimation); |
| return d->anglesFrom.x(); |
| } |
| |
| void QQuick3DQuaternionAnimation::setFromXRotation(float f) |
| { |
| Q_D(QQuick3DQuaternionAnimation); |
| if (d->anglesFrom.x() == f) |
| return; |
| d->anglesFrom.setX(f); |
| setFrom(QQuaternion::fromEulerAngles(d->anglesFrom)); |
| emit fromXRotationChanged(f); |
| } |
| |
| /*! |
| \qmlproperty float QtQuick3D::QuaternionAnimation::fromYRotation |
| |
| This property holds the starting value of the animation for the Y axis as |
| an euler angle in degrees. |
| |
| */ |
| |
| float QQuick3DQuaternionAnimation::fromYRotation() const |
| { |
| Q_D(const QQuick3DQuaternionAnimation); |
| return d->anglesFrom.y(); |
| } |
| |
| void QQuick3DQuaternionAnimation::setFromYRotation(float f) |
| { |
| Q_D(QQuick3DQuaternionAnimation); |
| if (d->anglesFrom.y() == f) |
| return; |
| d->anglesFrom.setY(f); |
| setFrom(QQuaternion::fromEulerAngles(d->anglesFrom)); |
| emit fromYRotationChanged(f); |
| } |
| |
| /*! |
| \qmlproperty float QtQuick3D::QuaternionAnimation::fromZRotation |
| |
| This property holds the starting value of the animation for the Z axis as |
| an euler angle in degrees. |
| |
| */ |
| |
| float QQuick3DQuaternionAnimation::fromZRotation() const |
| { |
| Q_D(const QQuick3DQuaternionAnimation); |
| return d->anglesFrom.z(); |
| } |
| |
| void QQuick3DQuaternionAnimation::setFromZRotation(float f) |
| { |
| Q_D(QQuick3DQuaternionAnimation); |
| if (d->anglesFrom.z() == f) |
| return; |
| d->anglesFrom.setZ(f); |
| setFrom(QQuaternion::fromEulerAngles(d->anglesFrom)); |
| emit fromZRotationChanged(f); |
| } |
| |
| /*! |
| \qmlproperty float QtQuick3D::QuaternionAnimation::toXRotation |
| |
| This property holds the ending value of the animation for the X axis as |
| an euler angle in degrees. |
| |
| */ |
| |
| float QQuick3DQuaternionAnimation::toXRotation() const |
| { |
| Q_D(const QQuick3DQuaternionAnimation); |
| return d->anglesTo.x(); |
| } |
| |
| void QQuick3DQuaternionAnimation::setToXRotation(float f) |
| { |
| Q_D(QQuick3DQuaternionAnimation); |
| if (d->anglesTo.x() == f) |
| return; |
| d->anglesTo.setX(f); |
| setTo(QQuaternion::fromEulerAngles(d->anglesTo)); |
| emit toXRotationChanged(f); |
| } |
| |
| /*! |
| \qmlproperty float QtQuick3D::QuaternionAnimation::toYRotation |
| |
| This property holds the ending value of the animation for the Y axis as |
| an euler angle in degrees. |
| |
| */ |
| |
| float QQuick3DQuaternionAnimation::toYRotation() const |
| { |
| Q_D(const QQuick3DQuaternionAnimation); |
| return d->anglesTo.y(); |
| } |
| |
| void QQuick3DQuaternionAnimation::setToYRotation(float f) |
| { |
| Q_D(QQuick3DQuaternionAnimation); |
| if (d->anglesTo.y() == f) |
| return; |
| d->anglesTo.setY(f); |
| setTo(QQuaternion::fromEulerAngles(d->anglesTo)); |
| emit toYRotationChanged(f); |
| } |
| |
| /*! |
| \qmlproperty float QtQuick3D::QuaternionAnimation::toZRotation |
| |
| This property holds the ending value of the animation for the Z axis as |
| an euler angle in degrees. |
| |
| */ |
| |
| float QQuick3DQuaternionAnimation::toZRotation() const |
| { |
| Q_D(const QQuick3DQuaternionAnimation); |
| return d->anglesTo.z(); |
| } |
| |
| void QQuick3DQuaternionAnimation::setToZRotation(float f) |
| { |
| Q_D(QQuick3DQuaternionAnimation); |
| if (d->anglesTo.z() == f) |
| return; |
| d->anglesTo.setZ(f); |
| setTo(QQuaternion::fromEulerAngles(d->anglesTo)); |
| emit toZRotationChanged(f); |
| } |
| |
| QT_END_NAMESPACE |