186QQuickParticleEmitter::QQuickParticleEmitter(QQuickItem *parent) :
188 , m_particlesPerSecond(10)
189 , m_particleDuration(1000)
190 , m_particleDurationVariation(0)
193 , m_extruder(
nullptr)
194 , m_defaultExtruder(
nullptr)
195 , m_velocity(&m_nullVector)
196 , m_acceleration(&m_nullVector)
198 , m_particleEndSize(-1)
199 , m_particleSizeVariation(0)
203 , m_maxParticleCount(-1)
204 , m_velocity_from_movement(0)
206 , m_last_timestamp(-1)
208 , m_groupIdNeedRecalculation(
false)
209 , m_groupId(QQuickParticleGroupData::DefaultGroupID)
213 connect(
this, &QQuickParticleEmitter::particlesPerSecondChanged,
214 this, &QQuickParticleEmitter::particleCountChanged);
215 connect(
this, &QQuickParticleEmitter::particleDurationChanged,
216 this, &QQuickParticleEmitter::particleCountChanged);
290void QQuickParticleEmitter::setMaxParticleCount(
int arg)
292 if (m_maxParticleCount != arg) {
293 if (arg < 0 && m_maxParticleCount >= 0){
294 connect(
this, &QQuickParticleEmitter::particlesPerSecondChanged,
295 this, &QQuickParticleEmitter::particleCountChanged);
296 connect(
this, &QQuickParticleEmitter::particleDurationChanged,
297 this, &QQuickParticleEmitter::particleCountChanged);
298 }
else if (arg >= 0 && m_maxParticleCount < 0){
299 disconnect(
this, &QQuickParticleEmitter::particlesPerSecondChanged,
300 this, &QQuickParticleEmitter::particleCountChanged);
301 disconnect(
this, &QQuickParticleEmitter::particleDurationChanged,
302 this, &QQuickParticleEmitter::velocityFromMovementChanged);
304 m_overwrite = arg < 0;
305 m_maxParticleCount = arg;
306 callSystemEmittersChanged();
307 emit maximumEmittedChanged(arg);
308 emit particleCountChanged();
325void QQuickParticleEmitter::emitWindow(
int timeStamp)
327 if (m_system ==
nullptr)
329 if ((!m_enabled || m_particlesPerSecond <= 0)&& !m_pulseLeft && m_burstQueue.isEmpty()){
335 m_last_emitter = m_last_last_emitter = QPointF(x(), y());
336 if (m_last_timestamp == -1)
337 m_last_timestamp = (timeStamp - m_startTime)/1000.;
339 m_last_timestamp = timeStamp/1000.;
340 m_last_emission = m_last_timestamp;
341 m_reset_last =
false;
346 m_pulseLeft -= timeStamp - m_last_timestamp * 1000.;
347 if (m_pulseLeft < 0){
349 timeStamp += m_pulseLeft;
353 qreal time = timeStamp / 1000.;
354 qreal particleRatio = 1. / m_particlesPerSecond;
355 qreal pt = m_last_emission;
356 qreal maxLife = (m_particleDuration + m_particleDurationVariation)/1000.0;
357 if (pt + maxLife < time)
361 qreal dt = time - m_last_timestamp;
366 qreal dex = (x() - m_last_emitter.x());
367 qreal dey = (y() - m_last_emitter.y());
369 qreal ax = (m_last_last_emitter.x() + m_last_emitter.x()) / 2;
370 qreal bx = m_last_emitter.x();
371 qreal cx = (x() + m_last_emitter.x()) / 2;
372 qreal ay = (m_last_last_emitter.y() + m_last_emitter.y()) / 2;
373 qreal by = m_last_emitter.y();
374 qreal cy = (y() + m_last_emitter.y()) / 2;
376 qreal sizeAtEnd = m_particleEndSize >= 0 ? m_particleEndSize : m_particleSize;
377 qreal emitter_x_offset = m_last_emitter.x() - x();
378 qreal emitter_y_offset = m_last_emitter.y() - y();
379 if (!m_burstQueue.isEmpty() && !m_pulseLeft && !m_enabled)
382 QList<QQuickParticleData*> toEmit;
384 while ((pt < time && m_emitCap) || !m_burstQueue.isEmpty()) {
386 QQuickParticleData* datum = m_system->newDatum(m_system->groupIds[m_group], !m_overwrite);
388 qreal t = 1 - (pt - opt) / dt;
391 + 2 * bx * (1 - 2 * t)
395 + 2 * by * (1 - 2 * t)
403 + (QRandomGenerator::global()->bounded((m_particleDurationVariation*2) + 1) - m_particleDurationVariation))
406 if (datum->lifeSpan >= m_system->maxLife){
407 datum->lifeSpan = m_system->maxLife;
409 m_emitCap = particleCount();
415 if (!m_burstQueue.isEmpty()){
416 boundsRect = QRectF(m_burstQueue.first().second.x() - x(), m_burstQueue.first().second.y() - y(),
419 boundsRect = QRectF(emitter_x_offset + dex * (pt - opt) / dt, emitter_y_offset + dey * (pt - opt) / dt
420 , width(), height());
422 QPointF newPos = effectiveExtruder()->extrude(boundsRect);
423 datum->x = newPos.x();
424 datum->y = newPos.y();
427 const QPointF &velocity = m_velocity->sample(newPos);
428 datum->vx = velocity.x()
429 + m_velocity_from_movement * vx;
430 datum->vy = velocity.y()
431 + m_velocity_from_movement * vy;
434 const QPointF &accel = m_acceleration->sample(newPos);
435 datum->ax = accel.x();
436 datum->ay = accel.y();
439 float sizeVariation = -m_particleSizeVariation
440 + QRandomGenerator::global()->bounded(m_particleSizeVariation * 2);
442 float size = qMax((qreal)0.0 , m_particleSize + sizeVariation);
443 float endSize = qMax((qreal)0.0 , sizeAtEnd + sizeVariation);
446 datum->endSize = endSize;
450 if (m_burstQueue.isEmpty()){
453 m_burstQueue.first().first--;
454 if (m_burstQueue.first().first <= 0)
455 m_burstQueue.pop_front();
459 foreach (QQuickParticleData* d, toEmit)
460 m_system->emitParticle(d,
this);
462 if (isEmitConnected()) {
466 QList<QQuickV4ParticleData> particles;
467 particles.reserve(toEmit.size());
468 for (QQuickParticleData *particle : std::as_const(toEmit))
469 particles.push_back(particle->v4Value(m_system));
471 emit emitParticles(particles);
474 m_last_emission = pt;
476 m_last_last_emitter = m_last_emitter;
477 m_last_emitter = QPointF(x(), y());
478 m_last_timestamp = time;