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());
}
}
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).
*/
/*!
, 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)
m_last_timestamp = timeStamp/1000.;
m_last_emission = m_last_timestamp;
m_reset_last = false;
+ m_emitCap = particleCount();
}
if (m_burstLeft){
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)
// 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()){
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;
}
}
+ virtual void reset();
public:
int particleCount() const;
- virtual void reset();
QSGParticleExtruder* extruder() const
{
return m_extruder;
//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;
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;
}
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)
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)
public:
QSGParticleDataHeap();
void insert(QSGParticleData* data);
+ void insertTimed(QSGParticleData* data, int time);
int top();
float curSize();
void clone(const QSGParticleData& other);//Not =, leaves meta-data like index
QDeclarativeV8Handle v8Value();
+ void extendLife(float time);
private:
QSGV8ParticleData* v8Datum;
};
int count(){ return m_particle_count; }
+ static const int maxLife = 600000;
+
signals:
void systemInitialized();