diff options
Diffstat (limited to 'src/quick/items')
-rw-r--r-- | src/quick/items/items.pri | 8 | ||||
-rw-r--r-- | src/quick/items/items.qrc | 4 | ||||
-rw-r--r-- | src/quick/items/qquickanimatedsprite.cpp | 692 | ||||
-rw-r--r-- | src/quick/items/qquickanimatedsprite_p.h | 286 | ||||
-rw-r--r-- | src/quick/items/qquickanimatedsprite_p_p.h | 96 | ||||
-rw-r--r-- | src/quick/items/qquicksprite_p.h | 2 | ||||
-rw-r--r-- | src/quick/items/qquickspriteengine.cpp | 14 | ||||
-rw-r--r-- | src/quick/items/qquickspriteengine_p.h | 2 | ||||
-rw-r--r-- | src/quick/items/qquickspritesequence.cpp | 408 | ||||
-rw-r--r-- | src/quick/items/qquickspritesequence_p.h | 68 | ||||
-rw-r--r-- | src/quick/items/qquickspritesequence_p_p.h | 90 | ||||
-rw-r--r-- | src/quick/items/shaders/sprite.frag | 12 | ||||
-rw-r--r-- | src/quick/items/shaders/sprite.vert | 23 | ||||
-rw-r--r-- | src/quick/items/shaders/sprite_core.frag | 16 | ||||
-rw-r--r-- | src/quick/items/shaders/sprite_core.vert | 24 |
15 files changed, 775 insertions, 970 deletions
diff --git a/src/quick/items/items.pri b/src/quick/items/items.pri index 3f1e438c2b..beaf3540bc 100644 --- a/src/quick/items/items.pri +++ b/src/quick/items/items.pri @@ -83,7 +83,9 @@ HEADERS += \ $$PWD/qquickspriteengine_p.h \ $$PWD/qquicksprite_p.h \ $$PWD/qquickspritesequence_p.h \ - $$PWD/qquickanimatedsprite_p.h + $$PWD/qquickanimatedsprite_p.h \ + $$PWD/qquickanimatedsprite_p_p.h \ + $$PWD/qquickspritesequence_p_p.h SOURCES += \ $$PWD/qquickevents.cpp \ @@ -159,14 +161,10 @@ contains(QT_CONFIG, opengl(es1|es2)?) { $$PWD/qquickframebufferobject.h OTHER_FILES += \ - $$PWD/shaders/sprite.vert \ - $$PWD/shaders/sprite.frag \ $$PWD/shaders/shadereffect.vert \ $$PWD/shaders/shadereffect.frag \ $$PWD/shaders/shadereffectfallback.vert \ $$PWD/shaders/shadereffectfallback.frag \ - $$PWD/shaders/sprite_core.vert \ - $$PWD/shaders/sprite_core.frag \ $$PWD/shaders/shadereffect_core.vert \ $$PWD/shaders/shadereffect_core.frag \ $$PWD/shaders/shadereffectfallback_core.vert \ diff --git a/src/quick/items/items.qrc b/src/quick/items/items.qrc index 99f9b5224f..6aaf757c29 100644 --- a/src/quick/items/items.qrc +++ b/src/quick/items/items.qrc @@ -1,7 +1,5 @@ <RCC> <qresource prefix="/qt-project.org/items"> - <file>shaders/sprite.frag</file> - <file>shaders/sprite.vert</file> <file>shaders/shadereffect.vert</file> <file>shaders/shadereffect.frag</file> <file>shaders/shadereffectfallback.frag</file> @@ -10,7 +8,5 @@ <file>shaders/shadereffect_core.vert</file> <file>shaders/shadereffectfallback_core.frag</file> <file>shaders/shadereffectfallback_core.vert</file> - <file>shaders/sprite_core.frag</file> - <file>shaders/sprite_core.vert</file> </qresource> </RCC> diff --git a/src/quick/items/qquickanimatedsprite.cpp b/src/quick/items/qquickanimatedsprite.cpp index aaa0487afd..991ca8519f 100644 --- a/src/quick/items/qquickanimatedsprite.cpp +++ b/src/quick/items/qquickanimatedsprite.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qquickanimatedsprite_p.h" +#include "qquickanimatedsprite_p_p.h" #include "qquicksprite_p.h" #include "qquickspriteengine_p.h" #include <QtQuick/private/qsgcontext_p.h> @@ -55,117 +56,6 @@ QT_BEGIN_NAMESPACE -class QQuickAnimatedSpriteMaterial : public QSGMaterial -{ -public: - QQuickAnimatedSpriteMaterial(); - ~QQuickAnimatedSpriteMaterial(); - QSGMaterialType *type() const Q_DECL_OVERRIDE { static QSGMaterialType type; return &type; } - QSGMaterialShader *createShader() const Q_DECL_OVERRIDE; - int compare(const QSGMaterial *other) const Q_DECL_OVERRIDE - { - return this - static_cast<const QQuickAnimatedSpriteMaterial *>(other); - } - - QSGTexture *texture; - - float animT; - float animX1; - float animY1; - float animX2; - float animY2; - float animW; - float animH; -}; - -QQuickAnimatedSpriteMaterial::QQuickAnimatedSpriteMaterial() - : texture(0) - , animT(0.0f) - , animX1(0.0f) - , animY1(0.0f) - , animX2(0.0f) - , animY2(0.0f) - , animW(1.0f) - , animH(1.0f) -{ - setFlag(Blending, true); -} - -QQuickAnimatedSpriteMaterial::~QQuickAnimatedSpriteMaterial() -{ - delete texture; -} - -#ifndef QT_NO_OPENGL -class AnimatedSpriteMaterialData : public QSGMaterialShader -{ -public: - AnimatedSpriteMaterialData() - : QSGMaterialShader() - { - setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/items/shaders/sprite.vert")); - setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/items/shaders/sprite.frag")); - } - - void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *) Q_DECL_OVERRIDE - { - QQuickAnimatedSpriteMaterial *m = static_cast<QQuickAnimatedSpriteMaterial *>(newEffect); - m->texture->bind(); - - program()->setUniformValue(m_opacity_id, state.opacity()); - program()->setUniformValue(m_animData_id, m->animW, m->animH, m->animT); - program()->setUniformValue(m_animPos_id, m->animX1, m->animY1, m->animX2, m->animY2); - - if (state.isMatrixDirty()) - program()->setUniformValue(m_matrix_id, state.combinedMatrix()); - } - - void initialize() Q_DECL_OVERRIDE { - m_matrix_id = program()->uniformLocation("qt_Matrix"); - m_opacity_id = program()->uniformLocation("qt_Opacity"); - m_animData_id = program()->uniformLocation("animData"); - m_animPos_id = program()->uniformLocation("animPos"); - } - - char const *const *attributeNames() const Q_DECL_OVERRIDE { - static const char *attr[] = { - "vPos", - "vTex", - 0 - }; - return attr; - } - - int m_matrix_id; - int m_opacity_id; - int m_animData_id; - int m_animPos_id; -}; -#endif - -QSGMaterialShader *QQuickAnimatedSpriteMaterial::createShader() const -{ -#ifndef QT_NO_OPENGL - return new AnimatedSpriteMaterialData; -#else - return nullptr; -#endif -} - -struct AnimatedSpriteVertex { - float x; - float y; - float tx; - float ty; -}; - -struct AnimatedSpriteVertices { - AnimatedSpriteVertex v1; - AnimatedSpriteVertex v2; - AnimatedSpriteVertex v3; - AnimatedSpriteVertex v4; -}; - /*! \qmltype AnimatedSprite \instantiates QQuickAnimatedSprite @@ -321,18 +211,11 @@ struct AnimatedSpriteVertices { //TODO: Implicitly size element to size of sprite QQuickAnimatedSprite::QQuickAnimatedSprite(QQuickItem *parent) : - QQuickItem(parent) - , m_sprite(new QQuickSprite(this)) - , m_spriteEngine(0) - , m_curFrame(0) - , m_pleaseReset(false) - , m_running(true) - , m_paused(false) - , m_interpolate(true) - , m_loops(-1) - , m_curLoop(0) - , m_pauseOffset(0) + QQuickItem(*(new QQuickAnimatedSpritePrivate), parent) { + Q_D(QQuickAnimatedSprite); + d->m_sprite = new QQuickSprite(this); + setFlag(ItemHasContents); connect(this, SIGNAL(widthChanged()), this, SLOT(reset())); @@ -340,6 +223,96 @@ QQuickAnimatedSprite::QQuickAnimatedSprite(QQuickItem *parent) : this, SLOT(reset())); } +bool QQuickAnimatedSprite::running() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_running; +} + +bool QQuickAnimatedSprite::interpolate() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_interpolate; +} + +QUrl QQuickAnimatedSprite::source() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_sprite->source(); +} + +bool QQuickAnimatedSprite::reverse() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_sprite->reverse(); +} + +bool QQuickAnimatedSprite::frameSync() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_sprite->frameSync(); +} + +int QQuickAnimatedSprite::frameCount() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_sprite->frames(); +} + +int QQuickAnimatedSprite::frameHeight() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_sprite->frameHeight(); +} + +int QQuickAnimatedSprite::frameWidth() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_sprite->frameWidth(); +} + +int QQuickAnimatedSprite::frameX() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_sprite->frameX(); +} + +int QQuickAnimatedSprite::frameY() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_sprite->frameY(); +} + +qreal QQuickAnimatedSprite::frameRate() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_sprite->frameRate(); +} + +int QQuickAnimatedSprite::frameDuration() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_sprite->frameDuration(); +} + +int QQuickAnimatedSprite::loops() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_loops; +} + +bool QQuickAnimatedSprite::paused() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_paused; +} + +int QQuickAnimatedSprite::currentFrame() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_curFrame; +} + bool QQuickAnimatedSprite::isCurrentFrameChangedConnected() { IS_SIGNAL_CONNECTED(this, QQuickAnimatedSprite, currentFrameChanged, (int)); @@ -354,23 +327,25 @@ void QQuickAnimatedSprite::reloadImage() void QQuickAnimatedSprite::componentComplete() { + Q_D(const QQuickAnimatedSprite); createEngine(); QQuickItem::componentComplete(); - if (m_running) + if (d->m_running) start(); } void QQuickAnimatedSprite::start() { - m_running = true; + Q_D(QQuickAnimatedSprite); + d->m_running = true; if (!isComponentComplete()) return; - m_curLoop = 0; - m_timestamp.start(); - if (m_spriteEngine) { - m_spriteEngine->stop(0); - m_spriteEngine->updateSprites(0); - m_spriteEngine->start(0); + d->m_curLoop = 0; + d->m_timestamp.start(); + if (d->m_spriteEngine) { + d->m_spriteEngine->stop(0); + d->m_spriteEngine->updateSprites(0); + d->m_spriteEngine->start(0); } emit currentFrameChanged(0); emit runningChanged(true); @@ -379,10 +354,11 @@ void QQuickAnimatedSprite::start() void QQuickAnimatedSprite::stop() { - m_running = false; + Q_D(QQuickAnimatedSprite); + d->m_running = false; if (!isComponentComplete()) return; - m_pauseOffset = 0; + d->m_pauseOffset = 0; emit runningChanged(false); update(); } @@ -394,14 +370,15 @@ void QQuickAnimatedSprite::stop() */ void QQuickAnimatedSprite::advance(int frames) { + Q_D(QQuickAnimatedSprite); if (!frames) return; //TODO-C: May not work when running - only when paused - m_curFrame += frames; - while (m_curFrame < 0) - m_curFrame += m_spriteEngine->maxFrames(); - m_curFrame = m_curFrame % m_spriteEngine->maxFrames(); - emit currentFrameChanged(m_curFrame); + d->m_curFrame += frames; + while (d->m_curFrame < 0) + d->m_curFrame += d->m_spriteEngine->maxFrames(); + d->m_curFrame = d->m_curFrame % d->m_spriteEngine->maxFrames(); + emit currentFrameChanged(d->m_curFrame); update(); } @@ -415,10 +392,12 @@ void QQuickAnimatedSprite::advance(int frames) */ void QQuickAnimatedSprite::pause() { - if (m_paused) + Q_D(QQuickAnimatedSprite); + + if (d->m_paused) return; - m_pauseOffset = m_timestamp.elapsed(); - m_paused = true; + d->m_pauseOffset = d->m_timestamp.elapsed(); + d->m_paused = true; emit pausedChanged(true); update(); } @@ -433,246 +412,363 @@ void QQuickAnimatedSprite::pause() */ void QQuickAnimatedSprite::resume() { - if (!m_paused) + Q_D(QQuickAnimatedSprite); + + if (!d->m_paused) return; - m_pauseOffset = m_pauseOffset - m_timestamp.elapsed(); - m_paused = false; + d->m_pauseOffset = d->m_pauseOffset - d->m_timestamp.elapsed(); + d->m_paused = false; emit pausedChanged(false); update(); } -void QQuickAnimatedSprite::createEngine() +void QQuickAnimatedSprite::setRunning(bool arg) { - if (m_spriteEngine) - delete m_spriteEngine; - QList<QQuickSprite*> spriteList; - spriteList << m_sprite; - m_spriteEngine = new QQuickSpriteEngine(QList<QQuickSprite*>(spriteList), this); - m_spriteEngine->startAssemblingImage(); - reset(); - update(); + Q_D(QQuickAnimatedSprite); + + if (d->m_running != arg) { + if (d->m_running) + stop(); + else + start(); + } } -static QSGGeometry::Attribute AnimatedSprite_Attributes[] = { - QSGGeometry::Attribute::create(0, 2, QSGGeometry::TypeFloat, true), // pos - QSGGeometry::Attribute::create(1, 2, QSGGeometry::TypeFloat), // tex -}; +void QQuickAnimatedSprite::setPaused(bool arg) +{ + Q_D(const QQuickAnimatedSprite); -static QSGGeometry::AttributeSet AnimatedSprite_AttributeSet = + if (d->m_paused != arg) { + if (d->m_paused) + resume(); + else + pause(); + } +} + +void QQuickAnimatedSprite::setInterpolate(bool arg) +{ + Q_D(QQuickAnimatedSprite); + + if (d->m_interpolate != arg) { + d->m_interpolate = arg; + Q_EMIT interpolateChanged(arg); + } +} + +void QQuickAnimatedSprite::setSource(QUrl arg) +{ + Q_D(QQuickAnimatedSprite); + + if (d->m_sprite->m_source != arg) { + d->m_sprite->setSource(arg); + Q_EMIT sourceChanged(arg); + reloadImage(); + } +} + +void QQuickAnimatedSprite::setReverse(bool arg) +{ + Q_D(QQuickAnimatedSprite); + + if (d->m_sprite->m_reverse != arg) { + d->m_sprite->setReverse(arg); + Q_EMIT reverseChanged(arg); + } +} + +void QQuickAnimatedSprite::setFrameSync(bool arg) +{ + Q_D(QQuickAnimatedSprite); + + if (d->m_sprite->m_frameSync != arg) { + d->m_sprite->setFrameSync(arg); + Q_EMIT frameSyncChanged(arg); + if (d->m_running) + restart(); + } +} + +void QQuickAnimatedSprite::setFrameCount(int arg) { - 2, // Attribute Count - (2+2) * sizeof(float), - AnimatedSprite_Attributes -}; + Q_D(QQuickAnimatedSprite); + + if (d->m_sprite->m_frames != arg) { + d->m_sprite->setFrameCount(arg); + Q_EMIT frameCountChanged(arg); + reloadImage(); + } +} -void QQuickAnimatedSprite::sizeVertices(QSGGeometryNode *node) +void QQuickAnimatedSprite::setFrameHeight(int arg) { - AnimatedSpriteVertices *p = (AnimatedSpriteVertices *) node->geometry()->vertexData(); - p->v1.x = 0; - p->v1.y = 0; + Q_D(QQuickAnimatedSprite); - p->v2.x = width(); - p->v2.y = 0; + if (d->m_sprite->m_frameHeight != arg) { + d->m_sprite->setFrameHeight(arg); + Q_EMIT frameHeightChanged(arg); + reloadImage(); + } +} - p->v3.x = 0; - p->v3.y = height(); +void QQuickAnimatedSprite::setFrameWidth(int arg) +{ + Q_D(QQuickAnimatedSprite); - p->v4.x = width(); - p->v4.y = height(); + if (d->m_sprite->m_frameWidth != arg) { + d->m_sprite->setFrameWidth(arg); + Q_EMIT frameWidthChanged(arg); + reloadImage(); + } } -QSGGeometryNode* QQuickAnimatedSprite::buildNode() +void QQuickAnimatedSprite::setFrameX(int arg) { - if (!m_spriteEngine) { + Q_D(QQuickAnimatedSprite); + + if (d->m_sprite->m_frameX != arg) { + d->m_sprite->setFrameX(arg); + Q_EMIT frameXChanged(arg); + reloadImage(); + } +} + +void QQuickAnimatedSprite::setFrameY(int arg) +{ + Q_D(QQuickAnimatedSprite); + + if (d->m_sprite->m_frameY != arg) { + d->m_sprite->setFrameY(arg); + Q_EMIT frameYChanged(arg); + reloadImage(); + } +} + +void QQuickAnimatedSprite::setFrameRate(qreal arg) +{ + Q_D(QQuickAnimatedSprite); + + if (d->m_sprite->m_frameRate != arg) { + d->m_sprite->setFrameRate(arg); + Q_EMIT frameRateChanged(arg); + if (d->m_running) + restart(); + } +} + +void QQuickAnimatedSprite::setFrameDuration(int arg) +{ + Q_D(QQuickAnimatedSprite); + + if (d->m_sprite->m_frameDuration != arg) { + d->m_sprite->setFrameDuration(arg); + Q_EMIT frameDurationChanged(arg); + if (d->m_running) + restart(); + } +} + +void QQuickAnimatedSprite::resetFrameRate() +{ + setFrameRate(-1.0); +} + +void QQuickAnimatedSprite::resetFrameDuration() +{ + setFrameDuration(-1); +} + +void QQuickAnimatedSprite::setLoops(int arg) +{ + Q_D(QQuickAnimatedSprite); + + if (d->m_loops != arg) { + d->m_loops = arg; + Q_EMIT loopsChanged(arg); + } +} + +void QQuickAnimatedSprite::setCurrentFrame(int arg) //TODO-C: Probably only works when paused +{ + Q_D(QQuickAnimatedSprite); + + if (d->m_curFrame != arg) { + d->m_curFrame = arg; + Q_EMIT currentFrameChanged(arg); //TODO-C Only emitted on manual advance! + update(); + } +} + +void QQuickAnimatedSprite::createEngine() +{ + Q_D(QQuickAnimatedSprite); + + if (d->m_spriteEngine) + delete d->m_spriteEngine; + QList<QQuickSprite*> spriteList; + spriteList << d->m_sprite; + d->m_spriteEngine = new QQuickSpriteEngine(QList<QQuickSprite*>(spriteList), this); + d->m_spriteEngine->startAssemblingImage(); + reset(); + update(); +} + +QSGSpriteNode* QQuickAnimatedSprite::initNode() +{ + Q_D(QQuickAnimatedSprite); + + if (!d->m_spriteEngine) { qmlInfo(this) << "No sprite engine..."; - return 0; - } else if (m_spriteEngine->status() == QQuickPixmap::Null) { - m_spriteEngine->startAssemblingImage(); + return nullptr; + } else if (d->m_spriteEngine->status() == QQuickPixmap::Null) { + d->m_spriteEngine->startAssemblingImage(); update();//Schedule another update, where we will check again - return 0; - } else if (m_spriteEngine->status() == QQuickPixmap::Loading) { + return nullptr; + } else if (d->m_spriteEngine->status() == QQuickPixmap::Loading) { update();//Schedule another update, where we will check again - return 0; + return nullptr; } - QQuickAnimatedSpriteMaterial *material = new QQuickAnimatedSpriteMaterial(); - - QImage image = m_spriteEngine->assembledImage(); //Engine prints errors if there are any + QImage image = d->m_spriteEngine->assembledImage(d->sceneGraphRenderContext()->maxTextureSize()); //Engine prints errors if there are any if (image.isNull()) - return 0; - m_sheetSize = QSizeF(image.size()); - material->texture = window()->createTextureFromImage(image); - m_spriteEngine->start(0); - material->animT = 0; - material->animX1 = m_spriteEngine->spriteX() / m_sheetSize.width(); - material->animY1 = m_spriteEngine->spriteY() / m_sheetSize.height(); - material->animX2 = material->animX1; - material->animY2 = material->animY1; - material->animW = m_spriteEngine->spriteWidth() / m_sheetSize.width(); - material->animH = m_spriteEngine->spriteHeight() / m_sheetSize.height(); - - int vCount = 4; - int iCount = 6; - QSGGeometry *g = new QSGGeometry(AnimatedSprite_AttributeSet, vCount, iCount); - g->setDrawingMode(QSGGeometry::DrawTriangles); - - AnimatedSpriteVertices *p = (AnimatedSpriteVertices *) g->vertexData(); - - QRectF texRect = material->texture->normalizedTextureSubRect(); - - p->v1.tx = texRect.topLeft().x(); - p->v1.ty = texRect.topLeft().y(); - - p->v2.tx = texRect.topRight().x(); - p->v2.ty = texRect.topRight().y(); - - p->v3.tx = texRect.bottomLeft().x(); - p->v3.ty = texRect.bottomLeft().y(); - - p->v4.tx = texRect.bottomRight().x(); - p->v4.ty = texRect.bottomRight().y(); - - quint16 *indices = g->indexDataAsUShort(); - indices[0] = 0; - indices[1] = 1; - indices[2] = 2; - indices[3] = 1; - indices[4] = 3; - indices[5] = 2; - - - QSGGeometryNode *node = new QSGGeometryNode(); - node->setGeometry(g); - node->setMaterial(material); - node->setFlag(QSGGeometryNode::OwnsMaterial); - node->setFlag(QSGGeometryNode::OwnsGeometry); - sizeVertices(node); + return nullptr; + + QSGSpriteNode *node = d->sceneGraphContext()->createSpriteNode(); + + d->m_sheetSize = QSize(image.size()); + node->setTexture(window()->createTextureFromImage(image)); + d->m_spriteEngine->start(0); + node->setTime(0.0f); + node->setSourceA(QPoint(d->m_spriteEngine->spriteX(), d->m_spriteEngine->spriteY())); + node->setSourceB(QPoint(d->m_spriteEngine->spriteX(), d->m_spriteEngine->spriteY())); + node->setSpriteSize(QSize(d->m_spriteEngine->spriteWidth(), d->m_spriteEngine->spriteHeight())); + node->setSheetSize(d->m_sheetSize); + node->setSize(QSizeF(width(), height())); return node; } void QQuickAnimatedSprite::reset() { - m_pleaseReset = true; + Q_D(QQuickAnimatedSprite); + d->m_pleaseReset = true; update(); } QSGNode *QQuickAnimatedSprite::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) { - if (m_pleaseReset) { + Q_D(QQuickAnimatedSprite); + + if (d->m_pleaseReset) { delete oldNode; - oldNode = 0; - m_pleaseReset = false; + oldNode = nullptr; + d->m_pleaseReset = false; } - QSGGeometryNode *node = static_cast<QSGGeometryNode *>(oldNode); + QSGSpriteNode *node = static_cast<QSGSpriteNode *>(oldNode); if (!node) - node = buildNode(); + node = initNode(); if (node) prepareNextFrame(node); - if (m_running) { - if (!m_paused) - update(); - - if (node) { - node->markDirty(QSGNode::DirtyMaterial); - } - } + if (d->m_running && !d->m_paused) + update(); return node; } -void QQuickAnimatedSprite::prepareNextFrame(QSGGeometryNode *node) +void QQuickAnimatedSprite::prepareNextFrame(QSGSpriteNode *node) { - int timeInt = m_timestamp.elapsed() + m_pauseOffset; + Q_D(QQuickAnimatedSprite); + + int timeInt = d->m_timestamp.elapsed() + d->m_pauseOffset; qreal time = timeInt / 1000.; int frameAt; qreal progress = 0.0; - int lastFrame = m_curFrame; - if (m_running && !m_paused) { - const int nColumns = int(m_sheetSize.width()) / m_spriteEngine->spriteWidth(); + int lastFrame = d->m_curFrame; + if (d->m_running && !d->m_paused) { + const int nColumns = d->m_sheetSize.width() / d->m_spriteEngine->spriteWidth(); //Advance State (keeps time for psuedostates) - m_spriteEngine->updateSprites(timeInt); + d->m_spriteEngine->updateSprites(timeInt); //Advance AnimatedSprite - qreal animT = m_spriteEngine->spriteStart()/1000.0; - const int frameCountInRow = m_spriteEngine->spriteFrames(); - const qreal frameDuration = m_spriteEngine->spriteDuration()/frameCountInRow; + qreal animT = d->m_spriteEngine->spriteStart()/1000.0; + const int frameCountInRow = d->m_spriteEngine->spriteFrames(); + const qreal frameDuration = d->m_spriteEngine->spriteDuration() / frameCountInRow; if (frameDuration > 0) { qreal frame = (time - animT)/(frameDuration / 1000.0); - bool lastLoop = m_loops > 0 && m_curLoop == m_loops-1; + bool lastLoop = d->m_loops > 0 && d->m_curLoop == d->m_loops-1; //don't visually interpolate for the last frame of the last loop const int max = lastLoop ? frameCountInRow - 1 : frameCountInRow; frame = qBound(qreal(0.0), frame, qreal(max)); double intpart; progress = std::modf(frame,&intpart); frameAt = (int)intpart; - const int rowIndex = m_spriteEngine->spriteY()/frameHeight(); + const int rowIndex = d->m_spriteEngine->spriteY()/frameHeight(); const int newFrame = rowIndex * nColumns + frameAt; - if (m_curFrame > newFrame) //went around - m_curLoop++; - m_curFrame = newFrame; + if (d->m_curFrame > newFrame) //went around + d->m_curLoop++; + d->m_curFrame = newFrame; } else { - m_curFrame++; - if (m_curFrame >= m_spriteEngine->maxFrames()) { // maxFrames: total number of frames including all rows - m_curFrame = 0; - m_curLoop++; + d->m_curFrame++; + if (d->m_curFrame >= d->m_spriteEngine->maxFrames()) { // maxFrames: total number of frames including all rows + d->m_curFrame = 0; + d->m_curLoop++; } - frameAt = m_curFrame % nColumns; + frameAt = d->m_curFrame % nColumns; if (frameAt == 0) - m_spriteEngine->advance(); + d->m_spriteEngine->advance(); progress = 0; } - if (m_loops > 0 && m_curLoop >= m_loops) { + if (d->m_loops > 0 && d->m_curLoop >= d->m_loops) { frameAt = 0; - m_running = false; + d->m_running = false; emit runningChanged(false); update(); } } else { - frameAt = m_curFrame; + frameAt = d->m_curFrame; } - if (m_curFrame != lastFrame) { + if (d->m_curFrame != lastFrame) { if (isCurrentFrameChangedConnected()) - emit currentFrameChanged(m_curFrame); + emit currentFrameChanged(d->m_curFrame); update(); } - qreal frameCount = m_spriteEngine->spriteFrames(); - bool reverse = m_spriteEngine->sprite()->reverse(); + qreal frameCount = d->m_spriteEngine->spriteFrames(); + bool reverse = d->m_spriteEngine->sprite()->reverse(); if (reverse) frameAt = (frameCount - 1) - frameAt; - qreal w = m_spriteEngine->spriteWidth() / m_sheetSize.width(); - qreal h = m_spriteEngine->spriteHeight() / m_sheetSize.height(); - qreal x1; - qreal y1; - if (m_paused) { - int spriteY = m_spriteEngine->spriteY(); + int w = d->m_spriteEngine->spriteWidth(); + int h = d->m_spriteEngine->spriteHeight(); + int x1; + int y1; + if (d->m_paused) { + int spriteY = d->m_spriteEngine->spriteY(); if (reverse) { - int rows = m_spriteEngine->maxFrames() * m_spriteEngine->spriteWidth() / m_sheetSize.width(); - spriteY -= rows * m_spriteEngine->spriteHeight(); + int rows = d->m_spriteEngine->maxFrames() * d->m_spriteEngine->spriteWidth() / d->m_sheetSize.width(); + spriteY -= rows * d->m_spriteEngine->spriteHeight(); frameAt = (frameCount - 1) - frameAt; } - int position = frameAt * m_spriteEngine->spriteWidth() + m_spriteEngine->spriteX(); - int row = position / m_sheetSize.width(); + int position = frameAt * d->m_spriteEngine->spriteWidth() + d->m_spriteEngine->spriteX(); + int row = position / d->m_sheetSize.width(); - x1 = (position - (row * m_sheetSize.width())) / m_sheetSize.width(); - y1 = (row * m_spriteEngine->spriteHeight() + spriteY) / m_sheetSize.height(); + x1 = (position - (row * d->m_sheetSize.width())); + y1 = (row * d->m_spriteEngine->spriteHeight() + spriteY); } else { - x1 = m_spriteEngine->spriteX() / m_sheetSize.width() + frameAt * w; - y1 = m_spriteEngine->spriteY() / m_sheetSize.height(); + x1 = d->m_spriteEngine->spriteX() + frameAt * w; + y1 = d->m_spriteEngine->spriteY(); } //### hard-coded 0/1 work because we are the only // images in the sprite sheet (without this we cannot assume // where in the sheet we begin/end). - qreal x2; - qreal y2; + int x2; + int y2; if (reverse) { if (frameAt > 0) { x2 = x1 - w; @@ -682,9 +778,9 @@ void QQuickAnimatedSprite::prepareNextFrame(QSGGeometryNode *node) y2 = y1 - h; if (y2 < 0.0) { //the last row may not fill the entire width - int maxRowFrames = m_sheetSize.width() / m_spriteEngine->spriteWidth(); - if (m_spriteEngine->maxFrames() % maxRowFrames) - x2 = ((m_spriteEngine->maxFrames() % maxRowFrames) - 1) * w; + int maxRowFrames = d->m_sheetSize.width() / d->m_spriteEngine->spriteWidth(); + if (d->m_spriteEngine->maxFrames() % maxRowFrames) + x2 = ((d->m_spriteEngine->maxFrames() % maxRowFrames) - 1) * w; y2 = 1.0 - h; } @@ -701,15 +797,13 @@ void QQuickAnimatedSprite::prepareNextFrame(QSGGeometryNode *node) } } - QQuickAnimatedSpriteMaterial *material = static_cast<QQuickAnimatedSpriteMaterial *>(node->material()); - material->animX1 = x1; - material->animY1 = y1; - material->animX2 = x2; - material->animY2 = y2; - material->animW = w; - material->animH = h; - material->animT = m_interpolate ? progress : 0.0; - material->texture->setFiltering(smooth() ? QSGTexture::Linear : QSGTexture::Nearest); + node->setSourceA(QPoint(x1, y1)); + node->setSourceB(QPoint(x2, y2)); + node->setSpriteSize(QSize(w, h)); + node->setTime(d->m_interpolate ? progress : 0.0); + node->setSize(QSizeF(width(), height())); + node->setFiltering(smooth() ? QSGTexture::Linear : QSGTexture::Nearest); + node->update(); } QT_END_NAMESPACE diff --git a/src/quick/items/qquickanimatedsprite_p.h b/src/quick/items/qquickanimatedsprite_p.h index 1e5981c1a4..cbd6524c40 100644 --- a/src/quick/items/qquickanimatedsprite_p.h +++ b/src/quick/items/qquickanimatedsprite_p.h @@ -62,6 +62,8 @@ class QQuickSprite; class QQuickSpriteEngine; class QSGGeometryNode; class QQuickAnimatedSpriteMaterial; +class QQuickAnimatedSpritePrivate; +class QSGSpriteNode; class Q_AUTOTEST_EXPORT QQuickAnimatedSprite : public QQuickItem { Q_OBJECT @@ -94,80 +96,21 @@ public: }; Q_ENUM(LoopParameters) - bool running() const - { - return m_running; - } - - bool interpolate() const - { - return m_interpolate; - } - - QUrl source() const - { - return m_sprite->source(); - } - - bool reverse() const - { - return m_sprite->reverse(); - } - - bool frameSync() const - { - return m_sprite->frameSync(); - } - - int frameCount() const - { - return m_sprite->frames(); - } - - int frameHeight() const - { - return m_sprite->frameHeight(); - } - - int frameWidth() const - { - return m_sprite->frameWidth(); - } - - int frameX() const - { - return m_sprite->frameX(); - } - - int frameY() const - { - return m_sprite->frameY(); - } - - qreal frameRate() const - { - return m_sprite->frameRate(); - } - - int frameDuration() const - { - return m_sprite->frameDuration(); - } - - int loops() const - { - return m_loops; - } - - bool paused() const - { - return m_paused; - } - - int currentFrame() const - { - return m_curFrame; - } + bool running() const; + bool interpolate() const; + QUrl source() const; + bool reverse() const; + bool frameSync() const; + int frameCount() const; + int frameHeight() const; + int frameWidth() const; + int frameX() const; + int frameY() const; + qreal frameRate() const; + int frameDuration() const; + int loops() const; + bool paused() const; + int currentFrame() const; Q_SIGNALS: @@ -176,27 +119,16 @@ Q_SIGNALS: void interpolateChanged(bool arg); void sourceChanged(QUrl arg); - void reverseChanged(bool arg); - void frameSyncChanged(bool arg); - void frameCountChanged(int arg); - void frameHeightChanged(int arg); - void frameWidthChanged(int arg); - void frameXChanged(int arg); - void frameYChanged(int arg); - void frameRateChanged(qreal arg); - void frameDurationChanged(int arg); - void loopsChanged(int arg); - void currentFrameChanged(int arg); public Q_SLOTS: @@ -207,157 +139,27 @@ public Q_SLOTS: void pause(); void resume(); - void setRunning(bool arg) - { - if (m_running != arg) { - if (m_running) - stop(); - else - start(); - } - } - - void setPaused(bool arg) - { - if (m_paused != arg) { - if (m_paused) - resume(); - else - pause(); - } - } - - void setInterpolate(bool arg) - { - if (m_interpolate != arg) { - m_interpolate = arg; - Q_EMIT interpolateChanged(arg); - } - } - - void setSource(QUrl arg) - { - if (m_sprite->m_source != arg) { - m_sprite->setSource(arg); - Q_EMIT sourceChanged(arg); - reloadImage(); - } - } - - void setReverse(bool arg) - { - if (m_sprite->m_reverse != arg) { - m_sprite->setReverse(arg); - Q_EMIT reverseChanged(arg); - } - } - - void setFrameSync(bool arg) - { - if (m_sprite->m_frameSync != arg) { - m_sprite->setFrameSync(arg); - Q_EMIT frameSyncChanged(arg); - if (m_running) - restart(); - } - } - - void setFrameCount(int arg) - { - if (m_sprite->m_frames != arg) { - m_sprite->setFrameCount(arg); - Q_EMIT frameCountChanged(arg); - reloadImage(); - } - } - - void setFrameHeight(int arg) - { - if (m_sprite->m_frameHeight != arg) { - m_sprite->setFrameHeight(arg); - Q_EMIT frameHeightChanged(arg); - reloadImage(); - } - } - - void setFrameWidth(int arg) - { - if (m_sprite->m_frameWidth != arg) { - m_sprite->setFrameWidth(arg); - Q_EMIT frameWidthChanged(arg); - reloadImage(); - } - } - - void setFrameX(int arg) - { - if (m_sprite->m_frameX != arg) { - m_sprite->setFrameX(arg); - Q_EMIT frameXChanged(arg); - reloadImage(); - } - } - - void setFrameY(int arg) - { - if (m_sprite->m_frameY != arg) { - m_sprite->setFrameY(arg); - Q_EMIT frameYChanged(arg); - reloadImage(); - } - } - - void setFrameRate(qreal arg) - { - if (m_sprite->m_frameRate != arg) { - m_sprite->setFrameRate(arg); - Q_EMIT frameRateChanged(arg); - if (m_running) - restart(); - } - } - - void setFrameDuration(int arg) - { - if (m_sprite->m_frameDuration != arg) { - m_sprite->setFrameDuration(arg); - Q_EMIT frameDurationChanged(arg); - if (m_running) - restart(); - } - } - - void resetFrameRate() - { - setFrameRate(-1.0); - } - - void resetFrameDuration() - { - setFrameDuration(-1); - } - - void setLoops(int arg) - { - if (m_loops != arg) { - m_loops = arg; - Q_EMIT loopsChanged(arg); - } - } - - void setCurrentFrame(int arg) //TODO-C: Probably only works when paused - { - if (m_curFrame != arg) { - m_curFrame = arg; - Q_EMIT currentFrameChanged(arg); //TODO-C Only emitted on manual advance! - update(); - } - } + void setRunning(bool arg); + void setPaused(bool arg); + void setInterpolate(bool arg); + void setSource(QUrl arg); + void setReverse(bool arg); + void setFrameSync(bool arg); + void setFrameCount(int arg); + void setFrameHeight(int arg); + void setFrameWidth(int arg); + void setFrameX(int arg); + void setFrameY(int arg); + void setFrameRate(qreal arg); + void setFrameDuration(int arg); + void resetFrameRate(); + void resetFrameDuration(); + void setLoops(int arg); + void setCurrentFrame(int arg); private Q_SLOTS: void createEngine(); - void sizeVertices(QSGGeometryNode *node); protected Q_SLOTS: void reset(); @@ -367,21 +169,13 @@ protected: QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE; private: bool isCurrentFrameChangedConnected(); - void prepareNextFrame(QSGGeometryNode *node); + void prepareNextFrame(QSGSpriteNode *node); void reloadImage(); - QSGGeometryNode* buildNode(); - QQuickSprite* m_sprite; - QQuickSpriteEngine* m_spriteEngine; - QElapsedTimer m_timestamp; - int m_curFrame; - bool m_pleaseReset; - bool m_running; - bool m_paused; - bool m_interpolate; - QSizeF m_sheetSize; - int m_loops; - int m_curLoop; - int m_pauseOffset; + QSGSpriteNode* initNode(); + +private: + Q_DISABLE_COPY(QQuickAnimatedSprite) + Q_DECLARE_PRIVATE(QQuickAnimatedSprite) }; QT_END_NAMESPACE diff --git a/src/quick/items/qquickanimatedsprite_p_p.h b/src/quick/items/qquickanimatedsprite_p_p.h new file mode 100644 index 0000000000..0e4a1e9066 --- /dev/null +++ b/src/quick/items/qquickanimatedsprite_p_p.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKANIMATEDSPRITE_P_P_H +#define QQUICKANIMATEDSPRITE_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qquickitem_p.h" +#include "qquicksprite_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickAnimatedSprite; + +class QQuickAnimatedSpritePrivate : public QQuickItemPrivate +{ + Q_DECLARE_PUBLIC(QQuickAnimatedSprite) + +public: + QQuickAnimatedSpritePrivate() + : m_sprite(nullptr) + , m_spriteEngine(nullptr) + , m_curFrame(0) + , m_pleaseReset(false) + , m_running(true) + , m_paused(false) + , m_interpolate(true) + , m_loops(-1) + , m_curLoop(0) + , m_pauseOffset(0) + { + } + + QQuickSprite* m_sprite; + QQuickSpriteEngine* m_spriteEngine; + QElapsedTimer m_timestamp; + int m_curFrame; + bool m_pleaseReset; + bool m_running; + bool m_paused; + bool m_interpolate; + QSize m_sheetSize; + int m_loops; + int m_curLoop; + int m_pauseOffset; +}; + +QT_END_NAMESPACE + +#endif // QQUICKANIMATEDSPRITE_P_P_H diff --git a/src/quick/items/qquicksprite_p.h b/src/quick/items/qquicksprite_p.h index 1b8c8cee84..684d432f39 100644 --- a/src/quick/items/qquicksprite_p.h +++ b/src/quick/items/qquicksprite_p.h @@ -300,7 +300,7 @@ private Q_SLOTS: private: friend class QQuickImageParticle; - friend class QQuickSpriteSequence; + //friend class QQuickSpriteSequence; friend class QQuickAnimatedSprite; friend class QQuickSpriteEngine; friend class QQuickStochasticEngine; diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp index 2137c8d8d5..083e02fe3f 100644 --- a/src/quick/items/qquickspriteengine.cpp +++ b/src/quick/items/qquickspriteengine.cpp @@ -372,7 +372,7 @@ void QQuickSpriteEngine::startAssemblingImage() m_startedImageAssembly = true; } -QImage QQuickSpriteEngine::assembledImage() +QImage QQuickSpriteEngine::assembledImage(int maxSize) { QQuickPixmap::Status stat = status(); if (!m_errorsPrinted && stat == QQuickPixmap::Error) { @@ -389,19 +389,7 @@ QImage QQuickSpriteEngine::assembledImage() int w = 0; m_maxFrames = 0; m_imageStateCount = 0; - int maxSize = 0; -#ifndef QT_NO_OPENGL - //If there is no current OpenGL Context - if (!QOpenGLContext::currentContext()) - return QImage(); - QOpenGLContext::currentContext()->functions()->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize); -#else - maxSize = 2048; -#endif -#ifdef SPRITE_IMAGE_DEBUG - qDebug() << "MAX TEXTURE SIZE" << maxSize; -#endif foreach (QQuickSprite* state, m_sprites){ if (state->frames() > m_maxFrames) m_maxFrames = state->frames(); diff --git a/src/quick/items/qquickspriteengine_p.h b/src/quick/items/qquickspriteengine_p.h index 65f58fafcb..1bdcc9a741 100644 --- a/src/quick/items/qquickspriteengine_p.h +++ b/src/quick/items/qquickspriteengine_p.h @@ -295,7 +295,7 @@ public: bool isError() { return status() == QQuickPixmap::Error; } QQuickPixmap::Status status();//Composed status of all Sprites void startAssemblingImage(); - QImage assembledImage(); + QImage assembledImage(int maxSize = 2048); private: int pseudospriteProgress(int,int,int*rd=0); diff --git a/src/quick/items/qquickspritesequence.cpp b/src/quick/items/qquickspritesequence.cpp index 6654c7a964..25a39f951a 100644 --- a/src/quick/items/qquickspritesequence.cpp +++ b/src/quick/items/qquickspritesequence.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qquickspritesequence_p.h" +#include "qquickspritesequence_p_p.h" #include "qquicksprite_p.h" #include "qquickspriteengine_p.h" #include <QtQuick/private/qsgcontext_p.h> @@ -54,117 +55,6 @@ QT_BEGIN_NAMESPACE -class QQuickSpriteSequenceMaterial : public QSGMaterial -{ -public: - QQuickSpriteSequenceMaterial(); - ~QQuickSpriteSequenceMaterial(); - QSGMaterialType *type() const Q_DECL_OVERRIDE{ static QSGMaterialType type; return &type; } - QSGMaterialShader *createShader() const Q_DECL_OVERRIDE; - int compare(const QSGMaterial *other) const Q_DECL_OVERRIDE - { - return this - static_cast<const QQuickSpriteSequenceMaterial *>(other); - } - - QSGTexture *texture; - - float animT; - float animX1; - float animY1; - float animX2; - float animY2; - float animW; - float animH; -}; - -QQuickSpriteSequenceMaterial::QQuickSpriteSequenceMaterial() - : texture(0) - , animT(0.0f) - , animX1(0.0f) - , animY1(0.0f) - , animX2(0.0f) - , animY2(0.0f) - , animW(1.0f) - , animH(1.0f) -{ - setFlag(Blending, true); -} - -QQuickSpriteSequenceMaterial::~QQuickSpriteSequenceMaterial() -{ - delete texture; -} - -#ifndef QT_NO_OPENGL -class SpriteSequenceMaterialData : public QSGMaterialShader -{ -public: - SpriteSequenceMaterialData() - : QSGMaterialShader() - { - setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/items/shaders/sprite.vert")); - setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/items/shaders/sprite.frag")); - } - - void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *) Q_DECL_OVERRIDE - { - QQuickSpriteSequenceMaterial *m = static_cast<QQuickSpriteSequenceMaterial *>(newEffect); - m->texture->bind(); - - program()->setUniformValue(m_opacity_id, state.opacity()); - program()->setUniformValue(m_animData_id, m->animW, m->animH, m->animT); - program()->setUniformValue(m_animPos_id, m->animX1, m->animY1, m->animX2, m->animY2); - - if (state.isMatrixDirty()) - program()->setUniformValue(m_matrix_id, state.combinedMatrix()); - } - - void initialize() Q_DECL_OVERRIDE { - m_matrix_id = program()->uniformLocation("qt_Matrix"); - m_opacity_id = program()->uniformLocation("qt_Opacity"); - m_animData_id = program()->uniformLocation("animData"); - m_animPos_id = program()->uniformLocation("animPos"); - } - - char const *const *attributeNames() const Q_DECL_OVERRIDE { - static const char *attr[] = { - "vPos", - "vTex", - 0 - }; - return attr; - } - - int m_matrix_id; - int m_opacity_id; - int m_animData_id; - int m_animPos_id; -}; -#endif - -QSGMaterialShader *QQuickSpriteSequenceMaterial::createShader() const -{ -#ifndef QT_NO_OPENGL - return new SpriteSequenceMaterialData; -#else - return nullptr; -#endif -} - -struct SpriteVertex { - float x; - float y; - float tx; - float ty; -}; - -struct SpriteVertices { - SpriteVertex v1; - SpriteVertex v2; - SpriteVertex v3; - SpriteVertex v4; -}; - /*! \qmltype SpriteSequence \instantiates QQuickSpriteSequence @@ -224,213 +114,185 @@ struct SpriteVertices { //TODO: Implicitly size element to size of first sprite? QQuickSpriteSequence::QQuickSpriteSequence(QQuickItem *parent) : - QQuickItem(parent) - , m_node(0) - , m_material(0) - , m_spriteEngine(0) - , m_curFrame(0) - , m_pleaseReset(false) - , m_running(true) - , m_interpolate(true) - , m_curStateIdx(0) + QQuickItem(*(new QQuickSpriteSequencePrivate), parent) { setFlag(ItemHasContents); connect(this, SIGNAL(runningChanged(bool)), this, SLOT(update())); - connect(this, SIGNAL(widthChanged()), - this, SLOT(sizeVertices())); - connect(this, SIGNAL(heightChanged()), - this, SLOT(sizeVertices())); } void QQuickSpriteSequence::jumpTo(const QString &sprite) { - if (!m_spriteEngine) + Q_D(QQuickSpriteSequence); + if (!d->m_spriteEngine) return; - m_spriteEngine->setGoal(m_spriteEngine->stateIndex(sprite), 0, true); + d->m_spriteEngine->setGoal(d->m_spriteEngine->stateIndex(sprite), 0, true); } void QQuickSpriteSequence::setGoalSprite(const QString &sprite) { - if (m_goalState != sprite){ - m_goalState = sprite; + Q_D(QQuickSpriteSequence); + if (d->m_goalState != sprite){ + d->m_goalState = sprite; emit goalSpriteChanged(sprite); - if (m_spriteEngine) - m_spriteEngine->setGoal(m_spriteEngine->stateIndex(sprite)); + if (d->m_spriteEngine) + d->m_spriteEngine->setGoal(d->m_spriteEngine->stateIndex(sprite)); } } -QQmlListProperty<QQuickSprite> QQuickSpriteSequence::sprites() +void QQuickSpriteSequence::setRunning(bool arg) { - return QQmlListProperty<QQuickSprite>(this, &m_sprites, spriteAppend, spriteCount, spriteAt, spriteClear); + Q_D(QQuickSpriteSequence); + if (d->m_running != arg) { + d->m_running = arg; + Q_EMIT runningChanged(arg); + } } -void QQuickSpriteSequence::createEngine() +void QQuickSpriteSequence::setInterpolate(bool arg) { - //TODO: delay until component complete - if (m_spriteEngine) - delete m_spriteEngine; - if (m_sprites.count()) { - m_spriteEngine = new QQuickSpriteEngine(m_sprites, this); - if (!m_goalState.isEmpty()) - m_spriteEngine->setGoal(m_spriteEngine->stateIndex(m_goalState)); - } else { - m_spriteEngine = 0; + Q_D(QQuickSpriteSequence); + if (d->m_interpolate != arg) { + d->m_interpolate = arg; + Q_EMIT interpolateChanged(arg); } - reset(); } -static QSGGeometry::Attribute SpriteSequence_Attributes[] = { - QSGGeometry::Attribute::create(0, 2, QSGGeometry::TypeFloat, true), // pos - QSGGeometry::Attribute::create(1, 2, QSGGeometry::TypeFloat), // tex -}; - -static QSGGeometry::AttributeSet SpriteSequence_AttributeSet = +QQmlListProperty<QQuickSprite> QQuickSpriteSequence::sprites() { - 2, // Attribute Count - (2+2) * sizeof(float), - SpriteSequence_Attributes -}; + Q_D(QQuickSpriteSequence); + return QQmlListProperty<QQuickSprite>(this, &d->m_sprites, spriteAppend, spriteCount, spriteAt, spriteClear); +} -void QQuickSpriteSequence::sizeVertices() +bool QQuickSpriteSequence::running() const { - if (!m_node) - return; + Q_D(const QQuickSpriteSequence); + return d->m_running; +} - SpriteVertices *p = (SpriteVertices *) m_node->geometry()->vertexData(); - p->v1.x = 0; - p->v1.y = 0; +bool QQuickSpriteSequence::interpolate() const +{ + Q_D(const QQuickSpriteSequence); + return d->m_interpolate; +} - p->v2.x = width(); - p->v2.y = 0; +QString QQuickSpriteSequence::goalSprite() const +{ + Q_D(const QQuickSpriteSequence); + return d->m_goalState; +} - p->v3.x = 0; - p->v3.y = height(); +QString QQuickSpriteSequence::currentSprite() const +{ + Q_D(const QQuickSpriteSequence); + return d->m_curState; +} - p->v4.x = width(); - p->v4.y = height(); +void QQuickSpriteSequence::createEngine() +{ + Q_D(QQuickSpriteSequence); + //TODO: delay until component complete + if (d->m_spriteEngine) + delete d->m_spriteEngine; + if (d->m_sprites.count()) { + d->m_spriteEngine = new QQuickSpriteEngine(d->m_sprites, this); + if (!d->m_goalState.isEmpty()) + d->m_spriteEngine->setGoal(d->m_spriteEngine->stateIndex(d->m_goalState)); + } else { + d->m_spriteEngine = 0; + } + reset(); } -QSGGeometryNode* QQuickSpriteSequence::buildNode() +QSGSpriteNode *QQuickSpriteSequence::initNode() { - if (!m_spriteEngine) { + Q_D(QQuickSpriteSequence); + + if (!d->m_spriteEngine) { qmlInfo(this) << "No sprite engine..."; - return 0; - } else if (m_spriteEngine->status() == QQuickPixmap::Null) { - m_spriteEngine->startAssemblingImage(); + return nullptr; + } else if (d->m_spriteEngine->status() == QQuickPixmap::Null) { + d->m_spriteEngine->startAssemblingImage(); update();//Schedule another update, where we will check again - return 0; - } else if (m_spriteEngine->status() == QQuickPixmap::Loading) { + return nullptr; + } else if (d->m_spriteEngine->status() == QQuickPixmap::Loading) { update();//Schedule another update, where we will check again - return 0; + return nullptr; } - m_material = new QQuickSpriteSequenceMaterial(); - - QImage image = m_spriteEngine->assembledImage(); + QImage image = d->m_spriteEngine->assembledImage(d->sceneGraphRenderContext()->maxTextureSize()); if (image.isNull()) - return 0; - m_sheetSize = QSizeF(image.size()); - m_material->texture = window()->createTextureFromImage(image); - m_material->texture->setFiltering(QSGTexture::Linear); - m_spriteEngine->start(0); - m_material->animT = 0; - m_material->animX1 = m_spriteEngine->spriteX() / m_sheetSize.width(); - m_material->animY1 = m_spriteEngine->spriteY() / m_sheetSize.height(); - m_material->animX2 = m_material->animX1; - m_material->animY2 = m_material->animY1; - m_material->animW = m_spriteEngine->spriteWidth() / m_sheetSize.width(); - m_material->animH = m_spriteEngine->spriteHeight() / m_sheetSize.height(); - m_curState = m_spriteEngine->state(m_spriteEngine->curState())->name(); - emit currentSpriteChanged(m_curState); - - int vCount = 4; - int iCount = 6; - QSGGeometry *g = new QSGGeometry(SpriteSequence_AttributeSet, vCount, iCount); - g->setDrawingMode(QSGGeometry::DrawTriangles); - - SpriteVertices *p = (SpriteVertices *) g->vertexData(); - QRectF texRect = m_material->texture->normalizedTextureSubRect(); - - p->v1.tx = texRect.topLeft().x(); - p->v1.ty = texRect.topLeft().y(); - - p->v2.tx = texRect.topRight().x(); - p->v2.ty = texRect.topRight().y(); - - p->v3.tx = texRect.bottomLeft().x(); - p->v3.ty = texRect.bottomLeft().y(); - - p->v4.tx = texRect.bottomRight().x(); - p->v4.ty = texRect.bottomRight().y(); - - quint16 *indices = g->indexDataAsUShort(); - indices[0] = 0; - indices[1] = 1; - indices[2] = 2; - indices[3] = 1; - indices[4] = 3; - indices[5] = 2; - - - m_timestamp.start(); - m_node = new QSGGeometryNode(); - m_node->setGeometry(g); - m_node->setMaterial(m_material); - m_node->setFlag(QSGGeometryNode::OwnsMaterial); - sizeVertices(); - return m_node; + return nullptr; + + QSGSpriteNode *node = d->sceneGraphContext()->createSpriteNode(); + + d->m_sheetSize = QSize(image.size()); + node->setTexture(window()->createTextureFromImage(image)); + d->m_spriteEngine->start(0); + node->setTime(0.0f); + node->setSourceA(QPoint(d->m_spriteEngine->spriteX(), d->m_spriteEngine->spriteY())); + node->setSourceB(QPoint(d->m_spriteEngine->spriteX(), d->m_spriteEngine->spriteY())); + node->setSpriteSize(QSize(d->m_spriteEngine->spriteWidth(), d->m_spriteEngine->spriteHeight())); + node->setSheetSize(d->m_sheetSize); + node->setSize(QSizeF(width(), height())); + + d->m_curState = d->m_spriteEngine->state(d->m_spriteEngine->curState())->name(); + emit currentSpriteChanged(d->m_curState); + d->m_timestamp.start(); + return node; } void QQuickSpriteSequence::reset() { - m_pleaseReset = true; + Q_D(QQuickSpriteSequence); + d->m_pleaseReset = true; } -QSGNode *QQuickSpriteSequence::updatePaintNode(QSGNode *, UpdatePaintNodeData *) +QSGNode *QQuickSpriteSequence::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) { - if (m_pleaseReset) { - delete m_node; + Q_D(QQuickSpriteSequence); - m_node = 0; - m_material = 0; - m_pleaseReset = false; + if (d->m_pleaseReset) { + delete oldNode; + + oldNode = nullptr; + d->m_pleaseReset = false; } - prepareNextFrame(); + QSGSpriteNode *node = static_cast<QSGSpriteNode *>(oldNode); + if (!node) + node = initNode(); + + if (node) + prepareNextFrame(node); - if (m_running) { + if (d->m_running) { update(); - if (m_node) - m_node->markDirty(QSGNode::DirtyMaterial); } - return m_node; + return node; } -void QQuickSpriteSequence::prepareNextFrame() +void QQuickSpriteSequence::prepareNextFrame(QSGSpriteNode *node) { - if (m_node == 0) - m_node = buildNode(); - if (m_node == 0) //error creating node - return; + Q_D(QQuickSpriteSequence); - uint timeInt = m_timestamp.elapsed(); + uint timeInt = d->m_timestamp.elapsed(); qreal time = timeInt / 1000.; //Advance State - m_spriteEngine->updateSprites(timeInt); - if (m_curStateIdx != m_spriteEngine->curState()) { - m_curStateIdx = m_spriteEngine->curState(); - m_curState = m_spriteEngine->state(m_spriteEngine->curState())->name(); - emit currentSpriteChanged(m_curState); - m_curFrame= -1; + d->m_spriteEngine->updateSprites(timeInt); + if (d->m_curStateIdx != d->m_spriteEngine->curState()) { + d->m_curStateIdx = d->m_spriteEngine->curState(); + d->m_curState = d->m_spriteEngine->state(d->m_spriteEngine->curState())->name(); + emit currentSpriteChanged(d->m_curState); + d->m_curFrame= -1; } //Advance Sprite - qreal animT = m_spriteEngine->spriteStart()/1000.0; - qreal frameCount = m_spriteEngine->spriteFrames(); - qreal frameDuration = m_spriteEngine->spriteDuration()/frameCount; + qreal animT = d->m_spriteEngine->spriteStart()/1000.0; + qreal frameCount = d->m_spriteEngine->spriteFrames(); + qreal frameDuration = d->m_spriteEngine->spriteDuration()/frameCount; double frameAt; qreal progress; if (frameDuration > 0) { @@ -438,32 +300,32 @@ void QQuickSpriteSequence::prepareNextFrame() frame = qBound(qreal(0.0), frame, frameCount - qreal(1.0));//Stop at count-1 frames until we have between anim interpolation progress = std::modf(frame,&frameAt); } else { - m_curFrame++; - if (m_curFrame >= frameCount){ - m_curFrame = 0; - m_spriteEngine->advance(); + d->m_curFrame++; + if (d->m_curFrame >= frameCount){ + d->m_curFrame = 0; + d->m_spriteEngine->advance(); } - frameAt = m_curFrame; + frameAt = d->m_curFrame; progress = 0; } - if (m_spriteEngine->sprite()->reverse()) - frameAt = (m_spriteEngine->spriteFrames() - 1) - frameAt; - qreal y = m_spriteEngine->spriteY() / m_sheetSize.height(); - qreal w = m_spriteEngine->spriteWidth() / m_sheetSize.width(); - qreal h = m_spriteEngine->spriteHeight() / m_sheetSize.height(); - qreal x1 = m_spriteEngine->spriteX() / m_sheetSize.width(); + if (d->m_spriteEngine->sprite()->reverse()) + frameAt = (d->m_spriteEngine->spriteFrames() - 1) - frameAt; + int y = d->m_spriteEngine->spriteY(); + int w = d->m_spriteEngine->spriteWidth(); + int h = d->m_spriteEngine->spriteHeight(); + int x1 = d->m_spriteEngine->spriteX(); x1 += frameAt * w; - qreal x2 = x1; + int x2 = x1; if (frameAt < (frameCount-1)) x2 += w; - m_material->animX1 = x1; - m_material->animY1 = y; - m_material->animX2 = x2; - m_material->animY2 = y; - m_material->animW = w; - m_material->animH = h; - m_material->animT = m_interpolate ? progress : 0.0; + node->setSourceA(QPoint(x1, y)); + node->setSourceB(QPoint(x2, y)); + node->setSpriteSize(QSize(w, h)); + node->setTime(d->m_interpolate ? progress : 0.0); + node->setSize(QSizeF(width(), height())); + node->setFiltering(smooth() ? QSGTexture::Linear : QSGTexture::Nearest); + node->update(); } QT_END_NAMESPACE diff --git a/src/quick/items/qquickspritesequence_p.h b/src/quick/items/qquickspritesequence_p.h index b4cc133821..34af110a98 100644 --- a/src/quick/items/qquickspritesequence_p.h +++ b/src/quick/items/qquickspritesequence_p.h @@ -59,8 +59,8 @@ QT_BEGIN_NAMESPACE class QSGContext; class QQuickSprite; class QQuickSpriteEngine; -class QSGGeometryNode; -class QQuickSpriteSequenceMaterial; +class QQuickSpriteSequencePrivate; +class QSGSpriteNode; class Q_AUTOTEST_EXPORT QQuickSpriteSequence : public QQuickItem { Q_OBJECT @@ -77,25 +77,10 @@ public: QQmlListProperty<QQuickSprite> sprites(); - bool running() const - { - return m_running; - } - - bool interpolate() const - { - return m_interpolate; - } - - QString goalSprite() const - { - return m_goalState; - } - - QString currentSprite() const - { - return m_curState; - } + bool running() const; + bool interpolate() const; + QString goalSprite() const; + QString currentSprite() const; Q_SIGNALS: @@ -108,46 +93,23 @@ public Q_SLOTS: void jumpTo(const QString &sprite); void setGoalSprite(const QString &sprite); - - void setRunning(bool arg) - { - if (m_running != arg) { - m_running = arg; - Q_EMIT runningChanged(arg); - } - } - - void setInterpolate(bool arg) - { - if (m_interpolate != arg) { - m_interpolate = arg; - Q_EMIT interpolateChanged(arg); - } - } + void setRunning(bool arg); + void setInterpolate(bool arg); private Q_SLOTS: void createEngine(); - void sizeVertices(); protected: void reset(); QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE; private: - void prepareNextFrame(); - QSGGeometryNode* buildNode(); - QSGGeometryNode *m_node; - QQuickSpriteSequenceMaterial *m_material; - QList<QQuickSprite*> m_sprites; - QQuickSpriteEngine* m_spriteEngine; - QTime m_timestamp; - int m_curFrame; - bool m_pleaseReset; - bool m_running; - bool m_interpolate; - QString m_goalState; - QString m_curState; - int m_curStateIdx; - QSizeF m_sheetSize; + void prepareNextFrame(QSGSpriteNode *node); + QSGSpriteNode* initNode(); + + +private: + Q_DISABLE_COPY(QQuickSpriteSequence) + Q_DECLARE_PRIVATE(QQuickSpriteSequence) }; QT_END_NAMESPACE diff --git a/src/quick/items/qquickspritesequence_p_p.h b/src/quick/items/qquickspritesequence_p_p.h new file mode 100644 index 0000000000..4f352b5b69 --- /dev/null +++ b/src/quick/items/qquickspritesequence_p_p.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKSPRITESEQUENCE_P_P_H +#define QQUICKSPRITESEQUENCE_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qquickitem_p.h" +#include "qquicksprite_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickSpriteSequence; + +class QQuickSpriteSequencePrivate :public QQuickItemPrivate +{ + Q_DECLARE_PUBLIC(QQuickSpriteSequence) +public: + QQuickSpriteSequencePrivate() + : m_spriteEngine(nullptr) + , m_curFrame(0) + , m_pleaseReset(false) + , m_running(true) + , m_interpolate(true) + , m_curStateIdx(0) + { + + } + QList<QQuickSprite*> m_sprites; + QQuickSpriteEngine* m_spriteEngine; + QTime m_timestamp; + int m_curFrame; + bool m_pleaseReset; + bool m_running; + bool m_interpolate; + QString m_goalState; + QString m_curState; + int m_curStateIdx; + QSize m_sheetSize; +}; + +QT_END_NAMESPACE + +#endif // QQUICKSPRITESEQUENCE_P_P_H diff --git a/src/quick/items/shaders/sprite.frag b/src/quick/items/shaders/sprite.frag deleted file mode 100644 index e1fcb0f006..0000000000 --- a/src/quick/items/shaders/sprite.frag +++ /dev/null @@ -1,12 +0,0 @@ -uniform sampler2D _qt_texture; -uniform lowp float qt_Opacity; - -varying highp vec4 fTexS; -varying lowp float progress; - -void main() -{ - gl_FragColor = mix(texture2D(_qt_texture, fTexS.xy), - texture2D(_qt_texture, fTexS.zw), - progress) * qt_Opacity; -}
\ No newline at end of file diff --git a/src/quick/items/shaders/sprite.vert b/src/quick/items/shaders/sprite.vert deleted file mode 100644 index fc826f60b4..0000000000 --- a/src/quick/items/shaders/sprite.vert +++ /dev/null @@ -1,23 +0,0 @@ -attribute highp vec2 vPos; -attribute highp vec2 vTex; - -uniform highp vec3 animData;// w,h(premultiplied of anim), interpolation progress -uniform highp vec4 animPos;//x,y, x,y (two frames for interpolation) - -uniform highp mat4 qt_Matrix; - -varying highp vec4 fTexS; -varying lowp float progress; - -void main() -{ - progress = animData.z; - - // Calculate frame location in texture - fTexS.xy = animPos.xy + vTex.xy * animData.xy; - - // Next frame is also passed, for interpolation - fTexS.zw = animPos.zw + vTex.xy * animData.xy; - - gl_Position = qt_Matrix * vec4(vPos.x, vPos.y, 0, 1); -}
\ No newline at end of file diff --git a/src/quick/items/shaders/sprite_core.frag b/src/quick/items/shaders/sprite_core.frag deleted file mode 100644 index c1087a8754..0000000000 --- a/src/quick/items/shaders/sprite_core.frag +++ /dev/null @@ -1,16 +0,0 @@ -#version 150 core - -in vec4 fTexS; -in float progress; - -out vec4 fragColor; - -uniform sampler2D _qt_texture; -uniform float qt_Opacity; - -void main() -{ - fragColor = mix(texture(_qt_texture, fTexS.xy), - texture(_qt_texture, fTexS.zw), - progress) * qt_Opacity; -}
\ No newline at end of file diff --git a/src/quick/items/shaders/sprite_core.vert b/src/quick/items/shaders/sprite_core.vert deleted file mode 100644 index 5027bf03fc..0000000000 --- a/src/quick/items/shaders/sprite_core.vert +++ /dev/null @@ -1,24 +0,0 @@ -#version 150 core - -in vec2 vPos; -in vec2 vTex; - -out vec4 fTexS; -out float progress; - -uniform vec3 animData; // w,h(premultiplied of anim), interpolation progress -uniform vec4 animPos; // x,y, x,y (two frames for interpolation) -uniform mat4 qt_Matrix; - -void main() -{ - progress = animData.z; - - // Calculate frame location in texture - fTexS.xy = animPos.xy + vTex.xy * animData.xy; - - // Next frame is also passed, for interpolation - fTexS.zw = animPos.zw + vTex.xy * animData.xy; - - gl_Position = qt_Matrix * vec4(vPos.x, vPos.y, 0, 1); -}
\ No newline at end of file |