aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/declarative/imageelements/simplesprite.qml2
-rw-r--r--examples/declarative/imageelements/spriteimage.qml10
-rw-r--r--src/quick/items/qquicksprite.cpp123
-rw-r--r--src/quick/items/qquicksprite_p.h173
-rw-r--r--src/quick/items/qquickspriteengine.cpp30
-rw-r--r--src/quick/items/qquickspriteengine_p.h60
6 files changed, 321 insertions, 77 deletions
diff --git a/examples/declarative/imageelements/simplesprite.qml b/examples/declarative/imageelements/simplesprite.qml
index accddf975b..ec696c6810 100644
--- a/examples/declarative/imageelements/simplesprite.qml
+++ b/examples/declarative/imageelements/simplesprite.qml
@@ -50,8 +50,8 @@ Item {
anchors.fill: parent
Sprite{
source: "content/speaker.png"
- duration: -1
frames: 60
+ frameSync: true
frameWidth: 170
frameHeight: 170
}
diff --git a/examples/declarative/imageelements/spriteimage.qml b/examples/declarative/imageelements/spriteimage.qml
index 95b3b7d260..bace7ef7e2 100644
--- a/examples/declarative/imageelements/spriteimage.qml
+++ b/examples/declarative/imageelements/spriteimage.qml
@@ -66,7 +66,7 @@ Item {
frames: 1
frameWidth: 256
frameHeight: 256
- duration: 100
+ frameDuration: 100
to: {"still":1, "blink":0.1, "floating":0}
}
Sprite{
@@ -75,7 +75,7 @@ Item {
frames: 3
frameWidth: 256
frameHeight: 256
- duration: 100
+ frameDuration: 100
to: {"still":1}
}
Sprite{
@@ -84,7 +84,7 @@ Item {
frames: 9
frameWidth: 256
frameHeight: 256
- duration: 160
+ frameDuration: 160
to: {"still":0, "flailing":1}
}
Sprite{
@@ -93,7 +93,7 @@ Item {
frames: 8
frameWidth: 256
frameHeight: 256
- duration: 160
+ frameDuration: 160
to: {"falling":1}
}
Sprite{
@@ -102,7 +102,7 @@ Item {
frames: 5
frameWidth: 256
frameHeight: 256
- duration: 160
+ frameDuration: 160
to: {"falling":1}
}
}
diff --git a/src/quick/items/qquicksprite.cpp b/src/quick/items/qquicksprite.cpp
index 4c7dafafbb..8b5369d3f6 100644
--- a/src/quick/items/qquicksprite.cpp
+++ b/src/quick/items/qquicksprite.cpp
@@ -53,13 +53,59 @@ QT_BEGIN_NAMESPACE
/*!
\qmlproperty int QtQuick2::Sprite::duration
- Time between frames. Use -1 to indicate one sprite frame per rendered frame.
+ Duration of the animation. Values below 0 are invalid.
+
+ If frameRate is valid then it will be used to calculate the duration of the frames.
+ If not, and frameDuration is valid, then frameDuration will be used. Otherwise duration is used.
*/
/*!
\qmlproperty int QtQuick2::Sprite::durationVariation
- The time between frames can vary by up to this amount. Variation will never decrease the time
- between frames to less than 0.
+ The duration of the animation can vary by up to this amount. Variation will never decrease the
+ length of the animation to less than 0.
+
+ durationVariation will only take effect if duration is
+ used to calculate the duration of frames.
+
+ Default is 0.
+*/
+
+/*!
+ \qmlproperty qreal QtQuick2::Sprite::frameRate
+
+ Frames per second to show in the animation. Values below 0 are invalid.
+
+ If frameRate is valid then it will be used to calculate the duration of the frames.
+ If not, and frameDuration is valid , then frameDuration will be used. Otherwise duration is used.
+*/
+/*!
+ \qmlproperty qreal QtQuick2::Sprite::frameRateVariation
+
+ The frame rate between animations can vary by up to this amount. Variation will never decrease the
+ length of the animation to less than 0.
+
+ frameRateVariation will only take effect if frameRate is
+ used to calculate the duration of frames.
+
+ Default is 0.
+*/
+
+/*!
+ \qmlproperty int QtQuick2::Sprite::frameDuration
+
+ Duration of each frame of the animation. Values below 0 are invalid.
+
+ If frameRate is valid then it will be used to calculate the duration of the frames.
+ If not, and frameDuration is valid, then frameDuration will be used. Otherwise duration is used.
+*/
+/*!
+ \qmlproperty int QtQuick2::Sprite::frameDurationVariation
+
+ The duration of a frame in the animation can vary by up to this amount. Variation will never decrease the
+ length of the animation to less than 0.
+
+ frameDurationVariation will only take effect if frameDuration is
+ used to calculate the duration of frames.
Default is 0.
*/
@@ -99,22 +145,87 @@ QT_BEGIN_NAMESPACE
Width of a single frame in this sprite.
*/
/*!
+ \qmlproperty int QtQuick2::Sprite::frameX
+
+ The X coordinate in the image file of the first frame of the sprite.
+*/
+/*!
+ \qmlproperty int QtQuick2::Sprite::frameY
+
+ The Y coordinate in the image file of the first frame of the sprite.
+*/
+/*!
\qmlproperty url QtQuick2::Sprite::source
The image source for the animation.
If frameHeight and frameWidth are not specified, it is assumed to be a single long row of square frames.
Otherwise, it can be multiple contiguous rows or rectangluar frames, when one row runs out the next will be used.
+
+ If frameX and frameY are specified, the row of frames will be taken with that x/y coordinate as the upper left corner.
+*/
+
+/*!
+ \qmlproperty bool QtQuick2::Sprite::reverse
+
+ If true, then the animation will be played in reverse.
+
+ Default is false.
*/
-QQuickSprite::QQuickSprite(QObject *parent) :
- QQuickStochasticState(parent)
+/*!
+ \qmlproperty bool QtQuick2::Sprite::frameSync
+
+ If true, then the animation will have no duration. Instead, the animation will advance
+ one frame each time a frame is rendered to the screen. This syncronizes it with the painting
+ rate as opposed to elapsed time.
+
+ If frameSync is set to true, it overrides all of duration, frameRate and frameDuration.
+
+ Default is false.
+*/
+
+static const int unsetDuration = -2;//-1 means perframe for duration
+QQuickSprite::QQuickSprite(QObject *parent)
+ : QQuickStochasticState(parent)
, m_generatedCount(0)
, m_framesPerRow(0)
+ , m_rowY(0)
+ , m_reverse(false)
, m_frameHeight(0)
, m_frameWidth(0)
- , m_rowY(0)
+ , m_frames(1)
+ , m_frameX(0)
+ , m_frameY(0)
+ , m_frameRate(unsetDuration)
+ , m_frameRateVariation(0)
+ , m_frameDuration(unsetDuration)
+ , m_frameDurationVariation(0)
+ , m_frameSync(false)
+{
+}
+
+int QQuickSprite::variedDuration() const //Deals with precedence when multiple durations are set
{
+ if (m_frameSync)
+ return 0;
+
+ if (m_frameRate != unsetDuration) {
+ qreal fpms = (m_frameRate
+ + (m_frameRateVariation * ((qreal)qrand()/RAND_MAX) * 2)
+ - m_frameRateVariation) / 1000.0;
+ return qMax(qreal(0.0) , m_frames / fpms);
+ } else if (m_frameDuration != unsetDuration) {
+ int mspf = m_frameDuration
+ + (m_frameDurationVariation * ((qreal)qrand()/RAND_MAX) * 2)
+ - m_frameDurationVariation;
+ return qMax(0, m_frames * mspf);
+ }
+ qWarning() << "Sprite::duration is changing meaning to the full animation duration.";
+ qWarning() << "Use Sprite::frameDuration for the old meaning, of per frame duration.";
+ qWarning() << "As an interim measure, duration/durationVariation means the same as frameDuration/frameDurationVariation, and you'll get this warning spewed out everywhere to movtivate you.";
+ //Note that the spammyness is due to this being the best location to detect, but also called once each animation loop
+ return QQuickStochasticState::variedDuration() * m_frames;
}
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicksprite_p.h b/src/quick/items/qquicksprite_p.h
index e8a033caa8..6aab74f8dd 100644
--- a/src/quick/items/qquicksprite_p.h
+++ b/src/quick/items/qquicksprite_p.h
@@ -56,10 +56,20 @@ class QQuickSprite : public QQuickStochasticState
{
Q_OBJECT
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+ 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)
//If frame height or width is not specified, it is assumed to be a single long row of square frames.
//Otherwise, it can be multiple contiguous rows, when one row runs out the next will be used.
Q_PROPERTY(int frameHeight READ frameHeight WRITE setFrameHeight NOTIFY frameHeightChanged)
Q_PROPERTY(int frameWidth READ frameWidth WRITE setFrameWidth NOTIFY frameWidthChanged)
+ Q_PROPERTY(int frameX READ frameX WRITE setFrameX NOTIFY frameXChanged)
+ Q_PROPERTY(int frameY READ frameY WRITE setFrameY NOTIFY frameYChanged)
+ //Precedence order: frameRate, frameDuration, duration
+ Q_PROPERTY(qreal frameRate READ frameRate WRITE setFrameRate NOTIFY frameRateChanged RESET resetFrameRate)
+ Q_PROPERTY(qreal frameRateVariation READ frameRateVariation WRITE setFrameRateVariation NOTIFY frameRateVariationChanged)
+ Q_PROPERTY(int frameDuration READ frameDuration WRITE setFrameDuration NOTIFY frameDurationChanged RESET resetFrameDuration)
+ Q_PROPERTY(int frameDurationVariation READ frameDurationVariation WRITE setFrameDurationVariation NOTIFY frameDurationVariationChanged)
public:
explicit QQuickSprite(QObject *parent = 0);
@@ -80,6 +90,63 @@ public:
}
+ bool reverse() const
+ {
+ return m_reverse;
+ }
+
+ int frames() const
+ {
+ return m_frames;
+ }
+
+ int frameX() const
+ {
+ return m_frameX;
+ }
+
+ int frameY() const
+ {
+ return m_frameY;
+ }
+
+ void resetFrameRate()
+ {
+ setFrameRate(-1);
+ }
+
+ qreal frameRate() const
+ {
+ return m_frameRate;
+ }
+
+ qreal frameRateVariation() const
+ {
+ return m_frameRateVariation;
+ }
+
+ void resetFrameDuration()
+ {
+ setFrameDuration(-1);
+ }
+
+ int frameDuration() const
+ {
+ return m_frameDuration;
+ }
+
+ int frameDurationVariation() const
+ {
+ return m_frameDurationVariation;
+ }
+
+ int variedDuration() const;
+
+ bool frameSync() const
+ {
+ return m_frameSync;
+ }
+
signals:
void sourceChanged(QUrl arg);
@@ -88,6 +155,24 @@ signals:
void frameWidthChanged(int arg);
+ void reverseChanged(bool arg);
+
+ void framesChanged(int arg);
+
+ void frameXChanged(int arg);
+
+ void frameYChanged(int arg);
+
+ void frameRateChanged(qreal arg);
+
+ void frameRateVariationChanged(qreal arg);
+
+ void frameDurationChanged(int arg);
+
+ void frameDurationVariationChanged(int arg);
+
+ void frameSyncChanged(bool arg);
+
public slots:
void setSource(QUrl arg)
@@ -115,17 +200,99 @@ public slots:
}
+ void setReverse(bool arg)
+ {
+ if (m_reverse != arg) {
+ m_reverse = arg;
+ emit reverseChanged(arg);
+ }
+ }
+
+ void setFrames(int arg)
+ {
+ if (m_frames != arg) {
+ m_frames = arg;
+ emit framesChanged(arg);
+ }
+ }
+
+ void setFrameX(int arg)
+ {
+ if (m_frameX != arg) {
+ m_frameX = arg;
+ emit frameXChanged(arg);
+ }
+ }
+
+ void setFrameY(int arg)
+ {
+ if (m_frameY != arg) {
+ m_frameY = arg;
+ emit frameYChanged(arg);
+ }
+ }
+
+ void setFrameRate(qreal arg)
+ {
+ if (m_frameRate != arg) {
+ m_frameRate = arg;
+ emit frameRateChanged(arg);
+ }
+ }
+
+ void setFrameRateVariation(qreal arg)
+ {
+ if (m_frameRateVariation != arg) {
+ m_frameRateVariation = arg;
+ emit frameRateVariationChanged(arg);
+ }
+ }
+
+ void setFrameDuration(int arg)
+ {
+ if (m_frameDuration != arg) {
+ m_frameDuration = arg;
+ emit frameDurationChanged(arg);
+ }
+ }
+
+ void setFrameDurationVariation(int arg)
+ {
+ if (m_frameDurationVariation != arg) {
+ m_frameDurationVariation = arg;
+ emit frameDurationVariationChanged(arg);
+ }
+ }
+
+ void setFrameSync(bool arg)
+ {
+ if (m_frameSync != arg) {
+ m_frameSync = arg;
+ emit frameSyncChanged(arg);
+ }
+ }
+
private:
- friend class QSGImageParticle;
+ friend class QQuickImageParticle;
+ friend class QQuickSpriteImage;
friend class QQuickSpriteEngine;
friend class QQuickStochasticEngine;
int m_generatedCount;
int m_framesPerRow;
+ int m_rowY;
+
QUrl m_source;
+ bool m_reverse;
int m_frameHeight;
int m_frameWidth;
- int m_rowY;
-
+ int m_frames;
+ int m_frameX;
+ int m_frameY;
+ qreal m_frameRate;
+ qreal m_frameRateVariation;
+ int m_frameDuration;
+ int m_frameDurationVariation;
+ bool m_frameSync;
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp
index 38be93f1ce..470aa6d160 100644
--- a/src/quick/items/qquickspriteengine.cpp
+++ b/src/quick/items/qquickspriteengine.cpp
@@ -139,12 +139,12 @@ int QQuickSpriteEngine::spriteState(int sprite)
if (!m_sprites[state]->m_generatedCount)
return state;
int extra;
- if (m_sprites[state]->duration() < 0) {
+ 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;
+ int rowDuration = m_duration[sprite] * m_sprites[state]->m_framesPerRow / m_sprites[state]->m_frames;
extra = (m_timeOffset - m_startTimes[sprite])/rowDuration;
}
return state + extra;
@@ -157,7 +157,7 @@ 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;
+ int rowDuration = m_duration[sprite] * m_sprites[state]->m_framesPerRow / m_sprites[state]->m_frames;
int extra = (m_timeOffset - m_startTimes[sprite])/rowDuration;
return m_startTimes[sprite] + extra*rowDuration;
}
@@ -168,12 +168,12 @@ int QQuickSpriteEngine::spriteFrames(int sprite)
if (!m_sprites[state]->m_generatedCount)
return m_sprites[state]->frames();
int extra;
- if (m_sprites[state]->duration() < 0) {
+ 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;
+ int rowDuration = m_duration[sprite] * m_sprites[state]->m_framesPerRow / m_sprites[state]->m_frames;
extra = (m_timeOffset - m_startTimes[sprite])/rowDuration;
}
if (extra == m_sprites[state]->m_generatedCount - 1)//last state
@@ -188,11 +188,11 @@ int QQuickSpriteEngine::spriteDuration(int sprite)//Full duration, not per frame
return m_duration[sprite];
int state = m_things[sprite];
if (!m_sprites[state]->m_generatedCount)
- return m_duration[sprite] * m_sprites[state]->frames();
- int rowDuration = m_duration[sprite] * m_sprites[state]->m_framesPerRow;
+ 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;
if (extra == m_sprites[state]->m_generatedCount - 1)//last state
- return (m_duration[sprite] * m_sprites[state]->frames()) % rowDuration;
+ return m_duration[sprite] % rowDuration;
else
return rowDuration;
}
@@ -203,12 +203,12 @@ int QQuickSpriteEngine::spriteY(int sprite)
if (!m_sprites[state]->m_generatedCount)
return m_sprites[state]->m_rowY;
int extra;
- if (m_sprites[state]->duration() < 0) {
+ 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;
+ int rowDuration = m_duration[sprite] * m_sprites[state]->m_framesPerRow / m_sprites[state]->m_frames;
extra = (m_timeOffset - m_startTimes[sprite])/rowDuration;
}
return m_sprites[state]->m_rowY + m_sprites[state]->m_frameHeight * extra;
@@ -397,7 +397,7 @@ void QQuickStochasticEngine::restart(int index)
m_startTimes[index] = m_timeOffset;
if (m_addAdvance)
m_startTimes[index] += m_advanceTime.elapsed();
- int time = m_duration[index] * m_states[m_things[index]]->frames() + m_startTimes[index];
+ int time = m_duration[index] + m_startTimes[index];
for (int i=0; i<m_stateUpdates.count(); i++)
m_stateUpdates[i].second.removeAll(index);
if (m_duration[index] >= 0)
@@ -406,7 +406,7 @@ void QQuickStochasticEngine::restart(int index)
void QQuickSpriteEngine::restart(int index) //Reimplemented to recognize and handle pseudostates
{
- if (m_sprites[m_things[index]]->duration() < 0) {//Manually advanced
+ if (m_sprites[m_things[index]]->frameSync()) {//Manually advanced
m_startTimes[index] = 0;
} else {
m_startTimes[index] = m_timeOffset;
@@ -436,7 +436,7 @@ void QQuickSpriteEngine::advance(int idx) //Reimplemented to recognize and handl
if (idx >= m_things.count())
return;//TODO: Proper fix(because this has happened and I just ignored it)
if (m_duration[idx] == 0) {
- if (m_sprites[m_things[idx]]->duration() < 0) {
+ if (m_sprites[m_things[idx]]->frameSync()) {
//Manually called, advance inner substate count
m_startTimes[idx]++;
if (m_startTimes[idx] < m_sprites[m_things[idx]]->m_generatedCount) {
@@ -446,8 +446,8 @@ void QQuickSpriteEngine::advance(int idx) //Reimplemented to recognize and handl
}
}
//just go past the pseudostate logic
- } else if (m_startTimes[idx] + m_duration[idx] * m_states[m_things[idx]]->frames()
- > m_timeOffset + (m_addAdvance ? m_advanceTime.elapsed() : 0)) {
+ } else if (m_startTimes[idx] + m_duration[idx]
+ > int(m_timeOffset + (m_addAdvance ? m_advanceTime.elapsed() : 0))) {
//only a pseduostate ended
emit stateChanged(idx);
addToUpdateList(m_timeOffset + spriteDuration(idx), idx);
diff --git a/src/quick/items/qquickspriteengine_p.h b/src/quick/items/qquickspriteengine_p.h
index 48ef6c305e..7a147a2e88 100644
--- a/src/quick/items/qquickspriteengine_p.h
+++ b/src/quick/items/qquickspriteengine_p.h
@@ -56,20 +56,17 @@ QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QQuickSprite;
-class Q_AUTOTEST_EXPORT QQuickStochasticState : public QObject //For internal use
+class Q_AUTOTEST_EXPORT QQuickStochasticState : public QObject //Currently for internal use only - Sprite and ParticleGroup
{
Q_OBJECT
Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
- Q_PROPERTY(int durationVariation READ durationVariance WRITE setDurationVariance NOTIFY durationVarianceChanged)
+ Q_PROPERTY(int durationVariation READ durationVariation WRITE setDurationVariation NOTIFY durationVariationChanged)
Q_PROPERTY(QVariantMap to READ to WRITE setTo NOTIFY toChanged)
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
- Q_PROPERTY(qreal speedModifiesDuration READ speedModifer WRITE setSpeedModifier NOTIFY speedModifierChanged)
- Q_PROPERTY(int frames READ frames WRITE setFrames NOTIFY framesChanged)
public:
QQuickStochasticState(QObject* parent = 0)
: QObject(parent)
- , m_frames(1)
, m_duration(1000)
{
}
@@ -89,27 +86,17 @@ public:
return m_to;
}
- qreal speedModifer() const
+ int durationVariation() const
{
- return m_speedModifier;
+ return m_durationVariation;
}
- int durationVariance() const
- {
- return m_durationVariance;
- }
-
- int variedDuration() const
+ virtual int variedDuration() const
{
return qMax(qreal(0.0) , m_duration
- + (m_durationVariance * ((qreal)qrand()/RAND_MAX) * 2)
- - m_durationVariance);
- }
-
- int frames() const
- {
- return m_frames;
+ + (m_durationVariation * ((qreal)qrand()/RAND_MAX) * 2)
+ - m_durationVariation);
}
signals:
@@ -119,12 +106,9 @@ signals:
void toChanged(QVariantMap arg);
- void speedModifierChanged(qreal arg);
-
- void durationVarianceChanged(int arg);
+ void durationVariationChanged(int arg);
void entered();//### Just playing around - don't expect full state API
- void framesChanged(int arg);
public slots:
void setDuration(int arg)
@@ -151,37 +135,19 @@ public slots:
}
}
- void setSpeedModifier(qreal arg)
- {
- if (m_speedModifier != arg) {
- m_speedModifier = arg;
- emit speedModifierChanged(arg);
- }
- }
-
- void setDurationVariance(int arg)
- {
- if (m_durationVariance != arg) {
- m_durationVariance = arg;
- emit durationVarianceChanged(arg);
- }
- }
-
- void setFrames(int arg)
+ void setDurationVariation(int arg)
{
- if (m_frames != arg) {
- m_frames = arg;
- emit framesChanged(arg);
+ if (m_durationVariation != arg) {
+ m_durationVariation = arg;
+ emit durationVariationChanged(arg);
}
}
private:
QString m_name;
- int m_frames;
QVariantMap m_to;
int m_duration;
- qreal m_speedModifier;
- int m_durationVariance;
+ int m_durationVariation;
friend class QQuickStochasticEngine;
};