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
qtimeline.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 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
4#include "qtimeline.h"
5
6#include <private/qproperty_p.h>
7#include <private/qobject_p.h>
8#include <QtCore/qcoreevent.h>
9#include <QtCore/qmath.h>
10#include <QtCore/qelapsedtimer.h>
11
13
15{
16 Q_DECLARE_PUBLIC(QTimeLine)
17public:
21
22 int startTime = 0;
23 void setDuration(int duration) { q_func()->setDuration(duration); }
26 int startFrame = 0;
27 int endFrame = 0;
28 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QTimeLinePrivate, int, updateInterval, 1000 / 25)
31
32 void setCurrentTimeForwardToQ(int time) { q_func()->setCurrentTime(time); }
35 int timerId = 0;
36
37 void setDirection(QTimeLine::Direction direction) { q_func()->setDirection(direction); }
42 {
43 Q_Q(QTimeLine);
44 if (newState != state)
45 emit q->stateChanged(state = newState, QTimeLine::QPrivateSignal());
46 }
47
48 void setCurrentTime(int msecs);
49};
50
55{
56 Q_Q(QTimeLine);
57 currentTime.removeBindingUnlessInWrapper();
58 const auto previousCurrentTime = currentTime.valueBypassingBindings();
59
60 const qreal lastValue = q->valueForTime(previousCurrentTime);
61 const int lastFrame = q->frameForTime(previousCurrentTime);
62
63 // Determine if we are looping.
64 const int elapsed = (direction == QTimeLine::Backward) ? (-msecs + duration) : msecs;
65 const int loopCountNow = elapsed / duration;
66
67 const bool looping = (loopCountNow != currentLoopCount);
68#ifdef QTIMELINE_DEBUG
69 qDebug() << "QTimeLinePrivate::setCurrentTime:" << msecs << duration << "with loopCountNow"
70 << loopCountNow << "currentLoopCount" << currentLoopCount << "looping" << looping;
71#endif
72 if (looping)
73 currentLoopCount = loopCountNow;
74
75 // Normalize msecs to be between 0 and duration, inclusive.
76 currentTime.setValueBypassingBindings(elapsed % duration);
77 if (direction.value() == QTimeLine::Backward)
78 currentTime.setValueBypassingBindings(duration - currentTime.valueBypassingBindings());
79
80 // Check if we have reached the end of loopcount.
81 bool finished = false;
82 if (loopCount && currentLoopCount >= loopCount) {
83 finished = true;
84 currentTime.setValueBypassingBindings((direction == QTimeLine::Backward) ? 0 : duration);
85 currentLoopCount = loopCount - 1;
86 }
87
88 const int currentFrame = q->frameForTime(currentTime.valueBypassingBindings());
89#ifdef QTIMELINE_DEBUG
90 qDebug() << "QTimeLinePrivate::setCurrentTime: frameForTime"
91 << currentTime.valueBypassingBindings() << currentFrame;
92#endif
93 const qreal currentValue = q->valueForTime(currentTime.valueBypassingBindings());
94 if (!qFuzzyCompare(lastValue, currentValue))
95 emit q->valueChanged(currentValue, QTimeLine::QPrivateSignal());
96 if (lastFrame != currentFrame) {
97 const int transitionframe = (direction == QTimeLine::Forward ? endFrame : startFrame);
98 if (looping && !finished && transitionframe != currentFrame) {
99#ifdef QTIMELINE_DEBUG
100 qDebug("QTimeLinePrivate::setCurrentTime: transitionframe");
101#endif
102 emit q->frameChanged(transitionframe, QTimeLine::QPrivateSignal());
103 }
104#ifdef QTIMELINE_DEBUG
105 else {
106 QByteArray reason;
107 if (!looping)
108 reason += " not looping";
109 if (finished) {
110 if (!reason.isEmpty())
111 reason += " and";
112 reason += " finished";
113 }
114 if (transitionframe == currentFrame) {
115 if (!reason.isEmpty())
116 reason += " and";
117 reason += " transitionframe is equal to currentFrame: " + QByteArray::number(currentFrame);
118 }
119 qDebug("QTimeLinePrivate::setCurrentTime: not transitionframe because %s", reason.constData());
120 }
121#endif
122 emit q->frameChanged(currentFrame, QTimeLine::QPrivateSignal());
123 }
124 if (finished && state == QTimeLine::Running) {
125 q->stop();
126 emit q->finished(QTimeLine::QPrivateSignal());
127 }
128 if (currentTime.valueBypassingBindings() != previousCurrentTime)
129 currentTime.notify();
130}
132{
133 Q_D(QTimeLine);
134 return &d->currentTime;
135}
136
263QTimeLine::QTimeLine(int duration, QObject *parent)
264 : QObject(*new QTimeLinePrivate, parent)
265{
267}
268
273{
274 Q_D(QTimeLine);
275
276 if (d->state == Running)
277 stop();
278}
279
286{
287 Q_D(const QTimeLine);
288 return d->state;
289}
290
300{
301 Q_D(const QTimeLine);
302 return d->loopCount;
303}
304
306{
307 Q_D(QTimeLine);
308 d->loopCount = count;
309}
310
312{
313 Q_D(QTimeLine);
314 return &d->loopCount;
315}
316
332{
333 Q_D(const QTimeLine);
334 return d->direction;
335}
337{
338 Q_D(QTimeLine);
339 d->direction.removeBindingUnlessInWrapper();
340 const auto previousDirection = d->direction.valueBypassingBindings();
341 d->direction.setValueBypassingBindings(direction);
342 d->startTime = d->currentTime;
343 d->timer.start();
344 if (previousDirection != d->direction.valueBypassingBindings())
345 d->direction.notify();
346}
347
348QBindable<QTimeLine::Direction> QTimeLine::bindableDirection()
349{
350 Q_D(QTimeLine);
351 return &d->direction;
352}
353
367{
368 Q_D(const QTimeLine);
369 return d->duration;
370}
371void QTimeLine::setDuration(int duration)
372{
373 Q_D(QTimeLine);
374 if (duration <= 0) {
375 qWarning("QTimeLine::setDuration: cannot set duration <= 0");
376 return;
377 }
378 d->duration.removeBindingUnlessInWrapper();
379 if (duration != d->duration.valueBypassingBindings()) {
380 d->duration.setValueBypassingBindings(duration);
381 d->duration.notify();
382 }
383}
384
386{
387 Q_D(QTimeLine);
388 return &d->duration;
389}
390
398{
399 Q_D(const QTimeLine);
400 return d->startFrame;
401}
402
410{
411 Q_D(QTimeLine);
412 d->startFrame = frame;
413}
414
422{
423 Q_D(const QTimeLine);
424 return d->endFrame;
425}
426
434{
435 Q_D(QTimeLine);
436 d->endFrame = frame;
437}
438
450void QTimeLine::setFrameRange(int startFrame, int endFrame)
451{
452 Q_D(QTimeLine);
453 d->startFrame = startFrame;
454 d->endFrame = endFrame;
455}
456
469{
470 Q_D(const QTimeLine);
471 return d->updateInterval;
472}
474{
475 Q_D(QTimeLine);
476 d->updateInterval = interval;
477}
479{
480 Q_D(QTimeLine);
481 return &d->updateInterval;
482}
483
496{
497 Q_D(const QTimeLine);
498 return d->easingCurve;
499}
500
502{
503 Q_D(QTimeLine);
504 d->easingCurve = curve;
505}
506
507QBindable<QEasingCurve> QTimeLine::bindableEasingCurve()
508{
509 Q_D(QTimeLine);
510 return &d->easingCurve;
511}
512
529{
530 Q_D(const QTimeLine);
531 return d->currentTime;
532}
534{
535 Q_D(QTimeLine);
536 d->startTime = 0;
537 d->currentLoopCount = 0;
538 d->timer.restart();
539 d->setCurrentTime(msec);
540}
541
548{
549 Q_D(const QTimeLine);
550 return frameForTime(d->currentTime);
551}
552
559{
560 Q_D(const QTimeLine);
561 return valueForTime(d->currentTime);
562}
563
571int QTimeLine::frameForTime(int msec) const
572{
573 Q_D(const QTimeLine);
574 if (d->direction == Forward)
575 return d->startFrame + int((d->endFrame - d->startFrame) * valueForTime(msec));
576 return d->startFrame + qCeil((d->endFrame - d->startFrame) * valueForTime(msec));
577}
578
590{
591 Q_D(const QTimeLine);
592 msec = qBound(0, msec, d->duration.value());
593
594 qreal value = msec / qreal(d->duration.value());
595 return d->easingCurve.value().valueForProgress(value);
596}
597
612{
613 Q_D(QTimeLine);
614 if (d->timerId) {
615 qWarning("QTimeLine::start: already running");
616 return;
617 }
618 int curTime = 0;
619 if (d->direction == Backward)
620 curTime = d->duration;
621 d->timerId = startTimer(d->updateInterval);
622 d->startTime = curTime;
623 d->currentLoopCount = 0;
624 d->timer.start();
625 d->setState(Running);
626 d->setCurrentTime(curTime);
627}
628
640{
641 Q_D(QTimeLine);
642 if (d->timerId) {
643 qWarning("QTimeLine::resume: already running");
644 return;
645 }
646 d->timerId = startTimer(d->updateInterval);
647 d->startTime = d->currentTime;
648 d->timer.start();
649 d->setState(Running);
650}
651
658{
659 Q_D(QTimeLine);
660 if (d->timerId)
661 killTimer(d->timerId);
662 d->setState(NotRunning);
663 d->timerId = 0;
664}
665
674void QTimeLine::setPaused(bool paused)
675{
676 Q_D(QTimeLine);
677 if (d->state == NotRunning) {
678 qWarning("QTimeLine::setPaused: Not running");
679 return;
680 }
681 if (paused && d->state != Paused) {
682 d->startTime = d->currentTime;
683 killTimer(d->timerId);
684 d->timerId = 0;
685 d->setState(Paused);
686 } else if (!paused && d->state == Paused) {
687 // Same as resume()
688 d->timerId = startTimer(d->updateInterval);
689 d->startTime = d->currentTime;
690 d->timer.start();
691 d->setState(Running);
692 }
693}
694
704{
705 Q_D(QTimeLine);
706 setDirection(d->direction == Forward ? Backward : Forward);
707}
708
713{
714 Q_D(QTimeLine);
715 if (event->timerId() != d->timerId) {
716 event->ignore();
717 return;
718 }
719 event->accept();
720
721 if (d->direction == Forward) {
722 d->setCurrentTime(d->startTime + d->timer.elapsed());
723 } else {
724 d->setCurrentTime(d->startTime - d->timer.elapsed());
725 }
726}
727
729
730#include "moc_qtimeline.cpp"
\inmodule QtCore
Definition qbytearray.h:57
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:124
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:107
static QByteArray number(int, int base=10)
Returns a byte-array representing the whole number n as text.
\inmodule QtCore
\inmodule QtCore
\inmodule QtCore
Definition qobject.h:103
int startTimer(int interval, Qt::TimerType timerType=Qt::CoarseTimer)
This is an overloaded function that will start a timer of type timerType and a timeout of interval mi...
Definition qobject.cpp:1817
void killTimer(int id)
Kills the timer with timer identifier, id.
Definition qobject.cpp:1912
void setCurrentTimeForwardToQ(int time)
Definition qtimeline.cpp:32
Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QTimeLinePrivate, int, duration, &QTimeLinePrivate::setDuration, 1000) int startFrame=0
void setDirection(QTimeLine::Direction direction)
Definition qtimeline.cpp:37
Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QTimeLinePrivate, QEasingCurve, easingCurve, QEasingCurve::InOutSine) int startTime=0
void setCurrentTime(int msecs)
Definition qtimeline.cpp:54
Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QTimeLinePrivate, int, currentTime, &QTimeLinePrivate::setCurrentTimeForwardToQ, 0) int timerId=0
void setDuration(int duration)
Definition qtimeline.cpp:23
Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QTimeLinePrivate, QTimeLine::Direction, direction, &QTimeLinePrivate::setDirection, QTimeLine::Forward) QTimeLine voi setState)(QTimeLine::State newState)
Definition qtimeline.cpp:41
QElapsedTimer timer
Definition qtimeline.cpp:18
\inmodule QtCore
Definition qtimeline.h:19
int currentTime
the current time of the time line.
Definition qtimeline.h:24
int loopCount
the number of times the timeline should loop before it's finished.
Definition qtimeline.h:26
void timerEvent(QTimerEvent *event) override
\reimp
int currentFrame() const
Returns the frame corresponding to the current time.
QTimeLine(int duration=1000, QObject *parent=nullptr)
Constructs a timeline with a duration of duration milliseconds.
int startFrame() const
Returns the start frame, which is the frame corresponding to the start of the timeline (i....
qreal currentValue() const
Returns the value corresponding to the current time.
State state() const
Returns the state of the timeline.
void setPaused(bool paused)
If paused is true, the timeline is paused, causing QTimeLine to enter Paused state.
int duration
the total duration of the timeline in milliseconds.
Definition qtimeline.h:21
QBindable< int > bindableCurrentTime()
int frameForTime(int msec) const
Returns the frame corresponding to the time msec.
void setEasingCurve(const QEasingCurve &curve)
int endFrame() const
Returns the end frame, which is the frame corresponding to the end of the timeline (i....
void setUpdateInterval(int interval)
QBindable< QEasingCurve > bindableEasingCurve()
int updateInterval
the time in milliseconds between each time QTimeLine updates its current time.
Definition qtimeline.h:23
QBindable< int > bindableLoopCount()
virtual qreal valueForTime(int msec) const
Returns the timeline value for the time msec.
QBindable< int > bindableDuration()
void start()
Starts the timeline.
void setLoopCount(int count)
void setDirection(Direction direction)
void setStartFrame(int frame)
Sets the start frame, which is the frame corresponding to the start of the timeline (i....
Direction direction
the direction of the timeline when QTimeLine is in \l Running state.
Definition qtimeline.h:25
QBindable< int > bindableUpdateInterval()
State
This enum describes the state of the timeline.
Definition qtimeline.h:30
void setFrameRange(int startFrame, int endFrame)
Sets the timeline's frame counter to start at startFrame, and end and endFrame.
void setCurrentTime(int msec)
QBindable< Direction > bindableDirection()
QEasingCurve easingCurve
Definition qtimeline.h:28
void setDuration(int duration)
void stop()
Stops the timeline, causing QTimeLine to enter NotRunning state.
void toggleDirection()
Toggles the direction of the timeline.
Direction
This enum describes the direction of the timeline when in \l Running state.
Definition qtimeline.h:35
void setEndFrame(int frame)
Sets the end frame, which is the frame corresponding to the end of the timeline (i....
virtual ~QTimeLine()
Destroys the timeline.
void resume()
Resumes the timeline from the current time.
\inmodule QtCore
Definition qcoreevent.h:366
direction
else opt state
[0]
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
Combined button and popup list for selecting options.
qint64 startTime
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:333
#define qDebug
[1]
Definition qlogging.h:164
#define qWarning
Definition qlogging.h:166
int qCeil(T v)
Definition qmath.h:36
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
GLenum GLenum GLsizei count
struct _cl_event * event
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
#define Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(...)
Definition qproperty.h:1266
#define Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(...)
static double elapsed(qint64 after, qint64 before)
#define emit
double qreal
Definition qtypes.h:187
static double currentTime()
QFrame frame
[0]