From 16ca1d7d65e66969724d4b490fa9a614b88f4bc3 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Thu, 19 Jan 2012 20:57:07 +1000 Subject: Implement reverse mode for sprites Change-Id: I1e8c124e883b881938fce01aeb67ac369fe0bc28 Reviewed-by: Alan Alpert --- src/quick/items/qquicksprite_p.h | 1 + src/quick/items/qquickspriteengine.cpp | 106 ++++++++++++++++++++++++--------- src/quick/items/qquickspriteengine_p.h | 5 +- src/quick/items/qquickspriteimage.cpp | 2 + 4 files changed, 85 insertions(+), 29 deletions(-) (limited to 'src/quick/items') diff --git a/src/quick/items/qquicksprite_p.h b/src/quick/items/qquicksprite_p.h index 2ec2380ea8..3e3c7f759a 100644 --- a/src/quick/items/qquicksprite_p.h +++ b/src/quick/items/qquicksprite_p.h @@ -56,6 +56,7 @@ class QQuickSprite : public QQuickStochasticState { Q_OBJECT Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) + //Renderers have to query this hint when advancing frames Q_PROPERTY(bool reverse READ reverse WRITE setReverse NOTIFY reverseChanged) Q_PROPERTY(bool frameSync READ frameSync WRITE setFrameSync NOTIFY frameSyncChanged) Q_PROPERTY(int frames READ frames WRITE setFrames NOTIFY framesChanged) diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp index 6e2e8764e1..d8bfacd33d 100644 --- a/src/quick/items/qquickspriteengine.cpp +++ b/src/quick/items/qquickspriteengine.cpp @@ -128,26 +128,41 @@ int QQuickSpriteEngine::maxFrames() TODO: All these calculations should be pre-calculated and cached during initialization for a significant performance boost TODO: Above idea needs to have the varying duration offset added to it */ -//TODO: Should these be adding advanceTime as well? +//TODO: Should these be adding advanceTime as well? But only if advanceTime was added to your startTime... /* To get these working with duration=-1, m_startTimes will be messed with should duration=-1 m_startTimes will be set in advance/restart to 0->(m_framesPerRow-1) and can be used directly as extra. This makes it 'frame' instead, but is more memory efficient than two arrays and less hideous than a vector of unions. */ +int QQuickSpriteEngine::pseudospriteProgress(int sprite, int state, int* rowDuration) +{ + int myRowDuration = m_duration[sprite] * m_sprites[state]->m_framesPerRow / m_sprites[state]->m_frames; + if (rowDuration) + *rowDuration = myRowDuration; + + if (m_sprites[state]->reverse()) //shift start-time back by the amount of time the first frame is smaller than rowDuration + return (m_timeOffset - (m_startTimes[sprite] - (myRowDuration - (m_duration[sprite] % myRowDuration))) ) + / myRowDuration; + else + return (m_timeOffset - m_startTimes[sprite]) / myRowDuration; +} + int QQuickSpriteEngine::spriteState(int sprite) { int state = m_things[sprite]; if (!m_sprites[state]->m_generatedCount) return state; + int extra; - if (m_sprites[state]->frameSync()) { + if (m_sprites[state]->frameSync()) extra = m_startTimes[sprite]; - } else { - if (!m_duration[sprite]) - return state; - int rowDuration = m_duration[sprite] * m_sprites[state]->m_framesPerRow / m_sprites[state]->m_frames; - extra = (m_timeOffset - m_startTimes[sprite])/rowDuration; - } + else if (!m_duration[sprite]) + return state; + else + extra = pseudospriteProgress(sprite, state); + if (m_sprites[state]->reverse()) + extra = (m_sprites[state]->m_generatedCount - 1) - extra; + return state + extra; } @@ -158,8 +173,10 @@ int QQuickSpriteEngine::spriteStart(int sprite) int state = m_things[sprite]; if (!m_sprites[state]->m_generatedCount) return m_startTimes[sprite]; - int rowDuration = m_duration[sprite] * m_sprites[state]->m_framesPerRow / m_sprites[state]->m_frames; - int extra = (m_timeOffset - m_startTimes[sprite])/rowDuration; + int rowDuration; + int extra = pseudospriteProgress(sprite, state, &rowDuration); + if (m_sprites[state]->reverse()) + return m_startTimes[sprite] + (extra ? (extra - 1)*rowDuration + (m_duration[sprite] % rowDuration) : 0); return m_startTimes[sprite] + extra*rowDuration; } @@ -168,15 +185,18 @@ int QQuickSpriteEngine::spriteFrames(int sprite) int state = m_things[sprite]; if (!m_sprites[state]->m_generatedCount) return m_sprites[state]->frames(); + int extra; - if (m_sprites[state]->frameSync()) { + if (m_sprites[state]->frameSync()) extra = m_startTimes[sprite]; - } else { - if (!m_duration[sprite]) - return state; - int rowDuration = m_duration[sprite] * m_sprites[state]->m_framesPerRow / m_sprites[state]->m_frames; - extra = (m_timeOffset - m_startTimes[sprite])/rowDuration; - } + else if (!m_duration[sprite]) + return m_sprites[state]->frames(); + else + extra = pseudospriteProgress(sprite, state); + if (m_sprites[state]->reverse()) + extra = (m_sprites[state]->m_generatedCount - 1) - extra; + + if (extra == m_sprites[state]->m_generatedCount - 1)//last state return m_sprites[state]->frames() % m_sprites[state]->m_framesPerRow; else @@ -190,8 +210,11 @@ int QQuickSpriteEngine::spriteDuration(int sprite)//Full duration, not per frame int state = m_things[sprite]; if (!m_sprites[state]->m_generatedCount) return m_duration[sprite]; - int rowDuration = m_duration[sprite] * m_sprites[state]->m_framesPerRow / m_sprites[state]->m_frames; - int extra = (m_timeOffset - m_startTimes[sprite])/rowDuration; + int rowDuration; + int extra = pseudospriteProgress(sprite, state, &rowDuration); + if (m_sprites[state]->reverse()) + extra = (m_sprites[state]->m_generatedCount - 1) - extra; + if (extra == m_sprites[state]->m_generatedCount - 1)//last state return m_duration[sprite] % rowDuration; else @@ -203,18 +226,47 @@ int QQuickSpriteEngine::spriteY(int sprite) int state = m_things[sprite]; if (!m_sprites[state]->m_generatedCount) return m_sprites[state]->m_rowY; + int extra; - if (m_sprites[state]->frameSync()) { + if (m_sprites[state]->frameSync()) extra = m_startTimes[sprite]; - } else { - if (!m_duration[sprite]) - return state; - int rowDuration = m_duration[sprite] * m_sprites[state]->m_framesPerRow / m_sprites[state]->m_frames; - extra = (m_timeOffset - m_startTimes[sprite])/rowDuration; - } + else if (!m_duration[sprite]) + return m_sprites[state]->m_rowY; + else + extra = pseudospriteProgress(sprite, state); + if (m_sprites[state]->reverse()) + extra = (m_sprites[state]->m_generatedCount - 1) - extra; + + return m_sprites[state]->m_rowY + m_sprites[state]->m_frameHeight * extra; } +int QQuickSpriteEngine::spriteX(int sprite) +{ + int state = m_things[sprite]; + if (!m_sprites[state]->m_generatedCount) + return m_sprites[state]->m_rowStartX; + + int extra; + if (m_sprites[state]->frameSync()) + extra = m_startTimes[sprite]; + else if (!m_duration[sprite]) + return m_sprites[state]->m_rowStartX; + else + extra = pseudospriteProgress(sprite, state); + if (m_sprites[state]->reverse()) + extra = (m_sprites[state]->m_generatedCount - 1) - extra; + + if (extra) + return 0; + return m_sprites[state]->m_rowStartX; +} + +QQuickSprite* QQuickSpriteEngine::sprite(int sprite) +{ + return m_sprites[m_things[sprite]]; +} + int QQuickSpriteEngine::spriteWidth(int sprite) { int state = m_things[sprite]; @@ -470,7 +522,7 @@ void QQuickSpriteEngine::advance(int idx) //Reimplemented to recognize and handl > int(m_timeOffset + (m_addAdvance ? m_advanceTime.elapsed() : 0))) { //only a pseduostate ended emit stateChanged(idx); - addToUpdateList(m_timeOffset + spriteDuration(idx), idx); + addToUpdateList(spriteStart(idx) + spriteDuration(idx) + (m_addAdvance ? m_advanceTime.elapsed() : 0), idx); return; } int nextIdx = nextState(m_things[idx],idx); diff --git a/src/quick/items/qquickspriteengine_p.h b/src/quick/items/qquickspriteengine_p.h index 6adab97430..cb954f26ff 100644 --- a/src/quick/items/qquickspriteengine_p.h +++ b/src/quick/items/qquickspriteengine_p.h @@ -264,12 +264,12 @@ public: return QDeclarativeListProperty(this, m_sprites); } - + QQuickSprite* sprite(int sprite=0); int spriteState(int sprite=0); int spriteStart(int sprite=0); int spriteFrames(int sprite=0); int spriteDuration(int sprite=0);//Full duration, not per frame - int spriteX(int /* sprite */ = 0) { return 0; }//Currently all rows are 0 aligned, if we get more space efficient we might change this + int spriteX(int sprite=0); int spriteY(int sprite=0); int spriteWidth(int sprite=0); int spriteHeight(int sprite=0); @@ -281,6 +281,7 @@ public: virtual void restart(int index=0); virtual void advance(int index=0); private: + int pseudospriteProgress(int,int,int*rd=0); QList m_sprites; }; diff --git a/src/quick/items/qquickspriteimage.cpp b/src/quick/items/qquickspriteimage.cpp index 1819decf10..e34944b970 100644 --- a/src/quick/items/qquickspriteimage.cpp +++ b/src/quick/items/qquickspriteimage.cpp @@ -452,6 +452,8 @@ void QQuickSpriteImage::prepareNextFrame() frameAt = 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(); -- cgit v1.2.3