1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qquick3dquaternionanimation_p.h"
5#include <QtQuick/private/qquickanimation_p_p.h>
6
7QT_BEGIN_NAMESPACE
8
9/*!
10 \qmltype QuaternionAnimation
11 \inherits PropertyAnimation
12 \inqmlmodule QtQuick3D
13 \since 5.15
14
15 \brief A PropertyAnimation for quaternions.
16
17 A specialized \l{PropertyAnimation} that defines an animation between two
18 \l{QQuaternion}{quaternions}.
19
20 By default spherical linear interpolation is used. This can be changed to
21 the faster but less accurate normalized linear interpolation by setting the
22 \a type property.
23
24 Instead of specifying quaternions directly in the \a from and \a to
25 properties, it is also possible to provide euler angles in degrees in the
26 \a fromXRotation, \a toXRotation, \a fromYRotation, \a toYRotation,
27 \a fromZRotation, \a toZRotation properties.
28
29 \note Avoid mixing the quaternion and euler angle-based properties. The
30 from and to values are expected to be fully specified either via a
31 quaternion or the three euler angles.
32
33 \sa {Animation and Transitions in Qt Quick} QQuaternion QQuaternion::slerp() QQuaternion::nlerp()
34*/
35
36class QQuick3DQuaternionAnimationPrivate : public QQuickPropertyAnimationPrivate
37{
38 Q_DECLARE_PUBLIC(QQuick3DQuaternionAnimation)
39
40public:
41 QQuick3DQuaternionAnimationPrivate() :
42 type(QQuick3DQuaternionAnimation::Slerp)
43 { }
44
45 QQuick3DQuaternionAnimation::Type type;
46 QVector3D anglesFrom;
47 QVector3D anglesTo;
48};
49
50
51QVariant q_quaternionInterpolator(const QQuaternion &from, const QQuaternion &to, qreal progress)
52{
53 return QVariant::fromValue(value: QQuaternion::slerp(q1: from, q2: to, t: progress));
54}
55
56QVariant q_quaternionNlerpInterpolator(const QQuaternion &from, const QQuaternion &to, qreal progress)
57{
58 return QVariant::fromValue(value: QQuaternion::nlerp(q1: from, q2: to, t: progress));
59}
60
61QQuick3DQuaternionAnimation::QQuick3DQuaternionAnimation(QObject *parent)
62 : QQuickPropertyAnimation(*(new QQuick3DQuaternionAnimationPrivate), parent)
63{
64 Q_D(QQuick3DQuaternionAnimation);
65 d->interpolatorType = qMetaTypeId<QQuaternion>();
66 d->defaultToInterpolatorType = true;
67 d->interpolator = QVariantAnimationPrivate::getInterpolator(interpolationType: d->interpolatorType);
68}
69
70/*!
71 \qmlproperty quaternion QtQuick3D::QuaternionAnimation::from
72
73 This property holds the starting value for the animation.
74
75*/
76
77QQuaternion QQuick3DQuaternionAnimation::from() const
78{
79 Q_D(const QQuick3DQuaternionAnimation);
80 return d->from.value<QQuaternion>();
81}
82
83void QQuick3DQuaternionAnimation::setFrom(const QQuaternion &f)
84{
85 QQuickPropertyAnimation::setFrom(QVariant::fromValue(value: f));
86}
87
88/*!
89 \qmlproperty quaternion QtQuick3D::QuaternionAnimation::to
90
91 This property holds the ending value for the animation.
92
93*/
94
95QQuaternion QQuick3DQuaternionAnimation::to() const
96{
97 Q_D(const QQuick3DQuaternionAnimation);
98 return d->to.value<QQuaternion>();
99}
100
101void QQuick3DQuaternionAnimation::setTo(const QQuaternion &t)
102{
103 QQuickPropertyAnimation::setTo(QVariant::fromValue(value: t));
104}
105
106/*!
107 \qmlproperty enumeration QtQuick3D::QuaternionAnimation::type
108
109 This property defines the interpolation mode.
110
111 \value QuaternionAnimation.Slerp Spherical linear interpolation.
112 \value QuaternionAnimation.Nlerp Normalized linear interpolation.
113
114*/
115
116QQuick3DQuaternionAnimation::Type QQuick3DQuaternionAnimation::type() const
117{
118 Q_D(const QQuick3DQuaternionAnimation);
119 return d->type;
120}
121
122void QQuick3DQuaternionAnimation::setType(Type type)
123{
124 Q_D(QQuick3DQuaternionAnimation);
125 if (d->type == type)
126 return;
127
128 d->type = type;
129 switch (type) {
130 case Nlerp:
131 d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(reinterpret_cast<void(*)()>(&q_quaternionNlerpInterpolator));
132 break;
133 case Slerp:
134 default:
135 d->interpolator = QVariantAnimationPrivate::getInterpolator(interpolationType: d->interpolatorType);
136 break;
137 }
138
139 emit typeChanged(type);
140}
141
142/*!
143 \qmlproperty float QtQuick3D::QuaternionAnimation::fromXRotation
144
145 This property holds the starting value of the animation for the X axis as
146 an euler angle in degrees.
147
148*/
149
150float QQuick3DQuaternionAnimation::fromXRotation() const
151{
152 Q_D(const QQuick3DQuaternionAnimation);
153 return d->anglesFrom.x();
154}
155
156void QQuick3DQuaternionAnimation::setFromXRotation(float f)
157{
158 Q_D(QQuick3DQuaternionAnimation);
159 if (d->anglesFrom.x() == f)
160 return;
161 d->anglesFrom.setX(f);
162 setFrom(QQuaternion::fromEulerAngles(eulerAngles: d->anglesFrom));
163 emit fromXRotationChanged(value: f);
164}
165
166/*!
167 \qmlproperty float QtQuick3D::QuaternionAnimation::fromYRotation
168
169 This property holds the starting value of the animation for the Y axis as
170 an euler angle in degrees.
171
172*/
173
174float QQuick3DQuaternionAnimation::fromYRotation() const
175{
176 Q_D(const QQuick3DQuaternionAnimation);
177 return d->anglesFrom.y();
178}
179
180void QQuick3DQuaternionAnimation::setFromYRotation(float f)
181{
182 Q_D(QQuick3DQuaternionAnimation);
183 if (d->anglesFrom.y() == f)
184 return;
185 d->anglesFrom.setY(f);
186 setFrom(QQuaternion::fromEulerAngles(eulerAngles: d->anglesFrom));
187 emit fromYRotationChanged(value: f);
188}
189
190/*!
191 \qmlproperty float QtQuick3D::QuaternionAnimation::fromZRotation
192
193 This property holds the starting value of the animation for the Z axis as
194 an euler angle in degrees.
195
196*/
197
198float QQuick3DQuaternionAnimation::fromZRotation() const
199{
200 Q_D(const QQuick3DQuaternionAnimation);
201 return d->anglesFrom.z();
202}
203
204void QQuick3DQuaternionAnimation::setFromZRotation(float f)
205{
206 Q_D(QQuick3DQuaternionAnimation);
207 if (d->anglesFrom.z() == f)
208 return;
209 d->anglesFrom.setZ(f);
210 setFrom(QQuaternion::fromEulerAngles(eulerAngles: d->anglesFrom));
211 emit fromZRotationChanged(value: f);
212}
213
214/*!
215 \qmlproperty float QtQuick3D::QuaternionAnimation::toXRotation
216
217 This property holds the ending value of the animation for the X axis as
218 an euler angle in degrees.
219
220*/
221
222float QQuick3DQuaternionAnimation::toXRotation() const
223{
224 Q_D(const QQuick3DQuaternionAnimation);
225 return d->anglesTo.x();
226}
227
228void QQuick3DQuaternionAnimation::setToXRotation(float f)
229{
230 Q_D(QQuick3DQuaternionAnimation);
231 if (d->anglesTo.x() == f)
232 return;
233 d->anglesTo.setX(f);
234 setTo(QQuaternion::fromEulerAngles(eulerAngles: d->anglesTo));
235 emit toXRotationChanged(value: f);
236}
237
238/*!
239 \qmlproperty float QtQuick3D::QuaternionAnimation::toYRotation
240
241 This property holds the ending value of the animation for the Y axis as
242 an euler angle in degrees.
243
244*/
245
246float QQuick3DQuaternionAnimation::toYRotation() const
247{
248 Q_D(const QQuick3DQuaternionAnimation);
249 return d->anglesTo.y();
250}
251
252void QQuick3DQuaternionAnimation::setToYRotation(float f)
253{
254 Q_D(QQuick3DQuaternionAnimation);
255 if (d->anglesTo.y() == f)
256 return;
257 d->anglesTo.setY(f);
258 setTo(QQuaternion::fromEulerAngles(eulerAngles: d->anglesTo));
259 emit toYRotationChanged(value: f);
260}
261
262/*!
263 \qmlproperty float QtQuick3D::QuaternionAnimation::toZRotation
264
265 This property holds the ending value of the animation for the Z axis as
266 an euler angle in degrees.
267
268*/
269
270float QQuick3DQuaternionAnimation::toZRotation() const
271{
272 Q_D(const QQuick3DQuaternionAnimation);
273 return d->anglesTo.z();
274}
275
276void QQuick3DQuaternionAnimation::setToZRotation(float f)
277{
278 Q_D(QQuick3DQuaternionAnimation);
279 if (d->anglesTo.z() == f)
280 return;
281 d->anglesTo.setZ(f);
282 setTo(QQuaternion::fromEulerAngles(eulerAngles: d->anglesTo));
283 emit toZRotationChanged(value: f);
284}
285
286QT_END_NAMESPACE
287

source code of qtquick3d/src/quick3d/qquick3dquaternionanimation.cpp