aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Alpert <alan.alpert@nokia.com>2011-09-01 20:11:42 +1000
committerQt by Nokia <qt-info@nokia.com>2011-09-08 03:34:41 +0200
commite45295bef132ddf220cecfa3f4343d90908744c5 (patch)
tree9ae1704c6943207353434907175bea7d0b54f4af
parent0da97d5ab9aff9ed8d0000f835de67d2510f472c (diff)
Allow particles to have eternal life
Change-Id: I3b776a6e79cb064e826cb7b7721a3a57744225c1 Reviewed-on: http://codereview.qt-project.org/4064 Reviewed-by: Alan Alpert <alan.alpert@nokia.com> Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
-rw-r--r--src/declarative/particles/qsgparticleaffector.cpp2
-rw-r--r--src/declarative/particles/qsgparticleemitter.cpp17
-rw-r--r--src/declarative/particles/qsgparticleemitter_p.h9
-rw-r--r--src/declarative/particles/qsgparticlesystem.cpp38
-rw-r--r--src/declarative/particles/qsgparticlesystem_p.h4
5 files changed, 61 insertions, 9 deletions
diff --git a/src/declarative/particles/qsgparticleaffector.cpp b/src/declarative/particles/qsgparticleaffector.cpp
index a64b4ee06c..83912898cf 100644
--- a/src/declarative/particles/qsgparticleaffector.cpp
+++ b/src/declarative/particles/qsgparticleaffector.cpp
@@ -166,7 +166,7 @@ void QSGParticleAffector::affectSystem(qreal dt)
m_system->m_needsReset << d;
if (m_onceOff)
m_onceOffed << qMakePair(d->group, d->index);
- if (m_signal)
+ if (m_signal)//###Make signal based on if connected, and then m_signal just affects AffectParticle for base?
emit affected(curPos.x(), curPos.y());
}
}
diff --git a/src/declarative/particles/qsgparticleemitter.cpp b/src/declarative/particles/qsgparticleemitter.cpp
index 2a76f77cf1..6519bf5f9e 100644
--- a/src/declarative/particles/qsgparticleemitter.cpp
+++ b/src/declarative/particles/qsgparticleemitter.cpp
@@ -100,6 +100,12 @@ QT_BEGIN_NAMESPACE
The time in milliseconds each emitted particle should last for.
+ If you do not want particles to automatically die after a time, for example if
+ you wish to dispose of them manually, set lifeSpan to Emitter.InfiniteLife.
+
+ lifeSpans greater than or equal to 600000 (10 minutes) will be treated as infinite.
+ Particles with lifeSpans less than or equal to 0 will start out dead.
+
Default value is 1000 (one second).
*/
/*!
@@ -205,7 +211,6 @@ QSGParticleEmitter::QSGParticleEmitter(QSGItem *parent) :
, m_maxParticleCount(-1)
, m_burstLeft(0)
, m_speed_from_movement(0)
- , m_particle_count(0)
, m_reset_last(true)
, m_last_timestamp(-1)
, m_last_emission(0)
@@ -339,6 +344,7 @@ void QSGParticleEmitter::emitWindow(int timeStamp)
m_last_timestamp = timeStamp/1000.;
m_last_emission = m_last_timestamp;
m_reset_last = false;
+ m_emitCap = particleCount();
}
if (m_burstLeft){
@@ -375,7 +381,7 @@ void QSGParticleEmitter::emitWindow(int timeStamp)
qreal emitter_y_offset = m_last_emitter.y() - y();
if (!m_burstQueue.isEmpty() && !m_burstLeft && !m_emitting)//'outside time' emissions only
pt = time;
- while (pt < time || !m_burstQueue.isEmpty()) {
+ while ((pt < time && m_emitCap) || !m_burstQueue.isEmpty()) {
//int pos = m_last_particle % m_particle_count;
QSGParticleData* datum = m_system->newDatum(m_system->m_groupIds[m_particle], !m_overwrite);
if (datum){//actually emit(otherwise we've been asked to skip this one)
@@ -393,11 +399,16 @@ void QSGParticleEmitter::emitWindow(int timeStamp)
// Particle timestamp
datum->t = pt;
- datum->lifeSpan = //TODO:Promote to base class?
+ datum->lifeSpan =
(m_particleDuration
+ ((rand() % ((m_particleDurationVariation*2) + 1)) - m_particleDurationVariation))
/ 1000.0;
+ if (datum->lifeSpan >= m_system->maxLife){
+ datum->lifeSpan = m_system->maxLife;
+ m_emitCap--;//emitCap keeps us from reemitting 'infinite' particles after their life. Unless you reset the emitter.
+ }
+
// Particle position
QRectF boundsRect;
if (!m_burstQueue.isEmpty()){
diff --git a/src/declarative/particles/qsgparticleemitter_p.h b/src/declarative/particles/qsgparticleemitter_p.h
index cd14fa55e9..9e1fc7a9d8 100644
--- a/src/declarative/particles/qsgparticleemitter_p.h
+++ b/src/declarative/particles/qsgparticleemitter_p.h
@@ -80,11 +80,16 @@ class QSGParticleEmitter : public QSGItem
Q_PROPERTY(QSGStochasticDirection *acceleration READ acceleration WRITE setAcceleration NOTIFY accelerationChanged)
Q_PROPERTY(qreal speedFromMovement READ speedFromMovement WRITE setSpeedFromMovement NOTIFY speedFromMovementChanged)
+ Q_ENUMS(Lifetime)
public:
explicit QSGParticleEmitter(QSGItem *parent = 0);
virtual ~QSGParticleEmitter();
virtual void emitWindow(int timeStamp);
+ enum Lifetime {
+ InfiniteLife = QSGParticleSystem::maxLife
+ };
+
bool emitting() const
{
return m_emitting;
@@ -264,10 +269,10 @@ public slots:
}
}
+ virtual void reset();
public:
int particleCount() const;
- virtual void reset();
QSGParticleExtruder* extruder() const
{
return m_extruder;
@@ -340,7 +345,7 @@ protected:
//Used in default implementation, but might be useful
qreal m_speed_from_movement;
- int m_particle_count;
+ int m_emitCap;
bool m_reset_last;
qreal m_last_timestamp;
qreal m_last_emission;
diff --git a/src/declarative/particles/qsgparticlesystem.cpp b/src/declarative/particles/qsgparticlesystem.cpp
index 0888e7b90e..534b1ca8a1 100644
--- a/src/declarative/particles/qsgparticlesystem.cpp
+++ b/src/declarative/particles/qsgparticlesystem.cpp
@@ -147,9 +147,13 @@ void QSGParticleDataHeap::grow() //###Consider automatic growth vs resize() call
m_data.resize(1 << ++m_size);
}
-void QSGParticleDataHeap::insert(QSGParticleData* data)//TODO: Optimize 0 lifespan (or already dead) case
+void QSGParticleDataHeap::insert(QSGParticleData* data)
{
- int time = roundedTime(data->t + data->lifeSpan);
+ insertTimed(data, roundedTime(data->t + data->lifeSpan));
+}
+
+void QSGParticleDataHeap::insertTimed(QSGParticleData* data, int time){
+ //TODO: Optimize 0 lifespan (or already dead) case
if (m_lookups.contains(time)){
m_data[m_lookups[time]].data << data;
return;
@@ -330,7 +334,13 @@ bool QSGParticleGroupData::recycle()
}
void QSGParticleGroupData::prepareRecycler(QSGParticleData* d){
- dataHeap.insert(d);
+ if (d->lifeSpan*1000 < m_system->maxLife){
+ dataHeap.insert(d);
+ } else {
+ while ((roundedTime(d->t) + 2*m_system->maxLife/3) <= m_system->m_timeInt)
+ d->extendLife(m_system->maxLife/3000.0);
+ dataHeap.insertTimed(d, roundedTime(d->t) + 2*m_system->maxLife/3);
+ }
}
QSGParticleData::QSGParticleData(QSGParticleSystem* sys)
@@ -529,6 +539,28 @@ float QSGParticleData::lifeLeft()
return (t + lifeSpan) - (system->m_timeInt/1000.0);
}
+void QSGParticleData::extendLife(float time)
+{
+ qreal newX = curX();
+ qreal newY = curY();
+ qreal newVX = curVX();
+ qreal newVY = curVY();
+
+ t += time;
+ animT += time;
+
+ qreal elapsed = (system->m_timeInt / 1000.0) - t;
+ qreal evy = newVY - elapsed*ay;
+ qreal ey = newY - elapsed*evy - 0.5 * elapsed*elapsed*ay;
+ qreal evx = newVX - elapsed*ax;
+ qreal ex = newX - elapsed*evx - 0.5 * elapsed*elapsed*ax;
+
+ x = ex;
+ vx = evx;
+ y = ey;
+ vy = evy;
+}
+
QSGParticleSystem::QSGParticleSystem(QSGItem *parent) :
QSGItem(parent), m_particle_count(0), m_running(true)
, m_startTime(0), m_nextIndex(0), m_componentComplete(false), m_spriteEngine(0)
diff --git a/src/declarative/particles/qsgparticlesystem_p.h b/src/declarative/particles/qsgparticlesystem_p.h
index 5df6afb923..17b67d9cce 100644
--- a/src/declarative/particles/qsgparticlesystem_p.h
+++ b/src/declarative/particles/qsgparticlesystem_p.h
@@ -80,6 +80,7 @@ class QSGParticleDataHeap {
public:
QSGParticleDataHeap();
void insert(QSGParticleData* data);
+ void insertTimed(QSGParticleData* data, int time);
int top();
@@ -211,6 +212,7 @@ public:
float curSize();
void clone(const QSGParticleData& other);//Not =, leaves meta-data like index
QDeclarativeV8Handle v8Value();
+ void extendLife(float time);
private:
QSGV8ParticleData* v8Datum;
};
@@ -242,6 +244,8 @@ public:
int count(){ return m_particle_count; }
+ static const int maxLife = 600000;
+
signals:
void systemInitialized();