Refactor BasicEmitter into Emitter
authorAlan Alpert <alan.alpert@nokia.com>
Thu, 11 Aug 2011 09:36:07 +0000 (19:36 +1000)
committerQt by Nokia <qt-info@nokia.com>
Mon, 15 Aug 2011 03:16:45 +0000 (05:16 +0200)
No real point having a separate class, and it makes the docs more
complex.

Change-Id: I48aa7bafce541b0b5b792351adb5edf77fc67de2
Reviewed-on: http://codereview.qt.nokia.com/2853
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Alan Alpert <alan.alpert@nokia.com>
src/declarative/particles/particles.pri
src/declarative/particles/qsgemitter.cpp [deleted file]
src/declarative/particles/qsgemitter_p.h [deleted file]
src/declarative/particles/qsgfollowemitter.cpp
src/declarative/particles/qsgparticleemitter.cpp
src/declarative/particles/qsgparticleemitter_p.h
src/declarative/particles/qsgparticlesmodule.cpp

index 582e1d3..1fc5783 100644 (file)
@@ -4,7 +4,6 @@ HEADERS += \
     $$PWD/qsgangleddirection_p.h \
     $$PWD/qsgcustomparticle_p.h \
     $$PWD/qsgellipseextruder_p.h \
-    $$PWD/qsgemitter_p.h \
     $$PWD/qsgfollowemitter_p.h \
     $$PWD/qsgfriction_p.h \
     $$PWD/qsggravity_p.h \
@@ -37,7 +36,6 @@ SOURCES += \
     $$PWD/qsgangleddirection.cpp \
     $$PWD/qsgcustomparticle.cpp \
     $$PWD/qsgellipseextruder.cpp \
-    $$PWD/qsgemitter.cpp \
     $$PWD/qsgfollowemitter.cpp \
     $$PWD/qsgfriction.cpp \
     $$PWD/qsggravity.cpp \
diff --git a/src/declarative/particles/qsgemitter.cpp b/src/declarative/particles/qsgemitter.cpp
deleted file mode 100644 (file)
index 10d59df..0000000
+++ /dev/null
@@ -1,262 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsgemitter_p.h"
-#include "qsgparticlesystem_p.h"
-QT_BEGIN_NAMESPACE
-
-/*!
-    \qmlclass Emitter QSGBasicEmitter
-    \inqmlmodule QtQuick.Particles 2
-    \since QtQuick.Particles 2.0
-    \brief The Emitter element allows you to emit logical particles.
-
-    This element emits logical particles into the ParticleSystem, with the
-    given starting attributes.
-
-    Note that logical particles are not
-    automatically rendered, you will need to have one or more
-    ParticlePainter elements visualizing them.
-
-    Note that the given starting attributes can be modified at any point
-    in the particle's lifetime by any Affector element in the same
-    ParticleSystem. This includes attributes like lifespan.
-*/
-
-QSGBasicEmitter::QSGBasicEmitter(QSGItem* parent)
-    : QSGParticleEmitter(parent)
-    , m_speed_from_movement(0)
-    , m_particle_count(0)
-    , m_reset_last(true)
-    , m_last_timestamp(0)
-    , m_last_emission(0)
-{
-//    setFlag(ItemHasContents);
-}
-
-/*!
-    \qmlproperty ParticleSystem QtQuick.Particles2::Emitter::system
-
-    This is the Particle system that the Emitter will emit into.
-    This can be omitted if the Emitter is a direct child of the ParticleSystem
-*/
-/*!
-    \qmlproperty string QtQuick.Particles2::Emitter::particle
-*/
-/*!
-    \qmlproperty Shape QtQuick.Particles2::Emitter::shape
-*/
-/*!
-    \qmlproperty bool QtQuick.Particles2::Emitter::emitting
-*/
-/*!
-    \qmlproperty real QtQuick.Particles2::Emitter::emitRate
-*/
-/*!
-    \qmlproperty int QtQuick.Particles2::Emitter::lifeSpan
-*/
-/*!
-    \qmlproperty int QtQuick.Particles2::Emitter::lifeSpanVariation
-*/
-/*!
-    \qmlproperty int QtQuick.Particles2::Emitter::emitCap
-*/
-/*!
-    \qmlproperty real QtQuick.Particles2::Emitter::size
-*/
-/*!
-    \qmlproperty real QtQuick.Particles2::Emitter::endSize
-*/
-/*!
-    \qmlproperty real QtQuick.Particles2::Emitter::sizeVariation
-*/
-/*!
-    \qmlproperty StochasticDirection QtQuick.Particles2::Emitter::speed
-*/
-/*!
-    \qmlproperty StochasticDirection QtQuick.Particles2::Emitter::acceleration
-*/
-/*!
-    \qmlproperty qreal QtQuick.Particles2::Emitter::speedFromMovement
-*/
-
-void QSGBasicEmitter::setSpeedFromMovement(qreal t)
-{
-    if (t == m_speed_from_movement)
-        return;
-    m_speed_from_movement = t;
-    emit speedFromMovementChanged();
-}
-
-void QSGBasicEmitter::reset()
-{
-    m_reset_last = true;
-}
-
-void QSGBasicEmitter::emitWindow(int timeStamp)
-{
-    if (m_system == 0)
-        return;
-    if ((!m_emitting || !m_particlesPerSecond)&& !m_burstLeft && m_burstQueue.isEmpty()){
-        m_reset_last = true;
-        return;
-    }
-
-    if (m_reset_last) {
-        m_last_emitter = m_last_last_emitter = QPointF(x(), y());
-        m_last_timestamp = timeStamp/1000.;
-        m_last_emission = m_last_timestamp;
-        m_reset_last = false;
-    }
-
-    if (m_burstLeft){
-        m_burstLeft -= timeStamp - m_last_timestamp * 1000.;
-        if (m_burstLeft < 0){
-            if (!m_emitting)
-                timeStamp += m_burstLeft;
-            m_burstLeft = 0;
-        }
-    }
-
-    qreal time = timeStamp / 1000.;
-
-    qreal particleRatio = 1. / m_particlesPerSecond;
-    qreal pt = m_last_emission;
-
-    qreal opt = pt; // original particle time
-    qreal dt = time - m_last_timestamp; // timestamp delta...
-    if (!dt)
-        dt = 0.000001;
-
-    // emitter difference since last...
-    qreal dex = (x() - m_last_emitter.x());
-    qreal dey = (y() - m_last_emitter.y());
-
-    qreal ax = (m_last_last_emitter.x() + m_last_emitter.x()) / 2;
-    qreal bx = m_last_emitter.x();
-    qreal cx = (x() + m_last_emitter.x()) / 2;
-    qreal ay = (m_last_last_emitter.y() + m_last_emitter.y()) / 2;
-    qreal by = m_last_emitter.y();
-    qreal cy = (y() + m_last_emitter.y()) / 2;
-
-    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();
-    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;
-        QSGParticleData* datum = m_system->newDatum(m_system->m_groupIds[m_particle]);
-        if (datum){//actually emit(otherwise we've been asked to skip this one)
-            datum->e = this;//###useful?
-            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
-            datum->t = pt;
-            datum->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);
-            datum->x = newPos.x();
-            datum->y = newPos.y();
-
-            // Particle speed
-            const QPointF &speed = m_speed->sample(newPos);
-            datum->vx = speed.x()
-                    + m_speed_from_movement * vx;
-            datum->vy = speed.y()
-                    + m_speed_from_movement * vy;
-
-            // Particle acceleration
-            const QPointF &accel = m_acceleration->sample(newPos);
-            datum->ax = accel.x();
-            datum->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);
-
-            datum->size = size;// * float(m_emitting);
-            datum->endSize = endSize;// * float(m_emitting);
-
-            m_system->emitParticle(datum);
-        }
-        if (m_burstQueue.isEmpty()){
-            pt += particleRatio;
-        }else{
-            m_burstQueue.first().first--;
-            if (m_burstQueue.first().first <= 0)
-                m_burstQueue.pop_front();
-        }
-    }
-    m_last_emission = pt;
-
-    m_last_last_last_emitter = m_last_last_emitter;
-    m_last_last_emitter = m_last_emitter;
-    m_last_emitter = QPointF(x(), y());
-    m_last_timestamp = time;
-}
-
-
-QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgemitter_p.h b/src/declarative/particles/qsgemitter_p.h
deleted file mode 100644 (file)
index f61da15..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef TRAILSEMITTER_H
-#define TRAILSEMITTER_H
-
-#include <QtCore>//FIXME
-#include <QtGui>
-
-#include "qsgparticleemitter_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-
-class QSGGeometryNode;
-
-class QSGBasicEmitter : public QSGParticleEmitter
-{
-    Q_OBJECT
-
-    Q_PROPERTY(qreal speedFromMovement READ speedFromMovement WRITE setSpeedFromMovement NOTIFY speedFromMovementChanged)
-
-public:
-    explicit QSGBasicEmitter(QSGItem* parent=0);
-    virtual ~QSGBasicEmitter(){}
-    virtual void emitWindow(int timeStamp);
-
-
-    qreal speedFromMovement() const { return m_speed_from_movement; }
-    void setSpeedFromMovement(qreal s);
-
-    qreal renderOpacity() const { return m_render_opacity; }
-
-signals:
-
-    void speedFromMovementChanged();
-
-public slots:
-public:
-    virtual void reset();
-protected:
-
-private:
-
-    qreal m_speed_from_movement;
-
-    // derived values...
-    int m_particle_count;
-    bool m_reset_last;
-    qreal m_last_timestamp;
-    qreal m_last_emission;
-
-    QPointF m_last_emitter;
-    QPointF m_last_last_emitter;
-    QPointF m_last_last_last_emitter;
-
-    qreal m_render_opacity;
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // TRAILSEMITTER_H
index 0d4e7f7..a074f44 100644 (file)
 QT_BEGIN_NAMESPACE
 
 /*!
-    \qmlclass Emitter QSGBasicEmitter
+    \qmlclass FollowEmitter QSGFollowEmitter
     \inqmlmodule QtQuick.Particles 2
+    \inherits QSGParticleEmitter
     \since QtQuick.Particles 2.0
-    \brief The Emitter element allows you to emit logical particles.
+    \brief The FollowEmitter element allows you to emit logical particles from other logical particles.
 
     This element emits logical particles into the ParticleSystem, with the
-    given starting attributes.
-
-    Note that logical particles are not
-    automatically rendered, you will need to have one or more
-    ParticlePainter elements visualizing them.
-
-    Note that the given starting attributes can be modified at any point
-    in the particle's lifetime by any Affector element in the same
-    ParticleSystem. This includes attributes like lifespan.
+    starting positions based on those of other logical particles.
 */
 QSGFollowEmitter::QSGFollowEmitter(QSGItem *parent) :
     QSGParticleEmitter(parent)
@@ -80,24 +73,17 @@ QSGFollowEmitter::QSGFollowEmitter(QSGItem *parent) :
             this, SLOT(recalcParticlesPerSecond()));
 }
 
-
-/*!
-    \qmlproperty ParticleSystem QtQuick.Particles2::FollowEmitter::system
-
-    This is the Particle system that the FollowEmitter will emit into.
-    This can be omitted if the FollowEmitter is a direct child of the ParticleSystem
-*/
-/*!
-    \qmlproperty string QtQuick.Particles2::FollowEmitter::particle
-*/
 /*!
     \qmlproperty string QtQuick.Particles2::FollowEmitter::follow
+
+    The type of logical particle which this is emitting from.
 */
-/*!
-    \qmlproperty Shape QtQuick.Particles2::FollowEmitter::shape
-*/
+
 /*!
     \qmlproperty Shape QtQuick.Particles2::FollowEmitter::emitShape
+
+    As the area of a FollowEmitter is the area it follows, a separate shape can be provided
+    to be the shape it emits out of.
 */
 /*!
     \qmlproperty real QtQuick.Particles2::FollowEmitter::emitWidth
@@ -106,38 +92,9 @@ QSGFollowEmitter::QSGFollowEmitter(QSGItem *parent) :
     \qmlproperty real QtQuick.Particles2::FollowEmitter::emitHeight
 */
 /*!
-    \qmlproperty bool QtQuick.Particles2::FollowEmitter::emitting
-*/
-/*!
     \qmlproperty real QtQuick.Particles2::FollowEmitter::emitRatePerParticle
 */
-/*!
-    \qmlproperty int QtQuick.Particles2::FollowEmitter::lifeSpan
-*/
-/*!
-    \qmlproperty int QtQuick.Particles2::FollowEmitter::lifeSpanVariation
-*/
-/*!
-    \qmlproperty int QtQuick.Particles2::FollowEmitter::emitCap
-*/
-/*!
-    \qmlproperty real QtQuick.Particles2::FollowEmitter::size
-*/
-/*!
-    \qmlproperty real QtQuick.Particles2::FollowEmitter::endSize
-*/
-/*!
-    \qmlproperty real QtQuick.Particles2::FollowEmitter::sizeVariation
-*/
-/*!
-    \qmlproperty StochasticDirection QtQuick.Particles2::FollowEmitter::speed
-*/
-/*!
-    \qmlproperty StochasticDirection QtQuick.Particles2::FollowEmitter::acceleration
-*/
-/*!
-    \qmlproperty qreal QtQuick.Particles2::FollowEmitter::speedFromMovement
-*/
+
 
 void QSGFollowEmitter::recalcParticlesPerSecond(){
     if (!m_system)
index dfd1618..c1d6e5e 100644 (file)
 
 #include "qsgparticleemitter_p.h"
 QT_BEGIN_NAMESPACE
-//Not visible from QML, so not documented. Document subclasses.
+
+
+
+/*!
+    \qmlclass Emitter QSGParticleEmitter
+    \inqmlmodule QtQuick.Particles 2
+    \since QtQuick.Particles 2.0
+    \brief The Emitter element allows you to emit logical particles.
+
+    This element emits logical particles into the ParticleSystem, with the
+    given starting attributes.
+
+    Note that logical particles are not
+    automatically rendered, you will need to have one or more
+    ParticlePainter elements visualizing them.
+
+    Note that the given starting attributes can be modified at any point
+    in the particle's lifetime by any Affector element in the same
+    ParticleSystem. This includes attributes like lifespan.
+*/
+
+
+/*!
+    \qmlproperty ParticleSystem QtQuick.Particles2::Emitter::system
+
+    This is the Particle system that the Emitter will emit into.
+    This can be omitted if the Emitter is a direct child of the ParticleSystem
+*/
+/*!
+    \qmlproperty string QtQuick.Particles2::Emitter::particle
+
+    This is the type of logical particle which it will emit.
+
+    Default value is "" (empty string).
+*/
+/*!
+    \qmlproperty Shape QtQuick.Particles2::Emitter::shape
+
+    This shape is applied to the bounding box of the emitter. Particles are then emitting
+    from inside the area of the shape.
+
+*/
+/*!
+    \qmlproperty bool QtQuick.Particles2::Emitter::emitting
+
+    If set to false, the emitter will cease emissions until it is set to true.
+
+    Default value is true.
+*/
+/*!
+    \qmlproperty real QtQuick.Particles2::Emitter::emitRate
+
+    Number of particles emitted per second.
+
+    Default value is 10 particles per second.
+*/
+/*!
+    \qmlproperty int QtQuick.Particles2::Emitter::lifeSpan
+
+    The time in milliseconds each emitted particle should last for.
+
+    Default value is 1000 (one second).
+*/
+/*!
+    \qmlproperty int QtQuick.Particles2::Emitter::lifeSpanVariation
+
+    Particle lifespans will vary by up to this much in either direction.
+
+    Default value is 0.
+*/
+/*!
+    \qmlproperty int QtQuick.Particles2::Emitter::emitCap
+
+    The maximum number of particles at a time that this emitter will have alive.
+
+    This can be set as a performance optimization (when using burst and pulse) or
+    to stagger emissions. The default value is emitRate * lifeSpan in seconds, which
+    is the number of particles that would be alive at any one time given the default settings.
+*/
+/*!
+    \qmlproperty real QtQuick.Particles2::Emitter::size
+
+    The size in pixels of the particles at the start of their life.
+
+    Default value is 16.
+*/
+/*!
+    \qmlproperty real QtQuick.Particles2::Emitter::endSize
+
+    The size in pixels of the particles at the end of their life. Size will
+    be linearly interpolated during the life of the particle from this value and
+    size. If endSize is -1, then the size of the particle will remain constant at
+    the starting size.
+
+    Default value is -1.
+*/
+/*!
+    \qmlproperty real QtQuick.Particles2::Emitter::sizeVariation
+
+    The size of a particle can vary by this much up or down from size/endSize. The same
+    random addition is made to both size and endSize for a single particle.
+
+    Default value is 0.
+*/
+/*!
+    \qmlproperty StochasticDirection QtQuick.Particles2::Emitter::speed
+
+    The starting speed of the particles emitted.
+*/
+/*!
+    \qmlproperty StochasticDirection QtQuick.Particles2::Emitter::acceleration
+
+    The starting acceleraton of the particles emitted.
+*/
+/*!
+    \qmlproperty qreal QtQuick.Particles2::Emitter::speedFromMovement
+
+    If this value is non-zero, then any movement of the emitter will provide additional
+    starting velocity to the particles based on the movement. The additional vector will be the
+    same angle as the emitter's movement, with a magnitude that is the magnitude of the emitters
+    movement multiplied by speedFromMovement.
+
+    Default value is 0.
+*/
+
 QSGParticleEmitter::QSGParticleEmitter(QSGItem *parent) :
     QSGItem(parent)
   , m_particlesPerSecond(10)
@@ -58,6 +182,11 @@ QSGParticleEmitter::QSGParticleEmitter(QSGItem *parent) :
   , m_particleSizeVariation(0)
   , m_maxParticleCount(-1)
   , m_burstLeft(0)
+  , m_speed_from_movement(0)
+  , m_particle_count(0)
+  , m_reset_last(true)
+  , m_last_timestamp(0)
+  , m_last_emission(0)
 
 {
     //TODO: Reset speed/acc back to null vector? Or allow null pointer?
@@ -83,11 +212,6 @@ void QSGParticleEmitter::componentComplete()
         qWarning() << "Emitter created without a particle system specified";//TODO: useful QML warnings, like line number?
     QSGItem::componentComplete();
 }
-void QSGParticleEmitter::emitWindow(int timeStamp)
-{
-    Q_UNUSED(timeStamp);
-}
-
 
 void QSGParticleEmitter::setEmitting(bool arg)
 {
@@ -155,4 +279,140 @@ int QSGParticleEmitter::particleCount() const
     return m_particlesPerSecond*((m_particleDuration+m_particleDurationVariation)/1000.0);
 }
 
+void QSGParticleEmitter::setSpeedFromMovement(qreal t)
+{
+    if (t == m_speed_from_movement)
+        return;
+    m_speed_from_movement = t;
+    emit speedFromMovementChanged();
+}
+
+void QSGParticleEmitter::emitWindow(int timeStamp)
+{
+    if (m_system == 0)
+        return;
+    if ((!m_emitting || !m_particlesPerSecond)&& !m_burstLeft && m_burstQueue.isEmpty()){
+        m_reset_last = true;
+        return;
+    }
+
+    if (m_reset_last) {
+        m_last_emitter = m_last_last_emitter = QPointF(x(), y());
+        m_last_timestamp = timeStamp/1000.;
+        m_last_emission = m_last_timestamp;
+        m_reset_last = false;
+    }
+
+    if (m_burstLeft){
+        m_burstLeft -= timeStamp - m_last_timestamp * 1000.;
+        if (m_burstLeft < 0){
+            if (!m_emitting)
+                timeStamp += m_burstLeft;
+            m_burstLeft = 0;
+        }
+    }
+
+    qreal time = timeStamp / 1000.;
+
+    qreal particleRatio = 1. / m_particlesPerSecond;
+    qreal pt = m_last_emission;
+
+    qreal opt = pt; // original particle time
+    qreal dt = time - m_last_timestamp; // timestamp delta...
+    if (!dt)
+        dt = 0.000001;
+
+    // emitter difference since last...
+    qreal dex = (x() - m_last_emitter.x());
+    qreal dey = (y() - m_last_emitter.y());
+
+    qreal ax = (m_last_last_emitter.x() + m_last_emitter.x()) / 2;
+    qreal bx = m_last_emitter.x();
+    qreal cx = (x() + m_last_emitter.x()) / 2;
+    qreal ay = (m_last_last_emitter.y() + m_last_emitter.y()) / 2;
+    qreal by = m_last_emitter.y();
+    qreal cy = (y() + m_last_emitter.y()) / 2;
+
+    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();
+    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;
+        QSGParticleData* datum = m_system->newDatum(m_system->m_groupIds[m_particle]);
+        if (datum){//actually emit(otherwise we've been asked to skip this one)
+            datum->e = this;//###useful?
+            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
+            datum->t = pt;
+            datum->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);
+            datum->x = newPos.x();
+            datum->y = newPos.y();
+
+            // Particle speed
+            const QPointF &speed = m_speed->sample(newPos);
+            datum->vx = speed.x()
+                    + m_speed_from_movement * vx;
+            datum->vy = speed.y()
+                    + m_speed_from_movement * vy;
+
+            // Particle acceleration
+            const QPointF &accel = m_acceleration->sample(newPos);
+            datum->ax = accel.x();
+            datum->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);
+
+            datum->size = size;// * float(m_emitting);
+            datum->endSize = endSize;// * float(m_emitting);
+
+            m_system->emitParticle(datum);
+        }
+        if (m_burstQueue.isEmpty()){
+            pt += particleRatio;
+        }else{
+            m_burstQueue.first().first--;
+            if (m_burstQueue.first().first <= 0)
+                m_burstQueue.pop_front();
+        }
+    }
+    m_last_emission = pt;
+
+    m_last_last_last_emitter = m_last_last_emitter;
+    m_last_last_emitter = m_last_emitter;
+    m_last_emitter = QPointF(x(), y());
+    m_last_timestamp = time;
+}
+
+
 QT_END_NAMESPACE
index 9cf130d..0b0fe91 100644 (file)
@@ -76,6 +76,8 @@ class QSGParticleEmitter : public QSGItem
 
     Q_PROPERTY(QSGStochasticDirection *speed READ speed WRITE setSpeed NOTIFY speedChanged)
     Q_PROPERTY(QSGStochasticDirection *acceleration READ acceleration WRITE setAcceleration NOTIFY accelerationChanged)
+    Q_PROPERTY(qreal speedFromMovement READ speedFromMovement WRITE setSpeedFromMovement NOTIFY speedFromMovementChanged)
+
 public:
     explicit QSGParticleEmitter(QSGItem *parent = 0);
     virtual ~QSGParticleEmitter();
@@ -111,6 +113,8 @@ public:
         return m_particleDurationVariation;
     }
 
+    qreal speedFromMovement() const { return m_speed_from_movement; }
+    void setSpeedFromMovement(qreal s);
     virtual void componentComplete();
 signals:
     void particlesPerSecondChanged(qreal);
@@ -138,6 +142,8 @@ signals:
     void maxParticleCountChanged(int arg);
     void particleCountChanged();
 
+    void speedFromMovementChanged();
+
 public slots:
     void pulse(qreal seconds);
     void burst(int num);
@@ -293,8 +299,22 @@ protected:
        int m_burstLeft;//TODO: Rename to pulse
        QList<QPair<int, QPointF > > m_burstQueue;
        int m_maxParticleCount;
+
+       //Used in default implementation, but might be useful
+       qreal m_speed_from_movement;
+
+       int m_particle_count;
+       bool m_reset_last;
+       qreal m_last_timestamp;
+       qreal m_last_emission;
+
+       QPointF m_last_emitter;
+       QPointF m_last_last_emitter;
+       QPointF m_last_last_last_emitter;
+
 private:
        QSGStochasticDirection m_nullVector;
+       qreal m_speedFromMovement;
 };
 
 QT_END_NAMESPACE
index 1bb06ea..f87115c 100644 (file)
@@ -42,7 +42,6 @@
 #include "qsgangleddirection_p.h"
 #include "qsgcustomparticle_p.h"
 #include "qsgellipseextruder_p.h"
-#include "qsgemitter_p.h"
 #include "qsgfollowemitter_p.h"
 #include "qsgfriction_p.h"
 #include "qsggravity_p.h"
@@ -75,12 +74,6 @@ QT_BEGIN_NAMESPACE
 void QSGParticlesModule::defineModule()
 {
     const char* uri = "QtQuick.Particles";
-    //Debugging only exposition
-    qmlRegisterType<QSGParticlePainter>(uri, 2, 0, "ParticlePainter");
-    qmlRegisterType<QSGParticleEmitter>(uri, 2, 0, "ParticleEmitter");
-    qmlRegisterType<QSGParticleExtruder>(uri, 2, 0, "ParticleExtruder");
-    qmlRegisterType<QSGStochasticDirection>(uri, 2, 0, "NullVector");
-    //Probably should be nocreate types
 
     qmlRegisterType<QSGParticleSystem>(uri, 2, 0, "ParticleSystem");
 
@@ -89,7 +82,7 @@ void QSGParticlesModule::defineModule()
     qmlRegisterType<QSGItemParticle>(uri, 2, 0, "ItemParticle");
     qmlRegisterType<QSGModelParticle>(uri, 2, 0, "ModelParticle");
 
-    qmlRegisterType<QSGBasicEmitter>(uri, 2, 0, "Emitter");//TODO: Rename BasicEmitter?
+    qmlRegisterType<QSGParticleEmitter>(uri, 2, 0, "Emitter");
     qmlRegisterType<QSGCustomEmitter>(uri, 2, 0, "CustomEmitter");
     qmlRegisterType<QSGFollowEmitter>(uri, 2, 0, "FollowEmitter");
 
@@ -112,6 +105,11 @@ void QSGParticlesModule::defineModule()
     qmlRegisterType<QSGSpriteGoalAffector>(uri, 2, 0, "SpriteGoal");
     qmlRegisterType<QSGTurbulenceAffector>(uri, 2, 0 , "Turbulence");
     qmlRegisterType<QSGTargetAffector>(uri, 2, 0 , "Target");
+
+    //Exposed just for completeness
+    qmlRegisterType<QSGParticlePainter>(uri, 2, 0, "ParticlePainter");
+    qmlRegisterType<QSGParticleExtruder>(uri, 2, 0, "ParticleExtruder");
+    qmlRegisterType<QSGStochasticDirection>(uri, 2, 0, "NullVector");
 }
 
 QT_END_NAMESPACE