diff options
Diffstat (limited to 'src/quick/items/qquickspritesequence.cpp')
-rw-r--r-- | src/quick/items/qquickspritesequence.cpp | 402 |
1 files changed, 135 insertions, 267 deletions
diff --git a/src/quick/items/qquickspritesequence.cpp b/src/quick/items/qquickspritesequence.cpp index f32e1afd50..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,111 +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; -} - -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; -}; - -QSGMaterialShader *QQuickSpriteSequenceMaterial::createShader() const -{ - return new SpriteSequenceMaterialData; -} - -struct SpriteVertex { - float x; - float y; - float tx; - float ty; -}; - -struct SpriteVertices { - SpriteVertex v1; - SpriteVertex v2; - SpriteVertex v3; - SpriteVertex v4; -}; - /*! \qmltype SpriteSequence \instantiates QQuickSpriteSequence @@ -218,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, GL_FLOAT, true), // pos - QSGGeometry::Attribute::create(1, 2, GL_FLOAT), // 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(GL_TRIANGLES); - - 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) { @@ -432,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 |