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;
}
*/
//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;
}
}
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{
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{
****************************************************************************/
#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.
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
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:
};
emit whenCollidingWithChanged(arg);
}
}
+public slots:
+ void updateOffsets();
protected:
friend class QSGParticleSystem;
QStringList m_whenCollidingWith;
bool isColliding(QSGParticleData* d);
-private slots:
- void updateOffsets();
};
QT_END_NAMESPACE
****************************************************************************/
#include "qsgparticleemitter_p.h"
+#include <private/qdeclarativeengine_p.h>
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.
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);
}
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);
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;
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;
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);
****************************************************************************/
#include "qsgtrailemitter_p.h"
+#include <private/qdeclarativeengine_p.h>
#include <cmath>
QT_BEGIN_NAMESPACE
\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);
}
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
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);
}
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;
}
}
signals:
- void emitFollowParticle(QDeclarativeV8Handle group, QDeclarativeV8Handle followed);
+ void emitFollowParticles(QDeclarativeV8Handle particles, QDeclarativeV8Handle followed);
void particlesPerParticlePerSecondChanged(int arg);