From 350a74ec69b535df07ad7ca45415090749c75293 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Tue, 8 Mar 2016 10:13:15 +0100 Subject: Particles: Shrink QQuickParticleData by 2 pointers. Samegame creates about 23,000 particles, so this reduces the memory by ~180kb on 32bit, so ~360kb on 64bit. Change-Id: I0581524ab232b474c5d43abeabd7ebf6174e740f Reviewed-by: Lars Knoll --- src/particles/qquickage.cpp | 22 +++--- src/particles/qquickcustomaffector.cpp | 22 +++--- src/particles/qquickfriction.cpp | 8 +-- src/particles/qquickgravity.cpp | 4 +- src/particles/qquickimageparticle.cpp | 10 +-- src/particles/qquickitemparticle.cpp | 10 +-- src/particles/qquickparticleaffector.cpp | 32 ++++----- src/particles/qquickparticleemitter.cpp | 5 +- src/particles/qquickparticlepainter.cpp | 6 +- src/particles/qquickparticlesystem.cpp | 114 +++++++++++++++---------------- src/particles/qquickparticlesystem_p.h | 50 +++++++------- src/particles/qquickpointattractor.cpp | 16 ++--- src/particles/qquickspritegoal.cpp | 2 +- src/particles/qquicktrailemitter.cpp | 19 +++--- src/particles/qquickturbulence.cpp | 6 +- src/particles/qquickv4particledata.cpp | 16 +++-- src/particles/qquickv4particledata_p.h | 3 +- src/particles/qquickwander.cpp | 24 +++---- 18 files changed, 183 insertions(+), 186 deletions(-) (limited to 'src/particles') diff --git a/src/particles/qquickage.cpp b/src/particles/qquickage.cpp index 9867e7e0ed..e1eb714623 100644 --- a/src/particles/qquickage.cpp +++ b/src/particles/qquickage.cpp @@ -88,23 +88,23 @@ QQuickAgeAffector::QQuickAgeAffector(QQuickItem *parent) : bool QQuickAgeAffector::affectParticle(QQuickParticleData *d, qreal dt) { Q_UNUSED(dt); - if (d->stillAlive()){ + if (d->stillAlive(m_system)){ qreal curT = (qreal)m_system->timeInt/1000.0; qreal ttl = (qreal)m_lifeLeft/1000.0; if (!m_advancePosition && ttl > 0){ - qreal x = d->curX(); - qreal vx = d->curVX(); + qreal x = d->curX(m_system); + qreal vx = d->curVX(m_system); qreal ax = d->curAX(); - qreal y = d->curY(); - qreal vy = d->curVY(); + qreal y = d->curY(m_system); + qreal vy = d->curVY(m_system); qreal ay = d->curAY(); d->t = curT - (d->lifeSpan - ttl); - d->setInstantaneousX(x); - d->setInstantaneousVX(vx); - d->setInstantaneousAX(ax); - d->setInstantaneousY(y); - d->setInstantaneousVY(vy); - d->setInstantaneousAY(ay); + d->setInstantaneousX(x, m_system); + d->setInstantaneousVX(vx, m_system); + d->setInstantaneousAX(ax, m_system); + d->setInstantaneousY(y, m_system); + d->setInstantaneousVY(vy, m_system); + d->setInstantaneousAY(ay, m_system); } else { d->t = curT - (d->lifeSpan - ttl); } diff --git a/src/particles/qquickcustomaffector.cpp b/src/particles/qquickcustomaffector.cpp index 6f50c17287..b95810bb62 100644 --- a/src/particles/qquickcustomaffector.cpp +++ b/src/particles/qquickcustomaffector.cpp @@ -138,8 +138,8 @@ void QQuickCustomAffector::affectSystem(qreal dt) if (justAffected) { foreach (QQuickParticleData* d, toAffect) {//Not postAffect to avoid saying the particle changed if (m_onceOff) - m_onceOffed << qMakePair(d->group, d->index); - emit affected(d->curX(), d->curY()); + m_onceOffed << qMakePair(d->groupId, d->index); + emit affected(d->curX(m_system), d->curY(m_system)); } return; } @@ -154,7 +154,7 @@ void QQuickCustomAffector::affectSystem(qreal dt) QV4::ScopedArrayObject array(scope, v4->newArrayObject(toAffect.size())); QV4::ScopedValue v(scope); for (int i=0; iputIndexed(i, (v = toAffect[i]->v4Value())); + array->putIndexed(i, (v = toAffect[i]->v4Value(m_system))); if (dt >= simulationCutoff || dt <= simulationDelta) { affectProperties(toAffect, dt); @@ -184,7 +184,7 @@ bool QQuickCustomAffector::affectParticle(QQuickParticleData *d, qreal dt) { //This does the property based affecting, called by superclass if signal isn't hooked up. bool changed = false; - QPointF curPos(d->curX(), d->curY()); + QPointF curPos(d->curX(m_system), d->curY(m_system)); if (m_acceleration != &m_nullVector){ QPointF pos = m_acceleration->sample(curPos); @@ -194,22 +194,22 @@ bool QQuickCustomAffector::affectParticle(QQuickParticleData *d, qreal dt) pos += curAcc; } if (pos != curAcc) { - d->setInstantaneousAX(pos.x()); - d->setInstantaneousAY(pos.y()); + d->setInstantaneousAX(pos.x(), m_system); + d->setInstantaneousAY(pos.y(), m_system); changed = true; } } if (m_velocity != &m_nullVector){ QPointF pos = m_velocity->sample(curPos); - QPointF curVel = QPointF(d->curVX(), d->curVY()); + QPointF curVel = QPointF(d->curVX(m_system), d->curVY(m_system)); if (m_relative) { pos *= dt; pos += curVel; } if (pos != curVel) { - d->setInstantaneousVX(pos.x()); - d->setInstantaneousVY(pos.y()); + d->setInstantaneousVX(pos.x(), m_system); + d->setInstantaneousVY(pos.y(), m_system); changed = true; } } @@ -221,8 +221,8 @@ bool QQuickCustomAffector::affectParticle(QQuickParticleData *d, qreal dt) pos += curPos; } if (pos != curPos) { - d->setInstantaneousX(pos.x()); - d->setInstantaneousY(pos.y()); + d->setInstantaneousX(pos.x(), m_system); + d->setInstantaneousY(pos.y(), m_system); changed = true; } } diff --git a/src/particles/qquickfriction.cpp b/src/particles/qquickfriction.cpp index f234bc27ad..401f4cd8c9 100644 --- a/src/particles/qquickfriction.cpp +++ b/src/particles/qquickfriction.cpp @@ -80,8 +80,8 @@ bool QQuickFrictionAffector::affectParticle(QQuickParticleData *d, qreal dt) { if (!m_factor) return false; - qreal curVX = d->curVX(); - qreal curVY = d->curVY(); + qreal curVX = d->curVX(m_system); + qreal curVY = d->curVY(m_system); if (!curVX && !curVY) return false; qreal newVX = curVX + (curVX * m_factor * -1 * dt); @@ -106,8 +106,8 @@ bool QQuickFrictionAffector::affectParticle(QQuickParticleData *d, qreal dt) } } - d->setInstantaneousVX(newVX); - d->setInstantaneousVY(newVY); + d->setInstantaneousVX(newVX, m_system); + d->setInstantaneousVY(newVY, m_system); return true; } QT_END_NAMESPACE diff --git a/src/particles/qquickgravity.cpp b/src/particles/qquickgravity.cpp index 54a03ac4bd..90f305f336 100644 --- a/src/particles/qquickgravity.cpp +++ b/src/particles/qquickgravity.cpp @@ -90,8 +90,8 @@ bool QQuickGravityAffector::affectParticle(QQuickParticleData *d, qreal dt) m_dy = m_magnitude * std::sin(m_angle * CONV); } - d->setInstantaneousVX(d->curVX() + m_dx*dt); - d->setInstantaneousVY(d->curVY() + m_dy*dt); + d->setInstantaneousVX(d->curVX(m_system) + m_dx*dt, m_system); + d->setInstantaneousVY(d->curVY(m_system) + m_dy*dt, m_system); return true; } QT_END_NAMESPACE diff --git a/src/particles/qquickimageparticle.cpp b/src/particles/qquickimageparticle.cpp index 5f2d1db663..07cbee1383 100644 --- a/src/particles/qquickimageparticle.cpp +++ b/src/particles/qquickimageparticle.cpp @@ -1168,21 +1168,21 @@ QQuickParticleData* QQuickImageParticle::getShadowDatum(QQuickParticleData* datu //Will return datum if the datum is a sentinel or uninitialized, to centralize that one check if (datum->systemIndex == -1) return datum; - QQuickParticleGroupData* gd = m_system->groupData[datum->group]; - if (!m_shadowData.contains(datum->group)) { + QQuickParticleGroupData* gd = m_system->groupData[datum->groupId]; + if (!m_shadowData.contains(datum->groupId)) { QVector data; const int gdSize = gd->size(); data.reserve(gdSize); for (int i = 0; i < gdSize; i++) { - QQuickParticleData* datum = new QQuickParticleData(m_system); + QQuickParticleData* datum = new QQuickParticleData; *datum = *(gd->data[i]); data << datum; } - m_shadowData.insert(datum->group, data); + m_shadowData.insert(datum->groupId, data); } //### If dynamic resize is added, remember to potentially resize the shadow data on out-of-bounds access request - return m_shadowData[datum->group][datum->index]; + return m_shadowData[datum->groupId][datum->index]; } bool QQuickImageParticle::loadingSomething() diff --git a/src/particles/qquickitemparticle.cpp b/src/particles/qquickitemparticle.cpp index ba6c6f915d..15cf19181e 100644 --- a/src/particles/qquickitemparticle.cpp +++ b/src/particles/qquickitemparticle.cpp @@ -206,8 +206,8 @@ void QQuickItemParticle::tick(int time) m_managed << d->delegate; } if (d && d->delegate){//###Data can be zero if creating an item leads to a reset - this screws things up. - d->delegate->setX(d->curX() - d->delegate->width()/2);//TODO: adjust for system? - d->delegate->setY(d->curY() - d->delegate->height()/2); + d->delegate->setX(d->curX(m_system) - d->delegate->width() / 2); //TODO: adjust for system? + d->delegate->setY(d->curY(m_system) - d->delegate->height() / 2); QQuickItemParticleAttached* mpa = qobject_cast(qmlAttachedPropertiesObject(d->delegate)); if (mpa){ mpa->m_mp = this; @@ -251,7 +251,7 @@ QSGNode* QQuickItemParticle::updatePaintNode(QSGNode* n, UpdatePaintNodeData* d) //### Constant resetting might lead to m_loadables never being populated when tick() occurs for (auto groupId : groupIds()) { for (QQuickParticleData* d : qAsConst(m_system->groupData[groupId]->data)) { - if (!d->delegate && d->t != -1 && d->stillAlive()) { + if (!d->delegate && d->t != -1 && d->stillAlive(m_system)) { m_loadables << d; } } @@ -301,8 +301,8 @@ void QQuickItemParticle::prepareNextFrame() item->setOpacity(o); } } - item->setX(data->curX() - item->width()/2 - m_systemOffset.x()); - item->setY(data->curY() - item->height()/2 - m_systemOffset.y()); + item->setX(data->curX(m_system) - item->width() / 2 - m_systemOffset.x()); + item->setY(data->curY(m_system) - item->height() / 2 - m_systemOffset.y()); } } } diff --git a/src/particles/qquickparticleaffector.cpp b/src/particles/qquickparticleaffector.cpp index 1878908a5d..6ed0d9e14a 100644 --- a/src/particles/qquickparticleaffector.cpp +++ b/src/particles/qquickparticleaffector.cpp @@ -162,13 +162,13 @@ bool QQuickParticleAffector::shouldAffect(QQuickParticleData* d) { if (!d) return false; - if (activeGroup(d->group)){ - if ((m_onceOff && m_onceOffed.contains(qMakePair(d->group, d->index))) - || !d->stillAlive()) + if (activeGroup(d->groupId)){ + if ((m_onceOff && m_onceOffed.contains(qMakePair(d->groupId, d->index))) + || !d->stillAlive(m_system)) return false; //Need to have previous location for affected anyways if (width() == 0 || height() == 0 - || m_shape->contains(QRectF(m_offset.x(), m_offset.y(), width(), height()), QPointF(d->curX(), d->curY()))){ + || m_shape->contains(QRectF(m_offset.x(), m_offset.y(), width(), height()), QPointF(d->curX(m_system), d->curY(m_system)))){ if (m_whenCollidingWith.isEmpty() || isColliding(d)){ return true; } @@ -182,9 +182,9 @@ void QQuickParticleAffector::postAffect(QQuickParticleData* d) { m_system->needsReset << d; if (m_onceOff) - m_onceOffed << qMakePair(d->group, d->index); + m_onceOffed << qMakePair(d->groupId, d->index); if (isAffectedConnected()) - emit affected(d->curX(), d->curY()); + emit affected(d->curX(m_system), d->curY(m_system)); } const qreal QQuickParticleAffector::simulationDelta = 0.020; @@ -210,7 +210,7 @@ void QQuickParticleAffector::affectSystem(qreal dt) m_system->timeInt -= myDt * 1000.0; while (myDt > simulationDelta) { m_system->timeInt += simulationDelta * 1000.0; - if (d->alive())//Only affect during the parts it was alive for + if (d->alive(m_system))//Only affect during the parts it was alive for affected = affectParticle(d, simulationDelta) || affected; myDt -= simulationDelta; } @@ -234,8 +234,8 @@ bool QQuickParticleAffector::affectParticle(QQuickParticleData *, qreal ) void QQuickParticleAffector::reset(QQuickParticleData* pd) {//TODO: This, among other ones, should be restructured so they don't all need to remember to call the superclass if (m_onceOff) - if (activeGroup(pd->group)) - m_onceOffed.remove(qMakePair(pd->group, pd->index)); + if (activeGroup(pd->groupId)) + m_onceOffed.remove(qMakePair(pd->groupId, pd->index)); } void QQuickParticleAffector::updateOffsets() @@ -246,16 +246,16 @@ void QQuickParticleAffector::updateOffsets() bool QQuickParticleAffector::isColliding(QQuickParticleData *d) { - qreal myCurX = d->curX(); - qreal myCurY = d->curY(); - qreal myCurSize = d->curSize()/2; + qreal myCurX = d->curX(m_system); + qreal myCurY = d->curY(m_system); + qreal myCurSize = d->curSize(m_system) / 2; foreach (const QString &group, m_whenCollidingWith){ foreach (QQuickParticleData* other, m_system->groupData[m_system->groupIds[group]]->data){ - if (!other->stillAlive()) + if (!other->stillAlive(m_system)) continue; - qreal otherCurX = other->curX(); - qreal otherCurY = other->curY(); - qreal otherCurSize = other->curSize()/2; + qreal otherCurX = other->curX(m_system); + qreal otherCurY = other->curY(m_system); + qreal otherCurSize = other->curSize(m_system) / 2; if ((myCurX + myCurSize > otherCurX - otherCurSize && myCurX - myCurSize < otherCurX + otherCurSize) && (myCurY + myCurSize > otherCurY - otherCurSize diff --git a/src/particles/qquickparticleemitter.cpp b/src/particles/qquickparticleemitter.cpp index 7cce4d481a..c72cbc01e0 100644 --- a/src/particles/qquickparticleemitter.cpp +++ b/src/particles/qquickparticleemitter.cpp @@ -407,7 +407,6 @@ void QQuickParticleEmitter::emitWindow(int timeStamp) //int pos = m_last_particle % m_particle_count; QQuickParticleData* datum = m_system->newDatum(m_system->groupIds[m_group], !m_overwrite); if (datum){//actually emit(otherwise we've been asked to skip this one) - datum->e = this;//###useful? qreal t = 1 - (pt - opt) / dt; qreal vx = - 2 * ax * (1 - t) @@ -480,7 +479,7 @@ void QQuickParticleEmitter::emitWindow(int timeStamp) } foreach (QQuickParticleData* d, toEmit) - m_system->emitParticle(d); + m_system->emitParticle(d, this); if (isEmitConnected()) { QQmlEngine *qmlEngine = ::qmlEngine(this); @@ -492,7 +491,7 @@ void QQuickParticleEmitter::emitWindow(int timeStamp) QV4::ScopedArrayObject array(scope, v4->newArrayObject(toEmit.size())); QV4::ScopedValue v(scope); for (int i=0; iputIndexed(i, (v = toEmit[i]->v4Value())); + array->putIndexed(i, (v = toEmit[i]->v4Value(m_system))); emitParticles(QQmlV4Handle(array));//A chance for arbitrary JS changes } diff --git a/src/particles/qquickparticlepainter.cpp b/src/particles/qquickparticlepainter.cpp index 556d137fd4..d6303eb219 100644 --- a/src/particles/qquickparticlepainter.cpp +++ b/src/particles/qquickparticlepainter.cpp @@ -139,17 +139,17 @@ void QQuickParticlePainter::setGroups(const QStringList &arg) void QQuickParticlePainter::load(QQuickParticleData* d) { - initialize(d->group, d->index); + initialize(d->groupId, d->index); if (m_pleaseReset) return; - m_pendingCommits << qMakePair(d->group, d->index); + m_pendingCommits << qMakePair(d->groupId, d->index); } void QQuickParticlePainter::reload(QQuickParticleData* d) { if (m_pleaseReset) return; - m_pendingCommits << qMakePair(d->group, d->index); + m_pendingCommits << qMakePair(d->groupId, d->index); } void QQuickParticlePainter::reset() diff --git a/src/particles/qquickparticlesystem.cpp b/src/particles/qquickparticlesystem.cpp index 8ccdec4792..e9bd073133 100644 --- a/src/particles/qquickparticlesystem.cpp +++ b/src/particles/qquickparticlesystem.cpp @@ -340,8 +340,8 @@ void QQuickParticleGroupData::setSize(int newSize) Q_ASSERT(newSize > m_size);//XXX allow shrinking data.resize(newSize); for (int i=m_size; igroup = index; + data[i] = new QQuickParticleData; + data[i]->groupId = index; data[i]->index = i; reusableIndexes << i; } @@ -358,7 +358,7 @@ void QQuickParticleGroupData::initList() void QQuickParticleGroupData::kill(QQuickParticleData* d) { - Q_ASSERT(d->group == index); + Q_ASSERT(d->groupId == index); d->lifeSpan = 0;//Kill off foreach (QQuickParticlePainter* p, painters) p->reload(d); @@ -372,7 +372,7 @@ QQuickParticleData* QQuickParticleGroupData::newDatum(bool respectsLimits) while (!reusableIndexes.empty()) { int idx = *(reusableIndexes.begin()); reusableIndexes.remove(idx); - if (data[idx]->stillAlive()) {// ### This means resurrection of 'dead' particles. Is that allowed? + if (data[idx]->stillAlive(m_system)) {// ### This means resurrection of 'dead' particles. Is that allowed? prepareRecycler(data[idx]); continue; } @@ -391,7 +391,7 @@ bool QQuickParticleGroupData::recycle() { while (dataHeap.top() <= m_system->timeInt) { foreach (QQuickParticleData* datum, dataHeap.pop()) { - if (!datum->stillAlive()) { + if (!datum->stillAlive(m_system)) { reusableIndexes << datum->index; } else { prepareRecycler(datum); //ttl has been altered mid-way, put it back @@ -409,17 +409,15 @@ void QQuickParticleGroupData::prepareRecycler(QQuickParticleData* d) dataHeap.insert(d); } else { while ((roundedTime(d->t) + 2*m_system->maxLife/3) <= m_system->timeInt) - d->extendLife(m_system->maxLife/3000.0); + d->extendLife(m_system->maxLife / 3000.0, m_system); dataHeap.insertTimed(d, roundedTime(d->t) + 2*m_system->maxLife/3); } } -QQuickParticleData::QQuickParticleData(QQuickParticleSystem* sys) - : e(0) - , system(sys) - , index(0) +QQuickParticleData::QQuickParticleData() + : index(0) , systemIndex(-1) - , group(0) + , groupId(0) , colorOwner(0) , rotationOwner(0) , deformationOwner(0) @@ -475,9 +473,7 @@ QQuickParticleData &QQuickParticleData::operator=(const QQuickParticleData &othe { clone(other); - group = other.group; - e = other.e; - system = other.system; + groupId = other.groupId; index = other.index; systemIndex = other.systemIndex; // Lazily initialized @@ -527,16 +523,16 @@ void QQuickParticleData::clone(const QQuickParticleData& other) animationOwner = other.animationOwner; } -QQmlV4Handle QQuickParticleData::v4Value() +QQmlV4Handle QQuickParticleData::v4Value(QQuickParticleSystem* particleSystem) { if (!v8Datum) - v8Datum = new QQuickV4ParticleData(QQmlEnginePrivate::getV8Engine(qmlEngine(system)), this); + v8Datum = new QQuickV4ParticleData(QQmlEnginePrivate::getV8Engine(qmlEngine(particleSystem)), this, particleSystem); return v8Datum->v4Value(); } //sets the x accleration without affecting the instantaneous x velocity or position -void QQuickParticleData::setInstantaneousAX(qreal ax) +void QQuickParticleData::setInstantaneousAX(qreal ax, QQuickParticleSystem* particleSystem) { - qreal t = (system->timeInt / 1000.0) - this->t; + qreal t = (particleSystem->timeInt / 1000.0) - this->t; qreal vx = (this->vx + t*this->ax) - t*ax; qreal ex = this->x + this->vx * t + 0.5 * this->ax * t * t; qreal x = ex - t*vx - 0.5 * t*t*ax; @@ -547,9 +543,9 @@ void QQuickParticleData::setInstantaneousAX(qreal ax) } //sets the x velocity without affecting the instantaneous x postion -void QQuickParticleData::setInstantaneousVX(qreal vx) +void QQuickParticleData::setInstantaneousVX(qreal vx, QQuickParticleSystem* particleSystem) { - qreal t = (system->timeInt / 1000.0) - this->t; + qreal t = (particleSystem->timeInt / 1000.0) - this->t; qreal evx = vx - t*this->ax; qreal ex = this->x + this->vx * t + 0.5 * this->ax * t * t; qreal x = ex - t*evx - 0.5 * t*t*this->ax; @@ -559,16 +555,16 @@ void QQuickParticleData::setInstantaneousVX(qreal vx) } //sets the instantaneous x postion -void QQuickParticleData::setInstantaneousX(qreal x) +void QQuickParticleData::setInstantaneousX(qreal x, QQuickParticleSystem* particleSystem) { - qreal t = (system->timeInt / 1000.0) - this->t; + qreal t = (particleSystem->timeInt / 1000.0) - this->t; this->x = x - t*this->vx - 0.5 * t*t*this->ax; } //sets the y accleration without affecting the instantaneous y velocity or position -void QQuickParticleData::setInstantaneousAY(qreal ay) +void QQuickParticleData::setInstantaneousAY(qreal ay, QQuickParticleSystem* particleSystem) { - qreal t = (system->timeInt / 1000.0) - this->t; + qreal t = (particleSystem->timeInt / 1000.0) - this->t; qreal vy = (this->vy + t*this->ay) - t*ay; qreal ey = this->y + this->vy * t + 0.5 * this->ay * t * t; qreal y = ey - t*vy - 0.5 * t*t*ay; @@ -579,9 +575,9 @@ void QQuickParticleData::setInstantaneousAY(qreal ay) } //sets the y velocity without affecting the instantaneous y position -void QQuickParticleData::setInstantaneousVY(qreal vy) +void QQuickParticleData::setInstantaneousVY(qreal vy, QQuickParticleSystem* particleSystem) { - qreal t = (system->timeInt / 1000.0) - this->t; + qreal t = (particleSystem->timeInt / 1000.0) - this->t; qreal evy = vy - t*this->ay; qreal ey = this->y + this->vy * t + 0.5 * this->ay * t * t; qreal y = ey - t*evy - 0.5 * t*t*this->ay; @@ -591,71 +587,71 @@ void QQuickParticleData::setInstantaneousVY(qreal vy) } //sets the instantaneous Y position -void QQuickParticleData::setInstantaneousY(qreal y) +void QQuickParticleData::setInstantaneousY(qreal y, QQuickParticleSystem* particleSystem) { - qreal t = (system->timeInt / 1000.0) - this->t; + qreal t = (particleSystem->timeInt / 1000.0) - this->t; this->y = y - t*this->vy - 0.5 * t*t*this->ay; } -qreal QQuickParticleData::curX() const +qreal QQuickParticleData::curX(QQuickParticleSystem* particleSystem) const { - qreal t = (system->timeInt / 1000.0) - this->t; + qreal t = (particleSystem->timeInt / 1000.0) - this->t; return this->x + this->vx * t + 0.5 * this->ax * t * t; } -qreal QQuickParticleData::curVX() const +qreal QQuickParticleData::curVX(QQuickParticleSystem* particleSystem) const { - qreal t = (system->timeInt / 1000.0) - this->t; + qreal t = (particleSystem->timeInt / 1000.0) - this->t; return this->vx + t*this->ax; } -qreal QQuickParticleData::curY() const +qreal QQuickParticleData::curY(QQuickParticleSystem* particleSystem) const { - qreal t = (system->timeInt / 1000.0) - this->t; + qreal t = (particleSystem->timeInt / 1000.0) - this->t; return y + vy * t + 0.5 * ay * t * t; } -qreal QQuickParticleData::curVY() const +qreal QQuickParticleData::curVY(QQuickParticleSystem* particleSystem) const { - qreal t = (system->timeInt / 1000.0) - this->t; + qreal t = (particleSystem->timeInt / 1000.0) - this->t; return vy + t*ay; } -void QQuickParticleData::debugDump() +void QQuickParticleData::debugDump(QQuickParticleSystem* particleSystem) { - qDebug() << "Particle" << systemIndex << group << "/" << index << stillAlive() + qDebug() << "Particle" << systemIndex << groupId << "/" << index << stillAlive(particleSystem) << "Pos: " << x << "," << y << "Vel: " << vx << "," << vy << "Acc: " << ax << "," << ay << "Size: " << size << "," << endSize - << "Time: " << t << "," <timeInt / 1000.0) ; + << "Time: " << t << "," <timeInt / 1000.0) ; } -float QQuickParticleData::curSize() +float QQuickParticleData::curSize(QQuickParticleSystem* particleSystem) { - if (!system || !lifeSpan) + if (!particleSystem || !lifeSpan) return 0.0f; - return size + (endSize - size) * (1 - (lifeLeft() / lifeSpan)); + return size + (endSize - size) * (1 - (lifeLeft(particleSystem) / lifeSpan)); } -float QQuickParticleData::lifeLeft() +float QQuickParticleData::lifeLeft(QQuickParticleSystem* particleSystem) { - if (!system) + if (!particleSystem) return 0.0f; - return (t + lifeSpan) - (system->timeInt/1000.0); + return (t + lifeSpan) - (particleSystem->timeInt/1000.0); } -void QQuickParticleData::extendLife(float time) +void QQuickParticleData::extendLife(float time, QQuickParticleSystem* particleSystem) { - qreal newX = curX(); - qreal newY = curY(); - qreal newVX = curVX(); - qreal newVY = curVY(); + qreal newX = curX(particleSystem); + qreal newY = curY(particleSystem); + qreal newVX = curVX(particleSystem); + qreal newVY = curVY(particleSystem); t += time; animT += time; - qreal elapsed = (system->timeInt / 1000.0) - t; + qreal elapsed = (particleSystem->timeInt / 1000.0) - t; qreal evy = newVY - elapsed*ay; qreal ey = newY - elapsed*evy - 0.5 * elapsed*elapsed*ay; qreal evx = newVX - elapsed*ax; @@ -1049,7 +1045,7 @@ void QQuickParticleSystem::particleStateChange(int idx) void QQuickParticleSystem::moveGroups(QQuickParticleData *d, int newGIdx) { - if (!d || newGIdx == d->group) + if (!d || newGIdx == d->groupId) return; QQuickParticleData* pd = newDatum(newGIdx, false, d->systemIndex); @@ -1060,7 +1056,7 @@ void QQuickParticleSystem::moveGroups(QQuickParticleData *d, int newGIdx) finishNewDatum(pd); d->systemIndex = -1; - groupData[d->group]->kill(d); + groupData[d->groupId]->kill(d); } int QQuickParticleSystem::nextSystemIndex() @@ -1102,17 +1098,17 @@ QQuickParticleData* QQuickParticleSystem::newDatum(int groupId, bool respectLimi bySysIdx[ret->systemIndex] = ret; if (stateEngine) - stateEngine->start(ret->systemIndex, ret->group); + stateEngine->start(ret->systemIndex, ret->groupId); m_empty = false; return ret; } -void QQuickParticleSystem::emitParticle(QQuickParticleData* pd) +void QQuickParticleSystem::emitParticle(QQuickParticleData* pd, QQuickParticleEmitter* particleEmitter) {// called from prepareNextFrame()->emitWindow - enforce? //Account for relative emitter position bool okay = false; - QTransform t = pd->e->itemTransform(this, &okay); + QTransform t = particleEmitter->itemTransform(this, &okay); if (okay) { qreal tx,ty; t.map(pd->x, pd->y, &tx, &ty); @@ -1126,12 +1122,12 @@ void QQuickParticleSystem::emitParticle(QQuickParticleData* pd) void QQuickParticleSystem::finishNewDatum(QQuickParticleData *pd) { Q_ASSERT(pd); - groupData[pd->group]->prepareRecycler(pd); + groupData[pd->groupId]->prepareRecycler(pd); foreach (QQuickParticleAffector *a, m_affectors) if (a && a->m_needsReset) a->reset(pd); - foreach (QQuickParticlePainter* p, groupData[pd->group]->painters) + foreach (QQuickParticlePainter* p, groupData[pd->groupId]->painters) if (p) p->load(pd); } @@ -1165,7 +1161,7 @@ void QQuickParticleSystem::updateCurrentTime( int currentTime ) foreach (QQuickParticleAffector* a, m_affectors) a->affectSystem(dt); foreach (QQuickParticleData* d, needsReset) - foreach (QQuickParticlePainter* p, groupData[d->group]->painters) + foreach (QQuickParticlePainter* p, groupData[d->groupId]->painters) p->reload(d); if (oldClear != m_empty) diff --git a/src/particles/qquickparticlesystem_p.h b/src/particles/qquickparticlesystem_p.h index 2745e73053..fcdd027a54 100644 --- a/src/particles/qquickparticlesystem_p.h +++ b/src/particles/qquickparticlesystem_p.h @@ -154,8 +154,8 @@ public: //TODO: Refactor particle data list out into a separate class QVector data; - QQuickParticleDataHeap dataHeap; QSet reusableIndexes; + QQuickParticleDataHeap dataHeap; bool recycle(); //Force recycling round, returns true if all indexes are now reusable void initList(); @@ -182,7 +182,7 @@ struct Color4ub { class Q_QUICKPARTICLES_PRIVATE_EXPORT QQuickParticleData { public: //TODO: QObject like memory management (without the cost, just attached to system) - QQuickParticleData(QQuickParticleSystem* sys); + QQuickParticleData(); ~QQuickParticleData(); QQuickParticleData(const QQuickParticleData &other); @@ -192,28 +192,28 @@ public: //If setting multiple parameters at once, doing the conversion yourself will be faster. //sets the x accleration without affecting the instantaneous x velocity or position - void setInstantaneousAX(qreal ax); + void setInstantaneousAX(qreal ax, QQuickParticleSystem *particleSystem); //sets the x velocity without affecting the instantaneous x postion - void setInstantaneousVX(qreal vx); + void setInstantaneousVX(qreal vx, QQuickParticleSystem *particleSystem); //sets the instantaneous x postion - void setInstantaneousX(qreal x); + void setInstantaneousX(qreal x, QQuickParticleSystem *particleSystem); //sets the y accleration without affecting the instantaneous y velocity or position - void setInstantaneousAY(qreal ay); + void setInstantaneousAY(qreal ay, QQuickParticleSystem *particleSystem); //sets the y velocity without affecting the instantaneous y postion - void setInstantaneousVY(qreal vy); + void setInstantaneousVY(qreal vy, QQuickParticleSystem *particleSystem); //sets the instantaneous Y postion - void setInstantaneousY(qreal y); + void setInstantaneousY(qreal y, QQuickParticleSystem *particleSystem); //TODO: Slight caching? - qreal curX() const; - qreal curVX() const; + qreal curX(QQuickParticleSystem *particleSystem) const; + qreal curVX(QQuickParticleSystem *particleSystem) const; qreal curAX() const { return ax; } - qreal curY() const; - qreal curVY() const; + qreal curAX(QQuickParticleSystem *) const { return ax; } // used by the macros in qquickv4particledata.cpp + qreal curY(QQuickParticleSystem *particleSystem) const; + qreal curVY(QQuickParticleSystem *particleSystem) const; qreal curAY() const { return ay; } + qreal curAY(QQuickParticleSystem *) const { return ay; } // used by the macros in qquickv4particledata.cpp - QQuickParticleEmitter* e;//### Needed? - QQuickParticleSystem* system; int index; int systemIndex; @@ -251,7 +251,7 @@ public: float animWidth; float animHeight; - int group; + QQuickParticleGroupData::ID groupId; //Used by ImageParticle data shadowing QQuickImageParticle* colorOwner; @@ -270,14 +270,14 @@ public: // 4 bytes wasted - void debugDump(); - bool stillAlive();//Only checks end, because usually that's all you need and it's a little faster. - bool alive(); - float lifeLeft(); - float curSize(); + void debugDump(QQuickParticleSystem *particleSystem); + bool stillAlive(QQuickParticleSystem *particleSystem);//Only checks end, because usually that's all you need and it's a little faster. + bool alive(QQuickParticleSystem *particleSystem); + float lifeLeft(QQuickParticleSystem *particleSystem); + float curSize(QQuickParticleSystem *particleSystem); void clone(const QQuickParticleData& other);//Not =, leaves meta-data like index - QQmlV4Handle v4Value(); - void extendLife(float time); + QQmlV4Handle v4Value(QQuickParticleSystem *particleSystem); + void extendLife(float time, QQuickParticleSystem *particleSystem); static inline Q_DECL_CONSTEXPR qreal EPSILON() Q_DECL_NOTHROW { return 0.001; } @@ -338,7 +338,7 @@ private Q_SLOTS: public: //These can be called multiple times per frame, performance critical - void emitParticle(QQuickParticleData* p); + void emitParticle(QQuickParticleData* p, QQuickParticleEmitter *particleEmitter); QQuickParticleData* newDatum(int groupId, bool respectLimits = true, int sysIdx = -1); void finishNewDatum(QQuickParticleData*); void moveGroups(QQuickParticleData *d, int newGIdx); @@ -429,14 +429,14 @@ private: QQuickParticleSystem* m_system; }; -inline bool QQuickParticleData::stillAlive() +inline bool QQuickParticleData::stillAlive(QQuickParticleSystem* system) { if (!system) return false; return (t + lifeSpan - EPSILON()) > ((qreal)system->timeInt/1000.0); } -inline bool QQuickParticleData::alive() +inline bool QQuickParticleData::alive(QQuickParticleSystem* system) { if (!system) return false; diff --git a/src/particles/qquickpointattractor.cpp b/src/particles/qquickpointattractor.cpp index 8b3cfbd1ff..779b2915f0 100644 --- a/src/particles/qquickpointattractor.cpp +++ b/src/particles/qquickpointattractor.cpp @@ -115,8 +115,8 @@ bool QQuickAttractorAffector::affectParticle(QQuickParticleData *d, qreal dt) { if (m_strength == 0.0) return false; - qreal dx = m_x+m_offset.x() - d->curX(); - qreal dy = m_y+m_offset.y() - d->curY(); + qreal dx = m_x+m_offset.x() - d->curX(m_system); + qreal dy = m_y+m_offset.y() - d->curY(m_system); qreal r = std::sqrt((dx*dx) + (dy*dy)); qreal theta = std::atan2(dy,dx); qreal ds = 0; @@ -146,15 +146,15 @@ bool QQuickAttractorAffector::affectParticle(QQuickParticleData *d, qreal dt) d->y = (d->y + dy); break; case Acceleration: - d->setInstantaneousAX(d->ax + dx); - d->setInstantaneousAY(d->ay + dy); + d->setInstantaneousAX(d->ax + dx, m_system); + d->setInstantaneousAY(d->ay + dy, m_system); break; case Velocity: //also default default: - vx = d->curVX(); - vy = d->curVY(); - d->setInstantaneousVX(vx + dx); - d->setInstantaneousVY(vy + dy); + vx = d->curVX(m_system); + vy = d->curVY(m_system); + d->setInstantaneousVX(vx + dx, m_system); + d->setInstantaneousVY(vy + dy, m_system); } return true; diff --git a/src/particles/qquickspritegoal.cpp b/src/particles/qquickspritegoal.cpp index 7afb787530..5784f1402d 100644 --- a/src/particles/qquickspritegoal.cpp +++ b/src/particles/qquickspritegoal.cpp @@ -124,7 +124,7 @@ bool QQuickSpriteGoalAffector::affectParticle(QQuickParticleData *d, qreal dt) QQuickStochasticEngine *engine = 0; if (!m_systemStates){ //TODO: Affect all engines - foreach (QQuickParticlePainter *p, m_system->groupData[d->group]->painters) + foreach (QQuickParticlePainter *p, m_system->groupData[d->groupId]->painters) if (qobject_cast(p)) engine = qobject_cast(p)->spriteEngine(); }else{ diff --git a/src/particles/qquicktrailemitter.cpp b/src/particles/qquicktrailemitter.cpp index 904421c296..d4d2adcfb2 100644 --- a/src/particles/qquicktrailemitter.cpp +++ b/src/particles/qquicktrailemitter.cpp @@ -182,7 +182,7 @@ void QQuickTrailEmitter::emitWindow(int timeStamp) int gId2 = groupId(); for (int i=0; igroupData[gId]->data.count(); i++) { QQuickParticleData *d = m_system->groupData[gId]->data[i]; - if (!d->stillAlive()){ + if (!d->stillAlive(m_system)){ m_lastEmission[i] = time; //Should only start emitting when it returns to life continue; } @@ -192,7 +192,8 @@ void QQuickTrailEmitter::emitWindow(int timeStamp) if (pt + maxLife < time)//We missed so much, that we should skip emiting particles that are dead by now pt = time - maxLife; - if ((width() || height()) && !effectiveExtruder()->contains(QRectF(offset.x(), offset.y(), width(), height()),QPointF(d->curX(), d->curY()))){ + if ((width() || height()) && !effectiveExtruder()->contains(QRectF(offset.x(), offset.y(), width(), height()), + QPointF(d->curX(m_system), d->curY(m_system)))) { m_lastEmission[d->index] = time;//jump over this time period without emitting, because it's outside continue; } @@ -202,8 +203,6 @@ void QQuickTrailEmitter::emitWindow(int timeStamp) while (pt < time || !m_burstQueue.isEmpty()){ QQuickParticleData* datum = m_system->newDatum(gId2, !m_overwrite); if (datum){//else, skip this emission - datum->e = this;//###useful? - // Particle timestamp datum->t = pt; datum->lifeSpan = @@ -215,8 +214,8 @@ void QQuickTrailEmitter::emitWindow(int timeStamp) // Note that burst location doesn't get used for follow emitter qreal followT = pt - d->t; qreal followT2 = followT * followT * 0.5; - qreal eW = m_emitterXVariation < 0 ? d->curSize() : m_emitterXVariation; - qreal eH = m_emitterYVariation < 0 ? d->curSize() : m_emitterYVariation; + qreal eW = m_emitterXVariation < 0 ? d->curSize(m_system) : m_emitterXVariation; + qreal eH = m_emitterYVariation < 0 ? d->curSize(m_system) : m_emitterYVariation; //Subtract offset, because PS expects this in emitter coordinates QRectF boundsRect(d->x - offset.x() + d->vx * followT + d->ax * followT2 - eW/2, d->y - offset.y() + d->vy * followT + d->ay * followT2 - eH/2, @@ -251,7 +250,7 @@ void QQuickTrailEmitter::emitWindow(int timeStamp) toEmit << datum; - m_system->emitParticle(datum); + m_system->emitParticle(datum, this); } if (!m_burstQueue.isEmpty()){ m_burstQueue.first().first--; @@ -263,7 +262,7 @@ void QQuickTrailEmitter::emitWindow(int timeStamp) } foreach (QQuickParticleData* d, toEmit) - m_system->emitParticle(d); + m_system->emitParticle(d, this); if (isEmitConnected() || isEmitFollowConnected()) { QQmlEngine *qmlEngine = ::qmlEngine(this); @@ -273,10 +272,10 @@ void QQuickTrailEmitter::emitWindow(int timeStamp) QV4::ScopedArrayObject array(scope, v4->newArrayObject(toEmit.size())); QV4::ScopedValue v(scope); for (int i=0; iputIndexed(i, (v = toEmit[i]->v4Value())); + array->putIndexed(i, (v = toEmit[i]->v4Value(m_system))); if (isEmitFollowConnected()) - emitFollowParticles(QQmlV4Handle(array), d->v4Value());//A chance for many arbitrary JS changes + emitFollowParticles(QQmlV4Handle(array), d->v4Value(m_system));//A chance for many arbitrary JS changes else if (isEmitConnected()) emitParticles(QQmlV4Handle(array));//A chance for arbitrary JS changes } diff --git a/src/particles/qquickturbulence.cpp b/src/particles/qquickturbulence.cpp index eed8604438..74558413a6 100644 --- a/src/particles/qquickturbulence.cpp +++ b/src/particles/qquickturbulence.cpp @@ -186,7 +186,7 @@ void QQuickTurbulenceAffector::affectSystem(qreal dt) foreach (QQuickParticleData *d, gd->data){ if (!shouldAffect(d)) continue; - QPoint pos = (QPointF(d->curX(), d->curY()) - m_offset).toPoint(); + QPoint pos = (QPointF(d->curX(m_system), d->curY(m_system)) - m_offset).toPoint(); if (!boundsRect.contains(pos,true))//Need to redo bounds checking due to quantization. continue; qreal fx = 0.0; @@ -194,8 +194,8 @@ void QQuickTurbulenceAffector::affectSystem(qreal dt) fx += m_vectorField[pos.x()][pos.y()].x() * m_strength; fy += m_vectorField[pos.x()][pos.y()].y() * m_strength; if (fx || fy){ - d->setInstantaneousVX(d->curVX()+ fx * dt); - d->setInstantaneousVY(d->curVY()+ fy * dt); + d->setInstantaneousVX(d->curVX(m_system)+ fx * dt, m_system); + d->setInstantaneousVY(d->curVY(m_system)+ fy * dt, m_system); postAffect(d); } } diff --git a/src/particles/qquickv4particledata.cpp b/src/particles/qquickv4particledata.cpp index 86e3c91ba8..3d7f4ce5b8 100644 --- a/src/particles/qquickv4particledata.cpp +++ b/src/particles/qquickv4particledata.cpp @@ -272,11 +272,13 @@ QT_BEGIN_NAMESPACE struct QV4ParticleData : public QV4::Object { struct Data : QV4::Object::Data { - Data(QQuickParticleData *datum) + Data(QQuickParticleData *datum, QQuickParticleSystem* particleSystem) : datum(datum) + , particleSystem(particleSystem) { } QQuickParticleData* datum;//TODO: Guard needed? + QQuickParticleSystem* particleSystem; }; V4_OBJECT(QV4::Object) }; @@ -312,7 +314,7 @@ static QV4::ReturnedValue particleData_lifeLeft(QV4::CallContext *ctx) if (!r || !r->d()->datum) return ctx->engine()->throwError(QStringLiteral("Not a valid ParticleData object")); - return QV4::Encode(r->d()->datum->lifeLeft()); + return QV4::Encode(r->d()->datum->lifeLeft(r->d()->particleSystem)); } static QV4::ReturnedValue particleData_curSize(QV4::CallContext *ctx) @@ -323,7 +325,7 @@ static QV4::ReturnedValue particleData_curSize(QV4::CallContext *ctx) if (!r || !r->d()->datum) return ctx->engine()->throwError(QStringLiteral("Not a valid ParticleData object")); - return QV4::Encode(r->d()->datum->curSize()); + return QV4::Encode(r->d()->datum->curSize(r->d()->particleSystem)); } #define COLOR_GETTER_AND_SETTER(VAR, NAME) static QV4::ReturnedValue particleData_get_ ## NAME (QV4::CallContext *ctx) \ { \ @@ -397,7 +399,7 @@ static QV4::ReturnedValue particleData_set_ ## VARIABLE (QV4::CallContext *ctx)\ if (!r || !r->d()->datum) \ ctx->engine()->throwError(QStringLiteral("Not a valid ParticleData object")); \ \ - return QV4::Encode(r->d()->datum-> GETTER ());\ + return QV4::Encode(r->d()->datum-> GETTER (r->d()->particleSystem));\ }\ \ static QV4::ReturnedValue particleData_set_ ## VARIABLE (QV4::CallContext *ctx)\ @@ -407,7 +409,7 @@ static QV4::ReturnedValue particleData_set_ ## VARIABLE (QV4::CallContext *ctx)\ if (!r || !r->d()->datum)\ ctx->engine()->throwError(QStringLiteral("Not a valid ParticleData object"));\ \ - r->d()->datum-> SETTER (ctx->argc() ? ctx->args()[0].toNumber() : qQNaN());\ + r->d()->datum-> SETTER (ctx->argc() ? ctx->args()[0].toNumber() : qQNaN(), r->d()->particleSystem);\ return QV4::Encode::undefined(); \ } @@ -503,7 +505,7 @@ QV4ParticleDataDeletable::~QV4ParticleDataDeletable() V4_DEFINE_EXTENSION(QV4ParticleDataDeletable, particleV4Data); -QQuickV4ParticleData::QQuickV4ParticleData(QV8Engine* engine, QQuickParticleData* datum) +QQuickV4ParticleData::QQuickV4ParticleData(QV8Engine* engine, QQuickParticleData* datum, QQuickParticleSystem *system) { if (!engine || !datum) return; @@ -511,7 +513,7 @@ QQuickV4ParticleData::QQuickV4ParticleData(QV8Engine* engine, QQuickParticleData QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); QV4::Scope scope(v4); QV4ParticleDataDeletable *d = particleV4Data(scope.engine); - QV4::ScopedObject o(scope, v4->memoryManager->allocObject(datum)); + QV4::ScopedObject o(scope, v4->memoryManager->allocObject(datum, system)); QV4::ScopedObject p(scope, d->proto.value()); o->setPrototype(p); m_v4Value = o; diff --git a/src/particles/qquickv4particledata_p.h b/src/particles/qquickv4particledata_p.h index b93c0333d7..0d88f0f9cc 100644 --- a/src/particles/qquickv4particledata_p.h +++ b/src/particles/qquickv4particledata_p.h @@ -58,9 +58,10 @@ QT_BEGIN_NAMESPACE class QQuickParticleData; +class QQuickParticleSystem; class QQuickV4ParticleData { public: - QQuickV4ParticleData(QV8Engine*,QQuickParticleData*); + QQuickV4ParticleData(QV8Engine*, QQuickParticleData*, QQuickParticleSystem *system); ~QQuickV4ParticleData(); QQmlV4Handle v4Value(); private: diff --git a/src/particles/qquickwander.cpp b/src/particles/qquickwander.cpp index 862c796dac..09d36ab2e8 100644 --- a/src/particles/qquickwander.cpp +++ b/src/particles/qquickwander.cpp @@ -151,29 +151,29 @@ bool QQuickWanderAffector::affectParticle(QQuickParticleData* data, qreal dt) qreal newX, newY; switch (m_affectedParameter){ case Position: - newX = data->curX() + dx; + newX = data->curX(m_system) + dx; if (m_xVariance > qAbs(newX) ) data->x += dx; - newY = data->curY() + dy; + newY = data->curY(m_system) + dy; if (m_yVariance > qAbs(newY) ) data->y += dy; break; default: case Velocity: - newX = data->curVX() + dx; - if (m_xVariance > qAbs(newX) ) - data->setInstantaneousVX(newX); - newY = data->curVY() + dy; - if (m_yVariance > qAbs(newY) ) - data->setInstantaneousVY(newY); + newX = data->curVX(m_system) + dx; + if (m_xVariance > qAbs(newX)) + data->setInstantaneousVX(newX, m_system); + newY = data->curVY(m_system) + dy; + if (m_yVariance > qAbs(newY)) + data->setInstantaneousVY(newY, m_system); break; case Acceleration: newX = data->ax + dx; - if (m_xVariance > qAbs(newX) ) - data->setInstantaneousAX(newX); + if (m_xVariance > qAbs(newX)) + data->setInstantaneousAX(newX, m_system); newY = data->ay + dy; - if (m_yVariance > qAbs(newY) ) - data->setInstantaneousAY(newY); + if (m_yVariance > qAbs(newY)) + data->setInstantaneousAY(newY, m_system); break; } return true; -- cgit v1.2.3