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);
284void QQuickParticleEmitter::setMaxParticleCount(
int arg)
286 if (m_maxParticleCount != arg) {
287 if (arg < 0 && m_maxParticleCount >= 0){
288 connect(
this, &QQuickParticleEmitter::particlesPerSecondChanged,
289 this, &QQuickParticleEmitter::particleCountChanged);
290 connect(
this, &QQuickParticleEmitter::particleDurationChanged,
291 this, &QQuickParticleEmitter::particleCountChanged);
292 }
else if (arg >= 0 && m_maxParticleCount < 0){
293 disconnect(
this, &QQuickParticleEmitter::particlesPerSecondChanged,
294 this, &QQuickParticleEmitter::particleCountChanged);
295 disconnect(
this, &QQuickParticleEmitter::particleDurationChanged,
296 this, &QQuickParticleEmitter::velocityFromMovementChanged);
298 m_overwrite = arg < 0;
299 m_maxParticleCount = arg;
300 emit maximumEmittedChanged(arg);
301 emit particleCountChanged();
318void QQuickParticleEmitter::emitWindow(
int timeStamp)
320 if (m_system ==
nullptr)
322 if ((!m_enabled || m_particlesPerSecond <= 0)&& !m_pulseLeft && m_burstQueue.isEmpty()){
328 m_last_emitter = m_last_last_emitter = QPointF(x(), y());
329 if (m_last_timestamp == -1)
330 m_last_timestamp = (timeStamp - m_startTime)/1000.;
332 m_last_timestamp = timeStamp/1000.;
333 m_last_emission = m_last_timestamp;
334 m_reset_last =
false;
339 m_pulseLeft -= timeStamp - m_last_timestamp * 1000.;
340 if (m_pulseLeft < 0){
342 timeStamp += m_pulseLeft;
346 qreal time = timeStamp / 1000.;
347 qreal particleRatio = 1. / m_particlesPerSecond;
348 qreal pt = m_last_emission;
349 qreal maxLife = (m_particleDuration + m_particleDurationVariation)/1000.0;
350 if (pt + maxLife < time)
354 qreal dt = time - m_last_timestamp;
359 qreal dex = (x() - m_last_emitter.x());
360 qreal dey = (y() - m_last_emitter.y());
362 qreal ax = (m_last_last_emitter.x() + m_last_emitter.x()) / 2;
363 qreal bx = m_last_emitter.x();
364 qreal cx = (x() + m_last_emitter.x()) / 2;
365 qreal ay = (m_last_last_emitter.y() + m_last_emitter.y()) / 2;
366 qreal by = m_last_emitter.y();
367 qreal cy = (y() + m_last_emitter.y()) / 2;
369 qreal sizeAtEnd = m_particleEndSize >= 0 ? m_particleEndSize : m_particleSize;
370 qreal emitter_x_offset = m_last_emitter.x() - x();
371 qreal emitter_y_offset = m_last_emitter.y() - y();
372 if (!m_burstQueue.isEmpty() && !m_pulseLeft && !m_enabled)
375 QList<QQuickParticleData*> toEmit;
377 while ((pt < time && m_emitCap) || !m_burstQueue.isEmpty()) {
379 QQuickParticleData* datum = m_system->newDatum(m_system->groupIds[m_group], !m_overwrite);
381 qreal t = 1 - (pt - opt) / dt;
384 + 2 * bx * (1 - 2 * t)
388 + 2 * by * (1 - 2 * t)
396 + (QRandomGenerator::global()->bounded((m_particleDurationVariation*2) + 1) - m_particleDurationVariation))
399 if (datum->lifeSpan >= m_system->maxLife){
400 datum->lifeSpan = m_system->maxLife;
402 m_emitCap = particleCount();
408 if (!m_burstQueue.isEmpty()){
409 boundsRect = QRectF(m_burstQueue.first().second.x() - x(), m_burstQueue.first().second.y() - y(),
412 boundsRect = QRectF(emitter_x_offset + dex * (pt - opt) / dt, emitter_y_offset + dey * (pt - opt) / dt
413 , width(), height());
415 QPointF newPos = effectiveExtruder()->extrude(boundsRect);
416 datum->x = newPos.x();
417 datum->y = newPos.y();
420 const QPointF &velocity = m_velocity->sample(newPos);
421 datum->vx = velocity.x()
422 + m_velocity_from_movement * vx;
423 datum->vy = velocity.y()
424 + m_velocity_from_movement * vy;
427 const QPointF &accel = m_acceleration->sample(newPos);
428 datum->ax = accel.x();
429 datum->ay = accel.y();
432 float sizeVariation = -m_particleSizeVariation
433 + QRandomGenerator::global()->bounded(m_particleSizeVariation * 2);
435 float size = qMax((qreal)0.0 , m_particleSize + sizeVariation);
436 float endSize = qMax((qreal)0.0 , sizeAtEnd + sizeVariation);
439 datum->endSize = endSize;
443 if (m_burstQueue.isEmpty()){
446 m_burstQueue.first().first--;
447 if (m_burstQueue.first().first <= 0)
448 m_burstQueue.pop_front();
452 foreach (QQuickParticleData* d, toEmit)
453 m_system->emitParticle(d,
this);
455 if (isEmitConnected()) {
459 QList<QQuickV4ParticleData> particles;
460 particles.reserve(toEmit.size());
461 for (QQuickParticleData *particle : std::as_const(toEmit))
462 particles.push_back(particle->v4Value(m_system));
464 emit emitParticles(particles);
467 m_last_emission = pt;
469 m_last_last_emitter = m_last_emitter;
470 m_last_emitter = QPointF(x(), y());
471 m_last_timestamp = time;