Rewrite last rewrite
authorAlan Alpert <alan.alpert@nokia.com>
Tue, 21 Jun 2011 02:02:08 +0000 (12:02 +1000)
committerAlan Alpert <alan.alpert@nokia.com>
Tue, 21 Jun 2011 02:02:08 +0000 (12:02 +1000)
Also rewrite to have all particle state shared, not just common
elements.

18 files changed:
src/declarative/particles/qsgcustomparticle.cpp
src/declarative/particles/qsgcustomparticle_p.h
src/declarative/particles/qsgemitter.cpp
src/declarative/particles/qsgfollowemitter.cpp
src/declarative/particles/qsggravity.cpp
src/declarative/particles/qsgimageparticle.cpp
src/declarative/particles/qsgimageparticle_p.h
src/declarative/particles/qsgitemparticle.cpp
src/declarative/particles/qsgitemparticle_p.h
src/declarative/particles/qsgkill.cpp
src/declarative/particles/qsgmodelparticle.cpp
src/declarative/particles/qsgmodelparticle_p.h
src/declarative/particles/qsgparticlepainter.cpp
src/declarative/particles/qsgparticlepainter_p.h
src/declarative/particles/qsgparticlesystem.cpp
src/declarative/particles/qsgparticlesystem_p.h
src/declarative/particles/qsgpointattractor.cpp
src/declarative/particles/qsgwander.cpp

index f91307e..09cfdda 100644 (file)
@@ -123,36 +123,8 @@ QSGCustomParticle::QSGCustomParticle(QSGItem* parent)
     : QSGParticlePainter(parent)
     , m_pleaseReset(true)
     , m_dirtyData(true)
-    , m_resizePending(false)
 {
     setFlag(QSGItem::ItemHasContents);
-    m_defaultVertices = new PlainVertices;
-    PlainVertex* vertices = (PlainVertex*) m_defaultVertices;
-    for (int i=0; i<4; ++i) {
-        vertices[i].x = 0;
-        vertices[i].y = 0;
-        vertices[i].t = -1;
-        vertices[i].lifeSpan = 0;
-        vertices[i].size = 0;
-        vertices[i].endSize = 0;
-        vertices[i].sx = 0;
-        vertices[i].sy = 0;
-        vertices[i].ax = 0;
-        vertices[i].ay = 0;
-        vertices[i].r = 0;
-    }
-
-    vertices[0].tx = 0;
-    vertices[0].ty = 0;
-
-    vertices[1].tx = 1;
-    vertices[1].ty = 0;
-
-    vertices[2].tx = 0;
-    vertices[2].ty = 1;
-
-    vertices[3].tx = 1;
-    vertices[3].ty = 1;
 }
 
 void QSGCustomParticle::componentComplete()
@@ -202,19 +174,6 @@ void QSGCustomParticle::setVertexShader(const QByteArray &code)
     emit vertexShaderChanged();
 }
 
-void QSGCustomParticle::resize(int oldCount, int newCount)
-{
-    if(!m_node)
-        return;
-    if(!m_resizePending){
-        m_pendingResizeVector.resize(oldCount);
-        PlainVertices *particles = (PlainVertices *) m_node->geometry()->vertexData();
-        for(int i=0; i<oldCount; i++)
-            m_pendingResizeVector[i] = &particles[i];
-    }
-    groupShuffle(m_pendingResizeVector, m_defaultVertices);
-}
-
 void QSGCustomParticle::reset()
 {
     disconnectPropertySignals();
@@ -411,8 +370,6 @@ QSGNode *QSGCustomParticle::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
         m_pleaseReset = false;
         m_dirtyData = false;
     }
-    if(m_resizePending)
-        performPendingResize();
 
     if(m_system && m_system->isRunning())
         prepareNextFrame();
@@ -437,32 +394,6 @@ void QSGCustomParticle::prepareNextFrame(){
         buildData();
 }
 
-void QSGCustomParticle::performPendingResize()
-{
-    m_resizePending = false;
-    if(!m_node)
-        return;
-    Q_ASSERT(m_pendingResizeVector.size() == m_count);//XXX
-    PlainVertices tmp[m_count];//###More vast memcpys that will decrease performance
-    for(int i=0; i<m_count; i++)
-        tmp[i] = *m_pendingResizeVector[i];
-    m_node->setFlag(QSGNode::OwnsGeometry, false);
-    m_node->geometry()->allocate(m_count*4, m_count*6);
-    memcpy(m_node->geometry()->vertexData(), tmp, sizeof(PlainVertices) * m_count);
-    quint16 *indices = m_node->geometry()->indexDataAsUShort();
-    for (int i=0; i<m_count; ++i) {
-        int o = i * 4;
-        indices[0] = o;
-        indices[1] = o + 1;
-        indices[2] = o + 2;
-        indices[3] = o + 1;
-        indices[4] = o + 3;
-        indices[5] = o + 2;
-        indices += 6;
-    }
-    m_node->setFlag(QSGNode::OwnsGeometry, true);
-}
-
 QSGShaderEffectNode* QSGCustomParticle::buildCustomNode()
 {
     if (m_count * 4 > 0xffff) {
@@ -475,8 +406,6 @@ QSGShaderEffectNode* QSGCustomParticle::buildCustomNode()
         return 0;
     }
 
-    m_resizePending = false;//reset resizes as well.
-
     //Create Particle Geometry
     int vCount = m_count * 4;
     int iCount = m_count * 6;
@@ -484,10 +413,18 @@ QSGShaderEffectNode* QSGCustomParticle::buildCustomNode()
     g->setDrawingMode(GL_TRIANGLES);
     PlainVertex *vertices = (PlainVertex *) g->vertexData();
     for (int p=0; p<m_count; ++p) {
-        double r = rand()/(double)RAND_MAX;//TODO: Seed?
-        memcpy(vertices, m_defaultVertices, sizeof(PlainVertices));
-        for(int i=0; i<4; i++)
-            vertices[i].r = r;
+        reload(p);
+        vertices[0].tx = 0;
+        vertices[0].ty = 0;
+
+        vertices[1].tx = 1;
+        vertices[1].ty = 0;
+
+        vertices[2].tx = 0;
+        vertices[2].ty = 1;
+
+        vertices[3].tx = 1;
+        vertices[3].ty = 1;
         vertices += 4;
     }
     quint16 *indices = g->indexDataAsUShort();
@@ -553,28 +490,31 @@ void QSGCustomParticle::buildData()
     m_dirtyData = false;
 }
 
-void QSGCustomParticle::load(QSGParticleData *d)
+void QSGCustomParticle::initialize(int idx)
 {
-    reload(d);//We don't do anything special in C++ here.
+    m_data[idx]->r = rand()/(qreal)RAND_MAX;
 }
 
-void QSGCustomParticle::reload(QSGParticleData *d)
+void QSGCustomParticle::reload(int idx)
 {
     if (m_node == 0)
         return;
 
     PlainVertices *particles = (PlainVertices *) m_node->geometry()->vertexData();
-
-    int pos = particleTypeIndex(d);
-
-    PlainVertices &p = particles[pos];
-
-    //Perhaps we could be more efficient?
-    vertexCopy(p.v1, d->pv);
-    vertexCopy(p.v2, d->pv);
-    vertexCopy(p.v3, d->pv);
-    vertexCopy(p.v4, d->pv);
-
+    PlainVertex *vertices = (PlainVertex *)&particles[idx];
+    for (int i=0; i<4; ++i) {
+        vertices[i].x = m_data[idx]->x - m_systemOffset.x();
+        vertices[i].y = m_data[idx]->y - m_systemOffset.y();
+        vertices[i].t = m_data[idx]->t;
+        vertices[i].lifeSpan = m_data[idx]->lifeSpan;
+        vertices[i].size = m_data[idx]->size;
+        vertices[i].endSize = m_data[idx]->endSize;
+        vertices[i].sx = m_data[idx]->sx;
+        vertices[i].sy = m_data[idx]->sy;
+        vertices[i].ax = m_data[idx]->ax;
+        vertices[i].ay = m_data[idx]->ay;
+        vertices[i].r = m_data[idx]->r;
+    }
 }
 
 QT_END_NAMESPACE
index 863da05..50ff37a 100644 (file)
@@ -62,8 +62,6 @@ class QSGCustomParticle : public QSGParticlePainter
 
 public:
     explicit QSGCustomParticle(QSGItem* parent=0);
-    virtual void load(QSGParticleData*);
-    virtual void reload(QSGParticleData*);
 
     QByteArray fragmentShader() const { return m_source.fragmentCode; }
     void setFragmentShader(const QByteArray &code);
@@ -77,6 +75,9 @@ Q_SIGNALS:
     void fragmentShaderChanged();
     void vertexShaderChanged();
 protected:
+    virtual void initialize(int idx);
+    virtual void reload(int idx);
+
     QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
     void prepareNextFrame();
     void setSource(const QVariant &var, int index);
@@ -108,9 +109,6 @@ private:
     QSGShaderEffectNode* m_node;
     qreal m_lastTime;
 
-    bool m_resizePending;
-    QVector<PlainVertices*> m_pendingResizeVector;
-    PlainVertices* m_defaultVertices;
 };
 
 QT_END_NAMESPACE
index 081dd8d..c3ec3ff 100644 (file)
@@ -124,7 +124,6 @@ void QSGBasicEmitter::emitWindow(int timeStamp)
         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?
-            ParticleVertex &p = datum->pv;
             qreal t = 1 - (pt - opt) / dt;
             qreal vx =
               - 2 * ax * (1 - t)
@@ -137,8 +136,8 @@ void QSGBasicEmitter::emitWindow(int timeStamp)
 
 
             // Particle timestamp
-            p.t = pt;
-            p.lifeSpan = //TODO:Promote to base class?
+            datum->t = pt;
+            datum->lifeSpan = //TODO:Promote to base class?
                     (m_particleDuration
                      + ((rand() % ((m_particleDurationVariation*2) + 1)) - m_particleDurationVariation))
                     / 1000.0;
@@ -153,20 +152,20 @@ void QSGBasicEmitter::emitWindow(int timeStamp)
                               , width(), height());
             }
             QPointF newPos = effectiveExtruder()->extrude(boundsRect);
-            p.x = newPos.x();
-            p.y = newPos.y();
+            datum->x = newPos.x();
+            datum->y = newPos.y();
 
             // Particle speed
             const QPointF &speed = m_speed->sample(newPos);
-            p.sx = speed.x()
+            datum->sx = speed.x()
                     + m_speed_from_movement * vx;
-            p.sy = speed.y()
+            datum->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();
+            datum->ax = accel.x();
+            datum->ay = accel.y();
 
             // Particle size
             float sizeVariation = -m_particleSizeVariation
@@ -175,8 +174,8 @@ void QSGBasicEmitter::emitWindow(int timeStamp)
             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);
+            datum->size = size;// * float(m_emitting);
+            datum->endSize = endSize;// * float(m_emitting);
 
             m_system->emitParticle(datum);
         }
index 28a082f..ba31e8f 100644 (file)
@@ -116,8 +116,8 @@ void QSGFollowEmitter::emitWindow(int timeStamp)
         if(!d || !d->stillAlive())
             continue;
         pt = m_lastEmission[d->index];
-        if(pt < d->pv.t)
-            pt = d->pv.t;
+        if(pt < d->t)
+            pt = d->t;
 
         if(!effectiveExtruder()->contains(QRectF(offset.x(), offset.y(), width(), height()),QPointF(d->curX(), d->curY()))){
             m_lastEmission[d->index] = time;//jump over this time period without emitting, because it's outside
@@ -127,45 +127,44 @@ void QSGFollowEmitter::emitWindow(int timeStamp)
             QSGParticleData* datum = m_system->newDatum(gId2);
             if(datum){//else, skip this emission
                 datum->e = this;//###useful?
-                ParticleVertex &p = datum->pv;
 
                 // Particle timestamp
-                p.t = pt;
-                p.lifeSpan =
+                datum->t = pt;
+                datum->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 followT =  pt - d->t;
                 qreal followT2 = followT * followT * 0.5;
-                qreal sizeOffset = d->pv.size/2;//TODO: Current size? As an option
+                qreal sizeOffset = d->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,
+                QRectF boundsRect(d->x - offset.x() + d->sx * followT + d->ax * followT2 - m_emitterXVariation/2,
+                                  d->y - offset.y() + d->sy * followT + d->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,
+    //            QRectF boundsRect(d->x + d->sx * followT + d->ax * followT2 + offset.x() - sizeOffset,
+    //                              d->y + d->sy * followT + d->ay * followT2 + offset.y() - sizeOffset,
     //                              sizeOffset*2,
     //                              sizeOffset*2);
 
                 QSGParticleExtruder* effectiveEmissionExtruder = m_emissionExtruder ? m_emissionExtruder : m_defaultEmissionExtruder;
                 const QPointF &newPos = effectiveEmissionExtruder->extrude(boundsRect);
-                p.x = newPos.x();
-                p.y = newPos.y();
+                datum->x = newPos.x();
+                datum->y = newPos.y();
 
                 // Particle speed
                 const QPointF &speed = m_speed->sample(newPos);
-                p.sx = speed.x();
-                p.sy = speed.y();
+                datum->sx = speed.x();
+                datum->sy = speed.y();
 
                 // Particle acceleration
                 const QPointF &accel = m_acceleration->sample(newPos);
-                p.ax = accel.x();
-                p.ay = accel.y();
+                datum->ax = accel.x();
+                datum->ay = accel.y();
 
                 // Particle size
                 float sizeVariation = -m_particleSizeVariation
@@ -174,8 +173,8 @@ void QSGFollowEmitter::emitWindow(int timeStamp)
                 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);
+                datum->size = size * float(m_emitting);
+                datum->endSize = endSize * float(m_emitting);
 
                 m_system->emitParticle(datum);
             }
index de735da..b1cf3e9 100644 (file)
@@ -64,11 +64,11 @@ bool QSGGravityAffector::affectParticle(QSGParticleData *d, qreal dt)
 {
     Q_UNUSED(dt);
     bool changed = false;
-    if(d->pv.ax != m_xAcc){
+    if(d->ax != m_xAcc){
         d->setInstantaneousAX(m_xAcc);
         changed = true;
     }
-    if(d->pv.ay != m_yAcc){
+    if(d->ay != m_yAcc){
         d->setInstantaneousAY(m_yAcc);
         changed = true;
     }
index 15bc88b..836236c 100644 (file)
@@ -305,62 +305,6 @@ QSGImageParticle::QSGImageParticle(QSGItem* parent)
     , m_lastLevel(Unknown)
 {
     setFlag(ItemHasContents);
-    //TODO: Clean up defaults here and in custom
-    m_defaultUltra = new UltraVertices;
-    m_defaultSimple = new SimpleVertices;
-    UltraVertex *vertices = (UltraVertex *) m_defaultUltra;
-    SimpleVertex *vertices2 = (SimpleVertex *) m_defaultSimple;
-    for (int i=0; i<4; ++i) {
-        vertices2[i].x = vertices[i].x = 0;
-        vertices2[i].y = vertices[i].y = 0;
-        vertices2[i].t = vertices[i].t = -1;
-        vertices2[i].lifeSpan = vertices[i].lifeSpan = 0;
-        vertices2[i].size = vertices[i].size = 0;
-        vertices2[i].endSize = vertices[i].endSize = 0;
-        vertices2[i].sx = vertices[i].sx = 0;
-        vertices2[i].sy = vertices[i].sy = 0;
-        vertices2[i].ax = vertices[i].ax = 0;
-        vertices2[i].ay = vertices[i].ay = 0;
-        vertices[i].xx = 1;
-        vertices[i].xy = 0;
-        vertices[i].yx = 0;
-        vertices[i].yy = 1;
-        vertices[i].rotation = 0;
-        vertices[i].rotationSpeed = 0;
-        vertices[i].autoRotate = 0;
-        vertices[i].animIdx = -1;
-        vertices[i].frameDuration = 1;
-        vertices[i].frameCount = 0;
-        vertices[i].animT = -1;
-        vertices[i].color.r = 255;
-        vertices[i].color.g = 255;
-        vertices[i].color.b = 255;
-        vertices[i].color.a = 255;
-    }
-
-    vertices[0].tx = 0;
-    vertices[0].ty = 0;
-
-    vertices[1].tx = 1;
-    vertices[1].ty = 0;
-
-    vertices[2].tx = 0;
-    vertices[2].ty = 1;
-
-    vertices[3].tx = 1;
-    vertices[3].ty = 1;
-
-    vertices2[0].tx = 0;
-    vertices2[0].ty = 0;
-
-    vertices2[1].tx = 1;
-    vertices2[1].ty = 0;
-
-    vertices2[2].tx = 0;
-    vertices2[2].ty = 1;
-
-    vertices2[3].tx = 1;
-    vertices2[3].ty = 1;
 }
 
 QDeclarativeListProperty<QSGSprite> QSGImageParticle::sprites()
@@ -411,7 +355,7 @@ void QSGImageParticle::setColor(const QColor &color)
         return;
     m_color = color;
     emit colorChanged();
-    if(perfLevel < Coloured)
+    if(perfLevel < Colored)
         reset();
 }
 
@@ -421,7 +365,7 @@ void QSGImageParticle::setColorVariation(qreal var)
         return;
     m_color_variation = var;
     emit colorVariationChanged();
-    if(perfLevel < Coloured)
+    if(perfLevel < Colored)
         reset();
 }
 
@@ -431,7 +375,7 @@ void QSGImageParticle::setAlphaVariation(qreal arg)
         m_alphaVariation = arg;
         emit alphaVariationChanged(arg);
     }
-    if(perfLevel < Coloured)
+    if(perfLevel < Colored)
         reset();
 }
 
@@ -441,7 +385,7 @@ void QSGImageParticle::setAlpha(qreal arg)
         m_alpha = arg;
         emit alphaChanged(arg);
     }
-    if(perfLevel < Coloured)
+    if(perfLevel < Colored)
         reset();
 }
 
@@ -451,7 +395,7 @@ void QSGImageParticle::setRedVariation(qreal arg)
         m_redVariation = arg;
         emit redVariationChanged(arg);
     }
-    if(perfLevel < Coloured)
+    if(perfLevel < Colored)
         reset();
 }
 
@@ -461,7 +405,7 @@ void QSGImageParticle::setGreenVariation(qreal arg)
         m_greenVariation = arg;
         emit greenVariationChanged(arg);
     }
-    if(perfLevel < Coloured)
+    if(perfLevel < Colored)
         reset();
 }
 
@@ -471,7 +415,7 @@ void QSGImageParticle::setBlueVariation(qreal arg)
         m_blueVariation = arg;
         emit blueVariationChanged(arg);
     }
-    if(perfLevel < Coloured)
+    if(perfLevel < Colored)
         reset();
 }
 
@@ -619,9 +563,34 @@ QSGGeometryNode* QSGImageParticle::buildSimpleParticleNode()
     QSGGeometry *g = new QSGGeometry(SimpleParticle_AttributeSet, vCount, iCount);
     g->setDrawingMode(GL_TRIANGLES);
 
-    SimpleVertices *vertices = (SimpleVertices *) g->vertexData();
-    for (int p=0; p<m_count; ++p)
-        memcpy(vertices++, m_defaultSimple, sizeof(SimpleVertices));
+    SimpleVertex *vertices = (SimpleVertex *) g->vertexData();
+    for (int p=0; p<m_count; ++p){
+        for(int i=0; i<4; i++){
+            vertices[i].x = m_data[p]->x;
+            vertices[i].y = m_data[p]->y;
+            vertices[i].t = m_data[p]->t;
+            vertices[i].size = m_data[p]->size;
+            vertices[i].endSize = m_data[p]->endSize;
+            vertices[i].sx = m_data[p]->sx;
+            vertices[i].sy = m_data[p]->sy;
+            vertices[i].ax = m_data[p]->ax;
+            vertices[i].ay = m_data[p]->ay;
+        }
+        //reload(p);
+        vertices[0].tx = 0;
+        vertices[0].ty = 0;
+
+        vertices[1].tx = 1;
+        vertices[1].ty = 0;
+
+        vertices[2].tx = 0;
+        vertices[2].ty = 1;
+
+        vertices[3].tx = 1;
+        vertices[3].ty = 1;
+
+        vertices += 4;
+    }
 
     quint16 *indices = g->indexDataAsUShort();
     for (int i=0; i<m_count; ++i) {
@@ -635,6 +604,9 @@ QSGGeometryNode* QSGImageParticle::buildSimpleParticleNode()
         indices += 6;
     }
 
+    m_node = new QSGGeometryNode();
+    m_node->setGeometry(g);
+
     if (m_material) {
         delete m_material;
         m_material = 0;
@@ -644,28 +616,24 @@ QSGGeometryNode* QSGImageParticle::buildSimpleParticleNode()
     m_material->texture = sceneGraphEngine()->createTextureFromImage(image);
     m_material->texture->setFiltering(QSGTexture::Linear);
     m_material->framecount = 1;
-    m_node = new QSGGeometryNode();
-    m_node->setGeometry(g);
     m_node->setMaterial(m_material);
 
     m_last_particle = 0;
-
     return m_node;
 }
 
 QSGGeometryNode* QSGImageParticle::buildParticleNode()
 {
     if (m_count * 4 > 0xffff) {
-        printf("UltraParticle: Too many particles... \n");//####Why is this here?
+        printf("UltraParticle: Too many particles... \n");//### Why is this here?
         return 0;
     }
 
     if(m_count <= 0) {
-        printf("UltraParticle: Too few particles... \n");
+        qDebug() << "UltraParticle: Too few particles... \n";//XXX: Is now a vaild intermediate state...
         return 0;
     }
 
-    m_resizePending = false;
     if(!m_sprites.count() && !m_bloat
             && m_colortable_name.isEmpty()
             && m_sizetable_name.isEmpty()
@@ -705,38 +673,29 @@ QSGGeometryNode* QSGImageParticle::buildParticleNode()
 
     QSGGeometry *g = new QSGGeometry(UltraParticle_AttributeSet, vCount, iCount);
     g->setDrawingMode(GL_TRIANGLES);
+    m_node = new QSGGeometryNode();
+    m_node->setGeometry(g);
 
     UltraVertex *vertices = (UltraVertex *) g->vertexData();
-    SimpleVertex *oldSimple = (SimpleVertex *) m_lastData;//TODO: Other levels
-    if(m_lastLevel == 1)
-        qDebug() << "Theta" << m_lastLevel << oldSimple[0].x << oldSimple[0].y << oldSimple[0].t;
     for (int p=0; p<m_count; ++p) {
-        memcpy(vertices, m_defaultUltra, sizeof(UltraVertices));
-        if (m_lastLevel == 1 && m_lastCount > p) {//Transplant/IntermediateVertices?
-            for (int i=0; i<4; ++i) {
-                vertices[i].x = oldSimple[i].x;
-                vertices[i].y = oldSimple[i].y;
-                vertices[i].t = oldSimple[i].t;
-                vertices[i].lifeSpan = oldSimple[i].lifeSpan;
-                vertices[i].size = oldSimple[i].size;
-                vertices[i].endSize = oldSimple[i].endSize;
-                vertices[i].sx = oldSimple[i].sx;
-                vertices[i].sy = oldSimple[i].sy;
-                vertices[i].ax = oldSimple[i].ax;
-                vertices[i].ay = oldSimple[i].ay;
-            /*
-                vertices[i].frameDuration = oldSimple[i].lifeSpan;
-                vertices[i].frameCount = 1;
-                vertices[i].animT = oldSimple[i].t;
-            */
-            }
-        }
+        reload(p);//reload gets geometry from node
+
+        vertices[0].tx = 0;
+        vertices[0].ty = 0;
+
+        vertices[1].tx = 1;
+        vertices[1].ty = 0;
+
+        vertices[2].tx = 0;
+        vertices[2].ty = 1;
+
+        vertices[3].tx = 1;
+        vertices[3].ty = 1;
 
         vertices += 4;
-        oldSimple += 4;
     }
 
-    quint16 *indices = g->indexDataAsUShort();//TODO: Speed gains by copying this over if count unchanged?
+    quint16 *indices = g->indexDataAsUShort();
     for (int i=0; i<m_count; ++i) {
         int o = i * 4;
         indices[0] = o;
@@ -780,8 +739,6 @@ QSGGeometryNode* QSGImageParticle::buildParticleNode()
         m_spriteEngine->setCount(m_count);
     }
 
-    m_node = new QSGGeometryNode();
-    m_node->setGeometry(g);
     m_node->setMaterial(m_material);
 
     m_last_particle = 0;
@@ -789,92 +746,11 @@ QSGGeometryNode* QSGImageParticle::buildParticleNode()
     return m_node;
 }
 
-void QSGImageParticle::resize(int oldCount, int newCount)
-{
-    //If perf level changes at the same time as a resize, we reset instead of doing pending resize
-    if(!m_node)
-        return;
-    switch(perfLevel){
-    default:
-    case Sprites:
-        if(m_spriteEngine)
-            reset();//TODO: Handle sprite resizeing (have to shuffle the engine too...)
-    case Coloured:
-    case Deformable:
-    case Tabled:
-        if(!m_resizePending){
-            m_resizePendingUltra.resize(oldCount);
-            UltraVertices *particles = (UltraVertices *) m_node->geometry()->vertexData();
-            for(int i=0; i<oldCount; i++)
-                m_resizePendingUltra[i] = &particles[i];
-        }
-        groupShuffle(m_resizePendingUltra, m_defaultUltra);
-        break;
-    case Simple:
-        if(!m_resizePending){
-            m_resizePendingSimple.resize(oldCount);
-            SimpleVertices *particles = (SimpleVertices *) m_node->geometry()->vertexData();
-            for(int i=0; i<oldCount; i++)
-                m_resizePendingSimple[i] = &particles[i];
-        }
-        groupShuffle(m_resizePendingSimple, m_defaultSimple);
-        break;
-    }
-    m_resizePending = true;
-}
-
-void QSGImageParticle::performPendingResize()
-{
-    m_resizePending = false;
-    if(!m_node)
-        return;
-    UltraVertices tmp1[m_count];//###More vast memcpys that will decrease performance
-    SimpleVertices tmp2[m_count];//###More vast memcpys that will decrease performance
-    switch(perfLevel){
-    case Sprites:
-    case Coloured:
-    case Deformable:
-    case Tabled:
-        Q_ASSERT(m_resizePendingUltra.size() == m_count);//XXX
-        for(int i=0; i<m_count; i++){
-            Q_ASSERT(m_resizePendingUltra[i]);
-            tmp1[i] = *m_resizePendingUltra[i];
-        }
-        m_node->setFlag(QSGNode::OwnsGeometry, false);
-        m_node->geometry()->allocate(m_count*4, m_count*6);
-        memcpy(m_node->geometry()->vertexData(), tmp1, sizeof(UltraVertices) * m_count);
-        m_node->setFlag(QSGNode::OwnsGeometry, true);
-        break;
-    case Simple:
-        Q_ASSERT(m_resizePendingSimple.size() == m_count);//XXX
-        for(int i=0; i<m_count; i++)
-                tmp2[i] = *m_resizePendingSimple[i];
-        m_node->setFlag(QSGNode::OwnsGeometry, false);
-        m_node->geometry()->allocate(m_count*4, m_count*6);
-        memcpy(m_node->geometry()->vertexData(), tmp2, sizeof(SimpleVertices) * m_count);
-        m_node->setFlag(QSGNode::OwnsGeometry, true);
-        break;
-    }
-    quint16 *indices = m_node->geometry()->indexDataAsUShort();
-    for (int i=0; i<m_count; ++i) {
-        int o = i * 4;
-        indices[0] = o;
-        indices[1] = o + 1;
-        indices[2] = o + 2;
-        indices[3] = o + 1;
-        indices[4] = o + 3;
-        indices[5] = o + 2;
-        indices += 6;
-    }
-    m_node->setFlag(QSGNode::OwnsGeometry, true);
-}
-
 QSGNode *QSGImageParticle::updatePaintNode(QSGNode *, UpdatePaintNodeData *)
 {
     if(m_pleaseReset){
         if(m_node){
             if(perfLevel == 1){
-                qDebug() << "Beta";
                 m_lastCount = m_node->geometry()->vertexCount() / 4;
                 m_lastData = qMalloc(m_lastCount*sizeof(SimpleVertices));
                 memcpy(m_lastData, m_node->geometry()->vertexData(), m_lastCount * sizeof(SimpleVertices));//TODO: Multiple levels
@@ -889,8 +765,6 @@ QSGNode *QSGImageParticle::updatePaintNode(QSGNode *, UpdatePaintNodeData *)
         m_material = 0;
         m_pleaseReset = false;
     }
-    if(m_resizePending)
-        performPendingResize();
 
     if(m_system && m_system->isRunning())
         prepareNextFrame();
@@ -904,7 +778,7 @@ QSGNode *QSGImageParticle::updatePaintNode(QSGNode *, UpdatePaintNodeData *)
 
 void QSGImageParticle::prepareNextFrame()
 {
-    if (m_node == 0){    //TODO: Staggered loading (as emitted)
+    if (m_node == 0){//TODO: Staggered loading (as emitted)
         m_node = buildParticleNode();
         if(m_node == 0)
             return;
@@ -935,67 +809,14 @@ void QSGImageParticle::prepareNextFrame()
     }
 }
 
-template <typename VT>
-IntermediateVertices* transplant(IntermediateVertices* iv, VT &v)
-{//Deliberate typemangling cast
-    iv->v1 = (UltraVertex*)&(v.v1);
-    iv->v2 = (UltraVertex*)&(v.v2);
-    iv->v3 = (UltraVertex*)&(v.v3);
-    iv->v4 = (UltraVertex*)&(v.v4);
-    return iv;
-}
-
-IntermediateVertices* QSGImageParticle::fetchIntermediateVertices(int pos)
-{
-    //Note that this class ruins typesafety for you. Maybe even thread safety.
-    //TODO: Something better, possibly with templates or inheritance
-    static IntermediateVertices iv;
-    SimpleVertices *sv;
-    UltraVertices *uv;
-    switch(perfLevel){
-        case Simple:
-            sv = (SimpleVertices *) m_node->geometry()->vertexData();
-            return transplant(&iv, sv[pos]);
-        case Coloured:
-        case Deformable:
-        case Tabled:
-        case Sprites:
-        default:
-            uv = (UltraVertices *) m_node->geometry()->vertexData();
-            return transplant(&iv,uv[pos]);
-    }
-}
-
 void QSGImageParticle::reloadColor(const Color4ub &c, QSGParticleData* d)
 {
-    UltraVertices *particles = (UltraVertices *) m_node->geometry()->vertexData();
-    int pos = particleTypeIndex(d);
-    UltraVertices &p = particles[pos];
-    p.v1.color = p.v2.color = p.v3.color = p.v4.color = c;
+    d->color = c;
+    //TODO: get index for reload - or make function take an index
 }
 
-void QSGImageParticle::reload(QSGParticleData *d)
+void QSGImageParticle::initialize(int idx)
 {
-    if (m_node == 0)
-        return;
-
-    int pos = particleTypeIndex(d);
-    IntermediateVertices* p = fetchIntermediateVertices(pos);
-
-    //Perhaps we could be more efficient?
-    vertexCopy(*p->v1, d->pv);
-    vertexCopy(*p->v2, d->pv);
-    vertexCopy(*p->v3, d->pv);
-    vertexCopy(*p->v4, d->pv);
-}
-
-void QSGImageParticle::load(QSGParticleData *d)
-{
-    if (m_node == 0)
-        return;
-
-    int pos = particleTypeIndex(d);
-    IntermediateVertices* p = fetchIntermediateVertices(pos);//Remember this removes typesafety!
     Color4ub color;
     qreal redVariation = m_color_variation + m_redVariation;
     qreal greenVariation = m_color_variation + m_greenVariation;
@@ -1003,66 +824,111 @@ void QSGImageParticle::load(QSGParticleData *d)
     switch(perfLevel){//Fall-through is intended on all of them
         case Sprites:
             // Initial Sprite State
-            p->v1->animT = p->v2->animT = p->v3->animT = p->v4->animT = p->v1->t;
-            p->v1->animIdx = p->v2->animIdx = p->v3->animIdx = p->v4->animIdx = 0;
+            m_data[idx]->animT = m_data[idx]->t;
+            m_data[idx]->animIdx = 0;
             if(m_spriteEngine){
-                m_spriteEngine->startSprite(pos);
-                p->v1->frameCount = p->v2->frameCount = p->v3->frameCount = p->v4->frameCount = m_spriteEngine->spriteFrames(pos);
-                p->v1->frameDuration = p->v2->frameDuration = p->v3->frameDuration = p->v4->frameDuration = m_spriteEngine->spriteDuration(pos);
+                m_spriteEngine->startSprite(idx);
+                m_data[idx]->frameCount = m_spriteEngine->spriteFrames(idx);
+                m_data[idx]->frameDuration = m_spriteEngine->spriteDuration(idx);
             }else{
-                p->v1->frameCount = p->v2->frameCount = p->v3->frameCount = p->v4->frameCount = 1;
-                p->v1->frameDuration = p->v2->frameDuration = p->v3->frameDuration = p->v4->frameDuration = 9999;
+                m_data[idx]->frameCount = 1;
+                m_data[idx]->frameDuration = 9999;
             }
         case Tabled:
         case Deformable:
             //Initial Rotation
             if(m_xVector){
-                const QPointF &ret = m_xVector->sample(QPointF(d->pv.x, d->pv.y));
-                p->v1->xx = p->v2->xx = p->v3->xx = p->v4->xx = ret.x();
-                p->v1->xy = p->v2->xy = p->v3->xy = p->v4->xy = ret.y();
+                const QPointF &ret = m_xVector->sample(QPointF(m_data[idx]->x, m_data[idx]->y));
+                m_data[idx]->xx = ret.x();
+                m_data[idx]->xy = ret.y();
             }
             if(m_yVector){
-                const QPointF &ret = m_yVector->sample(QPointF(d->pv.x, d->pv.y));
-                p->v1->yx = p->v2->yx = p->v3->yx = p->v4->yx = ret.x();
-                p->v1->yy = p->v2->yy = p->v3->yy = p->v4->yy = ret.y();
+                const QPointF &ret = m_yVector->sample(QPointF(m_data[idx]->x, m_data[idx]->y));
+                m_data[idx]->yx = ret.x();
+                m_data[idx]->yy = ret.y();
             }
-            p->v1->rotation = p->v2->rotation = p->v3->rotation = p->v4->rotation =
+            m_data[idx]->rotation =
                     (m_rotation + (m_rotationVariation - 2*((qreal)rand()/RAND_MAX)*m_rotationVariation) ) * CONV;
-            p->v1->rotationSpeed = p->v2->rotationSpeed = p->v3->rotationSpeed = p->v4->rotationSpeed =
+            m_data[idx]->rotationSpeed =
                     (m_rotationSpeed + (m_rotationSpeedVariation - 2*((qreal)rand()/RAND_MAX)*m_rotationSpeedVariation) ) * CONV;
-            p->v1->autoRotate = p->v2->autoRotate = p->v3->autoRotate = p->v4->autoRotate = m_autoRotation?1.0:0.0;
-        case Coloured:
+            m_data[idx]->autoRotate = m_autoRotation?1.0:0.0;
+        case Colored:
             //Color initialization
             // Particle color
             color.r = m_color.red() * (1 - redVariation) + rand() % 256 * redVariation;
             color.g = m_color.green() * (1 - greenVariation) + rand() % 256 * greenVariation;
             color.b = m_color.blue() * (1 - blueVariation) + rand() % 256 * blueVariation;
             color.a = m_alpha * m_color.alpha() * (1 - m_alphaVariation) + rand() % 256 * m_alphaVariation;
-            p->v1->color = p->v2->color = p->v3->color = p->v4->color = color;
+            m_data[idx]->color = color;
         default:
             break;
     }
-
-    vertexCopy(*p->v1, d->pv);
-    vertexCopy(*p->v2, d->pv);
-    vertexCopy(*p->v3, d->pv);
-    vertexCopy(*p->v4, d->pv);
 }
 
-/*
-void QSGImageParticle::verticesUpgrade(void *prev, void *next)
+void QSGImageParticle::reload(int idx)
 {
-    PerformanceLevel copyLevel = qMin(perfLevel, m_lastLevel);
-    switch(perfLevel){//Intentional fall-through
-        case Sprites:
-            if(copyLevel >= Sprites)
-        case Tabled:
-        case Deformable:
-        case Coloured:
+    if(!m_node)
+        return;
+
+    m_node->setFlag(QSGNode::OwnsGeometry, false);
+    UltraVertex *ultraVertices = (UltraVertex *) m_node->geometry()->vertexData();
+    SimpleVertex *simpleVertices = (SimpleVertex *) m_node->geometry()->vertexData();
+    switch(perfLevel){
+    case Sprites:
+        ultraVertices += idx*4;
+        for(int i=0; i<4; i++){
+            ultraVertices[i].x = m_data[idx]->x  - m_systemOffset.x();
+            ultraVertices[i].y = m_data[idx]->y  - m_systemOffset.y();
+            ultraVertices[i].t = m_data[idx]->t;
+            ultraVertices[i].lifeSpan = m_data[idx]->lifeSpan;
+            ultraVertices[i].size = m_data[idx]->size;
+            ultraVertices[i].endSize = m_data[idx]->endSize;
+            ultraVertices[i].sx = m_data[idx]->sx;
+            ultraVertices[i].sy = m_data[idx]->sy;
+            ultraVertices[i].ax = m_data[idx]->ax;
+            ultraVertices[i].ay = m_data[idx]->ay;
+            ultraVertices[i].xx = m_data[idx]->xx;
+            ultraVertices[i].xy = m_data[idx]->xy;
+            ultraVertices[i].yx = m_data[idx]->yx;
+            ultraVertices[i].yy = m_data[idx]->yy;
+            ultraVertices[i].rotation = m_data[idx]->rotation;
+            ultraVertices[i].rotationSpeed = m_data[idx]->rotationSpeed;
+            ultraVertices[i].autoRotate = m_data[idx]->autoRotate;
+            ultraVertices[i].animIdx = m_data[idx]->animIdx;
+            ultraVertices[i].frameDuration = m_data[idx]->frameDuration;
+            ultraVertices[i].frameCount = m_data[idx]->frameCount;
+            ultraVertices[i].animT = m_data[idx]->animT;
+            ultraVertices[i].color.r = m_data[idx]->color.r;
+            ultraVertices[i].color.g = m_data[idx]->color.g;
+            ultraVertices[i].color.b = m_data[idx]->color.b;
+            ultraVertices[i].color.a = m_data[idx]->color.a;
+        }
+        break;
+    case Tabled://TODO: Us
+    case Deformable:
+    case Colored:
+    case Simple:
+        simpleVertices += idx*4;
+        for(int i=0; i<4; i++){
+            simpleVertices[i].x = m_data[idx]->x - m_systemOffset.x();
+            simpleVertices[i].y = m_data[idx]->y - m_systemOffset.y();
+            simpleVertices[i].t = m_data[idx]->t;
+            simpleVertices[i].lifeSpan = m_data[idx]->lifeSpan;
+            simpleVertices[i].size = m_data[idx]->size;
+            simpleVertices[i].endSize = m_data[idx]->endSize;
+            simpleVertices[i].sx = m_data[idx]->sx;
+            simpleVertices[i].sy = m_data[idx]->sy;
+            simpleVertices[i].ax = m_data[idx]->ax;
+            simpleVertices[i].ay = m_data[idx]->ay;
+        }
+        break;
+    default:
+        break;
     }
 
+    m_node->setFlag(QSGNode::OwnsGeometry, true);
 }
-*/
+
 
 
 QT_END_NAMESPACE
index a644dd4..dc79c59 100644 (file)
@@ -57,13 +57,6 @@ class QSGGeometryNode;
 class QSGSprite;
 class QSGSpriteEngine;
 
-struct Color4ub {
-    uchar r;
-    uchar g;
-    uchar b;
-    uchar a;
-};
-
 struct SimpleVertex {
     float x;
     float y;
@@ -165,8 +158,6 @@ public:
     explicit QSGImageParticle(QSGItem *parent = 0);
     virtual ~QSGImageParticle(){}
 
-    virtual void load(QSGParticleData*);
-    virtual void reload(QSGParticleData*);
 
     QDeclarativeListProperty<QSGSprite> sprites();
     QSGSpriteEngine* spriteEngine() {return m_spriteEngine;}
@@ -174,7 +165,7 @@ public:
     enum PerformanceLevel{//TODO: Expose?
         Unknown = 0,
         Simple,
-        Coloured,
+        Colored,
         Deformable,
         Tabled,
         Sprites
@@ -292,20 +283,19 @@ public slots:
     void setBloat(bool arg);
 
 protected:
-    QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
     void reset();
+    virtual void initialize(int idx);
+    virtual void reload(int idx);
+
+    QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
     void prepareNextFrame();
     QSGGeometryNode* buildParticleNode();
     QSGGeometryNode* buildSimpleParticleNode();
-    void resize(int oldCount, int newCount);
-    void performPendingResize();
 
 private slots:
     void createEngine(); //### method invoked by sprite list changing (in engine.h) - pretty nasty
 
 private:
-    //template <class T> void verticesUpgrade(IntermediateVertices* prev, T* next);//### Loses typessafety again...
-    IntermediateVertices* fetchIntermediateVertices(int pos);
     bool m_do_reset;
 
     QUrl m_image_name;
@@ -347,13 +337,6 @@ private:
     PerformanceLevel m_lastLevel;
     void* m_lastData;
     int m_lastCount;
-
-    //TODO: Some smart method that scales to multiple types better
-    bool m_resizePending;
-    QVector<UltraVertices*> m_resizePendingUltra;
-    QVector<SimpleVertices*> m_resizePendingSimple;
-    UltraVertices* m_defaultUltra;
-    SimpleVertices* m_defaultSimple;
 };
 
 QT_END_NAMESPACE
index 1c6a8c4..5e324cd 100644 (file)
@@ -85,12 +85,13 @@ void QSGItemParticle::give(QSGItem *item)
     //TODO: This
 }
 
-void QSGItemParticle::load(QSGParticleData* d)
+void QSGItemParticle::initialize(int idx)
+{
+    m_loadables << idx;//defer to other thread
+}
+
+void QSGItemParticle::reload(int idx)
 {
-    Q_ASSERT(d);
-    int pos = particleTypeIndex(d);
-    m_data[pos] = d;
-    m_loadables << pos;
 }
 
 void QSGItemParticle::tick()
@@ -107,56 +108,41 @@ void QSGItemParticle::tick()
     m_deletables.clear();
 
     foreach(int pos, m_loadables){
-        if(m_stasis.contains(m_items[pos]))
+        if(m_stasis.contains(m_data[pos]->delegate))
             qWarning() << "Current model particles prefers overwrite:false";
         //remove old item from the particle that is dying to make room for this one
-        if(m_items[pos]){
-            m_deletables << m_items[pos];
+        if(m_data[pos]->delegate){
+            m_deletables << m_data[pos]->delegate;
             m_activeCount--;
         }
-        m_items[pos] = 0;
+        m_data[pos]->delegate = 0;
         if(!m_pendingItems.isEmpty()){
-            m_items[pos] = m_pendingItems.front();
+            m_data[pos]->delegate = m_pendingItems.front();
             m_pendingItems.pop_front();
         }else if(m_delegate){
-            m_items[pos] = qobject_cast<QSGItem*>(m_delegate->create(qmlContext(this)));
+            m_data[pos]->delegate = qobject_cast<QSGItem*>(m_delegate->create(qmlContext(this)));
         }
-        if(m_items[pos] && m_data[pos]){//###Data can be zero if creating an item leads to a reset - this screws things up.
-            m_items[pos]->setX(m_data[pos]->curX() - m_items[pos]->width()/2);//TODO: adjust for system?
-            m_items[pos]->setY(m_data[pos]->curY() - m_items[pos]->height()/2);
-            QSGItemParticleAttached* mpa = qobject_cast<QSGItemParticleAttached*>(qmlAttachedPropertiesObject<QSGItemParticle>(m_items[pos]));
+        if(m_data[pos]->delegate && m_data[pos]){//###Data can be zero if creating an item leads to a reset - this screws things up.
+            m_data[pos]->delegate->setX(m_data[pos]->curX() - m_data[pos]->delegate->width()/2);//TODO: adjust for system?
+            m_data[pos]->delegate->setY(m_data[pos]->curY() - m_data[pos]->delegate->height()/2);
+            QSGItemParticleAttached* mpa = qobject_cast<QSGItemParticleAttached*>(qmlAttachedPropertiesObject<QSGItemParticle>(m_data[pos]->delegate));
             if(mpa){
                 mpa->m_mp = this;
                 mpa->attach();
             }
-            m_items[pos]->setParentItem(this);
+            m_data[pos]->delegate->setParentItem(this);
             if(m_fade)
-                m_items[pos]->setOpacity(0.);
+                m_data[pos]->delegate->setOpacity(0.);
             m_activeCount++;
         }
     }
     m_loadables.clear();
 }
 
-void QSGItemParticle::reload(QSGParticleData* d)
-{
-    //No-op unless we start copying the data.
-}
-
-void QSGItemParticle::resize(int oldCount, int newCount)
-{
-    if(!m_system)
-        return;
-    groupShuffle(m_items, (QSGItem*)0);
-    groupShuffle(m_data, (QSGParticleData*)0);
-}
-
 void QSGItemParticle::reset()
 {
     QSGParticlePainter::reset();
     //TODO: Cleanup items?
-    m_items.fill(0);
-    m_data.fill(0);
     m_loadables.clear();
     //deletables?
 }
@@ -188,19 +174,18 @@ void QSGItemParticle::prepareNextFrame()
 
     //TODO: Size, better fade?
     for(int i=0; i<count(); i++){
-        QSGItem* item = m_items[i];
         QSGParticleData* data = m_data[i];
-        if(!item || !data)
+        QSGItem* item = data->delegate;
+        if(!item)
             continue;
-        qreal t = ((timeStamp/1000.0) - data->pv.t) / data->pv.lifeSpan;
+        qreal t = ((timeStamp/1000.0) - data->t) / data->lifeSpan;
         if(m_stasis.contains(item)) {
-            m_data[i]->pv.t += dt;//Stasis effect
+            m_data[i]->t += dt;//Stasis effect
             continue;
         }
         if(t >= 1.0){//Usually happens from load
             m_deletables << item;
-            m_items[i] = 0;
-            m_data[i] = 0;
+            m_data[i]->delegate = 0;
             m_activeCount--;
         }else{//Fade
             if(m_fade){
@@ -214,8 +199,8 @@ void QSGItemParticle::prepareNextFrame()
                 item->setOpacity(1.);//###Without fade, it's just a binary toggle - if we turn it off we have to turn it back on
             }
         }
-        item->setX(data->curX() - item->width()/2);
-        item->setY(data->curY() - item->height()/2);
+        item->setX(data->curX() - item->width()/2 - m_systemOffset.x());
+        item->setY(data->curY() - item->height()/2 - m_systemOffset.y());
     }
 }
 
index 7cea63b..24bbcf9 100644 (file)
@@ -63,8 +63,6 @@ public:
     bool fade() const { return m_fade; }
 
     virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
-    virtual void load(QSGParticleData*);
-    virtual void reload(QSGParticleData*);
 
     static QSGItemParticleAttached *qmlAttachedProperties(QObject *object);
     QDeclarativeComponent* delegate() const
@@ -95,7 +93,8 @@ public slots:
 
 protected:
     virtual void reset();
-    virtual void resize(int oldCount, int newCount);
+    virtual void reload(int idx);
+    virtual void initialize(int idx);
     void prepareNextFrame();
 private slots:
     void tick();
@@ -105,9 +104,6 @@ private:
     bool m_fade;
 
     QList<QSGItem*> m_pendingItems;
-    QVector<QSGItem*> m_items;
-    QVector<QSGParticleData*> m_data;
-    QVector<int> m_idx;
     QList<int> m_available;
     QSet<QSGItem*> m_stasis;
     qreal m_lastT;
index 1321898..eb3a55d 100644 (file)
@@ -52,7 +52,7 @@ bool QSGKillAffector::affectParticle(QSGParticleData *d, qreal dt)
 {
     Q_UNUSED(dt);
     if(d->stillAlive()){
-        d->pv.t -= d->pv.lifeSpan + 1;
+        d->t -= d->lifeSpan + 1;
         return true;
     }
 }
index aba68c6..47b8844 100644 (file)
@@ -149,26 +149,13 @@ void QSGModelParticle::unfreeze(QSGItem* item)
     m_stasis.remove(item);
 }
 
-void QSGModelParticle::load(QSGParticleData* d)
+void QSGModelParticle::initialize(int idx)
 {
     if(!m_model || !m_model->count())
         return;
-    int pos = particleTypeIndex(d);
     if(m_available.isEmpty())
         return;
-    if(m_items[pos]){
-        if(m_stasis.contains(m_items[pos]))
-            qWarning() << "Current model particles prefers overwrite:false";
-        //remove old item from the particle that is dying to make room for this one
-        m_deletables << m_items[pos];
-        m_available << m_idx[pos];
-        m_idx[pos] = -1;
-        m_items[pos] = 0;
-        m_data[pos] = 0;
-        m_activeCount--;
-    }
-    m_requests << pos;
-    m_data[pos] = d;
+    m_requests << idx;
     m_activeCount++;
 }
 
@@ -181,40 +168,42 @@ void QSGModelParticle::processPending()
     m_deletables.clear();
 
     foreach(int pos, m_requests){
+        if(m_data[pos]->delegate){
+            if(m_stasis.contains(m_data[pos]->delegate))
+                qWarning() << "Current model particles prefers overwrite:false";
+            //remove old item from the particle that is dying to make room for this one
+            m_deletables << m_data[pos]->delegate;
+            m_available << m_data[pos]->modelIndex;
+            m_data[pos]->modelIndex = -1;
+            m_data[pos]->delegate = 0;
+            m_data[pos] = 0;
+            m_activeCount--;
+        }
+
         if(!m_available.isEmpty()){
-            m_items[pos] = m_model->item(m_available.first());
-            m_idx[pos] = m_available.first();
+            m_data[pos]->delegate = m_model->item(m_available.first());
+            m_data[pos]->modelIndex = m_available.first();
             m_available.pop_front();
-            QSGModelParticleAttached* mpa = qobject_cast<QSGModelParticleAttached*>(qmlAttachedPropertiesObject<QSGModelParticle>(m_items[pos]));
+            QSGModelParticleAttached* mpa = qobject_cast<QSGModelParticleAttached*>(qmlAttachedPropertiesObject<QSGModelParticle>(m_data[pos]->delegate));
             if(mpa){
                 mpa->m_mp = this;
                 mpa->attach();
             }
-            m_items[pos]->setParentItem(this);
+            m_data[pos]->delegate->setParentItem(this);
         }
     }
     m_requests.clear();
 }
 
-void QSGModelParticle::reload(QSGParticleData* d)
+void QSGModelParticle::reload(int idx)
 {
     //No-op unless we start copying the data.
 }
 
-void QSGModelParticle::resize(int oldCount, int newCount)
-{
-    groupShuffle(m_items, (QSGItem *) 0);
-    groupShuffle(m_data, (QSGParticleData*) 0);
-    groupShuffle(m_idx, -1);
-}
-
 void QSGModelParticle::reset()
 {
     QSGParticlePainter::reset();
     //TODO: Cleanup items?
-    m_items.fill(0);
-    m_data.fill(0);
-    m_idx.fill(-1);
     //m_available.clear();//Should this be reset too?
     //m_pendingItems.clear();//TODO: Should this be done? If so, Emit signal?
 }
@@ -246,20 +235,19 @@ void QSGModelParticle::prepareNextFrame()
 
     //TODO: Size, better fade?
     for(int i=0; i<count(); i++){
-        QSGItem* item = m_items[i];
         QSGParticleData* data = m_data[i];
-        if(!item || !data)
+        if(!data->delegate)
             continue;
-        qreal t = ((timeStamp/1000.0) - data->pv.t) / data->pv.lifeSpan;
-        if(m_stasis.contains(item)) {
-            m_data[i]->pv.t += dt;//Stasis effect
+        qreal t = ((timeStamp/1000.0) - data->t) / data->lifeSpan;
+        if(m_stasis.contains(m_data[i]->delegate)) {
+            m_data[i]->t += dt;//Stasis effect
             continue;
         }
         if(t >= 1.0){//Usually happens from load
-            m_available << m_idx[i];
-            m_deletables << item;
-            m_idx[i] = -1;
-            m_items[i] = 0;
+            m_available << m_data[i]->modelIndex;
+            m_deletables << m_data[i]->delegate;
+            m_data[i]->modelIndex = -1;
+            m_data[i]->delegate = 0;
             m_data[i] = 0;
             m_activeCount--;
         }else{//Fade
@@ -269,13 +257,13 @@ void QSGModelParticle::prepareNextFrame()
                     o = t*5;
                 if(t>0.8)
                     o = (1-t)*5;
-                item->setOpacity(o);
+                m_data[i]->delegate->setOpacity(o);
             }else{
-                item->setOpacity(1.);//###Without fade, it's just a binary toggle - if we turn it off we have to turn it back on
+                m_data[i]->delegate->setOpacity(1.);//###Without fade, it's just a binary toggle - if we turn it off we have to turn it back on
             }
         }
-        item->setX(data->curX() - item->width()/2);
-        item->setY(data->curY() - item->height()/2);
+        m_data[i]->delegate->setX(data->curX() - m_data[i]->delegate->width()/2  - m_systemOffset.x());
+        m_data[i]->delegate->setY(data->curY() - m_data[i]->delegate->height()/2 - m_systemOffset.y());
     }
 }
 
index cef2008..31e4025 100644 (file)
@@ -74,8 +74,6 @@ public:
     bool fade() const { return m_fade; }
 
     virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
-    virtual void load(QSGParticleData*);
-    virtual void reload(QSGParticleData*);
 
     static QSGModelParticleAttached *qmlAttachedProperties(QObject *object);
 signals:
@@ -91,7 +89,8 @@ public slots:
     void setFade(bool arg){if(arg == m_fade) return; m_fade = arg; emit fadeChanged();}
 protected:
     virtual void reset();
-    virtual void resize(int oldCount, int newCount);
+    virtual void reload(int idx);
+    virtual void initialize(int idx);
     void prepareNextFrame();
 private slots:
     void updateCount();
@@ -106,9 +105,6 @@ private:
     bool m_fade;
 
     QList<QSGItem*> m_pendingItems;
-    QVector<QSGItem*> m_items;
-    QVector<QSGParticleData*> m_data;
-    QVector<int> m_idx;
     QList<int> m_available;
     QSet<QSGItem*> m_stasis;
     qreal m_lastT;
index 0d369fd..cf1d3c2 100644 (file)
@@ -44,7 +44,7 @@
 QT_BEGIN_NAMESPACE
 QSGParticlePainter::QSGParticlePainter(QSGItem *parent) :
     QSGItem(parent),
-    m_system(0), m_count(0), m_lastStart(0)
+    m_system(0), m_count(0), m_lastStart(0), m_sentinel(new QSGParticleData)
 {
     connect(this, SIGNAL(xChanged()),
             this, SLOT(calcSystemOffset()));
@@ -78,23 +78,70 @@ void QSGParticlePainter::setSystem(QSGParticleSystem *arg)
     }
 }
 
-void QSGParticlePainter::load(QSGParticleData*)
+void QSGParticlePainter::load(QSGParticleData* d)
 {
+    int idx = particleTypeIndex(d);
+    m_data[idx] = d;
+    initialize(idx);
+    reload(idx);
 }
 
-void QSGParticlePainter::reload(QSGParticleData*)
+void QSGParticlePainter::reload(QSGParticleData* d)
 {
+    reload(particleTypeIndex(d));
 }
 
 void QSGParticlePainter::reset()
 {
     //Have to every time because what it's emitting may have changed and that affects particleTypeIndex
-    if(m_system)
-        updateParticleStarts();
+    if(m_system && !m_inResize)
+        resize(0,1);//###Fix this by making resize take sensible arguments
+    //###This also means double resets. Make reset not virtual?
 }
 
-void QSGParticlePainter::resize(int, int)
+void QSGParticlePainter::resize(int oldSize, int newSize)
 {
+    if(newSize == oldSize)//TODO: What if particles switched so indices change but total count is the same?
+        return;
+
+    QHash<int, QPair<int, int> > oldStarts(m_particleStarts);
+    //Update particle starts datastore
+    m_particleStarts.clear();
+    m_lastStart = 0;
+    QList<int> particleList;
+    if(m_particles.isEmpty())
+        particleList << 0;
+    foreach(const QString &s, m_particles)
+        particleList << m_system->m_groupIds[s];
+    foreach(int gIdx, particleList){
+        QSGParticleGroupData *gd = m_system->m_groupData[gIdx];
+        m_particleStarts.insert(gIdx, qMakePair<int, int>(gd->size, m_lastStart));
+        m_lastStart += gd->size;
+    }
+
+    //Shuffle stuff around
+    //TODO: In place shuffling because it's faster
+    QVector<QSGParticleData*> oldData(m_data);
+    QVector<QObject*> oldAttached(m_attachedData);
+    m_data.clear();
+    m_data.resize(m_count);
+    m_attachedData.resize(m_count);
+    foreach(int gIdx, particleList){
+        QSGParticleGroupData *gd = m_system->m_groupData[gIdx];
+        for(int i=0; i<gd->data.size(); i++){//TODO: When group didn't exist before
+            int newIdx = m_particleStarts[gIdx].second + i;
+            int oldIdx = oldStarts[gIdx].second + i;
+            if(i >= oldStarts[gIdx].first || oldData.size() <= oldIdx){
+                m_data[newIdx] = m_sentinel;
+            }else{
+                m_data[newIdx] = oldData[oldIdx];
+                m_attachedData[newIdx] = oldAttached[oldIdx];
+            }
+        }
+    }
+    m_inResize = true;
+    reset();
+    m_inResize = false;
 }
 
 
@@ -105,8 +152,7 @@ void QSGParticlePainter::setCount(int c)
         return;
     int lastCount = m_count;
     m_count = c;
-    resize(lastCount, m_count);//### is virtual needed? Or should I just use the signal?
-    updateParticleStarts();
+    resize(lastCount, m_count);
     emit countChanged();
 }
 
@@ -115,23 +161,6 @@ int QSGParticlePainter::count()
     return m_count;
 }
 
-
-void QSGParticlePainter::updateParticleStarts()
-{
-    m_particleStarts.clear();
-    m_lastStart = 0;
-    QList<int> particleList;
-    if(m_particles.isEmpty())
-        particleList << 0;
-    foreach(const QString &s, m_particles)
-        particleList << m_system->m_groupIds[s];
-    foreach(int gIdx, particleList){
-        QSGParticleGroupData *gd = m_system->m_groupData[gIdx];
-        m_particleStarts.insert(gIdx, qMakePair<int, int>(gd->size, m_lastStart));
-        m_lastStart += gd->size;
-    }
-}
-
 int QSGParticlePainter::particleTypeIndex(QSGParticleData* d)
 {
     Q_ASSERT(d && m_particleStarts.contains(d->group));//XXX
index 6657d57..e506018 100644 (file)
@@ -61,8 +61,9 @@ class QSGParticlePainter : public QSGItem
 
 public:
     explicit QSGParticlePainter(QSGItem *parent = 0);
-    virtual void load(QSGParticleData*);
-    virtual void reload(QSGParticleData*);
+    //Data Interface to system
+    void load(QSGParticleData*);
+    void reload(QSGParticleData*);
     void setCount(int c);
     int count();
     QSGParticleSystem* system() const
@@ -94,68 +95,38 @@ void setParticles(QStringList arg)
 }
 private slots:
     void calcSystemOffset();
-    void updateParticleStarts();
 
 protected:
+    /* Reset resets all your internal data structures. But anything attached to a particle should
+       be in attached data. So reset + reloads should have no visible effect.
+       ###Hunt down all cases where we do a complete reset for convenience and be more targeted
+    */
     virtual void reset();
-    virtual void componentComplete();
 
+    virtual void componentComplete();
+    //Data interface to painters
+    QVector<QSGParticleData*> m_data; //Actually stored in arbitrary order,
+    QVector<QObject*> m_attachedData; //This data will be moved along with m_data in resizes (but you own it)
+    virtual void initialize(int){}
+    virtual void reload(int){}//If you need to do something on size changed, check m_data size in this? Or we reset you every time?
 
     QSGParticleSystem* m_system;
     friend class QSGParticleSystem;
     int m_count;
     bool m_pleaseReset;
     QStringList m_particles;
-    QHash<int,QPair<int, int> > m_particleStarts; //Group, size, idx
-    int m_lastStart;
     QPointF m_systemOffset;
 
-    template <typename VertexStruct>//just convenience
-    void vertexCopy(VertexStruct &b, const ParticleVertex& a)
-    {
-        b.x = a.x - m_systemOffset.x();
-        b.y = a.y - m_systemOffset.y();
-        b.t = a.t;
-        b.lifeSpan = a.lifeSpan;
-        b.size = a.size;
-        b.endSize = a.endSize;
-        b.sx = a.sx;
-        b.sy = a.sy;
-        b.ax = a.ax;
-        b.ay = a.ay;
-    }
-
-    //###Abstracted primarily for code reuse. Demote to subclasses?
-    int particleTypeIndex(QSGParticleData*);
-    virtual void resize(int oldCount, int newCount);
-    template <typename T>
-    void groupShuffle(QVector<T> &v, const T& zero)//Must be called inside resize
-    {
-        //TODO: In place shuffling because it's faster
-        QVector<T> v0(v);
-        v.clear();
-        v.resize(m_count);
-        int lastStart = 0;
-        QList<int> particleList;
-        if(m_particles.isEmpty())
-            particleList << 0;
-        foreach(const QString &s, m_particles)
-            particleList << m_system->m_groupIds[s];
-
-        foreach(int gIdx, particleList){
-            QSGParticleGroupData *gd = m_system->m_groupData[gIdx];
-            for(int i=0; i<gd->data.size(); i++){//TODO: When group didn't exist before
-                int newIdx = lastStart + i;//Have to make the same way as in updateParticleStarts
-                if(i >= m_particleStarts[gIdx].first || v0.size() <= m_particleStarts[gIdx].second + i)
-                    v[newIdx] = zero;
-                else
-                    v[newIdx] = v0[m_particleStarts[gIdx].second + i];
-            }
-            lastStart += gd->size;
-        }
-    }
 
 private:
+    int m_lastStart;
+    QHash<int, QPair<int, int> > m_particleStarts;
+    int particleTypeIndex(QSGParticleData* d);//Now private
+    void resize(int, int);
+
+    QSGParticleData* m_sentinel;
+    //QVector<QSGParticleData*> m_shadowData;//For when we implement overwrite: false
+    bool m_inResize;
 };
 
 QT_END_NAMESPACE
index a93f2a5..2dc2129 100644 (file)
@@ -54,15 +54,33 @@ QSGParticleData::QSGParticleData()
     , e(0)
     , index(0)
 {
-    pv.x = 0;
-    pv.y = 0;
-    pv.t = -1;
-    pv.size = 0;
-    pv.endSize = 0;
-    pv.sx = 0;
-    pv.sy = 0;
-    pv.ax = 0;
-    pv.ay = 0;
+    x = 0;
+    y = 0;
+    t = -1;
+    size = 0;
+    endSize = 0;
+    sx = 0;
+    sy = 0;
+    ax = 0;
+    ay = 0;
+    xx = 1;
+    xy = 0;
+    yx = 0;
+    yy = 1;
+    rotation = 0;
+    rotationSpeed = 0;
+    autoRotate = 0;
+    animIdx = -1;
+    frameDuration = 1;
+    frameCount = 0;
+    animT = -1;
+    color.r = 255;
+    color.g = 255;
+    color.b = 255;
+    color.a = 255;
+    r = 0;
+    delegate = 0;
+    modelIndex = -1;
 }
 
 QSGParticleSystem::QSGParticleSystem(QSGItem *parent) :
@@ -275,8 +293,8 @@ void QSGParticleSystem::emitParticle(QSGParticleData* pd)
     //Account for relative emitter position
     QPointF offset = this->mapFromItem(pd->e, QPointF(0, 0));
     if(!offset.isNull()){
-        pd->pv.x += offset.x();
-        pd->pv.y += offset.y();
+        pd->x += offset.x();
+        pd->y += offset.y();
     }
 
     foreach(QSGParticleAffector *a, m_affectors)
@@ -323,107 +341,107 @@ qint64 QSGParticleSystem::systemSync(QSGParticlePainter* p)
 //sets the x accleration without affecting the instantaneous x velocity or position
 void QSGParticleData::setInstantaneousAX(qreal ax)
 {
-    qreal t = (system->m_timeInt / 1000.0) - pv.t;
-    qreal sx = (pv.sx + t*pv.ax) - t*ax;
-    qreal ex = pv.x + pv.sx * t + 0.5 * pv.ax * t * t;
+    qreal t = (system->m_timeInt / 1000.0) - this->t;
+    qreal sx = (this->sx + t*this->ax) - t*ax;
+    qreal ex = this->x + this->sx * t + 0.5 * this->ax * t * t;
     qreal x = ex - t*sx - 0.5 * t*t*ax;
 
-    pv.ax = ax;
-    pv.sx = sx;
-    pv.x = x;
+    this->ax = ax;
+    this->sx = sx;
+    this->x = x;
 }
 
 //sets the x velocity without affecting the instantaneous x postion
 void QSGParticleData::setInstantaneousSX(qreal vx)
 {
-    qreal t = (system->m_timeInt / 1000.0) - pv.t;
-    qreal sx = vx - t*pv.ax;
-    qreal ex = pv.x + pv.sx * t + 0.5 * pv.ax * t * t;
-    qreal x = ex - t*sx - 0.5 * t*t*pv.ax;
+    qreal t = (system->m_timeInt / 1000.0) - this->t;
+    qreal sx = vx - t*this->ax;
+    qreal ex = this->x + this->sx * t + 0.5 * this->ax * t * t;
+    qreal x = ex - t*sx - 0.5 * t*t*this->ax;
 
-    pv.sx = sx;
-    pv.x = x;
+    this->sx = sx;
+    this->x = x;
 }
 
 //sets the instantaneous x postion
 void QSGParticleData::setInstantaneousX(qreal x)
 {
-    qreal t = (system->m_timeInt / 1000.0) - pv.t;
-    pv.x = x - t*pv.sx - 0.5 * t*t*pv.ax;
+    qreal t = (system->m_timeInt / 1000.0) - this->t;
+    this->x = x - t*this->sx - 0.5 * t*t*this->ax;
 }
 
 //sets the y accleration without affecting the instantaneous y velocity or position
 void QSGParticleData::setInstantaneousAY(qreal ay)
 {
-    qreal t = (system->m_timeInt / 1000.0) - pv.t;
-    qreal sy = (pv.sy + t*pv.ay) - t*ay;
-    qreal ey = pv.y + pv.sy * t + 0.5 * pv.ay * t * t;
+    qreal t = (system->m_timeInt / 1000.0) - this->t;
+    qreal sy = (this->sy + t*this->ay) - t*ay;
+    qreal ey = this->y + this->sy * t + 0.5 * this->ay * t * t;
     qreal y = ey - t*sy - 0.5 * t*t*ay;
 
-    pv.ay = ay;
-    pv.sy = sy;
-    pv.y = y;
+    this->ay = ay;
+    this->sy = sy;
+    this->y = y;
 }
 
 //sets the y velocity without affecting the instantaneous y position
 void QSGParticleData::setInstantaneousSY(qreal vy)
 {
-    qreal t = (system->m_timeInt / 1000.0) - pv.t;
-    //qDebug() << t << (system->m_timeInt/1000.0) << pv.x << pv.sx << pv.ax << pv.x + pv.sx * t + 0.5 * pv.ax * t * t;
-    qreal sy = vy - t*pv.ay;
-    qreal ey = pv.y + pv.sy * t + 0.5 * pv.ay * t * t;
-    qreal y = ey - t*sy - 0.5 * t*t*pv.ay;
-
-    pv.sy = sy;
-    pv.y = y;
+    qreal t = (system->m_timeInt / 1000.0) - this->t;
+    //qDebug() << t << (system->m_timeInt/1000.0) << this->x << this->sx << this->ax << this->x + this->sx * t + 0.5 * this->ax * t * t;
+    qreal sy = vy - t*this->ay;
+    qreal ey = this->y + this->sy * t + 0.5 * this->ay * t * t;
+    qreal y = ey - t*sy - 0.5 * t*t*this->ay;
+
+    this->sy = sy;
+    this->y = y;
 }
 
 //sets the instantaneous Y position
 void QSGParticleData::setInstantaneousY(qreal y)
 {
-    qreal t = (system->m_timeInt / 1000.0) - pv.t;
-    pv.y = y - t*pv.sy - 0.5 * t*t*pv.ay;
+    qreal t = (system->m_timeInt / 1000.0) - this->t;
+    this->y = y - t*this->sy - 0.5 * t*t*this->ay;
 }
 
 qreal QSGParticleData::curX() const
 {
-    qreal t = (system->m_timeInt / 1000.0) - pv.t;
-    return pv.x + pv.sx * t + 0.5 * pv.ax * t * t;
+    qreal t = (system->m_timeInt / 1000.0) - this->t;
+    return this->x + this->sx * t + 0.5 * this->ax * t * t;
 }
 
 qreal QSGParticleData::curSX() const
 {
-    qreal t = (system->m_timeInt / 1000.0) - pv.t;
-    return pv.sx + t*pv.ax;
+    qreal t = (system->m_timeInt / 1000.0) - this->t;
+    return this->sx + t*this->ax;
 }
 
 qreal QSGParticleData::curY() const
 {
-    qreal t = (system->m_timeInt / 1000.0) - pv.t;
-    return pv.y + pv.sy * t + 0.5 * pv.ay * t * t;
+    qreal t = (system->m_timeInt / 1000.0) - this->t;
+    return y + sy * t + 0.5 * ay * t * t;
 }
 
 qreal QSGParticleData::curSY() const
 {
-    qreal t = (system->m_timeInt / 1000.0) - pv.t;
-    return pv.sy + t*pv.ay;
+    qreal t = (system->m_timeInt / 1000.0) - this->t;
+    return sy + t*ay;
 }
 
 void QSGParticleData::debugDump()
 {
     qDebug() << "Particle" << group
-             << "Pos: " << pv.x << "," << pv.y
-             << "Vel: " << pv.sx << "," << pv.sy
-             << "Acc: " << pv.ax << "," << pv.ay
-             << "Size: " << pv.size << "," << pv.endSize
-             << "Time: " << pv.t << "," <<pv.lifeSpan;
+             << "Pos: " << x << "," << y
+             << "Vel: " << sx << "," << sy
+             << "Acc: " << ax << "," << ay
+             << "Size: " << size << "," << endSize
+             << "Time: " << t << "," <<lifeSpan;
 }
 
 bool QSGParticleData::stillAlive()
 {
     if(!system)
         return false;
-    return (pv.t + pv.lifeSpan) > (system->m_timeInt/1000.0);
+    return (t + lifeSpan) > (system->m_timeInt/1000.0);
 }
 
 QT_END_NAMESPACE
index 4c690ff..45b4e16 100644 (file)
@@ -173,28 +173,18 @@ private:
     QSignalMapper m_emitterMapper;
 };
 
-//TODO: Clean up all this into ParticleData
-
-struct ParticleVertex {
-    float x;
-    float y;
-    float t;
-    float lifeSpan;
-    float size;
-    float endSize;
-    float sx;
-    float sy;
-    float ax;
-    float ay;
-    //TODO: Need opacity over life control. More variable size over life?
+struct Color4ub {
+    uchar r;
+    uchar g;
+    uchar b;
+    uchar a;
 };
 
 class QSGParticleData{
 public:
+    //TODO: QObject like memory management (without the cost, just attached to system)
     QSGParticleData();
 
-    ParticleVertex pv;
-
     //Convenience functions for working backwards, because parameters are from the start of particle life
     //If setting multiple parameters at once, doing the conversion yourself will be faster.
 
@@ -222,6 +212,35 @@ public:
     QSGParticleSystem* system;
     int index;
 
+    //General Position Stuff
+    float x;
+    float y;
+    float t;
+    float lifeSpan;
+    float size;
+    float endSize;
+    float sx;
+    float sy;
+    float ax;
+    float ay;
+
+    //Other stuff, now universally shared
+    Color4ub color;
+    float xx;
+    float xy;
+    float yx;
+    float yy;
+    float rotation;
+    float rotationSpeed;
+    float autoRotate;//Assume that GPUs prefer floats to bools
+    float animIdx;
+    float frameDuration;
+    float frameCount;
+    float animT;
+    float r;
+    QSGItem* delegate;
+    int modelIndex;
+
     void debugDump();
     bool stillAlive();
 };
index 4c67523..0ee2fa4 100644 (file)
@@ -70,17 +70,17 @@ bool QSGPointAttractorAffector::affectParticle(QSGParticleData *d, qreal dt)
     dy = ds * sin(theta);
     switch(m_physics){
     case Position:
-        d->pv.x = (d->pv.x + dx);
-        d->pv.y = (d->pv.y + dy);
+        d->x = (d->x + dx);
+        d->y = (d->y + dy);
         break;
     case Acceleration:
-        d->setInstantaneousAX(d->pv.ax + dx);
-        d->setInstantaneousAY(d->pv.ay + dy);
+        d->setInstantaneousAX(d->ax + dx);
+        d->setInstantaneousAY(d->ay + dy);
         break;
     case Velocity: //also default
     default:
-        d->setInstantaneousSX(d->pv.sx + dx);
-        d->setInstantaneousSY(d->pv.sy + dy);
+        d->setInstantaneousSX(d->sx + dx);
+        d->setInstantaneousSY(d->sy + dy);
     }
 
     return true;
index 6e56d6a..26bea4e 100644 (file)
@@ -116,10 +116,10 @@ bool QSGWanderAffector::affectParticle(QSGParticleData* data, qreal dt)
     case Position:
         newX = data->curX() + dx;
         if(m_xVariance > qAbs(newX) )
-            data->pv.x += dx;
+            data->x += dx;
         newY = data->curY() + dy;
         if(m_yVariance > qAbs(newY) )
-            data->pv.y += dy;
+            data->y += dy;
         break;
     default:
     case Velocity:
@@ -131,10 +131,10 @@ bool QSGWanderAffector::affectParticle(QSGParticleData* data, qreal dt)
             data->setInstantaneousSY(newY);
         break;
     case Acceleration:
-        newX = data->pv.ax + dx;
+        newX = data->ax + dx;
         if(m_xVariance > qAbs(newX) )
             data->setInstantaneousAX(newX);
-        newY = data->pv.ay + dy;
+        newY = data->ay + dy;
         if(m_yVariance > qAbs(newY) )
             data->setInstantaneousAY(newY);
         break;