aboutsummaryrefslogtreecommitdiffstats
path: root/src/imports/particles
diff options
context:
space:
mode:
authorAlan Alpert <alan.alpert@nokia.com>2011-05-17 13:48:20 +1000
committerAlan Alpert <alan.alpert@nokia.com>2011-05-17 13:48:20 +1000
commitab858bc8e650f1120495f968379f37257c774b5f (patch)
treefb527c89ebd40f549937be17e2e87010eb2b4a07 /src/imports/particles
parent2257e544e1968ab63b03479659ae3a5ffa6c6a5b (diff)
Fix emitter burst method bugs
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.
Diffstat (limited to 'src/imports/particles')
-rw-r--r--src/imports/particles/followemitter.cpp123
-rw-r--r--src/imports/particles/killaffector.cpp6
-rw-r--r--src/imports/particles/particleemitter.cpp3
-rw-r--r--src/imports/particles/particleemitter.h7
-rw-r--r--src/imports/particles/trailsemitter.cpp130
5 files changed, 139 insertions, 130 deletions
diff --git a/src/imports/particles/followemitter.cpp b/src/imports/particles/followemitter.cpp
index 9e1ec7bbd2..17a544f62d 100644
--- a/src/imports/particles/followemitter.cpp
+++ b/src/imports/particles/followemitter.cpp
@@ -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;
}
diff --git a/src/imports/particles/killaffector.cpp b/src/imports/particles/killaffector.cpp
index 1af77918c5..c98a2f44e2 100644
--- a/src/imports/particles/killaffector.cpp
+++ b/src/imports/particles/killaffector.cpp
@@ -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
diff --git a/src/imports/particles/particleemitter.cpp b/src/imports/particles/particleemitter.cpp
index f490ed643e..dd7d73749b 100644
--- a/src/imports/particles/particleemitter.cpp
+++ b/src/imports/particles/particleemitter.cpp
@@ -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)
diff --git a/src/imports/particles/particleemitter.h b/src/imports/particles/particleemitter.h
index 61994e52fa..e272ae51ab 100644
--- a/src/imports/particles/particleemitter.h
+++ b/src/imports/particles/particleemitter.h
@@ -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;
diff --git a/src/imports/particles/trailsemitter.cpp b/src/imports/particles/trailsemitter.cpp
index 2355670801..41635a4299 100644
--- a/src/imports/particles/trailsemitter.cpp
+++ b/src/imports/particles/trailsemitter.cpp
@@ -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;