diff options
author | Alan Alpert <alan.alpert@nokia.com> | 2011-09-20 15:28:14 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-09-21 07:11:25 +0200 |
commit | ef98f5a80369e3f014585edc3dd63a2ec331d1ea (patch) | |
tree | 4e6abd6afb7ba04422a1acc9d11c2f8ff21169c1 | |
parent | 4114b9dcff68cdebc36e3b4818d4463d62421ecf (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.qml | 48 | ||||
-rw-r--r-- | examples/declarative/particles/emitters/customemitter.qml | 21 | ||||
-rw-r--r-- | src/declarative/particles/qsgcustomaffector.cpp | 43 | ||||
-rw-r--r-- | src/declarative/particles/qsgcustomaffector_p.h | 4 | ||||
-rw-r--r-- | src/declarative/particles/qsgparticleaffector_p.h | 4 | ||||
-rw-r--r-- | src/declarative/particles/qsgparticleemitter.cpp | 31 | ||||
-rw-r--r-- | src/declarative/particles/qsgparticleemitter_p.h | 2 | ||||
-rw-r--r-- | src/declarative/particles/qsgtrailemitter.cpp | 35 | ||||
-rw-r--r-- | src/declarative/particles/qsgtrailemitter_p.h | 2 |
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); |