Qt 6.x
The Qt SDK
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
5#include <private/qqmlengine_p.h>
6#include <private/qqmlglobal_p.h>
7#include <private/qjsvalue_p.h>
8#include <QRandomGenerator>
9#include <cmath>
11
25 , m_particlesPerParticlePerSecond(0)
26 , m_lastTimeStamp(0)
27 , m_emitterXVariation(0)
28 , m_emitterYVariation(0)
29 , m_followCount(0)
30 , m_emissionExtruder(nullptr)
31 , m_defaultEmissionExtruder(new QQuickParticleExtruder(this))
32{
33 //TODO: If followed increased their size
35 this, SLOT(recalcParticlesPerSecond()));
37 this, SLOT(recalcParticlesPerSecond()));
39 this, SLOT(recalcParticlesPerSecond()));
40}
41
93bool QQuickTrailEmitter::isEmitFollowConnected()
94{
96 (const QJSValue &, const QJSValue &));
97}
98
99void QQuickTrailEmitter::recalcParticlesPerSecond(){
100 if (!m_system)
101 return;
102 m_followCount = m_system->groupData[m_system->groupIds[m_follow]]->size();
103 if (!m_followCount){
104 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)
105 }else{
106 setParticlesPerSecond(m_particlesPerParticlePerSecond * m_followCount);
107 m_lastEmission.resize(m_followCount);
108 m_lastEmission.fill(m_lastTimeStamp);
109 }
110}
111
113{
114 m_followCount = 0;
115}
116
118{
119 if (m_system == nullptr)
120 return;
122 return;
123 if (m_followCount != m_system->groupData[m_system->groupIds[m_follow]]->size()){
125 recalcParticlesPerSecond();
126 if (m_particlesPerSecond != oldPPS)
127 return;//system may need to update
128 }
129
130 if (m_pulseLeft){
131 m_pulseLeft -= timeStamp - m_lastTimeStamp * 1000.;
132 if (m_pulseLeft < 0){
133 timeStamp += m_pulseLeft;
134 m_pulseLeft = 0;
135 }
136 }
137
138 //TODO: Implement startTime and velocityFromMovement
139 qreal time = timeStamp / 1000.;
140 qreal particleRatio = 1. / m_particlesPerParticlePerSecond;
141 qreal pt;
143
144 //Have to map it into this system, because particlesystem automaps it back
145 QPointF offset = m_system->mapFromItem(this, QPointF(0, 0));
147
148 int gId = m_system->groupIds[m_follow];
149 int gId2 = groupId();
150 for (int i=0; i<m_system->groupData[gId]->data.size(); i++) {
152 if (!d->stillAlive(m_system)){
153 m_lastEmission[i] = time; //Should only start emitting when it returns to life
154 continue;
155 }
156 pt = m_lastEmission[i];
157 if (pt < d->t)
158 pt = d->t;
159 if (pt + maxLife < time)//We missed so much, that we should skip emiting particles that are dead by now
160 pt = time - maxLife;
161
162 if ((width() || height()) && !effectiveExtruder()->contains(QRectF(offset.x(), offset.y(), width(), height()),
163 QPointF(d->curX(m_system), d->curY(m_system)))) {
164 m_lastEmission[d->index] = time;//jump over this time period without emitting, because it's outside
165 continue;
166 }
167
169
170 while (pt < time || !m_burstQueue.isEmpty()){
172 if (datum){//else, skip this emission
173 // Particle timestamp
174 datum->t = pt;
175 datum->lifeSpan =
178 / 1000.0;
179
180 // Particle position
181 // Note that burst location doesn't get used for follow emitter
182 qreal followT = pt - d->t;
183 qreal followT2 = followT * followT * 0.5;
184 qreal eW = m_emitterXVariation < 0 ? d->curSize(m_system) : m_emitterXVariation;
185 qreal eH = m_emitterYVariation < 0 ? d->curSize(m_system) : m_emitterYVariation;
186 //Subtract offset, because PS expects this in emitter coordinates
187 QRectF boundsRect(d->x - offset.x() + d->vx * followT + d->ax * followT2 - eW/2,
188 d->y - offset.y() + d->vy * followT + d->ay * followT2 - eH/2,
189 eW, eH);
190
191 QQuickParticleExtruder* effectiveEmissionExtruder = m_emissionExtruder ? m_emissionExtruder : m_defaultEmissionExtruder;
192 const QPointF &newPos = effectiveEmissionExtruder->extrude(boundsRect);
193 datum->x = newPos.x();
194 datum->y = newPos.y();
195
196 // Particle velocity
197 const QPointF &velocity = m_velocity->sample(newPos);
198 datum->vx = velocity.x()
200 datum->vy = velocity.y()
202
203 // Particle acceleration
204 const QPointF &accel = m_acceleration->sample(newPos);
205 datum->ax = accel.x();
206 datum->ay = accel.y();
207
208 // Particle size
211
212 float size = qMax((qreal)0.0, m_particleSize + sizeVariation);
213 float endSize = qMax((qreal)0.0, sizeAtEnd + sizeVariation);
214
215 datum->size = size * float(m_enabled);
216 datum->endSize = endSize * float(m_enabled);
217
218 toEmit << datum;
219
220 m_system->emitParticle(datum, this);
221 }
222 if (!m_burstQueue.isEmpty()){
223 m_burstQueue.first().first--;
224 if (m_burstQueue.first().first <= 0)
226 }else{
227 pt += particleRatio;
228 }
229 }
230
231 foreach (QQuickParticleData* d, toEmit)
232 m_system->emitParticle(d, this);
233
234 if (isEmitConnected() || isEmitFollowConnected()) {
237
238 QV4::Scope scope(v4);
239 QV4::ScopedArrayObject array(scope, v4->newArrayObject(toEmit.size()));
240 QV4::ScopedValue v(scope);
241 for (int i=0; i<toEmit.size(); i++)
242 array->put(i, (v = toEmit[i]->v4Value(m_system)));
243
244 QJSValue particles;
245 QJSValuePrivate::setValue(&particles, array);
246 if (isEmitFollowConnected()) {
247 //A chance for many arbitrary JS changes
249 particles, QJSValuePrivate::fromReturnedValue(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"
QV4::ExecutionEngine * handle() const
Definition qjsengine.h:292
static QJSValue fromReturnedValue(QV4::ReturnedValue d)
Definition qjsvalue_p.h:189
static void setValue(QJSValue *jsval, const QV4::Value &v)
Definition qjsvalue_p.h:282
The QJSValue class acts as a container for Qt/JavaScript data types.
Definition qjsvalue.h:31
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
bool isEmpty() const noexcept
Definition qlist.h:390
T & first()
Definition qlist.h:628
void pop_front() noexcept
Definition qlist.h:677
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
\inmodule QtCore\reentrant
Definition qpoint.h:214
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:333
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:338
The QQmlEngine class provides an environment for instantiating QML components.
Definition qqmlengine.h:57
virtual QPointF sample(const QPointF &from)
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:64
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:76
qreal height
This property holds the height of this item.
Definition qquickitem.h:77
void emitParticles(const QJSValue &particles)
QQuickParticleSystem * m_system
void particleDurationChanged(int)
QList< QPair< int, QPointF > > m_burstQueue
QQuickParticleExtruder * effectiveExtruder()
QQuickParticleGroupData::ID groupId() const
virtual QPointF extrude(const QRectF &)
void emitParticle(QQuickParticleData *p, QQuickParticleEmitter *particleEmitter)
QVarLengthArray< QQuickParticleGroupData *, 32 > groupData
QHash< QString, int > groupIds
QQuickParticleData * newDatum(int groupId, bool respectLimits=true, int sysIdx=-1)
void followChanged(const QString &arg)
QQuickTrailEmitter(QQuickItem *parent=nullptr)
\qmltype TrailEmitter \instantiates QQuickTrailEmitter \inqmlmodule QtQuick.Particles \inherits QQuic...
void emitFollowParticles(const QJSValue &particles, const QJSValue &followed)
void emitWindow(int timeStamp) override
void particlesPerParticlePerSecondChanged(int arg)
double generateDouble()
Generates one random qreal in the canonical range [0, 1) (that is, inclusive of zero and exclusive of...
Definition qrandom.h:58
static Q_DECL_CONST_FUNCTION QRandomGenerator * global()
\threadsafe
Definition qrandom.h:275
double bounded(double highest)
Generates one random double in the range between 0 (inclusive) and highest (exclusive).
Definition qrandom.h:72
\inmodule QtCore\reentrant
Definition qrect.h:483
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
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
#define SLOT(a)
Definition qobjectdefs.h:51
#define SIGNAL(a)
Definition qobjectdefs.h:52
GLsizei const GLfloat * v
[13]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei width
GLenum GLuint GLintptr offset
GLenum array
GLdouble GLdouble t
Definition qopenglext.h:243
QQmlEngine * qmlEngine(const QObject *obj)
Definition qqml.cpp:76
#define IS_SIGNAL_CONNECTED(Sender, SenderType, Name, Arguments)
#define emit
double qreal
Definition qtypes.h:92
QObject::connect nullptr
Heap::ArrayObject * newArrayObject(int count=0)
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent