Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qquicksmoothedanimation.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
6
8#include "private/qcontinuinganimationgroupjob_p.h"
9
10#include <qmath.h>
11#include <qqmlproperty.h>
12#include <private/qqmlproperty_p.h>
13
14#include <private/qqmlglobal_p.h>
15
16#include <QtCore/qdebug.h>
17
18
19#define DELAY_STOP_TIMER_INTERVAL 32
20
22
23
30
34
36{
37 m_animation->stop();
38}
39
41 : QAbstractAnimationJob(), to(0), velocity(200), userDuration(-1), maximumEasingTime(-1),
42 reversingMode(QQuickSmoothedAnimation::Eased), initialVelocity(0),
43 trackVelocity(0), initialValue(0), invert(false), finalDuration(-1), lastTime(0),
44 skipUpdate(false), delayedStopTimer(new QSmoothedAnimationTimer(this)), animationTemplate(priv)
45{
46 delayedStopTimer->setInterval(DELAY_STOP_TIMER_INTERVAL);
47 delayedStopTimer->setSingleShot(true);
48}
49
51{
52 delete delayedStopTimer;
53 if (animationTemplate) {
54 if (target.object()) {
55 auto it = animationTemplate->activeAnimations.constFind(target);
56 if (it != animationTemplate->activeAnimations.cend() && it.value() == this)
57 animationTemplate->activeAnimations.erase(it);
58 } else {
59 //target is no longer valid, need to search linearly
60 for (auto it = animationTemplate->activeAnimations.cbegin(); it != animationTemplate->activeAnimations.cend(); ++it) {
61 if (it.value() == this) {
62 animationTemplate->activeAnimations.erase(it);
63 break;
64 }
65 }
66 }
67 }
68}
69
71{
73 if (isRunning())
74 init();
75 else
76 start();
77}
78
80{
82 if (isRunning()) {
83 //we are joining a new wrapper group while running, our times need to be restarted
84 skipUpdate = true;
85 init();
86 lastTime = 0;
87 } else {
88 skipUpdate = false;
89 //we'll be started when the group starts, which will force an init()
90 }
91}
92
98
99void QSmoothedAnimation::delayedStop()
100{
101 if (!delayedStopTimer->isActive())
102 delayedStopTimer->start();
103}
104
106{
107 return -1;
108}
109
110bool QSmoothedAnimation::recalc()
111{
112 s = to - initialValue;
113 vi = initialVelocity;
114
115 s = (invert? -1.0: 1.0) * s;
116
117 if (userDuration >= 0 && velocity > 0) {
118 tf = s / velocity;
119 if (tf > (userDuration / 1000.)) tf = (userDuration / 1000.);
120 } else if (userDuration >= 0) {
121 tf = userDuration / 1000.;
122 } else if (velocity > 0) {
123 tf = s / velocity;
124 } else {
125 return false;
126 }
127
128 finalDuration = qCeil(tf * 1000.0);
129
130 if (maximumEasingTime == 0) {
131 a = 0;
132 d = 0;
133 tp = 0;
134 td = tf;
135 vp = velocity;
136 sp = 0;
137 sd = s;
138 } else if (maximumEasingTime != -1 && tf > (maximumEasingTime / 1000.)) {
139 qreal met = maximumEasingTime / 1000.;
140 /* tp| |td
141 * vp_ _______
142 * / \
143 * vi_ / \
144 * \
145 * \ _ 0
146 * |ta| |ta|
147 */
148 qreal ta = met / 2.;
149 a = (s - (vi * tf - 0.5 * vi * ta)) / (tf * ta - ta * ta);
150
151 vp = vi + a * ta;
152 d = vp / ta;
153 tp = ta;
154 sp = vi * ta + 0.5 * a * tp * tp;
155 sd = sp + vp * (tf - 2 * ta);
156 td = tf - ta;
157 } else {
158 qreal c1 = 0.25 * tf * tf;
159 qreal c2 = 0.5 * vi * tf - s;
160 qreal c3 = -0.25 * vi * vi;
161
162 qreal a1 = (-c2 + qSqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1);
163
164 qreal tp1 = 0.5 * tf - 0.5 * vi / a1;
165 qreal vp1 = a1 * tp1 + vi;
166
167 qreal sp1 = 0.5 * a1 * tp1 * tp1 + vi * tp1;
168
169 a = a1;
170 d = a1;
171 tp = tp1;
172 td = tp1;
173 vp = vp1;
174 sp = sp1;
175 sd = sp1;
176 }
177 return true;
178}
179
180qreal QSmoothedAnimation::easeFollow(qreal time_seconds)
181{
182 qreal value;
183 if (time_seconds < tp) {
184 trackVelocity = vi + time_seconds * a;
185 value = 0.5 * a * time_seconds * time_seconds + vi * time_seconds;
186 } else if (time_seconds < td) {
187 time_seconds -= tp;
188 trackVelocity = vp;
189 value = sp + time_seconds * vp;
190 } else if (time_seconds < tf) {
191 time_seconds -= td;
192 trackVelocity = vp - time_seconds * a;
193 value = sd - 0.5 * d * time_seconds * time_seconds + vp * time_seconds;
194 } else {
195 trackVelocity = 0;
196 value = s;
197 delayedStop();
198 }
199
200 // to normalize 's' between [0..1], divide 'value' by 's'
201 return value;
202}
203
205{
206 if (skipUpdate) {
207 skipUpdate = false;
208 return;
209 }
210
211 if (!isRunning() && !isPaused()) // This can happen if init() stops the animation in some cases
212 return;
213
214 qreal time_seconds = qreal(t - lastTime) / 1000.;
215
216 qreal value = easeFollow(time_seconds);
217 value *= (invert? -1.0: 1.0);
221}
222
224{
225 if (velocity == 0) {
226 stop();
227 return;
228 }
229
230 if (delayedStopTimer->isActive())
231 delayedStopTimer->stop();
232
233 initialValue = target.read().toReal();
234 lastTime = this->currentTime();
235
236 if (to == initialValue) {
237 stop();
238 return;
239 }
240
241 bool hasReversed = trackVelocity != 0. &&
242 ((!invert) == ((initialValue - to) > 0));
243
244 if (hasReversed) {
245 switch (reversingMode) {
246 default:
249 break;
254 trackVelocity = 0;
255 stop();
256 return;
258 initialVelocity = 0;
259 break;
260 }
261 }
262
264
265 invert = (to < initialValue);
266
267 if (!recalc()) {
271 stop();
272 return;
273 }
274}
275
277{
278 d << "SmoothedAnimationJob(" << Qt::hex << (const void *) this << Qt::dec << ")" << "duration:" << userDuration
279 << "velocity:" << velocity << "target:" << target.object() << "property:" << target.name()
280 << "to:" << to << "current velocity:" << trackVelocity;
281}
282
335
340
342{
343 typedef QHash<QQmlProperty, QSmoothedAnimation* >::iterator ActiveAnimationsHashIt;
344
345 delete anim;
346 for (ActiveAnimationsHashIt it = activeAnimations.begin(), end = activeAnimations.end(); it != end; ++it)
347 it.value()->clearTemplate();
348}
349
351{
352 for (QSmoothedAnimation *ease : std::as_const(activeAnimations)) {
353 ease->maximumEasingTime = anim->maximumEasingTime;
354 ease->reversingMode = anim->reversingMode;
355 ease->velocity = anim->velocity;
356 ease->userDuration = anim->userDuration;
357 ease->init();
358 }
359}
360
362 QQmlProperties &modified,
364 QObject *defaultTarget)
365{
368
369 const QQuickStateActions dataActions = QQuickPropertyAnimation::createTransitionActions(actions, modified, defaultTarget);
370
372
373 if (!dataActions.isEmpty()) {
374 QSet<QAbstractAnimationJob*> anims;
375 for (int i = 0; i < dataActions.size(); i++) {
376 QSmoothedAnimation *ease;
377 bool isActive;
378 if (!d->activeAnimations.contains(dataActions[i].property)) {
379 ease = new QSmoothedAnimation(d);
380 d->activeAnimations.insert(dataActions[i].property, ease);
381 ease->target = dataActions[i].property;
382 isActive = false;
383 } else {
384 ease = d->activeAnimations.value(dataActions[i].property);
385 isActive = true;
386 }
387 wrapperGroup->appendAnimation(initInstance(ease));
388
389 ease->to = dataActions[i].toValue.toReal();
390
391 // copying public members from main value holder animation
392 ease->maximumEasingTime = d->anim->maximumEasingTime;
393 ease->reversingMode = d->anim->reversingMode;
394 ease->velocity = d->anim->velocity;
395 ease->userDuration = d->anim->userDuration;
396
397 ease->initialVelocity = ease->trackVelocity;
398
399 if (isActive)
400 ease->prepareForRestart();
401 anims.insert(ease);
402 }
403
404 const auto copy = d->activeAnimations;
405 for (QSmoothedAnimation *ease : copy) {
406 if (!anims.contains(ease)) {
407 ease->clearTemplate();
408 d->activeAnimations.remove(ease->target);
409 }
410 }
411 }
412 return wrapperGroup;
413}
414
434
436{
438 if (d->anim->reversingMode == m)
439 return;
440
441 d->anim->reversingMode = m;
443 d->updateRunningAnimations();
444}
445
457{
458 Q_D(const QQuickSmoothedAnimation);
459 return d->anim->userDuration;
460}
461
463{
465 if (duration != -1)
467 if(duration == d->anim->userDuration)
468 return;
469 d->anim->userDuration = duration;
470 d->updateRunningAnimations();
471}
472
474{
475 Q_D(const QQuickSmoothedAnimation);
476 return d->anim->velocity;
477}
478
492{
494 if (d->anim->velocity == v)
495 return;
496
497 d->anim->velocity = v;
499 d->updateRunningAnimations();
500}
501
513{
514 Q_D(const QQuickSmoothedAnimation);
515 return d->anim->maximumEasingTime;
516}
517
519{
521 if(v == d->anim->maximumEasingTime)
522 return;
523 d->anim->maximumEasingTime = v;
525 d->updateRunningAnimations();
526}
527
529
530#include "moc_qquicksmoothedanimation_p_p.cpp"
531
532#include "moc_qquicksmoothedanimation_p.cpp"
bool isActive
\inmodule QtCore
\inmodule QtCore
Definition qhash.h:1103
iterator begin()
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in the hash.
Definition qhash.h:1212
const_iterator cbegin() const noexcept
Definition qhash.h:1214
const_iterator constFind(const Key &key) const noexcept
Definition qhash.h:1299
iterator erase(const_iterator it)
Definition qhash.h:1233
iterator end() noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last ...
Definition qhash.h:1216
const_iterator cend() const noexcept
Definition qhash.h:1218
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
static bool write(QObject *, const QQmlPropertyData &, const QVariant &, const QQmlRefPointer< QQmlContextData > &, QQmlPropertyData::WriteFlags flags={})
QAbstractAnimationJob * initInstance(QAbstractAnimationJob *animation)
virtual void setDuration(int)
QQuickStateActions createTransitionActions(QQuickStateActions &actions, QQmlProperties &modified, QObject *defaultTarget=nullptr)
QHash< QQmlProperty, QSmoothedAnimation * > activeAnimations
int duration() const override
\qmlproperty int QtQuick::SmoothedAnimation::duration
QAbstractAnimationJob * transition(QQuickStateActions &actions, QQmlProperties &modified, TransitionDirection direction, QObject *defaultTarget=nullptr) override
QQuickSmoothedAnimation(QObject *parent=nullptr)
\qmltype SmoothedAnimation \instantiates QQuickSmoothedAnimation \inqmlmodule QtQuick\inherits Number...
void setVelocity(qreal)
\qmlproperty real QtQuick::SmoothedAnimation::velocity
QSmoothedAnimationTimer(QSmoothedAnimation *animation, QObject *parent=nullptr)
void updateState(QAbstractAnimationJob::State, QAbstractAnimationJob::State) override
void updateCurrentTime(int) override
void debugAnimation(QDebug d) const override
QQuickSmoothedAnimation::ReversingMode reversingMode
QSmoothedAnimation(QQuickSmoothedAnimationPrivate *=nullptr)
int duration() const override
\inmodule QtCore
Definition qtimer.h:20
void setSingleShot(bool singleShot)
Definition qtimer.cpp:552
void start(int msec)
Starts or restarts the timer with a timeout interval of msec milliseconds.
Definition qtimer.cpp:241
void setInterval(int msec)
Definition qtimer.cpp:579
bool isActive() const
Returns true if the timer is running (pending); otherwise returns false.
Definition qtimer.cpp:167
void stop()
Stops the timer.
Definition qtimer.cpp:267
#define this
Definition dialogs.cpp:9
QSet< QString >::iterator it
direction
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
Combined button and popup list for selecting options.
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
QTextStream & dec(QTextStream &stream)
Calls QTextStream::setIntegerBase(10) on stream and returns stream.
static jboolean copy(JNIEnv *, jobject)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
qfloat16 qSqrt(qfloat16 f)
Definition qfloat16.h:289
int qCeil(T v)
Definition qmath.h:36
static const QMetaObjectPrivate * priv(const uint *data)
#define SLOT(a)
Definition qobjectdefs.h:52
#define SIGNAL(a)
Definition qobjectdefs.h:53
GLsizei const GLfloat * v
[13]
const GLfloat * m
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint GLuint end
GLbitfield GLuint64 timeout
[4]
GLenum target
GLdouble s
[6]
Definition qopenglext.h:235
GLdouble GLdouble t
Definition qopenglext.h:243
GLboolean invert
Definition qopenglext.h:226
#define DELAY_STOP_TIMER_INTERVAL
#define a1
#define emit
#define Q_UNUSED(x)
double qreal
Definition qtypes.h:187
MyCustomStruct c2
QPropertyAnimation animation
[0]