Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qquicktrailemitter.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
5
7
8#include <private/qqmlglobal_p.h>
9#include <private/qquickv4particledata_p.h>
10
11#include <QtCore/qrandom.h>
12
13#include <cmath>
14
16
30 , m_particlesPerParticlePerSecond(0)
31 , m_lastTimeStamp(0)
32 , m_emitterXVariation(0)
33 , m_emitterYVariation(0)
34 , m_followCount(0)
35 , m_emissionExtruder(nullptr)
36 , m_defaultEmissionExtruder(new QQuickParticleExtruder(this))
37{
38 //TODO: If followed increased their size
40 this, &QQuickTrailEmitter::recalcParticlesPerSecond);
42 this, &QQuickTrailEmitter::recalcParticlesPerSecond);
44 this, &QQuickTrailEmitter::recalcParticlesPerSecond);
45}
46
98bool QQuickTrailEmitter::isEmitFollowConnected()
99{
102 (const QList<QQuickV4ParticleData> &, const QQuickV4ParticleData &));
103}
104
105void QQuickTrailEmitter::recalcParticlesPerSecond(){
106 if (!m_system)
107 return;
108 m_followCount = m_system->groupData[m_system->groupIds[m_follow]]->size();
109 if (!m_followCount){
110 setParticlesPerSecond(1);//XXX: Fix this horrendous hack, needed so they aren't turned off from start (causes crashes - test that when gone you don't crash with 0 PPPS)
111 }else{
112 setParticlesPerSecond(m_particlesPerParticlePerSecond * m_followCount);
113 m_lastEmission.resize(m_followCount);
114 m_lastEmission.fill(m_lastTimeStamp);
115 }
116}
117
119{
120 m_followCount = 0;
121}
122
124{
125 if (m_system == nullptr)
126 return;
128 return;
129 if (m_followCount != m_system->groupData[m_system->groupIds[m_follow]]->size()){
131 recalcParticlesPerSecond();
132 if (m_particlesPerSecond != oldPPS)
133 return;//system may need to update
134 }
135
136 if (m_pulseLeft){
137 m_pulseLeft -= timeStamp - m_lastTimeStamp * 1000.;
138 if (m_pulseLeft < 0){
139 timeStamp += m_pulseLeft;
140 m_pulseLeft = 0;
141 }
142 }
143
144 //TODO: Implement startTime and velocityFromMovement
145 qreal time = timeStamp / 1000.;
146 qreal particleRatio = 1. / m_particlesPerParticlePerSecond;
147 qreal pt;
149
150 //Have to map it into this system, because particlesystem automaps it back
151 QPointF offset = m_system->mapFromItem(this, QPointF(0, 0));
153
154 int gId = m_system->groupIds[m_follow];
155 int gId2 = groupId();
156 for (int i=0; i<m_system->groupData[gId]->data.size(); i++) {
158 if (!d->stillAlive(m_system)){
159 m_lastEmission[i] = time; //Should only start emitting when it returns to life
160 continue;
161 }
162 pt = m_lastEmission[i];
163 if (pt < d->t)
164 pt = d->t;
165 if (pt + maxLife < time)//We missed so much, that we should skip emiting particles that are dead by now
166 pt = time - maxLife;
167
168 if ((width() || height()) && !effectiveExtruder()->contains(QRectF(offset.x(), offset.y(), width(), height()),
169 QPointF(d->curX(m_system), d->curY(m_system)))) {
170 m_lastEmission[d->index] = time;//jump over this time period without emitting, because it's outside
171 continue;
172 }
173
174 QList<QQuickParticleData*> toEmit;
175
176 while (pt < time || !m_burstQueue.isEmpty()){
178 if (datum){//else, skip this emission
179 // Particle timestamp
180 datum->t = pt;
181 datum->lifeSpan =
184 / 1000.0;
185
186 // Particle position
187 // Note that burst location doesn't get used for follow emitter
188 qreal followT = pt - d->t;
189 qreal followT2 = followT * followT * 0.5;
190 qreal eW = m_emitterXVariation < 0 ? d->curSize(m_system) : m_emitterXVariation;
191 qreal eH = m_emitterYVariation < 0 ? d->curSize(m_system) : m_emitterYVariation;
192 //Subtract offset, because PS expects this in emitter coordinates
193 QRectF boundsRect(d->x - offset.x() + d->vx * followT + d->ax * followT2 - eW/2,
194 d->y - offset.y() + d->vy * followT + d->ay * followT2 - eH/2,
195 eW, eH);
196
197 QQuickParticleExtruder* effectiveEmissionExtruder = m_emissionExtruder ? m_emissionExtruder : m_defaultEmissionExtruder;
198 const QPointF &newPos = effectiveEmissionExtruder->extrude(boundsRect);
199 datum->x = newPos.x();
200 datum->y = newPos.y();
201
202 // Particle velocity
203 const QPointF &velocity = m_velocity->sample(newPos);
204 datum->vx = velocity.x()
206 datum->vy = velocity.y()
208
209 // Particle acceleration
210 const QPointF &accel = m_acceleration->sample(newPos);
211 datum->ax = accel.x();
212 datum->ay = accel.y();
213
214 // Particle size
216 + QRandomGenerator::global()->generateDouble() * m_particleSizeVariation * 2;
217
218 float size = qMax((qreal)0.0, m_particleSize + sizeVariation);
219 float endSize = qMax((qreal)0.0, sizeAtEnd + sizeVariation);
220
221 datum->size = size * float(m_enabled);
222 datum->endSize = endSize * float(m_enabled);
223
224 toEmit << datum;
225
226 m_system->emitParticle(datum, this);
227 }
228 if (!m_burstQueue.isEmpty()){
229 m_burstQueue.first().first--;
230 if (m_burstQueue.first().first <= 0)
232 }else{
233 pt += particleRatio;
234 }
235 }
236
237 foreach (QQuickParticleData* d, toEmit)
238 m_system->emitParticle(d, this);
239
240 if (isEmitConnected() || isEmitFollowConnected()) {
241
242 QList<QQuickV4ParticleData> particles;
243 particles.reserve(toEmit.size());
244 for (QQuickParticleData *particle : std::as_const(toEmit))
245 particles.push_back(particle->v4Value(m_system));
246
247 if (isEmitFollowConnected()) {
248 //A chance for many arbitrary JS changes
249 emit emitFollowParticles(particles, d->v4Value(m_system));
250 } else if (isEmitConnected()) {
251 emit emitParticles(particles);//A chance for arbitrary JS changes
252 }
253 }
254 m_lastEmission[d->index] = pt;
255 }
256
257 m_lastTimeStamp = time;
258}
260
261#include "moc_qquicktrailemitter_p.cpp"
bool isEmpty() const noexcept
Definition qlist.h:401
T & first()
Definition qlist.h:645
void pop_front() noexcept
Definition qlist.h:680
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
\inmodule QtCore\reentrant
Definition qpoint.h:217
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:343
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:348
virtual QPointF sample(const QPointF &from)
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:63
Q_INVOKABLE QPointF mapFromItem(const QQuickItem *item, const QPointF &point) const
Maps the given point in item's coordinate system to the equivalent point within this item's coordinat...
virtual Q_INVOKABLE bool contains(const QPointF &point) const
\qmlmethod bool QtQuick::Item::contains(point point)
qreal width
This property holds the width of this item.
Definition qquickitem.h:75
qreal height
This property holds the height of this item.
Definition qquickitem.h:76
void emitParticles(const QList< QQuickV4ParticleData > &particles)
QQuickParticleSystem * m_system
void particleDurationChanged(int)
QList< QPair< int, QPointF > > m_burstQueue
QQuickParticleExtruder * effectiveExtruder()
QQuickParticleGroupData::ID groupId() const
QQuickParticleData * newDatum(int groupId, bool respectLimits=true, int sysIdx=-1, const QQuickParticleData *cloneFrom=nullptr)
void emitParticle(QQuickParticleData *p, QQuickParticleEmitter *particleEmitter)
QVarLengthArray< QQuickParticleGroupData *, 32 > groupData
QHash< QString, int > groupIds
void followChanged(const QString &arg)
void emitFollowParticles(const QList< QQuickV4ParticleData > &particles, const QQuickV4ParticleData &followed)
QQuickTrailEmitter(QQuickItem *parent=nullptr)
\qmltype TrailEmitter \instantiates QQuickTrailEmitter \inqmlmodule QtQuick.Particles \inherits QQuic...
void emitWindow(int timeStamp) override
void particlesPerParticlePerSecondChanged(int arg)
static Q_DECL_CONST_FUNCTION QRandomGenerator * global()
\threadsafe
Definition qrandom.h:275
\inmodule QtCore\reentrant
Definition qrect.h:484
constexpr size_type size() const noexcept
T * data() noexcept
#define this
Definition dialogs.cpp:9
Combined button and popup list for selecting options.
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei width
GLenum GLuint GLintptr offset
GLdouble GLdouble t
Definition qopenglext.h:243
#define IS_SIGNAL_CONNECTED(Sender, SenderType, Name, Arguments)
#define emit
double qreal
Definition qtypes.h:187
QObject::connect nullptr