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
qquickparticleemitter.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
14
18
186 QQuickItem(parent)
187 , m_particlesPerSecond(10)
188 , m_particleDuration(1000)
189 , m_particleDurationVariation(0)
190 , m_enabled(true)
191 , m_system(nullptr)
192 , m_extruder(nullptr)
193 , m_defaultExtruder(nullptr)
194 , m_velocity(&m_nullVector)
195 , m_acceleration(&m_nullVector)
196 , m_particleSize(16)
197 , m_particleEndSize(-1)
198 , m_particleSizeVariation(0)
199 , m_startTime(0)
200 , m_overwrite(true)
201 , m_pulseLeft(0)
202 , m_maxParticleCount(-1)
203 , m_velocity_from_movement(0)
204 , m_reset_last(true)
205 , m_last_timestamp(-1)
206 , m_last_emission(0)
207 , m_groupIdNeedRecalculation(false)
208 , m_groupId(QQuickParticleGroupData::DefaultGroupID)
209
210{
211 //TODO: Reset velocity/acc back to null vector? Or allow null pointer?
216}
217
223
225{
227 this, QQuickParticleEmitter, emitParticles, (const QList<QQuickV4ParticleData> &));
228}
229
231{
232 if (!m_system) {
234 return;
235 }
237 m_groupIdNeedRecalculation = m_groupId == QQuickParticleGroupData::InvalidID;
238}
239
241{
242 if (!m_system && qobject_cast<QQuickParticleSystem*>(parentItem()))
243 setSystem(qobject_cast<QQuickParticleSystem*>(parentItem()));
244 if (m_system)
247}
248
250{
251 if (m_enabled != arg) {
252 m_enabled = arg;
254 }
255}
256
257
266
267void QQuickParticleEmitter::pulse(int milliseconds)
268{
269 if (!m_enabled)
270 m_pulseLeft = milliseconds;
271}
272
277
282
303
311
313{
314 m_reset_last = true;
315}
316
318{
319 if (m_system == nullptr)
320 return;
322 m_reset_last = true;
323 return;
324 }
325
326 if (m_reset_last) {
328 if (m_last_timestamp == -1)
329 m_last_timestamp = (timeStamp - m_startTime)/1000.;
330 else
331 m_last_timestamp = timeStamp/1000.;
333 m_reset_last = false;
334 m_emitCap = -1;
335 }
336
337 if (m_pulseLeft){
338 m_pulseLeft -= timeStamp - m_last_timestamp * 1000.;
339 if (m_pulseLeft < 0){
340 if (!m_enabled)
341 timeStamp += m_pulseLeft;
342 m_pulseLeft = 0;
343 }
344 }
345 qreal time = timeStamp / 1000.;
346 qreal particleRatio = 1. / m_particlesPerSecond;
349 if (pt + maxLife < time)//We missed so much, that we should skip emiting particles that are dead by now
350 pt = time - maxLife;
351
352 qreal opt = pt; // original particle time
353 qreal dt = time - m_last_timestamp; // timestamp delta...
354 if (!dt)
355 dt = 0.000001;
356
357 // emitter difference since last...
358 qreal dex = (x() - m_last_emitter.x());
359 qreal dey = (y() - m_last_emitter.y());
360
361 qreal ax = (m_last_last_emitter.x() + m_last_emitter.x()) / 2;
362 qreal bx = m_last_emitter.x();
363 qreal cx = (x() + m_last_emitter.x()) / 2;
364 qreal ay = (m_last_last_emitter.y() + m_last_emitter.y()) / 2;
366 qreal cy = (y() + m_last_emitter.y()) / 2;
367
369 qreal emitter_x_offset = m_last_emitter.x() - x();
370 qreal emitter_y_offset = m_last_emitter.y() - y();
371 if (!m_burstQueue.isEmpty() && !m_pulseLeft && !m_enabled)//'outside time' emissions only
372 pt = time;
373
374 QList<QQuickParticleData*> toEmit;
375
376 while ((pt < time && m_emitCap) || !m_burstQueue.isEmpty()) {
377 //int pos = m_last_particle % m_particle_count;
379 if (datum){//actually emit(otherwise we've been asked to skip this one)
380 qreal t = 1 - (pt - opt) / dt;
381 qreal vx =
382 - 2 * ax * (1 - t)
383 + 2 * bx * (1 - 2 * t)
384 + 2 * cx * t;
385 qreal vy =
386 - 2 * ay * (1 - t)
387 + 2 * by * (1 - 2 * t)
388 + 2 * cy * t;
389
390
391 // Particle timestamp
392 datum->t = pt;
393 datum->lifeSpan =
396 / 1000.0;
397
398 if (datum->lifeSpan >= m_system->maxLife){
399 datum->lifeSpan = m_system->maxLife;
400 if (m_emitCap == -1)
402 m_emitCap--;//emitCap keeps us from reemitting 'infinite' particles after their life. Unless you reset the emitter.
403 }
404
405 // Particle position
406 QRectF boundsRect;
407 if (!m_burstQueue.isEmpty()){
408 boundsRect = QRectF(m_burstQueue.first().second.x() - x(), m_burstQueue.first().second.y() - y(),
409 width(), height());
410 } else {
411 boundsRect = QRectF(emitter_x_offset + dex * (pt - opt) / dt, emitter_y_offset + dey * (pt - opt) / dt
412 , width(), height());
413 }
414 QPointF newPos = effectiveExtruder()->extrude(boundsRect);
415 datum->x = newPos.x();
416 datum->y = newPos.y();
417
418 // Particle velocity
419 const QPointF &velocity = m_velocity->sample(newPos);
420 datum->vx = velocity.x()
422 datum->vy = velocity.y()
424
425 // Particle acceleration
426 const QPointF &accel = m_acceleration->sample(newPos);
427 datum->ax = accel.x();
428 datum->ay = accel.y();
429
430 // Particle size
433
434 float size = qMax((qreal)0.0 , m_particleSize + sizeVariation);
435 float endSize = qMax((qreal)0.0 , sizeAtEnd + sizeVariation);
436
437 datum->size = size;// * float(m_emitting);
438 datum->endSize = endSize;// * float(m_emitting);
439
440 toEmit << datum;
441 }
442 if (m_burstQueue.isEmpty()){
443 pt += particleRatio;
444 }else{
445 m_burstQueue.first().first--;
446 if (m_burstQueue.first().first <= 0)
448 }
449 }
450
451 foreach (QQuickParticleData* d, toEmit)
452 m_system->emitParticle(d, this);
453
454 if (isEmitConnected()) {
455 //Done after emitParticle so that the Painter::load is done first, this allows you to customize its static variables
456 //We then don't need to request another reload, because the first reload isn't scheduled until we get back to the render thread
457
458 QList<QQuickV4ParticleData> particles;
459 particles.reserve(toEmit.size());
460 for (QQuickParticleData *particle : std::as_const(toEmit))
461 particles.push_back(particle->v4Value(m_system));
462
463 emit emitParticles(particles);//A chance for arbitrary JS changes
464 }
465
466 m_last_emission = pt;
467
469 m_last_emitter = QPointF(x(), y());
471}
472
473
475
476#include "moc_qquickparticleemitter_p.cpp"
T value(const Key &key) const noexcept
Definition qhash.h:1054
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
qreal x
\qmlproperty real QtQuick::Item::x \qmlproperty real QtQuick::Item::y \qmlproperty real QtQuick::Item...
Definition qquickitem.h:72
void componentComplete() override
\reimp Derived classes should call the base class method before adding their own actions to perform a...
qreal y
Defines the item's y position relative to its parent.
Definition qquickitem.h:73
qreal width
This property holds the width of this item.
Definition qquickitem.h:75
QQuickItem * parentItem() const
void enabledChanged()
qreal height
This property holds the height of this item.
Definition qquickitem.h:76
QQuickParticleExtruder * m_extruder
void setSystem(QQuickParticleSystem *arg)
QQuickParticleEmitter(QQuickItem *parent=nullptr)
Emits logical particles.
void emitParticles(const QList< QQuickV4ParticleData > &particles)
QQuickParticleExtruder * m_defaultExtruder
QQuickParticleSystem * m_system
void maximumEmittedChanged(int arg)
void componentComplete() override
\reimp Derived classes should call the base class method before adding their own actions to perform a...
void particleDurationChanged(int)
virtual void emitWindow(int timeStamp)
QList< QPair< int, QPointF > > m_burstQueue
void velocityFromMovementChanged()
QQuickParticleExtruder * effectiveExtruder()
void pulse(int milliseconds)
void particlesPerSecondChanged(qreal)
virtual QPointF extrude(const QRectF &)
QQuickParticleData * newDatum(int groupId, bool respectLimits=true, int sysIdx=-1, const QQuickParticleData *cloneFrom=nullptr)
void finishRegisteringParticleEmitter(QQuickParticleEmitter *e)
void emitParticle(QQuickParticleData *p, QQuickParticleEmitter *particleEmitter)
QHash< QString, int > groupIds
static Q_DECL_CONST_FUNCTION QRandomGenerator * global()
\threadsafe
Definition qrandom.h:275
\inmodule QtCore\reentrant
Definition qrect.h:484
QStyleOptionButton opt
Combined button and popup list for selecting options.
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLint GLint GLint GLint GLint x
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint y
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint num
GLbyte by
QT_BEGIN_NAMESPACE constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2) noexcept(noexcept(std::make_pair(std::forward< T1 >(value1), std::forward< T2 >(value2))))
Definition qpair.h:19
#define IS_SIGNAL_CONNECTED(Sender, SenderType, Name, Arguments)
SSL_CTX int void * arg
#define emit
double qreal
Definition qtypes.h:187
QObject::connect nullptr
myObject disconnect()
[26]