9#include "private/qcontinuinganimationgroupjob_p.h"
12#include <qqmlproperty.h>
13#include <private/qqmlproperty_p.h>
15#include <private/qqmlglobal_p.h>
17#include <QtCore/qdebug.h>
20#define DELAY_STOP_TIMER_INTERVAL 32
27 , m_animation(animation)
29 connect(
this, SIGNAL(timeout()),
this, SLOT(stopAnimation()));
41QSmoothedAnimation::QSmoothedAnimation(QQuickSmoothedAnimationPrivate *priv)
42 : QAbstractAnimationJob(), to(0), velocity(200), userDuration(-1), maximumEasingTime(-1),
43 reversingMode(QQuickSmoothedAnimation::Eased), initialVelocity(0),
44 trackVelocity(0), initialValue(0), invert(
false), finalDuration(-1), lastTime(0),
45 skipUpdate(
false), delayedStopTimer(
new QSmoothedAnimationTimer(
this)), animationTemplate(priv)
48 delayedStopTimer->setSingleShot(
true);
51QSmoothedAnimation::~QSmoothedAnimation()
53 delete delayedStopTimer;
54 if (animationTemplate) {
55 if (target.object()) {
56 auto it = animationTemplate->activeAnimations.constFind(target);
57 if (it != animationTemplate->activeAnimations.cend() && it.value() ==
this)
58 animationTemplate->activeAnimations.erase(it);
61 for (
auto it = animationTemplate->activeAnimations.cbegin(); it != animationTemplate->activeAnimations.cend(); ++it) {
62 if (it.value() ==
this) {
63 animationTemplate->activeAnimations.erase(it);
71void QSmoothedAnimation::restart()
73 initialVelocity = trackVelocity;
80void QSmoothedAnimation::prepareForRestart()
82 initialVelocity = trackVelocity;
94void QSmoothedAnimation::updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State )
96 if (newState == QAbstractAnimationJob::Running)
100void QSmoothedAnimation::delayedStop()
102 if (!delayedStopTimer->isActive())
103 delayedStopTimer->start();
106int QSmoothedAnimation::duration()
const
111bool QSmoothedAnimation::recalc()
113 s = to - initialValue;
114 vi = initialVelocity;
116 s = (invert? -1.0: 1.0) * s;
118 if (userDuration >= 0 && velocity > 0) {
120 if (tf > (userDuration / 1000.)) tf = (userDuration / 1000.);
121 }
else if (userDuration >= 0) {
122 tf = userDuration / 1000.;
123 }
else if (velocity > 0) {
129 finalDuration = qCeil(tf * 1000.0);
131 if (maximumEasingTime == 0) {
139 }
else if (maximumEasingTime != -1 && tf > (maximumEasingTime / 1000.)) {
140 qreal met = maximumEasingTime / 1000.;
142
143
144
145
146
147
148
150 a = (s - (vi * tf - 0.5 * vi * ta)) / (tf * ta - ta * ta);
155 sp = vi * ta + 0.5 * a * tp * tp;
156 sd = sp + vp * (tf - 2 * ta);
159 qreal c1 = 0.25 * tf * tf;
160 qreal c2 = 0.5 * vi * tf - s;
161 qreal c3 = -0.25 * vi * vi;
163 qreal a1 = (-c2 + qSqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1);
165 qreal tp1 = 0.5 * tf - 0.5 * vi / a1;
166 qreal vp1 = a1 * tp1 + vi;
168 qreal sp1 = 0.5 * a1 * tp1 * tp1 + vi * tp1;
181qreal QSmoothedAnimation::easeFollow(qreal time_seconds)
184 if (time_seconds < tp) {
185 trackVelocity = vi + time_seconds * a;
186 value = 0.5 * a * time_seconds * time_seconds + vi * time_seconds;
187 }
else if (time_seconds < td) {
190 value = sp + time_seconds * vp;
191 }
else if (time_seconds < tf) {
193 trackVelocity = vp - time_seconds * a;
194 value = sd - 0.5 * d * time_seconds * time_seconds + vp * time_seconds;
205void QSmoothedAnimation::updateCurrentTime(
int t)
212 if (!isRunning() && !isPaused())
215 qreal time_seconds = qreal(t - lastTime) / 1000.;
217 qreal value = easeFollow(time_seconds);
218 value *= (invert? -1.0: 1.0);
219 QQmlPropertyPrivate::write(target, initialValue + value,
220 QQmlPropertyData::BypassInterceptor
221 | QQmlPropertyData::DontRemoveBinding);
224void QSmoothedAnimation::init()
231 if (delayedStopTimer->isActive())
232 delayedStopTimer->stop();
234 initialValue = target.read().toReal();
235 lastTime =
this->currentTime();
237 if (to == initialValue) {
242 bool hasReversed = trackVelocity != 0. &&
243 ((!invert) == ((initialValue - to) > 0));
246 switch (reversingMode) {
248 case QQuickSmoothedAnimation::Eased:
249 initialVelocity = -trackVelocity;
251 case QQuickSmoothedAnimation::Sync:
252 QQmlPropertyPrivate::write(target, to,
253 QQmlPropertyData::BypassInterceptor
254 | QQmlPropertyData::DontRemoveBinding);
258 case QQuickSmoothedAnimation::Immediate:
264 trackVelocity = initialVelocity;
266 invert = (to < initialValue);
269 QQmlPropertyPrivate::write(target, to,
270 QQmlPropertyData::BypassInterceptor
271 | QQmlPropertyData::DontRemoveBinding);
277void QSmoothedAnimation::debugAnimation(QDebug d)
const
279 d <<
"SmoothedAnimationJob(" << Qt::hex << (
const void *)
this << Qt::dec <<
")" <<
"duration:" << userDuration
280 <<
"velocity:" << velocity <<
"target:" << target.object() <<
"property:" << target.name()
281 <<
"to:" << to <<
"current velocity:" << trackVelocity;
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
330
332QQuickSmoothedAnimation::QQuickSmoothedAnimation(QObject *parent)
333: QQuickNumberAnimation(*(
new QQuickSmoothedAnimationPrivate), parent)
338 : anim(
new QSmoothedAnimation)
344 typedef QHash<QQmlProperty, QSmoothedAnimation* >::iterator ActiveAnimationsHashIt;
347 for (ActiveAnimationsHashIt it = activeAnimations.begin(), end = activeAnimations.end(); it != end; ++it)
348 it.value()->clearTemplate();
353 for (QSmoothedAnimation *ease : std::as_const(activeAnimations)) {
354 ease->maximumEasingTime = anim->maximumEasingTime;
355 ease->reversingMode = anim->reversingMode;
356 ease->velocity = anim->velocity;
357 ease->userDuration = anim->userDuration;
362QAbstractAnimationJob* QQuickSmoothedAnimation::transition(QQuickStateActions &actions,
363 QQmlProperties &modified,
364 TransitionDirection direction,
365 QObject *defaultTarget)
368 Q_D(QQuickSmoothedAnimation);
370 const QQuickStateActions dataActions = QQuickPropertyAnimation::createTransitionActions(actions, modified, defaultTarget);
372 QContinuingAnimationGroupJob *wrapperGroup =
new QContinuingAnimationGroupJob();
374 if (!dataActions.isEmpty()) {
375 QSet<QAbstractAnimationJob*> anims;
376 for (
int i = 0; i < dataActions.size(); i++) {
377 QSmoothedAnimation *ease;
379 if (!d->activeAnimations.contains(dataActions[i].property)) {
380 ease =
new QSmoothedAnimation(d);
381 d->activeAnimations.insert(dataActions[i].property, ease);
382 ease->target = dataActions[i].property;
385 ease = d->activeAnimations.value(dataActions[i].property);
388 wrapperGroup->appendAnimation(initInstance(ease));
390 ease->to = dataActions[i].toValue.toReal();
393 ease->maximumEasingTime = d->anim->maximumEasingTime;
394 ease->reversingMode = d->anim->reversingMode;
395 ease->velocity = d->anim->velocity;
396 ease->userDuration = d->anim->userDuration;
398 ease->initialVelocity = ease->trackVelocity;
401 ease->prepareForRestart();
405 const auto copy = d->activeAnimations;
406 for (QSmoothedAnimation *ease : copy) {
407 if (!anims.contains(ease)) {
408 ease->clearTemplate();
409 d->activeAnimations.remove(ease->target);
417
418
419
420
421
422
423
424
425
426
427
428
429
430QQuickSmoothedAnimation::ReversingMode QQuickSmoothedAnimation::reversingMode()
const
432 Q_D(
const QQuickSmoothedAnimation);
433 return (QQuickSmoothedAnimation::ReversingMode) d->anim->reversingMode;
436void QQuickSmoothedAnimation::setReversingMode(ReversingMode m)
438 Q_D(QQuickSmoothedAnimation);
439 if (d->anim->reversingMode == m)
442 d->anim->reversingMode = m;
443 emit reversingModeChanged();
444 d->updateRunningAnimations();
448
449
450
451
452
453
454
455
456
457int QQuickSmoothedAnimation::duration()
const
459 Q_D(
const QQuickSmoothedAnimation);
460 return d->anim->userDuration;
463void QQuickSmoothedAnimation::setDuration(
int duration)
465 Q_D(QQuickSmoothedAnimation);
467 QQuickNumberAnimation::setDuration(duration);
468 if(duration == d->anim->userDuration)
470 d->anim->userDuration = duration;
471 d->updateRunningAnimations();
474qreal QQuickSmoothedAnimation::velocity()
const
476 Q_D(
const QQuickSmoothedAnimation);
477 return d->anim->velocity;
481
482
483
484
485
486
487
488
489
490
491
492void QQuickSmoothedAnimation::setVelocity(qreal v)
494 Q_D(QQuickSmoothedAnimation);
495 if (d->anim->velocity == v)
498 d->anim->velocity = v;
499 emit velocityChanged();
500 d->updateRunningAnimations();
504
505
506
507
508
509
510
511
512
513int QQuickSmoothedAnimation::maximumEasingTime()
const
515 Q_D(
const QQuickSmoothedAnimation);
516 return d->anim->maximumEasingTime;
519void QQuickSmoothedAnimation::setMaximumEasingTime(
int v)
521 Q_D(QQuickSmoothedAnimation);
522 if(v == d->anim->maximumEasingTime)
524 d->anim->maximumEasingTime = v;
525 emit maximumEasingTimeChanged();
526 d->updateRunningAnimations();
531#include "moc_qquicksmoothedanimation_p_p.cpp"
533#include "moc_qquicksmoothedanimation_p.cpp"
QSmoothedAnimation * anim
~QQuickSmoothedAnimationPrivate()
void updateRunningAnimations()
~QSmoothedAnimationTimer()
Combined button and popup list for selecting options.
#define DELAY_STOP_TIMER_INTERVAL