aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12context.cpp5
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12context_p.h2
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12rendercontext.cpp6
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12rendercontext_p.h1
-rw-r--r--src/quick/items/items.pri8
-rw-r--r--src/quick/items/items.qrc4
-rw-r--r--src/quick/items/qquickanimatedsprite.cpp692
-rw-r--r--src/quick/items/qquickanimatedsprite_p.h286
-rw-r--r--src/quick/items/qquickanimatedsprite_p_p.h96
-rw-r--r--src/quick/items/qquicksprite_p.h2
-rw-r--r--src/quick/items/qquickspriteengine.cpp14
-rw-r--r--src/quick/items/qquickspriteengine_p.h2
-rw-r--r--src/quick/items/qquickspritesequence.cpp408
-rw-r--r--src/quick/items/qquickspritesequence_p.h68
-rw-r--r--src/quick/items/qquickspritesequence_p_p.h90
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp11
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h2
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp11
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h5
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp10
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater_p.h2
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder.cpp10
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder_p.h2
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp139
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode_p.h92
-rw-r--r--src/quick/scenegraph/adaptations/software/software.pri6
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer_p.h20
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h4
-rw-r--r--src/quick/scenegraph/qsgdefaultcontext.cpp6
-rw-r--r--src/quick/scenegraph/qsgdefaultcontext_p.h1
-rw-r--r--src/quick/scenegraph/qsgdefaultrendercontext_p.h2
-rw-r--r--src/quick/scenegraph/qsgdefaultspritenode.cpp303
-rw-r--r--src/quick/scenegraph/qsgdefaultspritenode_p.h87
-rw-r--r--src/quick/scenegraph/scenegraph.pri2
-rw-r--r--src/quick/scenegraph/scenegraph.qrc4
-rw-r--r--src/quick/scenegraph/shaders/sprite.frag (renamed from src/quick/items/shaders/sprite.frag)0
-rw-r--r--src/quick/scenegraph/shaders/sprite.vert (renamed from src/quick/items/shaders/sprite.vert)0
-rw-r--r--src/quick/scenegraph/shaders/sprite_core.frag (renamed from src/quick/items/shaders/sprite_core.frag)0
-rw-r--r--src/quick/scenegraph/shaders/sprite_core.vert (renamed from src/quick/items/shaders/sprite_core.vert)0
39 files changed, 1504 insertions, 899 deletions
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12context.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12context.cpp
index 1b29ddd59c..64c6313b42 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12context.cpp
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12context.cpp
@@ -127,4 +127,9 @@ QSGNinePatchNode *QSGD3D12Context::createNinePatchNode()
return new QSGD3D12NinePatchNode;
}
+QSGSpriteNode *QSGD3D12Context::createSpriteNode()
+{
+ return nullptr;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12context_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12context_p.h
index f4d9429c7b..70cc606b52 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12context_p.h
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12context_p.h
@@ -75,6 +75,8 @@ public:
QSGRectangleNode *createRectangleNode() override;
QSGImageNode *createImageNode() override;
QSGNinePatchNode *createNinePatchNode() override;
+ QSGSpriteNode *createSpriteNode() override;
+
};
QT_END_NAMESPACE
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext.cpp
index 1a63117ec0..e261cb6447 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext.cpp
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext.cpp
@@ -115,6 +115,12 @@ QSGRenderer *QSGD3D12RenderContext::createRenderer()
return new QSGD3D12Renderer(this);
}
+int QSGD3D12RenderContext::maxTextureSize() const
+{
+ // XXX: Do it the correct way
+ return 4096;
+}
+
void QSGD3D12RenderContext::renderNextFrame(QSGRenderer *renderer, uint fbo)
{
static_cast<QSGD3D12Renderer *>(renderer)->renderScene(fbo);
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext_p.h
index 5cd0b52f4b..ca85aaa46f 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext_p.h
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext_p.h
@@ -68,6 +68,7 @@ public:
void renderNextFrame(QSGRenderer *renderer, uint fbo) override;
QSGTexture *createTexture(const QImage &image, uint flags) const override;
QSGRenderer *createRenderer() override;
+ int maxTextureSize() const override;
void setEngine(QSGD3D12Engine *engine);
QSGD3D12Engine *engine() { return m_engine; }
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/scenegraph/adaptations/software/qsgsoftwarecontext.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp
index d9a298f855..94e9c81f70 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp
@@ -47,6 +47,7 @@
#include "qsgsoftwarepublicnodes_p.h"
#include "qsgsoftwarelayer_p.h"
#include "qsgsoftwarerenderer_p.h"
+#include "qsgsoftwarespritenode_p.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QElapsedTimer>
@@ -154,6 +155,11 @@ void QSGSoftwareRenderContext::renderNextFrame(QSGRenderer *renderer, uint fbo)
renderer->renderScene(fbo);
}
+int QSGSoftwareRenderContext::maxTextureSize() const
+{
+ return 2048;
+}
+
QSGRendererInterface *QSGSoftwareContext::rendererInterface(QSGRenderContext *renderContext)
{
Q_UNUSED(renderContext);
@@ -175,6 +181,11 @@ QSGNinePatchNode *QSGSoftwareContext::createNinePatchNode()
return new QSGSoftwareNinePatchNode;
}
+QSGSpriteNode *QSGSoftwareContext::createSpriteNode()
+{
+ return new QSGSoftwareSpriteNode;
+}
+
QSGRendererInterface::GraphicsApi QSGSoftwareContext::graphicsApi() const
{
return Software;
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h
index 9a939a0948..3c3686c268 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h
@@ -75,6 +75,7 @@ public:
void renderNextFrame(QSGRenderer *renderer, uint fbo) override;
QSGTexture *createTexture(const QImage &image, uint flags = CreateTexture_Alpha) const override;
QSGRenderer *createRenderer() override;
+ int maxTextureSize() const override;
bool m_initialized;
};
@@ -96,6 +97,7 @@ public:
QSGRectangleNode *createRectangleNode() override;
QSGImageNode *createImageNode() override;
QSGNinePatchNode *createNinePatchNode() override;
+ QSGSpriteNode *createSpriteNode() override;
GraphicsApi graphicsApi() const override;
ShaderType shaderType() const override;
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp
index 385b257e44..1b2a836dfa 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp
@@ -45,6 +45,7 @@
#include "qsgsoftwarepublicnodes_p.h"
#include "qsgsoftwarepainternode_p.h"
#include "qsgsoftwarepixmaptexture_p.h"
+#include "qsgsoftwarespritenode_p.h"
#include <QtQuick/QSGSimpleRectNode>
#include <QtQuick/qsgsimpletexturenode.h>
@@ -89,6 +90,9 @@ QSGSoftwareRenderableNode::QSGSoftwareRenderableNode(NodeType type, QSGNode *nod
case QSGSoftwareRenderableNode::SimpleImage:
m_handle.simpleImageNode = static_cast<QSGImageNode*>(node);
break;
+ case QSGSoftwareRenderableNode::SpriteNode:
+ m_handle.spriteNode = static_cast<QSGSoftwareSpriteNode*>(node);
+ break;
case QSGSoftwareRenderableNode::Invalid:
m_handle.simpleRectNode = nullptr;
break;
@@ -174,6 +178,10 @@ void QSGSoftwareRenderableNode::update()
boundingRect = m_handle.simpleImageNode->rect().toRect();
break;
+ case QSGSoftwareRenderableNode::SpriteNode:
+ m_isOpaque = m_handle.spriteNode->isOpaque();
+ boundingRect = m_handle.spriteNode->rect().toRect();
+ break;
default:
break;
}
@@ -256,6 +264,9 @@ QRegion QSGSoftwareRenderableNode::renderNode(QPainter *painter, bool forceOpaqu
case QSGSoftwareRenderableNode::SimpleImage:
static_cast<QSGSoftwareImageNode *>(m_handle.simpleImageNode)->paint(painter);
break;
+ case QSGSoftwareRenderableNode::SpriteNode:
+ static_cast<QSGSoftwareSpriteNode *>(m_handle.spriteNode)->paint(painter);
+ break;
default:
break;
}
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h
index fcbea7391a..dc224be2c0 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h
@@ -67,6 +67,7 @@ class QSGSoftwarePainterNode;
class QSGSoftwareInternalRectangleNode;
class QSGSoftwareGlyphNode;
class QSGSoftwareNinePatchNode;
+class QSGSoftwareSpriteNode;
class QSGSoftwareRenderableNode
{
@@ -81,7 +82,8 @@ public:
Glyph,
NinePatch,
SimpleRectangle,
- SimpleImage
+ SimpleImage,
+ SpriteNode
};
QSGSoftwareRenderableNode(NodeType type, QSGNode *node);
@@ -123,6 +125,7 @@ private:
QSGSoftwareNinePatchNode *ninePatchNode;
QSGRectangleNode *simpleRectangleNode;
QSGImageNode *simpleImageNode;
+ QSGSoftwareSpriteNode *spriteNode;
};
const NodeType m_nodeType;
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp
index f13edb87fb..cb866bec12 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp
@@ -180,6 +180,16 @@ void QSGSoftwareRenderableNodeUpdater::endVisit(QSGRootNode *)
{
}
+bool QSGSoftwareRenderableNodeUpdater::visit(QSGSpriteNode *node)
+{
+ return updateRenderableNode(QSGSoftwareRenderableNode::SpriteNode, node);
+}
+
+void QSGSoftwareRenderableNodeUpdater::endVisit(QSGSpriteNode *)
+{
+
+}
+
void QSGSoftwareRenderableNodeUpdater::updateNodes(QSGNode *node, bool isNodeRemoved)
{
m_opacityState.clear();
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater_p.h
index d7c12e8b02..5bc241cce1 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater_p.h
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater_p.h
@@ -86,6 +86,8 @@ public:
void endVisit(QSGGlyphNode *) override;
bool visit(QSGRootNode *) override;
void endVisit(QSGRootNode *) override;
+ bool visit(QSGSpriteNode *) override;
+ void endVisit(QSGSpriteNode *) override;
void updateNodes(QSGNode *node, bool isNodeRemoved = false);
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder.cpp
index ede2005918..ac00127b35 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder.cpp
@@ -140,6 +140,16 @@ void QSGSoftwareRenderListBuilder::endVisit(QSGRootNode *)
{
}
+bool QSGSoftwareRenderListBuilder::visit(QSGSpriteNode *node)
+{
+ return addRenderableNode(node);
+}
+
+void QSGSoftwareRenderListBuilder::endVisit(QSGSpriteNode *)
+{
+
+}
+
bool QSGSoftwareRenderListBuilder::addRenderableNode(QSGNode *node)
{
auto renderableNode = m_renderer->renderableNode(node);
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder_p.h
index ce538f835f..e34cc81e23 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder_p.h
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder_p.h
@@ -80,6 +80,8 @@ public:
void endVisit(QSGGlyphNode *) override;
bool visit(QSGRootNode *) override;
void endVisit(QSGRootNode *) override;
+ bool visit(QSGSpriteNode *) override;
+ void endVisit(QSGSpriteNode *) override;
private:
bool addRenderableNode(QSGNode *node);
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp
new file mode 100644
index 0000000000..ba7bbc2d11
--- /dev/null
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#include "qsgsoftwarespritenode_p.h"
+#include "qsgsoftwarepixmaptexture_p.h"
+#include <QtGui/QPainter>
+
+QT_BEGIN_NAMESPACE
+
+QSGSoftwareSpriteNode::QSGSoftwareSpriteNode()
+{
+ setMaterial((QSGMaterial*)1);
+ setGeometry((QSGGeometry*)1);
+}
+
+void QSGSoftwareSpriteNode::setTexture(QSGTexture *texture)
+{
+ m_texture = qobject_cast<QSGSoftwarePixmapTexture*>(texture);
+ markDirty(DirtyMaterial);
+}
+
+void QSGSoftwareSpriteNode::setTime(float time)
+{
+ if (m_time != time) {
+ m_time = time;
+ markDirty(DirtyMaterial);
+ }
+}
+
+void QSGSoftwareSpriteNode::setSourceA(const QPoint &source)
+{
+ if (m_sourceA != source) {
+ m_sourceA = source;
+ markDirty(DirtyMaterial);
+ }
+}
+
+void QSGSoftwareSpriteNode::setSourceB(const QPoint &source)
+{
+ if (m_sourceB != source) {
+ m_sourceB = source;
+ markDirty(DirtyMaterial);
+ }
+}
+
+void QSGSoftwareSpriteNode::setSpriteSize(const QSize &size)
+{
+ if (m_spriteSize != size) {
+ m_spriteSize = size;
+ markDirty(DirtyMaterial);
+ }
+}
+
+void QSGSoftwareSpriteNode::setSheetSize(const QSize &size)
+{
+ if (m_sheetSize != size) {
+ m_sheetSize = size;
+ markDirty(DirtyMaterial);
+ }
+}
+
+void QSGSoftwareSpriteNode::setSize(const QSizeF &size)
+{
+ if (m_size != size) {
+ m_size = size;
+ markDirty(DirtyGeometry);
+ }
+}
+
+void QSGSoftwareSpriteNode::setFiltering(QSGTexture::Filtering filtering)
+{
+ Q_UNUSED(filtering);
+}
+
+void QSGSoftwareSpriteNode::update()
+{
+}
+
+void QSGSoftwareSpriteNode::paint(QPainter *painter)
+{
+ //Get the pixmap handle from the texture
+ if (!m_texture)
+ return;
+
+ const QPixmap &pixmap = m_texture->pixmap();
+
+ // XXX try to do some kind of interpolation between sourceA and sourceB using time
+ painter->drawPixmap(QRectF(0, 0, m_size.width(), m_size.height()),
+ pixmap,
+ QRectF(m_sourceA, m_spriteSize));
+}
+
+bool QSGSoftwareSpriteNode::isOpaque() const
+{
+ return false;
+}
+
+QRectF QSGSoftwareSpriteNode::rect() const
+{
+ return QRectF(0, 0, m_size.width(), m_size.height());
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode_p.h
new file mode 100644
index 0000000000..284ed3dff5
--- /dev/null
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarespritenode_p.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** 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 QSGSOFTWARESPRITENODE_H
+#define QSGSOFTWARESPRITENODE_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 <private/qsgadaptationlayer_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSGSoftwarePixmapTexture;
+class QSGSoftwareSpriteNode : public QSGSpriteNode
+{
+public:
+ QSGSoftwareSpriteNode();
+
+ void setTexture(QSGTexture *texture) override;
+ void setTime(float time) override;
+ void setSourceA(const QPoint &source) override;
+ void setSourceB(const QPoint &source) override;
+ void setSpriteSize(const QSize &size) override;
+ void setSheetSize(const QSize &size) override;
+ void setSize(const QSizeF &size) override;
+ void setFiltering(QSGTexture::Filtering filtering) override;
+ void update() override;
+
+ void paint(QPainter *painter);
+ bool isOpaque() const;
+ QRectF rect() const;
+
+private:
+
+ QSGSoftwarePixmapTexture *m_texture;
+ float m_time;
+ QPoint m_sourceA;
+ QPoint m_sourceB;
+ QSize m_spriteSize;
+ QSize m_sheetSize;
+ QSizeF m_size;
+
+};
+
+QT_END_NAMESPACE
+
+#endif // QSGSOFTWARESPRITENODE_H
diff --git a/src/quick/scenegraph/adaptations/software/software.pri b/src/quick/scenegraph/adaptations/software/software.pri
index a8ba77c147..1933a37d48 100644
--- a/src/quick/scenegraph/adaptations/software/software.pri
+++ b/src/quick/scenegraph/adaptations/software/software.pri
@@ -18,7 +18,8 @@ SOURCES += \
$$PWD/qsgsoftwarerenderlistbuilder.cpp \
$$PWD/qsgsoftwarerenderloop.cpp \
$$PWD/qsgsoftwarelayer.cpp \
- $$PWD/qsgsoftwareadaptation.cpp
+ $$PWD/qsgsoftwareadaptation.cpp \
+ $$PWD/qsgsoftwarespritenode.cpp
HEADERS += \
$$PWD/qsgsoftwarecontext_p.h \
@@ -36,4 +37,5 @@ HEADERS += \
$$PWD/qsgsoftwarerenderlistbuilder_p.h \
$$PWD/qsgsoftwarerenderloop_p.h \
$$PWD/qsgsoftwarelayer_p.h \
- $$PWD/qsgsoftwareadaptation_p.h
+ $$PWD/qsgsoftwareadaptation_p.h \
+ $$PWD/qsgsoftwarespritenode_p.h
diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h
index bdb8ebb0f1..00441e1544 100644
--- a/src/quick/scenegraph/qsgadaptationlayer_p.h
+++ b/src/quick/scenegraph/qsgadaptationlayer_p.h
@@ -81,6 +81,7 @@ class QSGPainterNode;
class QSGInternalRectangleNode;
class QSGGlyphNode;
class QSGRootNode;
+class QSGSpriteNode;
class Q_QUICK_PRIVATE_EXPORT QSGNodeVisitorEx
{
@@ -106,6 +107,8 @@ public:
virtual void endVisit(QSGGlyphNode *) = 0;
virtual bool visit(QSGRootNode *) = 0;
virtual void endVisit(QSGRootNode *) = 0;
+ virtual bool visit(QSGSpriteNode *) = 0;
+ virtual void endVisit(QSGSpriteNode *) = 0;
void visitChildren(QSGNode *node);
};
@@ -207,6 +210,23 @@ Q_SIGNALS:
void scheduledUpdateCompleted();
};
+class Q_QUICK_PRIVATE_EXPORT QSGSpriteNode : public QSGVisitableNode
+{
+public:
+ virtual void setTexture(QSGTexture *texture) = 0;
+ virtual void setTime(float time) = 0;
+ virtual void setSourceA(const QPoint &source) = 0;
+ virtual void setSourceB(const QPoint &source) = 0;
+ virtual void setSpriteSize(const QSize &size) = 0;
+ virtual void setSheetSize(const QSize &size) = 0;
+ virtual void setSize(const QSizeF &size) = 0;
+ virtual void setFiltering(QSGTexture::Filtering filtering) = 0;
+
+ virtual void update() = 0;
+
+ virtual void accept(QSGNodeVisitorEx *visitor) { if (visitor->visit(this)) visitor->visitChildren(this); visitor->endVisit(this); }
+};
+
class Q_QUICK_PRIVATE_EXPORT QSGGuiThreadShaderEffectManager : public QObject
{
Q_OBJECT
diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h
index e34d2c3ebf..43cf1c28ab 100644
--- a/src/quick/scenegraph/qsgcontext_p.h
+++ b/src/quick/scenegraph/qsgcontext_p.h
@@ -87,6 +87,7 @@ class QSGGuiThreadShaderEffectManager;
class QSGRectangleNode;
class QSGImageNode;
class QSGNinePatchNode;
+class QSGSpriteNode;
Q_DECLARE_LOGGING_CATEGORY(QSG_LOG_TIME_RENDERLOOP)
Q_DECLARE_LOGGING_CATEGORY(QSG_LOG_TIME_COMPILATION)
@@ -126,6 +127,8 @@ public:
virtual void setAttachToGraphicsContext(bool attach) { Q_UNUSED(attach); }
+ virtual int maxTextureSize() const = 0;
+
void registerFontengineForCleanup(QFontEngine *engine);
Q_SIGNALS:
@@ -174,6 +177,7 @@ public:
virtual QSGGuiThreadShaderEffectManager *createGuiThreadShaderEffectManager();
virtual QSGShaderEffectNode *createShaderEffectNode(QSGRenderContext *renderContext,
QSGGuiThreadShaderEffectManager *mgr);
+ virtual QSGSpriteNode *createSpriteNode() = 0;
virtual QAnimationDriver *createAnimationDriver(QObject *parent);
virtual QSize minimumFBOSize() const;
diff --git a/src/quick/scenegraph/qsgdefaultcontext.cpp b/src/quick/scenegraph/qsgdefaultcontext.cpp
index 6324d84883..6964b74dc8 100644
--- a/src/quick/scenegraph/qsgdefaultcontext.cpp
+++ b/src/quick/scenegraph/qsgdefaultcontext.cpp
@@ -52,6 +52,7 @@
#include <QtQuick/private/qsgdefaultrectanglenode_p.h>
#include <QtQuick/private/qsgdefaultimagenode_p.h>
#include <QtQuick/private/qsgdefaultninepatchnode_p.h>
+#include <QtQuick/private/qsgdefaultspritenode_p.h>
#include <QtGui/QOpenGLContext>
#include <QtGui/QOpenGLFramebufferObject>
@@ -257,6 +258,11 @@ QSGNinePatchNode *QSGDefaultContext::createNinePatchNode()
return new QSGDefaultNinePatchNode;
}
+QSGSpriteNode *QSGDefaultContext::createSpriteNode()
+{
+ return new QSGDefaultSpriteNode;
+}
+
QSGRendererInterface::GraphicsApi QSGDefaultContext::graphicsApi() const
{
return OpenGL;
diff --git a/src/quick/scenegraph/qsgdefaultcontext_p.h b/src/quick/scenegraph/qsgdefaultcontext_p.h
index 908934d28c..88db5e1e9a 100644
--- a/src/quick/scenegraph/qsgdefaultcontext_p.h
+++ b/src/quick/scenegraph/qsgdefaultcontext_p.h
@@ -76,6 +76,7 @@ public:
QSGRectangleNode *createRectangleNode() override;
QSGImageNode *createImageNode() override;
QSGNinePatchNode *createNinePatchNode() override;
+ QSGSpriteNode *createSpriteNode() override;
void setDistanceFieldEnabled(bool enabled);
bool isDistanceFieldEnabled() const;
diff --git a/src/quick/scenegraph/qsgdefaultrendercontext_p.h b/src/quick/scenegraph/qsgdefaultrendercontext_p.h
index bc653565cf..0aed46b658 100644
--- a/src/quick/scenegraph/qsgdefaultrendercontext_p.h
+++ b/src/quick/scenegraph/qsgdefaultrendercontext_p.h
@@ -93,7 +93,7 @@ public:
static QSGDefaultRenderContext *from(QOpenGLContext *context);
bool hasBrokenIndexBufferObjects() const { return m_brokenIBOs; }
- int maxTextureSize() const { return m_maxTextureSize; }
+ int maxTextureSize() const override { return m_maxTextureSize; }
protected:
QOpenGLContext *m_gl;
diff --git a/src/quick/scenegraph/qsgdefaultspritenode.cpp b/src/quick/scenegraph/qsgdefaultspritenode.cpp
new file mode 100644
index 0000000000..89b26f8660
--- /dev/null
+++ b/src/quick/scenegraph/qsgdefaultspritenode.cpp
@@ -0,0 +1,303 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#include "qsgdefaultspritenode_p.h"
+
+#include <QtQuick/QSGMaterial>
+#include <QtGui/QOpenGLShaderProgram>
+
+QT_BEGIN_NAMESPACE
+
+struct SpriteVertex {
+ float x;
+ float y;
+ float tx;
+ float ty;
+};
+
+struct SpriteVertices {
+ SpriteVertex v1;
+ SpriteVertex v2;
+ SpriteVertex v3;
+ SpriteVertex v4;
+};
+
+class QQuickSpriteMaterial : public QSGMaterial
+{
+public:
+ QQuickSpriteMaterial();
+ ~QQuickSpriteMaterial();
+ QSGMaterialType *type() const override { static QSGMaterialType type; return &type; }
+ QSGMaterialShader *createShader() const override;
+ int compare(const QSGMaterial *other) const override
+ {
+ return this - static_cast<const QQuickSpriteMaterial *>(other);
+ }
+
+ QSGTexture *texture;
+
+ float animT;
+ float animX1;
+ float animY1;
+ float animX2;
+ float animY2;
+ float animW;
+ float animH;
+};
+
+QQuickSpriteMaterial::QQuickSpriteMaterial()
+ : 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);
+}
+
+QQuickSpriteMaterial::~QQuickSpriteMaterial()
+{
+ delete texture;
+}
+
+class SpriteMaterialData : public QSGMaterialShader
+{
+public:
+ SpriteMaterialData()
+ : QSGMaterialShader()
+ {
+ setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qt-project.org/scenegraph/shaders/sprite.vert"));
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qt-project.org/scenegraph/shaders/sprite.frag"));
+ }
+
+ void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *) Q_DECL_OVERRIDE
+ {
+ QQuickSpriteMaterial *m = static_cast<QQuickSpriteMaterial *>(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 *QQuickSpriteMaterial::createShader() const
+{
+ return new SpriteMaterialData;
+}
+
+static QSGGeometry::Attribute Sprite_Attributes[] = {
+ QSGGeometry::Attribute::create(0, 2, QSGGeometry::TypeFloat, true), // pos
+ QSGGeometry::Attribute::create(1, 2, QSGGeometry::TypeFloat), // tex
+};
+
+static QSGGeometry::AttributeSet Sprite_AttributeSet =
+{
+ 2, // Attribute Count
+ (2+2) * sizeof(float),
+ Sprite_Attributes
+};
+
+QSGDefaultSpriteNode::QSGDefaultSpriteNode()
+ : m_material(new QQuickSpriteMaterial)
+ , m_geometryDirty(true)
+ , m_sheetSize(QSize(64, 64))
+{
+ // Setup geometry data
+ m_geometry = new QSGGeometry(Sprite_AttributeSet, 4, 6);
+ m_geometry->setDrawingMode(QSGGeometry::DrawTriangles);
+ quint16 *indices = m_geometry->indexDataAsUShort();
+ indices[0] = 0;
+ indices[1] = 1;
+ indices[2] = 2;
+ indices[3] = 1;
+ indices[4] = 3;
+ indices[5] = 2;
+
+ setGeometry(m_geometry);
+ setMaterial(m_material);
+ setFlag(OwnsGeometry, true);
+ setFlag(OwnsMaterial, true);
+}
+
+void QSGDefaultSpriteNode::setTexture(QSGTexture *texture)
+{
+ m_material->texture = texture;
+ m_geometryDirty = true;
+ markDirty(DirtyMaterial);
+}
+
+void QSGDefaultSpriteNode::setTime(float time)
+{
+ m_material->animT = time;
+ markDirty(DirtyMaterial);
+}
+
+void QSGDefaultSpriteNode::setSourceA(const QPoint &source)
+{
+ if (m_sourceA != source) {
+ m_sourceA = source;
+ m_material->animX1 = static_cast<float>(source.x()) / m_sheetSize.width();
+ m_material->animY1 = static_cast<float>(source.y()) / m_sheetSize.height();
+ markDirty(DirtyMaterial);
+ }
+}
+
+void QSGDefaultSpriteNode::setSourceB(const QPoint &source)
+{
+ if (m_sourceB != source) {
+ m_sourceB = source;
+ m_material->animX2 = static_cast<float>(source.x()) / m_sheetSize.width();
+ m_material->animY2 = static_cast<float>(source.y()) / m_sheetSize.height();
+ markDirty(DirtyMaterial);
+ }
+}
+
+void QSGDefaultSpriteNode::setSpriteSize(const QSize &size)
+{
+ if (m_spriteSize != size) {
+ m_spriteSize = size;
+ m_material->animW = static_cast<float>(size.width()) / m_sheetSize.width();
+ m_material->animH = static_cast<float>(size.height()) / m_sheetSize.height();
+ markDirty(DirtyMaterial);
+ }
+
+}
+
+void QSGDefaultSpriteNode::setSheetSize(const QSize &size)
+{
+ if (m_sheetSize != size) {
+ m_sheetSize = size;
+
+ // Update all dependent properties
+ m_material->animX1 = static_cast<float>(m_sourceA.x()) / m_sheetSize.width();
+ m_material->animY1 = static_cast<float>(m_sourceA.y()) / m_sheetSize.height();
+ m_material->animX2 = static_cast<float>(m_sourceB.x()) / m_sheetSize.width();
+ m_material->animY2 = static_cast<float>(m_sourceB.y()) / m_sheetSize.height();
+ m_material->animW = static_cast<float>(m_spriteSize.width()) / m_sheetSize.width();
+ m_material->animH = static_cast<float>(m_spriteSize.height()) / m_sheetSize.height();
+ markDirty(DirtyMaterial);
+ }
+}
+
+void QSGDefaultSpriteNode::setSize(const QSizeF &size)
+{
+ if (m_size != size) {
+ m_size = size;
+ m_geometryDirty = true;
+ }
+}
+
+void QSGDefaultSpriteNode::setFiltering(QSGTexture::Filtering filtering)
+{
+ m_material->texture->setFiltering(filtering);
+ markDirty(DirtyMaterial);
+}
+
+void QSGDefaultSpriteNode::update()
+{
+ if (m_geometryDirty) {
+ updateGeometry();
+ m_geometryDirty = false;
+ }
+}
+
+void QSGDefaultSpriteNode::updateGeometry()
+{
+ if (!m_material->texture)
+ return;
+
+ SpriteVertices *p = (SpriteVertices *) m_geometry->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();
+
+ p->v1.x = 0;
+ p->v1.y = 0;
+
+ p->v2.x = m_size.width();
+ p->v2.y = 0;
+
+ p->v3.x = 0;
+ p->v3.y = m_size.height();
+
+ p->v4.x = m_size.width();
+ p->v4.y = m_size.height();
+ markDirty(DirtyGeometry);
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgdefaultspritenode_p.h b/src/quick/scenegraph/qsgdefaultspritenode_p.h
new file mode 100644
index 0000000000..cb76bf8d83
--- /dev/null
+++ b/src/quick/scenegraph/qsgdefaultspritenode_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** 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 QSGDEFAULTSPRITENODE_H
+#define QSGDEFAULTSPRITENODE_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 <private/qsgadaptationlayer_p.h>
+
+QT_BEGIN_NAMESPACE
+class QQuickSpriteMaterial;
+class QSGDefaultSpriteNode : public QSGSpriteNode
+{
+public:
+ QSGDefaultSpriteNode();
+
+ void setTexture(QSGTexture *texture) override;
+ void setTime(float time) override;
+ void setSourceA(const QPoint &source) override;
+ void setSourceB(const QPoint &source) override;
+ void setSpriteSize(const QSize &size) override;
+ void setSheetSize(const QSize &size) override;
+ void setSize(const QSizeF &size) override;
+ void setFiltering(QSGTexture::Filtering filtering) override;
+ void update() override;
+private:
+ void updateGeometry();
+
+ QQuickSpriteMaterial *m_material;
+ QSGGeometry *m_geometry;
+ bool m_geometryDirty;
+ QPoint m_sourceA;
+ QPoint m_sourceB;
+ QSize m_spriteSize;
+ QSize m_sheetSize;
+ QSizeF m_size;
+};
+
+QT_END_NAMESPACE
+
+#endif // QSGDEFAULTSPRITENODE_H
diff --git a/src/quick/scenegraph/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri
index 5b13b7449a..4ef8b0f638 100644
--- a/src/quick/scenegraph/scenegraph.pri
+++ b/src/quick/scenegraph/scenegraph.pri
@@ -115,6 +115,7 @@ contains(QT_CONFIG, opengl(es1|es2)?) {
$$PWD/qsgdefaultinternalrectanglenode.cpp \
$$PWD/qsgdefaultrendercontext.cpp \
$$PWD/qsgdefaultcontext.cpp \
+ $$PWD/qsgdefaultspritenode.cpp \
$$PWD/util/qsgdefaultpainternode.cpp \
$$PWD/util/qsgdefaultrectanglenode.cpp \
$$PWD/util/qsgdefaultimagenode.cpp \
@@ -130,6 +131,7 @@ contains(QT_CONFIG, opengl(es1|es2)?) {
$$PWD/qsgdefaultglyphnode_p_p.h \
$$PWD/qsgdefaultinternalimagenode_p.h \
$$PWD/qsgdefaultinternalrectanglenode_p.h \
+ $$PWD/qsgdefaultspritenode_p.h \
$$PWD/qsgdefaultrendercontext_p.h \
$$PWD/qsgdefaultcontext_p.h \
$$PWD/util/qsgdefaultpainternode_p.h \
diff --git a/src/quick/scenegraph/scenegraph.qrc b/src/quick/scenegraph/scenegraph.qrc
index ef6da71334..0687530be1 100644
--- a/src/quick/scenegraph/scenegraph.qrc
+++ b/src/quick/scenegraph/scenegraph.qrc
@@ -68,5 +68,9 @@
<file>shaders/vertexcolor_core.vert</file>
<file>shaders/visualization.vert</file>
<file>shaders/visualization.frag</file>
+ <file>shaders/sprite.frag</file>
+ <file>shaders/sprite.vert</file>
+ <file>shaders/sprite_core.frag</file>
+ <file>shaders/sprite_core.vert</file>
</qresource>
</RCC>
diff --git a/src/quick/items/shaders/sprite.frag b/src/quick/scenegraph/shaders/sprite.frag
index e1fcb0f006..e1fcb0f006 100644
--- a/src/quick/items/shaders/sprite.frag
+++ b/src/quick/scenegraph/shaders/sprite.frag
diff --git a/src/quick/items/shaders/sprite.vert b/src/quick/scenegraph/shaders/sprite.vert
index fc826f60b4..fc826f60b4 100644
--- a/src/quick/items/shaders/sprite.vert
+++ b/src/quick/scenegraph/shaders/sprite.vert
diff --git a/src/quick/items/shaders/sprite_core.frag b/src/quick/scenegraph/shaders/sprite_core.frag
index c1087a8754..c1087a8754 100644
--- a/src/quick/items/shaders/sprite_core.frag
+++ b/src/quick/scenegraph/shaders/sprite_core.frag
diff --git a/src/quick/items/shaders/sprite_core.vert b/src/quick/scenegraph/shaders/sprite_core.vert
index 5027bf03fc..5027bf03fc 100644
--- a/src/quick/items/shaders/sprite_core.vert
+++ b/src/quick/scenegraph/shaders/sprite_core.vert