1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt 3D module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qquaternionanimation_p.h"
41
42#include <QtQuick/private/qquickanimation_p_p.h>
43
44QT_BEGIN_NAMESPACE
45
46/*!
47 \qmltype QuaternionAnimation
48 \inherits PropertyAnimation
49 \inqmlmodule Qt3D.Core
50 \since 5.6
51
52 \brief A PropertyAnimation for quaternions.
53
54 A specialized \l{PropertyAnimation} that defines an animation between two
55 \l{QQuaternion}{quaternions}.
56
57 By default spherical linear interpolation is used. This can be changed to
58 the faster but less accurate normalized linear interpolation by setting the
59 \a type property.
60
61 Instead of specifying quaternions directly in the \a from and \a to
62 properties, it is also possible to provide euler angles in degrees in the
63 \a fromXRotation, \a toXRotation, \a fromYRotation, \a toYRotation,
64 \a fromZRotation, \a toZRotation properties.
65
66 \note Avoid mixing the quaternion and euler angle-based properties. The
67 from and to values are expected to be fully specified either via a
68 quaternion or the three euler angles.
69
70 \sa {Animation and Transitions in Qt Quick} QQuaternion QQuaternion::slerp() QQuaternion::nlerp()
71*/
72
73namespace Qt3DCore {
74namespace Quick {
75
76class QQuaternionAnimationPrivate : public QQuickPropertyAnimationPrivate
77{
78 Q_DECLARE_PUBLIC(QQuaternionAnimation)
79
80public:
81 QQuaternionAnimationPrivate() :
82 type(QQuaternionAnimation::Slerp)
83 { }
84
85 QQuaternionAnimation::Type type;
86 QVector3D anglesFrom;
87 QVector3D anglesTo;
88};
89
90QVariant q_quaternionInterpolator(const QQuaternion &from, const QQuaternion &to, qreal progress)
91{
92 return QVariant::fromValue(QQuaternion::slerp(from, to, progress));
93}
94
95QVariant q_quaternionNlerpInterpolator(const QQuaternion &from, const QQuaternion &to, qreal progress)
96{
97 return QVariant::fromValue(QQuaternion::nlerp(from, to, progress));
98}
99
100QQuaternionAnimation::QQuaternionAnimation(QObject *parent)
101 : QQuickPropertyAnimation(*(new QQuaternionAnimationPrivate), parent)
102{
103 Q_D(QQuaternionAnimation);
104 d->interpolatorType = qMetaTypeId<QQuaternion>();
105 d->defaultToInterpolatorType = true;
106 d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType);
107}
108
109QQuaternion QQuaternionAnimation::from() const
110{
111 Q_D(const QQuaternionAnimation);
112 return d->from.value<QQuaternion>();
113}
114
115void QQuaternionAnimation::setFrom(const QQuaternion &f)
116{
117 QQuickPropertyAnimation::setFrom(QVariant::fromValue(f));
118}
119
120QQuaternion QQuaternionAnimation::to() const
121{
122 Q_D(const QQuaternionAnimation);
123 return d->to.value<QQuaternion>();
124}
125
126void QQuaternionAnimation::setTo(const QQuaternion &t)
127{
128 QQuickPropertyAnimation::setTo(QVariant::fromValue(t));
129}
130
131QQuaternionAnimation::Type QQuaternionAnimation::type() const
132{
133 Q_D(const QQuaternionAnimation);
134 return d->type;
135}
136
137void QQuaternionAnimation::setType(Type type)
138{
139 Q_D(QQuaternionAnimation);
140 if (d->type == type)
141 return;
142
143 d->type = type;
144 switch (type) {
145 case Nlerp:
146QT_WARNING_PUSH
147QT_WARNING_DISABLE_GCC(-Wcast-function-type)
148 d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(&q_quaternionNlerpInterpolator);
149QT_WARNING_POP
150 break;
151 case Slerp:
152 default:
153 d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType);
154 break;
155 }
156
157 emit typeChanged(type);
158}
159
160float QQuaternionAnimation::fromXRotation() const
161{
162 Q_D(const QQuaternionAnimation);
163 return d->anglesFrom.x();
164}
165
166void QQuaternionAnimation::setFromXRotation(float f)
167{
168 Q_D(QQuaternionAnimation);
169 if (d->anglesFrom.x() == f)
170 return;
171 d->anglesFrom.setX(f);
172 setFrom(QQuaternion::fromEulerAngles(d->anglesFrom));
173 emit fromXRotationChanged(f);
174}
175
176float QQuaternionAnimation::fromYRotation() const
177{
178 Q_D(const QQuaternionAnimation);
179 return d->anglesFrom.y();
180}
181
182void QQuaternionAnimation::setFromYRotation(float f)
183{
184 Q_D(QQuaternionAnimation);
185 if (d->anglesFrom.y() == f)
186 return;
187 d->anglesFrom.setY(f);
188 setFrom(QQuaternion::fromEulerAngles(d->anglesFrom));
189 emit fromYRotationChanged(f);
190}
191
192float QQuaternionAnimation::fromZRotation() const
193{
194 Q_D(const QQuaternionAnimation);
195 return d->anglesFrom.z();
196}
197
198void QQuaternionAnimation::setFromZRotation(float f)
199{
200 Q_D(QQuaternionAnimation);
201 if (d->anglesFrom.z() == f)
202 return;
203 d->anglesFrom.setZ(f);
204 setFrom(QQuaternion::fromEulerAngles(d->anglesFrom));
205 emit fromZRotationChanged(f);
206}
207
208float QQuaternionAnimation::toXRotation() const
209{
210 Q_D(const QQuaternionAnimation);
211 return d->anglesTo.x();
212}
213
214void QQuaternionAnimation::setToXRotation(float f)
215{
216 Q_D(QQuaternionAnimation);
217 if (d->anglesTo.x() == f)
218 return;
219 d->anglesTo.setX(f);
220 setTo(QQuaternion::fromEulerAngles(d->anglesTo));
221 emit toXRotationChanged(f);
222}
223
224float QQuaternionAnimation::toYRotation() const
225{
226 Q_D(const QQuaternionAnimation);
227 return d->anglesTo.y();
228}
229
230void QQuaternionAnimation::setToYRotation(float f)
231{
232 Q_D(QQuaternionAnimation);
233 if (d->anglesTo.y() == f)
234 return;
235 d->anglesTo.setY(f);
236 setTo(QQuaternion::fromEulerAngles(d->anglesTo));
237 emit toYRotationChanged(f);
238}
239
240float QQuaternionAnimation::toZRotation() const
241{
242 Q_D(const QQuaternionAnimation);
243 return d->anglesTo.z();
244}
245
246void QQuaternionAnimation::setToZRotation(float f)
247{
248 Q_D(QQuaternionAnimation);
249 if (d->anglesTo.z() == f)
250 return;
251 d->anglesTo.setZ(f);
252 setTo(QQuaternion::fromEulerAngles(d->anglesTo));
253 emit toZRotationChanged(f);
254}
255
256} // namespace Quick
257} // namespace Qt3DCore
258
259QT_END_NAMESPACE
260