Qt 6.x
The Qt SDK
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
5#include <private/qqmlengine_p.h>
6#include <private/qqmlglobal_p.h>
7#include <private/qjsvalue_p.h>
8#include <QRandomGenerator>
10
14
183 , m_particlesPerSecond(10)
184 , m_particleDuration(1000)
185 , m_particleDurationVariation(0)
186 , m_enabled(true)
187 , m_system(nullptr)
188 , m_extruder(nullptr)
189 , m_defaultExtruder(nullptr)
190 , m_velocity(&m_nullVector)
191 , m_acceleration(&m_nullVector)
192 , m_particleSize(16)
193 , m_particleEndSize(-1)
194 , m_particleSizeVariation(0)
195 , m_startTime(0)
196 , m_overwrite(true)
197 , m_pulseLeft(0)
198 , m_maxParticleCount(-1)
199 , m_velocity_from_movement(0)
200 , m_reset_last(true)
201 , m_last_timestamp(-1)
202 , m_last_emission(0)
203 , m_groupIdNeedRecalculation(false)
204 , m_groupId(QQuickParticleGroupData::DefaultGroupID)
205
206{
207 //TODO: Reset velocity/acc back to null vector? Or allow null pointer?
212}
213
215{
217 delete m_defaultExtruder;
218}
219
221{
223}
224
226{
227 if (!m_system) {
229 return;
230 }
232 m_groupIdNeedRecalculation = m_groupId == QQuickParticleGroupData::InvalidID;
233}
234
236{
237 if (!m_system && qobject_cast<QQuickParticleSystem*>(parentItem()))
238 setSystem(qobject_cast<QQuickParticleSystem*>(parentItem()));
239 if (m_system)
242}
243
245{
246 if (m_enabled != arg) {
247 m_enabled = arg;
249 }
250}
251
252
254{
255 if (m_extruder)
256 return m_extruder;
259 return m_defaultExtruder;
260}
261
262void QQuickParticleEmitter::pulse(int milliseconds)
263{
264 if (!m_enabled)
265 m_pulseLeft = milliseconds;
266}
267
269{
270 m_burstQueue << qMakePair(num, QPointF(x(), y()));
271}
272
274{
276}
277
279{
280 if (m_maxParticleCount != arg) {
281 if (arg < 0 && m_maxParticleCount >= 0){
286 }else if (arg >= 0 && m_maxParticleCount < 0){
291 }
292 m_overwrite = arg < 0;
296 }
297}
298
300{
302 return;
305}
306
308{
309 m_reset_last = true;
310}
311
313{
314 if (m_system == nullptr)
315 return;
317 m_reset_last = true;
318 return;
319 }
320
321 if (m_reset_last) {
323 if (m_last_timestamp == -1)
324 m_last_timestamp = (timeStamp - m_startTime)/1000.;
325 else
326 m_last_timestamp = timeStamp/1000.;
328 m_reset_last = false;
329 m_emitCap = -1;
330 }
331
332 if (m_pulseLeft){
333 m_pulseLeft -= timeStamp - m_last_timestamp * 1000.;
334 if (m_pulseLeft < 0){
335 if (!m_enabled)
336 timeStamp += m_pulseLeft;
337 m_pulseLeft = 0;
338 }
339 }
340 qreal time = timeStamp / 1000.;
341 qreal particleRatio = 1. / m_particlesPerSecond;
344 if (pt + maxLife < time)//We missed so much, that we should skip emiting particles that are dead by now
345 pt = time - maxLife;
346
347 qreal opt = pt; // original particle time
348 qreal dt = time - m_last_timestamp; // timestamp delta...
349 if (!dt)
350 dt = 0.000001;
351
352 // emitter difference since last...
353 qreal dex = (x() - m_last_emitter.x());
354 qreal dey = (y() - m_last_emitter.y());
355
356 qreal ax = (m_last_last_emitter.x() + m_last_emitter.x()) / 2;
357 qreal bx = m_last_emitter.x();
358 qreal cx = (x() + m_last_emitter.x()) / 2;
359 qreal ay = (m_last_last_emitter.y() + m_last_emitter.y()) / 2;
361 qreal cy = (y() + m_last_emitter.y()) / 2;
362
364 qreal emitter_x_offset = m_last_emitter.x() - x();
365 qreal emitter_y_offset = m_last_emitter.y() - y();
366 if (!m_burstQueue.isEmpty() && !m_pulseLeft && !m_enabled)//'outside time' emissions only
367 pt = time;
368
370
371 while ((pt < time && m_emitCap) || !m_burstQueue.isEmpty()) {
372 //int pos = m_last_particle % m_particle_count;
374 if (datum){//actually emit(otherwise we've been asked to skip this one)
375 qreal t = 1 - (pt - opt) / dt;
376 qreal vx =
377 - 2 * ax * (1 - t)
378 + 2 * bx * (1 - 2 * t)
379 + 2 * cx * t;
380 qreal vy =
381 - 2 * ay * (1 - t)
382 + 2 * by * (1 - 2 * t)
383 + 2 * cy * t;
384
385
386 // Particle timestamp
387 datum->t = pt;
388 datum->lifeSpan =
391 / 1000.0;
392
393 if (datum->lifeSpan >= m_system->maxLife){
394 datum->lifeSpan = m_system->maxLife;
395 if (m_emitCap == -1)
397 m_emitCap--;//emitCap keeps us from reemitting 'infinite' particles after their life. Unless you reset the emitter.
398 }
399
400 // Particle position
401 QRectF boundsRect;
402 if (!m_burstQueue.isEmpty()){
403 boundsRect = QRectF(m_burstQueue.first().second.x() - x(), m_burstQueue.first().second.y() - y(),
404 width(), height());
405 } else {
406 boundsRect = QRectF(emitter_x_offset + dex * (pt - opt) / dt, emitter_y_offset + dey * (pt - opt) / dt
407 , width(), height());
408 }
409 QPointF newPos = effectiveExtruder()->extrude(boundsRect);
410 datum->x = newPos.x();
411 datum->y = newPos.y();
412
413 // Particle velocity
414 const QPointF &velocity = m_velocity->sample(newPos);
415 datum->vx = velocity.x()
417 datum->vy = velocity.y()
419
420 // Particle acceleration
421 const QPointF &accel = m_acceleration->sample(newPos);
422 datum->ax = accel.x();
423 datum->ay = accel.y();
424
425 // Particle size
428
429 float size = qMax((qreal)0.0 , m_particleSize + sizeVariation);
430 float endSize = qMax((qreal)0.0 , sizeAtEnd + sizeVariation);
431
432 datum->size = size;// * float(m_emitting);
433 datum->endSize = endSize;// * float(m_emitting);
434
435 toEmit << datum;
436 }
437 if (m_burstQueue.isEmpty()){
438 pt += particleRatio;
439 }else{
440 m_burstQueue.first().first--;
441 if (m_burstQueue.first().first <= 0)
443 }
444 }
445
446 foreach (QQuickParticleData* d, toEmit)
447 m_system->emitParticle(d, this);
448
449 if (isEmitConnected()) {
452 QV4::Scope scope(v4);
453
454 //Done after emitParticle so that the Painter::load is done first, this allows you to customize its static variables
455 //We then don't need to request another reload, because the first reload isn't scheduled until we get back to the render thread
456 QV4::ScopedArrayObject array(scope, v4->newArrayObject(toEmit.size()));
457 QV4::ScopedValue v(scope);
458 for (int i=0; i<toEmit.size(); i++)
459 array->put(i, (v = toEmit[i]->v4Value(m_system)));
460
461 QJSValue particles;
462 QJSValuePrivate::setValue(&particles, array);
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:1044
QV4::ExecutionEngine * handle() const
Definition qjsengine.h:292
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
qreal x
\qmlproperty real QtQuick::Item::x \qmlproperty real QtQuick::Item::y \qmlproperty real QtQuick::Item...
Definition qquickitem.h:73
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:74
qreal width
This property holds the width of this item.
Definition qquickitem.h:76
QQuickItem * parentItem() const
qreal height
This property holds the height of this item.
Definition qquickitem.h:77
QQuickParticleExtruder * m_extruder
void setSystem(QQuickParticleSystem *arg)
void emitParticles(const QJSValue &particles)
QQuickParticleEmitter(QQuickItem *parent=nullptr)
Emits logical particles.
QQuickParticleExtruder * m_defaultExtruder
QQuickParticleSystem * m_system
void enabledChanged(bool)
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 &)
void finishRegisteringParticleEmitter(QQuickParticleEmitter *e)
void emitParticle(QQuickParticleData *p, QQuickParticleEmitter *particleEmitter)
QHash< QString, int > groupIds
QQuickParticleData * newDatum(int groupId, bool respectLimits=true, int sysIdx=-1)
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
QStyleOptionButton opt
Combined button and popup list for selecting options.
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
#define SIGNAL(a)
Definition qobjectdefs.h:52
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint y
GLenum array
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint num
GLbyte by
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
QQmlEngine * qmlEngine(const QObject *obj)
Definition qqml.cpp:76
#define IS_SIGNAL_CONNECTED(Sender, SenderType, Name, Arguments)
SSL_CTX int(*) void arg)
#define emit
double qreal
Definition qtypes.h:92
QObject::connect nullptr
myObject disconnect()
[26]
Heap::ArrayObject * newArrayObject(int count=0)
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent