Fix emitter burst method bugs
authorAlan Alpert <alan.alpert@nokia.com>
Tue, 17 May 2011 03:48:20 +0000 (13:48 +1000)
committerAlan Alpert <alan.alpert@nokia.com>
Tue, 17 May 2011 03:48:20 +0000 (13:48 +1000)
Burst will now always burst at the x,y where it was called, and doesn't
leave trails between close bursts. Kill affector also gets a fix for
double killing things sometimes.

src/imports/particles/followemitter.cpp
src/imports/particles/killaffector.cpp
src/imports/particles/particleemitter.cpp
src/imports/particles/particleemitter.h
src/imports/particles/trailsemitter.cpp

index 9e1ec7b..17a544f 100644 (file)
@@ -84,7 +84,7 @@ void FollowEmitter::emitWindow(int timeStamp)
 {
     if (m_system == 0)
         return;
-    if(!m_emitting && !m_burstLeft && !m_emitLeft)
+    if(!m_emitting && !m_burstLeft && m_burstQueue.isEmpty())
         return;
     if(m_followCount != m_system->m_groupData[m_system->m_groupIds[m_follow]]->size){
         qreal oldPPS = m_particlesPerSecond;
@@ -123,70 +123,69 @@ void FollowEmitter::emitWindow(int timeStamp)
             m_lastEmission[i] = time;//jump over this time period without emitting, because it's outside
             continue;
         }
-        while(pt < time || m_emitLeft){
+        while(pt < time || !m_burstQueue.isEmpty()){
             ParticleData* datum = m_system->newDatum(gId2);
-            if(!datum){//skip this emission
-                if(m_emitLeft)
-                    --m_emitLeft;
-                else
-                    pt += particleRatio;
-                continue;
+            if(datum){//else, skip this emission
+                datum->e = this;//###useful?
+                ParticleVertex &p = datum->pv;
+
+                // Particle timestamp
+                p.t = pt;
+                p.lifeSpan =
+                        (m_particleDuration
+                         + ((rand() % ((m_particleDurationVariation*2) + 1)) - m_particleDurationVariation))
+                        / 1000.0;
+
+                // Particle position
+                // Note that burst location doesn't get used for follow emitter
+                qreal followT =  pt - d->pv.t;
+                qreal followT2 = followT * followT * 0.5;
+                qreal sizeOffset = d->pv.size/2;//TODO: Current size? As an option
+                //TODO: Set variations
+                //Subtract offset, because PS expects this in emitter coordinates
+                QRectF boundsRect(d->pv.x - offset.x() + d->pv.sx * followT + d->pv.ax * followT2 - m_emitterXVariation/2,
+                                  d->pv.y - offset.y() + d->pv.sy * followT + d->pv.ay * followT2 - m_emitterYVariation/2,
+                                  m_emitterXVariation,
+                                  m_emitterYVariation);
+    //            QRectF boundsRect(d->pv.x + d->pv.sx * followT + d->pv.ax * followT2 + offset.x() - sizeOffset,
+    //                              d->pv.y + d->pv.sy * followT + d->pv.ay * followT2 + offset.y() - sizeOffset,
+    //                              sizeOffset*2,
+    //                              sizeOffset*2);
+
+                ParticleExtruder* effectiveEmissionExtruder = m_emissionExtruder ? m_emissionExtruder : m_defaultEmissionExtruder;
+                const QPointF &newPos = effectiveEmissionExtruder->extrude(boundsRect);
+                p.x = newPos.x();
+                p.y = newPos.y();
+
+                // Particle speed
+                const QPointF &speed = m_speed->sample(newPos);
+                p.sx = speed.x();
+                p.sy = speed.y();
+
+                // Particle acceleration
+                const QPointF &accel = m_acceleration->sample(newPos);
+                p.ax = accel.x();
+                p.ay = accel.y();
+
+                // Particle size
+                float sizeVariation = -m_particleSizeVariation
+                        + rand() / float(RAND_MAX) * m_particleSizeVariation * 2;
+
+                float size = qMax((qreal)0.0, m_particleSize + sizeVariation);
+                float endSize = qMax((qreal)0.0, sizeAtEnd + sizeVariation);
+
+                p.size = size * float(m_emitting);
+                p.endSize = endSize * float(m_emitting);
+
+                m_system->emitParticle(datum);
             }
-            datum->e = this;//###useful?
-            ParticleVertex &p = datum->pv;
-
-            // Particle timestamp
-            p.t = pt;
-            p.lifeSpan =
-                    (m_particleDuration
-                     + ((rand() % ((m_particleDurationVariation*2) + 1)) - m_particleDurationVariation))
-                    / 1000.0;
-
-            // Particle position
-            qreal followT =  pt - d->pv.t;
-            qreal followT2 = followT * followT * 0.5;
-            qreal sizeOffset = d->pv.size/2;//TODO: Current size? As an option
-            //TODO: Set variations
-            //Subtract offset, because PS expects this in emitter coordinates
-            QRectF boundsRect(d->pv.x - offset.x() + d->pv.sx * followT + d->pv.ax * followT2 - m_emitterXVariation/2,
-                              d->pv.y - offset.y() + d->pv.sy * followT + d->pv.ay * followT2 - m_emitterYVariation/2,
-                              m_emitterXVariation,
-                              m_emitterYVariation);
-//            QRectF boundsRect(d->pv.x + d->pv.sx * followT + d->pv.ax * followT2 + offset.x() - sizeOffset,
-//                              d->pv.y + d->pv.sy * followT + d->pv.ay * followT2 + offset.y() - sizeOffset,
-//                              sizeOffset*2,
-//                              sizeOffset*2);
-
-            ParticleExtruder* effectiveEmissionExtruder = m_emissionExtruder ? m_emissionExtruder : m_defaultEmissionExtruder;
-            const QPointF &newPos = effectiveEmissionExtruder->extrude(boundsRect);
-            p.x = newPos.x();
-            p.y = newPos.y();
-
-            // Particle speed
-            const QPointF &speed = m_speed->sample(newPos);
-            p.sx = speed.x();
-            p.sy = speed.y();
-
-            // Particle acceleration
-            const QPointF &accel = m_acceleration->sample(newPos);
-            p.ax = accel.x();
-            p.ay = accel.y();
-
-            // Particle size
-            float sizeVariation = -m_particleSizeVariation
-                    + rand() / float(RAND_MAX) * m_particleSizeVariation * 2;
-
-            float size = qMax((qreal)0.0, m_particleSize + sizeVariation);
-            float endSize = qMax((qreal)0.0, sizeAtEnd + sizeVariation);
-
-            p.size = size * float(m_emitting);
-            p.endSize = endSize * float(m_emitting);
-
-            if(m_emitLeft)
-                --m_emitLeft;
-            else
+            if(!m_burstQueue.isEmpty()){
+                m_burstQueue.first().first--;
+                if(m_burstQueue.first().first <= 0)
+                    m_burstQueue.pop_front();
+            }else{
                 pt += particleRatio;
-            m_system->emitParticle(datum);
+            }
         }
         m_lastEmission[i] = pt;
     }
index 1af7791..c98a2f4 100644 (file)
@@ -51,7 +51,9 @@ KillAffector::KillAffector(QSGItem *parent) :
 bool KillAffector::affectParticle(ParticleData *d, qreal dt)
 {
     Q_UNUSED(dt);
-    d->pv.t -= d->pv.lifeSpan;
-    return true;
+    if(d->stillAlive()){
+        d->pv.t -= d->pv.lifeSpan + 1;
+        return true;
+    }
 }
 QT_END_NAMESPACE
index f490ed6..dd7d737 100644 (file)
@@ -57,7 +57,6 @@ ParticleEmitter::ParticleEmitter(QSGItem *parent) :
   , m_particleSizeVariation(0)
   , m_maxParticleCount(-1)
   , m_burstLeft(0)
-  , m_emitLeft(0)
 
 {
     //TODO: Reset speed/acc back to null vector? Or allow null pointer?
@@ -117,7 +116,7 @@ void ParticleEmitter::burst(int num)
 {
     if(!particleCount())
         qWarning() << "burst called on an emitter with a particle count of zero";
-    m_emitLeft += num;
+    m_burstQueue << qMakePair(num, QPointF(x(), y()));
 }
 
 void ParticleEmitter::setMaxParticleCount(int arg)
index 61994e5..e272ae5 100644 (file)
@@ -48,6 +48,9 @@
 #include "particleextruder.h"
 #include "varyingvector.h"
 
+#include <QList>
+#include <QPair>
+#include <QPointF>
 QT_BEGIN_HEADER
 
 QT_BEGIN_NAMESPACE
@@ -287,8 +290,8 @@ protected:
        qreal m_particleEndSize;
        qreal m_particleSizeVariation;
 
-       int m_burstLeft;
-       int m_emitLeft;
+       int m_burstLeft;//TODO: Rename to pulse
+       QList<QPair<int, QPointF > > m_burstQueue;
        int m_maxParticleCount;
 private:
        VaryingVector m_nullVector;
index 2355670..41635a4 100644 (file)
@@ -72,7 +72,7 @@ void TrailsEmitter::emitWindow(int timeStamp)
 {
     if (m_system == 0)
         return;
-    if((!m_emitting || !m_particlesPerSecond)&& !m_burstLeft && !m_emitLeft){
+    if((!m_emitting || !m_particlesPerSecond)&& !m_burstLeft && m_burstQueue.isEmpty()){
         m_reset_last = true;
         return;
     }
@@ -92,6 +92,7 @@ void TrailsEmitter::emitWindow(int timeStamp)
             m_burstLeft = 0;
         }
     }
+
     qreal time = timeStamp / 1000.;
 
     qreal particleRatio = 1. / m_particlesPerSecond;
@@ -116,71 +117,76 @@ void TrailsEmitter::emitWindow(int timeStamp)
     qreal sizeAtEnd = m_particleEndSize >= 0 ? m_particleEndSize : m_particleSize;
     qreal emitter_x_offset = m_last_emitter.x() - x();
     qreal emitter_y_offset = m_last_emitter.y() - y();
-    while (pt < time || m_emitLeft) {
+    if(!m_burstQueue.isEmpty() && !m_burstLeft && !m_emitting)//'outside time' emissions only
+        pt = time;
+    while (pt < time || !m_burstQueue.isEmpty()) {
         //int pos = m_last_particle % m_particle_count;
         ParticleData* datum = m_system->newDatum(m_system->m_groupIds[m_particle]);
-        if(!datum){//skip this emission
-            if(!m_emitLeft)
-                pt += particleRatio;
-            else
-                --m_emitLeft;
-            continue;
+        if(datum){//actually emit(otherwise we've been asked to skip this one)
+            datum->e = this;//###useful?
+            ParticleVertex &p = datum->pv;
+            qreal t = 1 - (pt - opt) / dt;
+            qreal vx =
+              - 2 * ax * (1 - t)
+              + 2 * bx * (1 - 2 * t)
+              + 2 * cx * t;
+            qreal vy =
+              - 2 * ay * (1 - t)
+              + 2 * by * (1 - 2 * t)
+              + 2 * cy * t;
+
+
+            // Particle timestamp
+            p.t = pt;
+            p.lifeSpan = //TODO:Promote to base class?
+                    (m_particleDuration
+                     + ((rand() % ((m_particleDurationVariation*2) + 1)) - m_particleDurationVariation))
+                    / 1000.0;
+
+            // Particle position
+            QRectF boundsRect;
+            if(!m_burstQueue.isEmpty()){
+                boundsRect = QRectF(m_burstQueue.first().second.x() - x(), m_burstQueue.first().second.y() - y(),
+                        width(), height());
+            } else {
+                boundsRect = QRectF(emitter_x_offset + dex * (pt - opt) / dt, emitter_y_offset + dey * (pt - opt) / dt
+                              , width(), height());
+            }
+            QPointF newPos = effectiveExtruder()->extrude(boundsRect);
+            p.x = newPos.x();
+            p.y = newPos.y();
+
+            // Particle speed
+            const QPointF &speed = m_speed->sample(newPos);
+            p.sx = speed.x()
+                    + m_speed_from_movement * vx;
+            p.sy = speed.y()
+                    + m_speed_from_movement * vy;
+
+            // Particle acceleration
+            const QPointF &accel = m_acceleration->sample(newPos);
+            p.ax = accel.x();
+            p.ay = accel.y();
+
+            // Particle size
+            float sizeVariation = -m_particleSizeVariation
+                    + rand() / float(RAND_MAX) * m_particleSizeVariation * 2;
+
+            float size = qMax((qreal)0.0 , m_particleSize + sizeVariation);
+            float endSize = qMax((qreal)0.0 , sizeAtEnd + sizeVariation);
+
+            p.size = size;// * float(m_emitting);
+            p.endSize = endSize;// * float(m_emitting);
+
+            m_system->emitParticle(datum);
         }
-        datum->e = this;//###useful?
-        ParticleVertex &p = datum->pv;
-        qreal t = 1 - (pt - opt) / dt;
-        qreal vx =
-          - 2 * ax * (1 - t)
-          + 2 * bx * (1 - 2 * t)
-          + 2 * cx * t;
-        qreal vy =
-          - 2 * ay * (1 - t)
-          + 2 * by * (1 - 2 * t)
-          + 2 * cy * t;
-
-
-        // Particle timestamp
-        p.t = pt;
-        p.lifeSpan = //TODO:Promote to base class?
-                (m_particleDuration
-                 + ((rand() % ((m_particleDurationVariation*2) + 1)) - m_particleDurationVariation))
-                / 1000.0;
-
-        // Particle position
-        QRectF boundsRect(emitter_x_offset + dex * (pt - opt) / dt, emitter_y_offset + dey * (pt - opt) / dt
-                          , width(), height());
-        QPointF newPos = effectiveExtruder()->extrude(boundsRect);
-        p.x = newPos.x();
-        p.y = newPos.y();
-
-        // Particle speed
-        const QPointF &speed = m_speed->sample(newPos);
-        p.sx = speed.x()
-                + m_speed_from_movement * vx;
-        p.sy = speed.y()
-                + m_speed_from_movement * vy;
-
-        // Particle acceleration
-        const QPointF &accel = m_acceleration->sample(newPos);
-        p.ax = accel.x();
-        p.ay = accel.y();
-
-        // Particle size
-        float sizeVariation = -m_particleSizeVariation
-                + rand() / float(RAND_MAX) * m_particleSizeVariation * 2;
-
-        float size = qMax((qreal)0.0 , m_particleSize + sizeVariation);
-        float endSize = qMax((qreal)0.0 , sizeAtEnd + sizeVariation);
-
-        p.size = size;// * float(m_emitting);
-        p.endSize = endSize;// * float(m_emitting);
-
-        if(!m_emitLeft)
+        if(m_burstQueue.isEmpty()){
             pt += particleRatio;
-        else
-            --m_emitLeft;
-
-        m_system->emitParticle(datum);
+        }else{
+            m_burstQueue.first().first--;
+            if(m_burstQueue.first().first <= 0)
+                m_burstQueue.pop_front();
+        }
     }
     m_last_emission = pt;