Implement reverse mode for sprites
Change-Id: I1e8c124e883b881938fce01aeb67ac369fe0bc28 Reviewed-by: Alan Alpert <alan.alpert@nokia.com>
This commit is contained in:
parent
cc3716f899
commit
16ca1d7d65
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -264,12 +264,12 @@ public:
|
|||
return QDeclarativeListProperty<QQuickSprite>(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<QQuickSprite*> m_sprites;
|
||||
};
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -1474,8 +1474,17 @@ void QQuickImageParticle::spritesUpdate(qreal time)
|
|||
//TODO: Interpolate between two different animations if it's going to transition next frame
|
||||
// This is particularly important for cut-up sprites.
|
||||
QQuickParticleData* datum = (mainDatum->animationOwner == this ? mainDatum : getShadowDatum(mainDatum));
|
||||
int spriteIdx = 0;
|
||||
for (int i = 0; i<m_startsIdx.count(); i++) {
|
||||
if (m_startsIdx[i].second == gIdx){
|
||||
spriteIdx = m_startsIdx[i].first + datum->index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
double frameAt;
|
||||
qreal progress = 0;
|
||||
|
||||
if (datum->frameDuration > 0) {
|
||||
qreal frame = (time - datum->animT)/(datum->frameDuration / 1000.0);
|
||||
frame = qBound((qreal)0.0, frame, (qreal)((qreal)datum->frameCount - 1.0));//Stop at count-1 frames until we have between anim interpolation
|
||||
|
@ -1487,15 +1496,12 @@ void QQuickImageParticle::spritesUpdate(qreal time)
|
|||
datum->frameAt++;
|
||||
if (datum->frameAt >= datum->frameCount){
|
||||
datum->frameAt = 0;
|
||||
for (int i = 0; i<m_startsIdx.count(); i++) {
|
||||
if (m_startsIdx[i].second == gIdx){
|
||||
m_spriteEngine->advance(m_startsIdx[i].first + datum->index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_spriteEngine->advance(spriteIdx);
|
||||
}
|
||||
frameAt = datum->frameAt;
|
||||
}
|
||||
if (m_spriteEngine->sprite(spriteIdx)->reverse())//### Store this in datum too?
|
||||
frameAt = (datum->frameCount - 1) - frameAt;
|
||||
QSizeF sheetSize = getState<ImageMaterialData>(m_material)->animSheetSize;
|
||||
qreal y = datum->animY / sheetSize.height();
|
||||
qreal w = datum->animWidth / sheetSize.width();
|
||||
|
|
Loading…
Reference in New Issue