9#include <QtQuick/private/qsgcontext_p.h>
10#include <QtQuick/private/qquickitem_p.h>
11#include <private/qsgadaptationlayer_p.h>
12#include <private/qqmlglobal_p.h>
13#include <QtQuick/qsgnode.h>
14#include <QtQuick/qsgtexturematerial.h>
15#include <QtQuick/qsgtexture.h>
16#include <QtQuick/qquickwindow.h>
17#include <QtQml/qqmlinfo.h>
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
101
102
103
104
105
106
109
110
111
112
113
114
115
118
119
120
121
122
123
124
125
126
129
130
131
132
133
134
135
136
137
140
141
142
143
145
146
147
148
149
150
152
153
154
155
156
157
159
160
161
162
163
164
166
167
168
169
170
171
173
174
175
176
177
178
179
180
181
184
185
186
187
188
189
192
193
194
195
196
197
198
199
200
201
202
203
206
207
208
209
210
211
212
213
216
217
218
219
220
221
224
225
226
227
228
231
232
233
234
235
236
237
238
239
240
241
244
245
246
247
250
251
252
253
254
255
256
257
259QQuickAnimatedSprite::QQuickAnimatedSprite(QQuickItem *parent) :
260 QQuickItem(*(
new QQuickAnimatedSpritePrivate), parent)
262 Q_D(QQuickAnimatedSprite);
263 d->m_sprite =
new QQuickSprite(
this);
265 setFlag(ItemHasContents);
266 connect(
this, SIGNAL(widthChanged()),
267 this, SLOT(reset()));
268 connect(
this, SIGNAL(heightChanged()),
269 this, SLOT(reset()));
272bool QQuickAnimatedSprite::running()
const
274 Q_D(
const QQuickAnimatedSprite);
278bool QQuickAnimatedSprite::interpolate()
const
280 Q_D(
const QQuickAnimatedSprite);
281 return d->m_interpolate;
284QUrl QQuickAnimatedSprite::source()
const
286 Q_D(
const QQuickAnimatedSprite);
287 return d->m_sprite->source();
290bool QQuickAnimatedSprite::reverse()
const
292 Q_D(
const QQuickAnimatedSprite);
293 return d->m_sprite->reverse();
296bool QQuickAnimatedSprite::frameSync()
const
298 Q_D(
const QQuickAnimatedSprite);
299 return d->m_sprite->frameSync();
302int QQuickAnimatedSprite::frameCount()
const
304 Q_D(
const QQuickAnimatedSprite);
305 return d->m_sprite->frames();
308int QQuickAnimatedSprite::frameHeight()
const
310 Q_D(
const QQuickAnimatedSprite);
311 return d->m_sprite->frameHeight();
314int QQuickAnimatedSprite::frameWidth()
const
316 Q_D(
const QQuickAnimatedSprite);
317 return d->m_sprite->frameWidth();
320int QQuickAnimatedSprite::frameX()
const
322 Q_D(
const QQuickAnimatedSprite);
323 return d->m_sprite->frameX();
326int QQuickAnimatedSprite::frameY()
const
328 Q_D(
const QQuickAnimatedSprite);
329 return d->m_sprite->frameY();
332qreal QQuickAnimatedSprite::frameRate()
const
334 Q_D(
const QQuickAnimatedSprite);
335 return d->m_sprite->frameRate();
338int QQuickAnimatedSprite::frameDuration()
const
340 Q_D(
const QQuickAnimatedSprite);
341 return d->m_sprite->frameDuration();
344int QQuickAnimatedSprite::loops()
const
346 Q_D(
const QQuickAnimatedSprite);
350bool QQuickAnimatedSprite::paused()
const
352 Q_D(
const QQuickAnimatedSprite);
356int QQuickAnimatedSprite::currentFrame()
const
358 Q_D(
const QQuickAnimatedSprite);
359 return d->m_curFrame;
362QQuickAnimatedSprite::FinishBehavior QQuickAnimatedSprite::finishBehavior()
const
364 Q_D(
const QQuickAnimatedSprite);
365 return d->m_finishBehavior;
368bool QQuickAnimatedSprite::isCurrentFrameChangedConnected()
370 IS_SIGNAL_CONNECTED(
this, QQuickAnimatedSprite, currentFrameChanged, (
int));
373void QQuickAnimatedSprite::reloadImage()
375 if (!isComponentComplete())
380void QQuickAnimatedSprite::componentComplete()
382 Q_D(QQuickAnimatedSprite);
384 QQuickItem::componentComplete();
386 d->m_running =
false;
392
393
394
395
396
397
398
399
400void QQuickAnimatedSprite::start()
402 Q_D(QQuickAnimatedSprite);
406 if (!isComponentComplete())
410 d->m_timestamp.start();
411 if (d->m_spriteEngine) {
412 d->m_spriteEngine->stop(0);
413 d->m_spriteEngine->updateSprites(0);
414 d->m_spriteEngine->start(0);
416 emit currentFrameChanged(0);
417 emit runningChanged(
true);
422
423
424
425
426
427
428
429
430void QQuickAnimatedSprite::stop()
432 Q_D(QQuickAnimatedSprite);
435 d->m_running =
false;
436 if (!isComponentComplete())
438 d->m_pauseOffset = 0;
439 emit runningChanged(
false);
444
445
446
447
448void QQuickAnimatedSprite::advance(
int frames)
450 Q_D(QQuickAnimatedSprite);
454 d->m_curFrame += frames;
455 while (d->m_curFrame < 0)
456 d->m_curFrame += d->m_spriteEngine->maxFrames();
457 d->m_curFrame = d->m_curFrame % d->m_spriteEngine->maxFrames();
458 emit currentFrameChanged(d->m_curFrame);
462void QQuickAnimatedSprite::maybeUpdate()
464 QQuickItemPrivate *priv = QQuickItemPrivate::get(
this);
465 const auto &extraData = priv->extra;
466 if ((extraData.isAllocated() && extraData->effectRefCount > 0) || priv->effectiveVisible)
470void QQuickAnimatedSprite::itemChange(ItemChange change,
const ItemChangeData &value)
472 Q_D(QQuickAnimatedSprite);
473 if (change == ItemVisibleHasChanged && d->m_running && !d->m_paused)
475 QQuickItem::itemChange(change, value);
479
480
481
482
483
484
485
486void QQuickAnimatedSprite::pause()
488 Q_D(QQuickAnimatedSprite);
492 d->m_pauseOffset = d->m_timestamp.elapsed();
494 emit pausedChanged(
true);
499
500
501
502
503
504
505
506void QQuickAnimatedSprite::resume()
508 Q_D(QQuickAnimatedSprite);
512 d->m_pauseOffset = d->m_pauseOffset - d->m_timestamp.elapsed();
514 emit pausedChanged(
false);
518void QQuickAnimatedSprite::setRunning(
bool arg)
520 Q_D(QQuickAnimatedSprite);
522 if (d->m_running != arg) {
530void QQuickAnimatedSprite::setPaused(
bool arg)
532 Q_D(
const QQuickAnimatedSprite);
534 if (d->m_paused != arg) {
542void QQuickAnimatedSprite::setInterpolate(
bool arg)
544 Q_D(QQuickAnimatedSprite);
546 if (d->m_interpolate != arg) {
547 d->m_interpolate = arg;
548 Q_EMIT interpolateChanged(arg);
552void QQuickAnimatedSprite::setSource(
const QUrl &arg)
554 Q_D(QQuickAnimatedSprite);
556 if (d->m_sprite->m_source != arg) {
557 const qreal targetDevicePixelRatio = d->effectiveDevicePixelRatio();
558 d->m_sprite->setDevicePixelRatio(targetDevicePixelRatio);
559 d->m_sprite->setSource(arg);
560 Q_EMIT sourceChanged(arg);
565void QQuickAnimatedSprite::setReverse(
bool arg)
567 Q_D(QQuickAnimatedSprite);
569 if (d->m_sprite->m_reverse != arg) {
570 d->m_sprite->setReverse(arg);
571 Q_EMIT reverseChanged(arg);
575void QQuickAnimatedSprite::setFrameSync(
bool arg)
577 Q_D(QQuickAnimatedSprite);
579 if (d->m_sprite->m_frameSync != arg) {
580 d->m_sprite->setFrameSync(arg);
581 Q_EMIT frameSyncChanged(arg);
587void QQuickAnimatedSprite::setFrameCount(
int arg)
589 Q_D(QQuickAnimatedSprite);
591 if (d->m_sprite->m_frames != arg) {
592 d->m_sprite->setFrameCount(arg);
593 Q_EMIT frameCountChanged(arg);
598void QQuickAnimatedSprite::setFrameHeight(
int arg)
600 Q_D(QQuickAnimatedSprite);
602 if (d->m_sprite->m_frameHeight != arg) {
603 d->m_sprite->setFrameHeight(arg);
604 Q_EMIT frameHeightChanged(arg);
605 setImplicitHeight(frameHeight());
610void QQuickAnimatedSprite::setFrameWidth(
int arg)
612 Q_D(QQuickAnimatedSprite);
614 if (d->m_sprite->m_frameWidth != arg) {
615 d->m_sprite->setFrameWidth(arg);
616 Q_EMIT frameWidthChanged(arg);
617 setImplicitWidth(frameWidth());
622void QQuickAnimatedSprite::setFrameX(
int arg)
624 Q_D(QQuickAnimatedSprite);
626 if (d->m_sprite->m_frameX != arg) {
627 d->m_sprite->setFrameX(arg);
628 Q_EMIT frameXChanged(arg);
633void QQuickAnimatedSprite::setFrameY(
int arg)
635 Q_D(QQuickAnimatedSprite);
637 if (d->m_sprite->m_frameY != arg) {
638 d->m_sprite->setFrameY(arg);
639 Q_EMIT frameYChanged(arg);
644void QQuickAnimatedSprite::setFrameRate(qreal arg)
646 Q_D(QQuickAnimatedSprite);
648 if (d->m_sprite->m_frameRate != arg) {
649 d->m_sprite->setFrameRate(arg);
650 Q_EMIT frameRateChanged(arg);
656void QQuickAnimatedSprite::setFrameDuration(
int arg)
658 Q_D(QQuickAnimatedSprite);
660 if (d->m_sprite->m_frameDuration != arg) {
661 d->m_sprite->setFrameDuration(arg);
662 Q_EMIT frameDurationChanged(arg);
668void QQuickAnimatedSprite::resetFrameRate()
673void QQuickAnimatedSprite::resetFrameDuration()
675 setFrameDuration(-1);
678void QQuickAnimatedSprite::setLoops(
int arg)
680 Q_D(QQuickAnimatedSprite);
682 if (d->m_loops != arg) {
684 Q_EMIT loopsChanged(arg);
688void QQuickAnimatedSprite::setCurrentFrame(
int arg)
690 Q_D(QQuickAnimatedSprite);
692 if (d->m_curFrame != arg) {
694 Q_EMIT currentFrameChanged(arg);
699void QQuickAnimatedSprite::setFinishBehavior(FinishBehavior arg)
701 Q_D(QQuickAnimatedSprite);
703 if (d->m_finishBehavior != arg) {
704 d->m_finishBehavior = arg;
705 Q_EMIT finishBehaviorChanged(arg);
709void QQuickAnimatedSprite::createEngine()
711 Q_D(QQuickAnimatedSprite);
713 if (d->m_spriteEngine)
714 delete d->m_spriteEngine;
715 QList<QQuickSprite*> spriteList;
716 spriteList << d->m_sprite;
717 d->m_spriteEngine =
new QQuickSpriteEngine(QList<QQuickSprite*>(spriteList),
this);
718 d->m_spriteEngine->startAssemblingImage();
722QSGSpriteNode* QQuickAnimatedSprite::initNode()
724 Q_D(QQuickAnimatedSprite);
726 if (!d->m_spriteEngine) {
727 qmlWarning(
this) <<
"No sprite engine...";
729 }
else if (d->m_spriteEngine->status() == QQuickPixmap::Null) {
730 d->m_spriteEngine->startAssemblingImage();
733 }
else if (d->m_spriteEngine->status() == QQuickPixmap::Loading) {
738 QImage image = d->m_spriteEngine->assembledImage(d->sceneGraphRenderContext()->maxTextureSize());
750 setImplicitWidth(frameWidth());
751 setImplicitHeight(frameHeight());
753 QSGSpriteNode *node = d->sceneGraphContext()->createSpriteNode();
755 d->m_sheetSize = QSize(image.size() / image.devicePixelRatio());
756 node->setTexture(window()->createTextureFromImage(image));
757 d->m_spriteEngine->start(0);
759 node->setSourceA(QPoint(d->m_spriteEngine->spriteX(), d->m_spriteEngine->spriteY()));
760 node->setSourceB(QPoint(d->m_spriteEngine->spriteX(), d->m_spriteEngine->spriteY()));
761 node->setSpriteSize(QSize(d->m_spriteEngine->spriteWidth(), d->m_spriteEngine->spriteHeight()));
762 node->setSheetSize(d->m_sheetSize);
763 node->setSize(QSizeF(width(), height()));
767void QQuickAnimatedSprite::reset()
769 Q_D(QQuickAnimatedSprite);
770 d->m_pleaseReset =
true;
774QSGNode *QQuickAnimatedSprite::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
776 Q_D(QQuickAnimatedSprite);
778 if (d->m_pleaseReset) {
782 d->m_pleaseReset =
false;
785 QSGSpriteNode *node =
static_cast<QSGSpriteNode *>(oldNode);
790 prepareNextFrame(node);
792 if (d->m_running && !d->m_paused)
798void QQuickAnimatedSprite::prepareNextFrame(QSGSpriteNode *node)
800 Q_D(QQuickAnimatedSprite);
802 int timeInt = d->m_timestamp.elapsed() + d->m_pauseOffset;
803 qreal time = timeInt / 1000.;
806 qreal progress = 0.0;
807 int lastFrame = d->m_curFrame;
808 if (d->m_running && !d->m_paused) {
809 const int nColumns = d->m_sheetSize.width() / d->m_spriteEngine->spriteWidth();
811 d->m_spriteEngine->updateSprites(timeInt);
814 qreal animT = d->m_spriteEngine->spriteStart()/1000.0;
815 const int frameCountInRow = d->m_spriteEngine->spriteFrames();
816 const qreal frameDuration = d->m_spriteEngine->spriteDuration() / frameCountInRow;
817 if (frameDuration > 0) {
818 qreal frame = (time - animT)/(frameDuration / 1000.0);
819 bool lastLoop = d->m_loops > 0 && d->m_curLoop == d->m_loops-1;
821 const int max = lastLoop ? frameCountInRow - 1 : frameCountInRow;
822 frame = qBound(qreal(0.0), frame, qreal(max));
824 progress = std::modf(frame,&intpart);
825 frameAt = (
int)intpart;
826 const int rowIndex = d->m_spriteEngine->spriteY()/frameHeight();
827 const int newFrame = rowIndex * nColumns + frameAt;
828 if (d->m_curFrame > newFrame)
830 d->m_curFrame = newFrame;
833 if (d->m_curFrame >= d->m_spriteEngine->maxFrames()) {
837 frameAt = d->m_curFrame % nColumns;
839 d->m_spriteEngine->advance();
842 if (d->m_loops > 0 && d->m_curLoop >= d->m_loops) {
843 if (d->m_finishBehavior == FinishAtInitialFrame)
846 frameAt = frameCount() - 1;
847 d->m_curFrame = frameAt;
848 d->m_running =
false;
849 emit runningChanged(
false);
854 frameAt = d->m_curFrame;
856 if (d->m_curFrame != lastFrame) {
857 if (isCurrentFrameChangedConnected())
858 emit currentFrameChanged(d->m_curFrame);
862 int frameCount = d->m_spriteEngine->spriteFrames();
863 bool reverse = d->m_spriteEngine->sprite()->reverse();
865 frameAt = (frameCount - 1) - frameAt;
867 int w = d->m_spriteEngine->spriteWidth();
868 int h = d->m_spriteEngine->spriteHeight();
872 int spriteY = d->m_spriteEngine->spriteY();
874 int rows = d->m_spriteEngine->maxFrames() * d->m_spriteEngine->spriteWidth() / d->m_sheetSize.width();
875 spriteY -= rows * d->m_spriteEngine->spriteHeight();
876 frameAt = (frameCount - 1) - frameAt;
879 int position = frameAt * d->m_spriteEngine->spriteWidth() + d->m_spriteEngine->spriteX();
880 int row = position / d->m_sheetSize.width();
882 x1 = (position - (row * d->m_sheetSize.width()));
883 y1 = (row * d->m_spriteEngine->spriteHeight() + spriteY);
885 x1 = d->m_spriteEngine->spriteX() + frameAt * w;
886 y1 = d->m_spriteEngine->spriteY();
899 x2 = d->m_sheetSize.width() - w;
903 int maxRowFrames = d->m_sheetSize.width() / d->m_spriteEngine->spriteWidth();
904 if (d->m_spriteEngine->maxFrames() % maxRowFrames)
905 x2 = ((d->m_spriteEngine->maxFrames() % maxRowFrames) - 1) * w;
907 y2 = d->m_sheetSize.height() - h;
911 if (frameAt < (frameCount-1)) {
917 if (y2 >= d->m_sheetSize.height())
922 node->setSourceA(QPoint(x1, y1));
923 node->setSourceB(QPoint(x2, y2));
924 node->setSpriteSize(QSize(w, h));
925 node->setTime(d->m_interpolate ? progress : 0.0);
926 node->setSize(QSizeF(width(), height()));
927 node->setFiltering(smooth() ? QSGTexture::Linear : QSGTexture::Nearest);
933#include "moc_qquickanimatedsprite_p.cpp"