aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Alpert <alan.alpert@nokia.com>2011-09-20 15:28:14 +1000
committerQt by Nokia <qt-info@nokia.com>2011-09-21 07:11:25 +0200
commitef98f5a80369e3f014585edc3dd63a2ec331d1ea (patch)
tree4e6abd6afb7ba04422a1acc9d11c2f8ff21169c1
parent4114b9dcff68cdebc36e3b4818d4463d62421ecf (diff)
CustomEmitter/Affector now affect whole lists at once
Better performance potential (fewer drops to JS, possibility of more optimzed JS). Change-Id: If386f06ac8714162a5bfc6b5eef7f2e67f9dae95 Reviewed-on: http://codereview.qt-project.org/5189 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Martin Jones <martin.jones@nokia.com>
-rw-r--r--examples/declarative/particles/affectors/customaffector.qml48
-rw-r--r--examples/declarative/particles/emitters/customemitter.qml21
-rw-r--r--src/declarative/particles/qsgcustomaffector.cpp43
-rw-r--r--src/declarative/particles/qsgcustomaffector_p.h4
-rw-r--r--src/declarative/particles/qsgparticleaffector_p.h4
-rw-r--r--src/declarative/particles/qsgparticleemitter.cpp31
-rw-r--r--src/declarative/particles/qsgparticleemitter_p.h2
-rw-r--r--src/declarative/particles/qsgtrailemitter.cpp35
-rw-r--r--src/declarative/particles/qsgtrailemitter_p.h2
9 files changed, 126 insertions, 64 deletions
diff --git a/examples/declarative/particles/affectors/customaffector.qml b/examples/declarative/particles/affectors/customaffector.qml
index 35708b7864..e9aea62a5a 100644
--- a/examples/declarative/particles/affectors/customaffector.qml
+++ b/examples/declarative/particles/affectors/customaffector.qml
@@ -71,7 +71,7 @@ Item {
property real speed: 1.5
width: parent.width
height: parent.height - 100
- onAffectParticle:{
+ onAffectParticles:{
/* //Linear movement
if (particle.r == 0){
particle.r = Math.random() > 0.5 ? -1 : 1;
@@ -86,14 +86,17 @@ Item {
}
*/
//Wobbly movement
- if (particle.r == 0.0){
- particle.r = Math.random() + 0.01;
+ for (var i=0; i<particles.length; i++) {
+ var particle = particles[i];
+ if (particle.r == 0.0) {
+ particle.r = Math.random() + 0.01;
+ }
+ particle.rotation += speed * particle.r * dt;
+ particle.r -= particle.rotation * coefficient;
+ if (particle.r == 0.0)
+ particle.r -= particle.rotation * 0.000001;
+ particle.update = 1;
}
- particle.rotation += speed * particle.r * dt;
- particle.r -= particle.rotation * coefficient;
- if (particle.r == 0.0)
- particle.r -= particle.rotation * 0.000001;
- particle.update = 1;
}
}
@@ -104,19 +107,22 @@ Item {
width: parent.width + 120
height: 100
anchors.bottom: parent.bottom
- onAffectParticle:{
- var pseudoRand = (Math.floor(particle.t*1327) % 10) + 1;
- var yslow = pseudoRand * 0.01 + 1.01;
- var xslow = pseudoRand * 0.005 + 1.0;
- if (particle.vy < 1)
- particle.vy = 0;
- else
- particle.vy = (particle.vy / yslow);
- if (particle.vx < 1)
- particle.vx = 0;
- else
- particle.vx = (particle.vx / xslow);
- particle.update = 1;
+ onAffectParticles:{
+ for (var i=0; i<particles.length; i++) {
+ var particle = particles[i];
+ var pseudoRand = (Math.floor(particle.t*1327) % 10) + 1;
+ var yslow = dt * pseudoRand * 0.5 + 1;
+ var xslow = dt * pseudoRand * 0.05 + 1;
+ if (particle.vy < 1)
+ particle.vy = 0;
+ else
+ particle.vy = (particle.vy / yslow);
+ if (particle.vx < 1)
+ particle.vx = 0;
+ else
+ particle.vx = (particle.vx / xslow);
+ particle.update = 1;
+ }
}
}
ImageParticle{
diff --git a/examples/declarative/particles/emitters/customemitter.qml b/examples/declarative/particles/emitters/customemitter.qml
index 55c3884a11..39e2d066f6 100644
--- a/examples/declarative/particles/emitters/customemitter.qml
+++ b/examples/declarative/particles/emitters/customemitter.qml
@@ -66,15 +66,18 @@ ParticleSystem{
emitRate: 120
size: 12
anchors.centerIn: parent
- onEmitParticle:{
- particle.startSize = Math.max(02,Math.min(492,Math.tan(particle.t/2)*24));
- var theta = Math.floor(Math.random() * 6.0) / 6.0;
- theta *= 2.0*Math.PI;
- theta += sys.convert(sys.petalRotation);
- particle.initialVX = petalLength * Math.cos(theta);
- particle.initialVY = petalLength * Math.sin(theta);
- particle.initialAX = particle.initialVX * -0.5;
- particle.initialAY = particle.initialVY * -0.5;
+ onEmitParticles:{
+ for (var i=0; i<particles.length; i++) {
+ var particle = particles[i];
+ particle.startSize = Math.max(02,Math.min(492,Math.tan(particle.t/2)*24));
+ var theta = Math.floor(Math.random() * 6.0) / 6.0;
+ theta *= 2.0*Math.PI;
+ theta += sys.convert(sys.petalRotation);
+ particle.initialVX = petalLength * Math.cos(theta);
+ particle.initialVY = petalLength * Math.sin(theta);
+ particle.initialAX = particle.initialVX * -0.5;
+ particle.initialAY = particle.initialVY * -0.5;
+ }
}
}
ImageParticle{
diff --git a/src/declarative/particles/qsgcustomaffector.cpp b/src/declarative/particles/qsgcustomaffector.cpp
index 70e1dbe035..77da5c58a6 100644
--- a/src/declarative/particles/qsgcustomaffector.cpp
+++ b/src/declarative/particles/qsgcustomaffector.cpp
@@ -40,15 +40,18 @@
****************************************************************************/
#include "qsgcustomaffector_p.h"
+#include <private/qv8engine_p.h>
+#include <private/qdeclarativeengine_p.h>
+#include <QDeclarativeEngine>
#include <QDebug>
QT_BEGIN_NAMESPACE
//TODO: Move docs (and inherit) to real base when docs can propagate
-//TODO: Document particle 'type'
/*!
- \qmlsignal QtQuick.Particles2::Affector::affectParticle(particle, dt)
+ \qmlsignal QtQuick.Particles2::Affector::affectParticles(Array particles, real dt)
- This handler is called when particles are selected to be affected.
+ This handler is called when particles are selected to be affected. particles contains
+ an array of particle objects which can be directly manipulated.
dt is the time since the last time it was affected. Use dt to normalize
trajectory manipulations to real time.
@@ -63,18 +66,38 @@ QSGCustomAffector::QSGCustomAffector(QSGItem *parent) :
bool QSGCustomAffector::isAffectConnected()
{
- static int idx = QObjectPrivate::get(this)->signalIndex("affectParticle(QDeclarativeV8Handle,qreal)");
+ static int idx = QObjectPrivate::get(this)->signalIndex("affectParticles(QDeclarativeV8Handle,qreal)");
return QObjectPrivate::get(this)->isSignalConnected(idx);
}
-bool QSGCustomAffector::affectParticle(QSGParticleData *d, qreal dt)
+void QSGCustomAffector::affectSystem(qreal dt)
{
- if (isAffectConnected()){
- d->update = 0.0;
- emit affectParticle(d->v8Value(), dt);
- return d->update == 1.0;
+ if (!isAffectConnected()) {
+ QSGParticleAffector::affectSystem(dt);
+ return;
}
- return true;
+ if (!m_enabled)
+ return;
+ updateOffsets();
+
+ QList<QSGParticleData*> toAffect;
+ foreach (QSGParticleGroupData* gd, m_system->m_groupData)
+ if (activeGroup(m_system->m_groupData.key(gd)))
+ foreach (QSGParticleData* d, gd->data)
+ if (shouldAffect(d))
+ toAffect << d;
+
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(QDeclarativeEnginePrivate::getV8Engine(qmlEngine(this))->context());
+ v8::Handle<v8::Array> array = v8::Array::New(toAffect.size());
+ for (int i=0; i<toAffect.size(); i++)
+ array->Set(i, toAffect[i]->v8Value().toHandle());
+
+ emit affectParticles(QDeclarativeV8Handle::fromHandle(array), dt);
+
+ foreach (QSGParticleData* d, toAffect)
+ if (d->update == 1.0)
+ postAffect(d);
}
QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgcustomaffector_p.h b/src/declarative/particles/qsgcustomaffector_p.h
index 7f39200298..fc0735e971 100644
--- a/src/declarative/particles/qsgcustomaffector_p.h
+++ b/src/declarative/particles/qsgcustomaffector_p.h
@@ -59,13 +59,13 @@ class QSGCustomAffector : public QSGParticleAffector
public:
explicit QSGCustomAffector(QSGItem *parent = 0);
+ virtual void affectSystem(qreal dt);
signals:
- void affectParticle(QDeclarativeV8Handle particle, qreal dt);
+ void affectParticles(QDeclarativeV8Handle particles, qreal dt);
public slots:
protected:
bool isAffectConnected();
- virtual bool affectParticle(QSGParticleData *d, qreal dt);
private:
};
diff --git a/src/declarative/particles/qsgparticleaffector_p.h b/src/declarative/particles/qsgparticleaffector_p.h
index c67912fada..c46164de5c 100644
--- a/src/declarative/particles/qsgparticleaffector_p.h
+++ b/src/declarative/particles/qsgparticleaffector_p.h
@@ -163,6 +163,8 @@ void setWhenCollidingWith(QStringList arg)
emit whenCollidingWithChanged(arg);
}
}
+public slots:
+ void updateOffsets();
protected:
friend class QSGParticleSystem;
@@ -189,8 +191,6 @@ private:
QStringList m_whenCollidingWith;
bool isColliding(QSGParticleData* d);
-private slots:
- void updateOffsets();
};
QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgparticleemitter.cpp b/src/declarative/particles/qsgparticleemitter.cpp
index f10bf1edd7..e1a7ef28a9 100644
--- a/src/declarative/particles/qsgparticleemitter.cpp
+++ b/src/declarative/particles/qsgparticleemitter.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qsgparticleemitter_p.h"
+#include <private/qdeclarativeengine_p.h>
QT_BEGIN_NAMESPACE
@@ -183,12 +184,12 @@ QT_BEGIN_NAMESPACE
Default value is 0.
*/
-//TODO: Document particle 'type'
+
/*!
- \qmlsignal QtQuick.Particles2::Emitter::onEmitParticle(Particle particle)
+ \qmlsignal QtQuick.Particles2::Emitter::onEmitParticles(Array particles)
- This handler is called when a particle is emitted. You can modify particle
- attributes from within the handler.
+ This handler is called when particles are emitted. particles is a javascript
+ array of Particle objects. You can modify particle attributes directly within the handler.
Note that JS is slower to execute, so it is not recommended to use this in
high-volume particle systems.
@@ -252,7 +253,7 @@ QSGParticleEmitter::~QSGParticleEmitter()
bool QSGParticleEmitter::isEmitConnected()
{
- static int idx = QObjectPrivate::get(this)->signalIndex("emitParticle(QDeclarativeV8Handle)");
+ static int idx = QObjectPrivate::get(this)->signalIndex("emitParticles(QDeclarativeV8Handle)");
return QObjectPrivate::get(this)->isSignalConnected(idx);
}
@@ -396,6 +397,9 @@ void QSGParticleEmitter::emitWindow(int timeStamp)
qreal emitter_y_offset = m_last_emitter.y() - y();
if (!m_burstQueue.isEmpty() && !m_burstLeft && !m_enabled)//'outside time' emissions only
pt = time;
+
+ QList<QSGParticleData*> toEmit;
+
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_group], !m_overwrite);
@@ -459,9 +463,7 @@ void QSGParticleEmitter::emitWindow(int timeStamp)
datum->size = size;// * float(m_emitting);
datum->endSize = endSize;// * float(m_emitting);
- if (isEmitConnected())
- emitParticle(datum->v8Value());//A chance for arbitrary JS changes
- m_system->emitParticle(datum);
+ toEmit << datum;
}
if (m_burstQueue.isEmpty()){
pt += particleRatio;
@@ -471,6 +473,19 @@ void QSGParticleEmitter::emitWindow(int timeStamp)
m_burstQueue.pop_front();
}
}
+
+ if (isEmitConnected()) {
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(QDeclarativeEnginePrivate::getV8Engine(qmlEngine(this))->context());
+ v8::Handle<v8::Array> array = v8::Array::New(toEmit.size());
+ for (int i=0; i<toEmit.size(); i++)
+ array->Set(i, toEmit[i]->v8Value().toHandle());
+
+ emitParticles(QDeclarativeV8Handle::fromHandle(array));//A chance for arbitrary JS changes
+ }
+ foreach (QSGParticleData* d, toEmit)
+ m_system->emitParticle(d);
+
m_last_emission = pt;
m_last_last_last_emitter = m_last_last_emitter;
diff --git a/src/declarative/particles/qsgparticleemitter_p.h b/src/declarative/particles/qsgparticleemitter_p.h
index 8bd205b207..11c79ec221 100644
--- a/src/declarative/particles/qsgparticleemitter_p.h
+++ b/src/declarative/particles/qsgparticleemitter_p.h
@@ -123,7 +123,7 @@ public:
void setSpeedFromMovement(qreal s);
virtual void componentComplete();
signals:
- void emitParticle(QDeclarativeV8Handle particle);
+ void emitParticles(QDeclarativeV8Handle particles);
void particlesPerSecondChanged(qreal);
void particleDurationChanged(int);
void enabledChanged(bool);
diff --git a/src/declarative/particles/qsgtrailemitter.cpp b/src/declarative/particles/qsgtrailemitter.cpp
index 5a19ac508b..e819663870 100644
--- a/src/declarative/particles/qsgtrailemitter.cpp
+++ b/src/declarative/particles/qsgtrailemitter.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qsgtrailemitter_p.h"
+#include <private/qdeclarativeengine_p.h>
#include <cmath>
QT_BEGIN_NAMESPACE
@@ -102,18 +103,17 @@ QSGTrailEmitter::QSGTrailEmitter(QSGItem *parent) :
\qmlproperty real QtQuick.Particles2::TrailEmitter::emitRatePerParticle
*/
/*!
- \qmlsignal QtQuick.Particles2::TrailEmitter::emitFollowParticle(particle, followed)
+ \qmlsignal QtQuick.Particles2::TrailEmitter::emitFollowParticles(Array particles, real followed)
- This handler is called when a particle is emitted. You can modify particle
- attributes from within the handler. followed is the particle that this is being
- emitted off of.
+ This handler is called when particles are emitted from the \a followed particle. \a particles contains an array of particle objects which can be directly manipulated.
+
+ If you use this signal handler, emitParticles will not be emitted.
- If you use this signal handler, emitParticle will not be emitted.
*/
bool QSGTrailEmitter::isEmitFollowConnected()
{
- static int idx = QObjectPrivate::get(this)->signalIndex("emitFollowParticle(QDeclarativeV8Handle,QDeclarativeV8Handle)");
+ static int idx = QObjectPrivate::get(this)->signalIndex("emitFollowParticles(QDeclarativeV8Handle,QDeclarativeV8Handle)");
return QObjectPrivate::get(this)->isSignalConnected(idx);
}
@@ -180,6 +180,9 @@ void QSGTrailEmitter::emitWindow(int timeStamp)
m_lastEmission[d->index] = time;//jump over this time period without emitting, because it's outside
continue;
}
+
+ QList<QSGParticleData*> toEmit;
+
while (pt < time || !m_burstQueue.isEmpty()){
QSGParticleData* datum = m_system->newDatum(gId2, !m_overwrite);
if (datum){//else, skip this emission
@@ -235,10 +238,7 @@ void QSGTrailEmitter::emitWindow(int timeStamp)
datum->size = size * float(m_enabled);
datum->endSize = endSize * float(m_enabled);
- if (isEmitFollowConnected())
- emitFollowParticle(datum->v8Value(), d->v8Value());//A chance for many arbitrary JS changes
- else if (isEmitConnected())
- emitParticle(datum->v8Value());//A chance for arbitrary JS changes
+ toEmit << datum;
m_system->emitParticle(datum);
}
@@ -250,6 +250,21 @@ void QSGTrailEmitter::emitWindow(int timeStamp)
pt += particleRatio;
}
}
+
+ if (isEmitConnected() || isEmitFollowConnected()) {
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(QDeclarativeEnginePrivate::getV8Engine(qmlEngine(this))->context());
+ v8::Handle<v8::Array> array = v8::Array::New(toEmit.size());
+ for (int i=0; i<toEmit.size(); i++)
+ array->Set(i, toEmit[i]->v8Value().toHandle());
+
+ if (isEmitFollowConnected())
+ emitFollowParticles(QDeclarativeV8Handle::fromHandle(array), d->v8Value());//A chance for many arbitrary JS changes
+ else if (isEmitConnected())
+ emitParticles(QDeclarativeV8Handle::fromHandle(array));//A chance for arbitrary JS changes
+ }
+ foreach (QSGParticleData* d, toEmit)
+ m_system->emitParticle(d);
m_lastEmission[d->index] = pt;
}
diff --git a/src/declarative/particles/qsgtrailemitter_p.h b/src/declarative/particles/qsgtrailemitter_p.h
index 009ccd508c..e0103afdc0 100644
--- a/src/declarative/particles/qsgtrailemitter_p.h
+++ b/src/declarative/particles/qsgtrailemitter_p.h
@@ -94,7 +94,7 @@ public:
}
signals:
- void emitFollowParticle(QDeclarativeV8Handle group, QDeclarativeV8Handle followed);
+ void emitFollowParticles(QDeclarativeV8Handle particles, QDeclarativeV8Handle followed);
void particlesPerParticlePerSecondChanged(int arg);