aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Alpert <alan.alpert@nokia.com>2011-06-21 12:02:08 +1000
committerAlan Alpert <alan.alpert@nokia.com>2011-06-21 12:02:08 +1000
commitf0ab52c313076fce7e854fd494b88c5dd0f71af5 (patch)
tree5e1ccd832abe0eae761c69627fd20a039ffd362c
parent7126b27f5dfeba005cc7f17610bcc09cf0003b52 (diff)
Rewrite last rewrite
Also rewrite to have all particle state shared, not just common elements.
-rw-r--r--src/declarative/particles/qsgcustomparticle.cpp118
-rw-r--r--src/declarative/particles/qsgcustomparticle_p.h8
-rw-r--r--src/declarative/particles/qsgemitter.cpp21
-rw-r--r--src/declarative/particles/qsgfollowemitter.cpp37
-rw-r--r--src/declarative/particles/qsggravity.cpp4
-rw-r--r--src/declarative/particles/qsgimageparticle.cpp410
-rw-r--r--src/declarative/particles/qsgimageparticle_p.h27
-rw-r--r--src/declarative/particles/qsgitemparticle.cpp65
-rw-r--r--src/declarative/particles/qsgitemparticle_p.h8
-rw-r--r--src/declarative/particles/qsgkill.cpp2
-rw-r--r--src/declarative/particles/qsgmodelparticle.cpp74
-rw-r--r--src/declarative/particles/qsgmodelparticle_p.h8
-rw-r--r--src/declarative/particles/qsgparticlepainter.cpp79
-rw-r--r--src/declarative/particles/qsgparticlepainter_p.h71
-rw-r--r--src/declarative/particles/qsgparticlesystem.cpp128
-rw-r--r--src/declarative/particles/qsgparticlesystem_p.h51
-rw-r--r--src/declarative/particles/qsgpointattractor.cpp12
-rw-r--r--src/declarative/particles/qsgwander.cpp8
18 files changed, 459 insertions, 672 deletions
diff --git a/src/declarative/particles/qsgcustomparticle.cpp b/src/declarative/particles/qsgcustomparticle.cpp
index f91307ed5c..09cfdda143 100644
--- a/src/declarative/particles/qsgcustomparticle.cpp
+++ b/src/declarative/particles/qsgcustomparticle.cpp
@@ -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
diff --git a/src/declarative/particles/qsgcustomparticle_p.h b/src/declarative/particles/qsgcustomparticle_p.h
index 863da052f3..50ff37a2a0 100644
--- a/src/declarative/particles/qsgcustomparticle_p.h
+++ b/src/declarative/particles/qsgcustomparticle_p.h
@@ -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
diff --git a/src/declarative/particles/qsgemitter.cpp b/src/declarative/particles/qsgemitter.cpp
index 081dd8dec5..c3ec3ffc9e 100644
--- a/src/declarative/particles/qsgemitter.cpp
+++ b/src/declarative/particles/qsgemitter.cpp
@@ -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);
}
diff --git a/src/declarative/particles/qsgfollowemitter.cpp b/src/declarative/particles/qsgfollowemitter.cpp
index 28a082f776..ba31e8f834 100644
--- a/src/declarative/particles/qsgfollowemitter.cpp
+++ b/src/declarative/particles/qsgfollowemitter.cpp
@@ -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);
}
diff --git a/src/declarative/particles/qsggravity.cpp b/src/declarative/particles/qsggravity.cpp
index de735da5ad..b1cf3e9481 100644
--- a/src/declarative/particles/qsggravity.cpp
+++ b/src/declarative/particles/qsggravity.cpp
@@ -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;
}
diff --git a/src/declarative/particles/qsgimageparticle.cpp b/src/declarative/particles/qsgimageparticle.cpp
index 15bc88b4c3..836236c13e 100644
--- a/src/declarative/particles/qsgimageparticle.cpp
+++ b/src/declarative/particles/qsgimageparticle.cpp
@@ -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
diff --git a/src/declarative/particles/qsgimageparticle_p.h b/src/declarative/particles/qsgimageparticle_p.h
index a644dd4216..dc79c5910e 100644
--- a/src/declarative/particles/qsgimageparticle_p.h
+++ b/src/declarative/particles/qsgimageparticle_p.h
@@ -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
diff --git a/src/declarative/particles/qsgitemparticle.cpp b/src/declarative/particles/qsgitemparticle.cpp
index 1c6a8c4db5..5e324cd43d 100644
--- a/src/declarative/particles/qsgitemparticle.cpp
+++ b/src/declarative/particles/qsgitemparticle.cpp
@@ -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());
}
}
diff --git a/src/declarative/particles/qsgitemparticle_p.h b/src/declarative/particles/qsgitemparticle_p.h
index 7cea63baa1..24bbcf97d8 100644
--- a/src/declarative/particles/qsgitemparticle_p.h
+++ b/src/declarative/particles/qsgitemparticle_p.h
@@ -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;
diff --git a/src/declarative/particles/qsgkill.cpp b/src/declarative/particles/qsgkill.cpp
index 1321898dc9..eb3a55d402 100644
--- a/src/declarative/particles/qsgkill.cpp
+++ b/src/declarative/particles/qsgkill.cpp
@@ -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;
}
}
diff --git a/src/declarative/particles/qsgmodelparticle.cpp b/src/declarative/particles/qsgmodelparticle.cpp
index aba68c6ce4..47b8844ad5 100644
--- a/src/declarative/particles/qsgmodelparticle.cpp
+++ b/src/declarative/particles/qsgmodelparticle.cpp
@@ -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());
}
}
diff --git a/src/declarative/particles/qsgmodelparticle_p.h b/src/declarative/particles/qsgmodelparticle_p.h
index cef2008b1a..31e4025bb4 100644
--- a/src/declarative/particles/qsgmodelparticle_p.h
+++ b/src/declarative/particles/qsgmodelparticle_p.h
@@ -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;
diff --git a/src/declarative/particles/qsgparticlepainter.cpp b/src/declarative/particles/qsgparticlepainter.cpp
index 0d369fd4d8..cf1d3c2894 100644
--- a/src/declarative/particles/qsgparticlepainter.cpp
+++ b/src/declarative/particles/qsgparticlepainter.cpp
@@ -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
diff --git a/src/declarative/particles/qsgparticlepainter_p.h b/src/declarative/particles/qsgparticlepainter_p.h
index 6657d57501..e506018f53 100644
--- a/src/declarative/particles/qsgparticlepainter_p.h
+++ b/src/declarative/particles/qsgparticlepainter_p.h
@@ -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
diff --git a/src/declarative/particles/qsgparticlesystem.cpp b/src/declarative/particles/qsgparticlesystem.cpp
index a93f2a5eba..2dc21299cf 100644
--- a/src/declarative/particles/qsgparticlesystem.cpp
+++ b/src/declarative/particles/qsgparticlesystem.cpp
@@ -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
diff --git a/src/declarative/particles/qsgparticlesystem_p.h b/src/declarative/particles/qsgparticlesystem_p.h
index 4c690ff7a8..45b4e164f1 100644
--- a/src/declarative/particles/qsgparticlesystem_p.h
+++ b/src/declarative/particles/qsgparticlesystem_p.h
@@ -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();
};
diff --git a/src/declarative/particles/qsgpointattractor.cpp b/src/declarative/particles/qsgpointattractor.cpp
index 4c675237ba..0ee2fa4c27 100644
--- a/src/declarative/particles/qsgpointattractor.cpp
+++ b/src/declarative/particles/qsgpointattractor.cpp
@@ -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;
diff --git a/src/declarative/particles/qsgwander.cpp b/src/declarative/particles/qsgwander.cpp
index 6e56d6a05b..26bea4ee04 100644
--- a/src/declarative/particles/qsgwander.cpp
+++ b/src/declarative/particles/qsgwander.cpp
@@ -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;