8#include "private/qcontinuinganimationgroupjob_p.h"
11#include <qqmlproperty.h>
12#include <private/qqmlproperty_p.h>
14#include <private/qqmlglobal_p.h>
16#include <QtCore/qdebug.h>
19#define DELAY_STOP_TIMER_INTERVAL 32
26 , m_animation(animation)
28 connect(
this, SIGNAL(timeout()),
this, SLOT(stopAnimation()));
40QSmoothedAnimation::QSmoothedAnimation(QQuickSmoothedAnimationPrivate *priv)
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)
47 delayedStopTimer->setSingleShot(
true);
50QSmoothedAnimation::~QSmoothedAnimation()
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);
60 for (
auto it = animationTemplate->activeAnimations.cbegin(); it != animationTemplate->activeAnimations.cend(); ++it) {
61 if (it.value() ==
this) {
62 animationTemplate->activeAnimations.erase(it);
70void QSmoothedAnimation::restart()
72 initialVelocity = trackVelocity;
79void QSmoothedAnimation::prepareForRestart()
81 initialVelocity = trackVelocity;
93void QSmoothedAnimation::updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State )
95 if (newState == QAbstractAnimationJob::Running)
99void QSmoothedAnimation::delayedStop()
101 if (!delayedStopTimer->isActive())
102 delayedStopTimer->start();
105int QSmoothedAnimation::duration()
const
110bool QSmoothedAnimation::recalc()
112 s = to - initialValue;
113 vi = initialVelocity;
115 s = (invert? -1.0: 1.0) * s;
117 if (userDuration >= 0 && velocity > 0) {
119 if (tf > (userDuration / 1000.)) tf = (userDuration / 1000.);
120 }
else if (userDuration >= 0) {
121 tf = userDuration / 1000.;
122 }
else if (velocity > 0) {
128 finalDuration = qCeil(tf * 1000.0);
130 if (maximumEasingTime == 0) {
138 }
else if (maximumEasingTime != -1 && tf > (maximumEasingTime / 1000.)) {
139 qreal met = maximumEasingTime / 1000.;
141
142
143
144
145
146
147
149 a = (s - (vi * tf - 0.5 * vi * ta)) / (tf * ta - ta * ta);
154 sp = vi * ta + 0.5 * a * tp * tp;
155 sd = sp + vp * (tf - 2 * ta);
158 qreal c1 = 0.25 * tf * tf;
159 qreal c2 = 0.5 * vi * tf - s;
160 qreal c3 = -0.25 * vi * vi;
162 qreal a1 = (-c2 + qSqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1);
164 qreal tp1 = 0.5 * tf - 0.5 * vi / a1;
165 qreal vp1 = a1 * tp1 + vi;
167 qreal sp1 = 0.5 * a1 * tp1 * tp1 + vi * tp1;
180qreal QSmoothedAnimation::easeFollow(qreal time_seconds)
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) {
189 value = sp + time_seconds * vp;
190 }
else if (time_seconds < tf) {
192 trackVelocity = vp - time_seconds * a;
193 value = sd - 0.5 * d * time_seconds * time_seconds + vp * time_seconds;
204void QSmoothedAnimation::updateCurrentTime(
int t)
211 if (!isRunning() && !isPaused())
214 qreal time_seconds = qreal(t - lastTime) / 1000.;
216 qreal value = easeFollow(time_seconds);
217 value *= (invert? -1.0: 1.0);
218 QQmlPropertyPrivate::write(target, initialValue + value,
219 QQmlPropertyData::BypassInterceptor
220 | QQmlPropertyData::DontRemoveBinding);
223void QSmoothedAnimation::init()
230 if (delayedStopTimer->isActive())
231 delayedStopTimer->stop();
233 initialValue = target.read().toReal();
234 lastTime =
this->currentTime();
236 if (to == initialValue) {
241 bool hasReversed = trackVelocity != 0. &&
242 ((!invert) == ((initialValue - to) > 0));
245 switch (reversingMode) {
247 case QQuickSmoothedAnimation::Eased:
248 initialVelocity = -trackVelocity;
250 case QQuickSmoothedAnimation::Sync:
251 QQmlPropertyPrivate::write(target, to,
252 QQmlPropertyData::BypassInterceptor
253 | QQmlPropertyData::DontRemoveBinding);
257 case QQuickSmoothedAnimation::Immediate:
263 trackVelocity = initialVelocity;
265 invert = (to < initialValue);
268 QQmlPropertyPrivate::write(target, to,
269 QQmlPropertyData::BypassInterceptor
270 | QQmlPropertyData::DontRemoveBinding);
276void QSmoothedAnimation::debugAnimation(QDebug d)
const
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;
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
331QQuickSmoothedAnimation::QQuickSmoothedAnimation(QObject *parent)
332: QQuickNumberAnimation(*(
new QQuickSmoothedAnimationPrivate), parent)
337 : anim(
new QSmoothedAnimation)
343 typedef QHash<QQmlProperty, QSmoothedAnimation* >::iterator ActiveAnimationsHashIt;
346 for (ActiveAnimationsHashIt it = activeAnimations.begin(), end = activeAnimations.end(); it != end; ++it)
347 it.value()->clearTemplate();
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;
361QAbstractAnimationJob* QQuickSmoothedAnimation::transition(QQuickStateActions &actions,
362 QQmlProperties &modified,
363 TransitionDirection direction,
364 QObject *defaultTarget)
367 Q_D(QQuickSmoothedAnimation);
369 const QQuickStateActions dataActions = QQuickPropertyAnimation::createTransitionActions(actions, modified, defaultTarget);
371 QContinuingAnimationGroupJob *wrapperGroup =
new QContinuingAnimationGroupJob();
373 if (!dataActions.isEmpty()) {
374 QSet<QAbstractAnimationJob*> anims;
375 for (
int i = 0; i < dataActions.size(); i++) {
376 QSmoothedAnimation *ease;
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;
384 ease = d->activeAnimations.value(dataActions[i].property);
387 wrapperGroup->appendAnimation(initInstance(ease));
389 ease->to = dataActions[i].toValue.toReal();
392 ease->maximumEasingTime = d->anim->maximumEasingTime;
393 ease->reversingMode = d->anim->reversingMode;
394 ease->velocity = d->anim->velocity;
395 ease->userDuration = d->anim->userDuration;
397 ease->initialVelocity = ease->trackVelocity;
400 ease->prepareForRestart();
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);
416
417
418
419
420
421
422
423
424
425
426
427
428
429QQuickSmoothedAnimation::ReversingMode QQuickSmoothedAnimation::reversingMode()
const
431 Q_D(
const QQuickSmoothedAnimation);
432 return (QQuickSmoothedAnimation::ReversingMode) d->anim->reversingMode;
435void QQuickSmoothedAnimation::setReversingMode(ReversingMode m)
437 Q_D(QQuickSmoothedAnimation);
438 if (d->anim->reversingMode == m)
441 d->anim->reversingMode = m;
442 emit reversingModeChanged();
443 d->updateRunningAnimations();
447
448
449
450
451
452
453
454
455
456int QQuickSmoothedAnimation::duration()
const
458 Q_D(
const QQuickSmoothedAnimation);
459 return d->anim->userDuration;
462void QQuickSmoothedAnimation::setDuration(
int duration)
464 Q_D(QQuickSmoothedAnimation);
466 QQuickNumberAnimation::setDuration(duration);
467 if(duration == d->anim->userDuration)
469 d->anim->userDuration = duration;
470 d->updateRunningAnimations();
473qreal QQuickSmoothedAnimation::velocity()
const
475 Q_D(
const QQuickSmoothedAnimation);
476 return d->anim->velocity;
480
481
482
483
484
485
486
487
488
489
490
491void QQuickSmoothedAnimation::setVelocity(qreal v)
493 Q_D(QQuickSmoothedAnimation);
494 if (d->anim->velocity == v)
497 d->anim->velocity = v;
498 emit velocityChanged();
499 d->updateRunningAnimations();
503
504
505
506
507
508
509
510
511
512int QQuickSmoothedAnimation::maximumEasingTime()
const
514 Q_D(
const QQuickSmoothedAnimation);
515 return d->anim->maximumEasingTime;
518void QQuickSmoothedAnimation::setMaximumEasingTime(
int v)
520 Q_D(QQuickSmoothedAnimation);
521 if(v == d->anim->maximumEasingTime)
523 d->anim->maximumEasingTime = v;
524 emit maximumEasingTimeChanged();
525 d->updateRunningAnimations();
530#include "moc_qquicksmoothedanimation_p_p.cpp"
532#include "moc_qquicksmoothedanimation_p.cpp"
QSmoothedAnimation * anim
~QQuickSmoothedAnimationPrivate()
void updateRunningAnimations()
~QSmoothedAnimationTimer()
Combined button and popup list for selecting options.
#define DELAY_STOP_TIMER_INTERVAL