185QQuickParticleEmitter::QQuickParticleEmitter(QQuickItem *parent) :
187 , m_particlesPerSecond(10)
188 , m_particleDuration(1000)
189 , m_particleDurationVariation(0)
192 , m_extruder(
nullptr)
193 , m_defaultExtruder(
nullptr)
194 , m_velocity(&m_nullVector)
195 , m_acceleration(&m_nullVector)
197 , m_particleEndSize(-1)
198 , m_particleSizeVariation(0)
202 , m_maxParticleCount(-1)
203 , m_velocity_from_movement(0)
205 , m_last_timestamp(-1)
207 , m_groupIdNeedRecalculation(
false)
208 , m_groupId(QQuickParticleGroupData::DefaultGroupID)
212 connect(
this, &QQuickParticleEmitter::particlesPerSecondChanged,
213 this, &QQuickParticleEmitter::particleCountChanged);
214 connect(
this, &QQuickParticleEmitter::particleDurationChanged,
215 this, &QQuickParticleEmitter::particleCountChanged);
283void QQuickParticleEmitter::setMaxParticleCount(
int arg)
285 if (m_maxParticleCount != arg) {
286 if (arg < 0 && m_maxParticleCount >= 0){
287 connect(
this, &QQuickParticleEmitter::particlesPerSecondChanged,
288 this, &QQuickParticleEmitter::particleCountChanged);
289 connect(
this, &QQuickParticleEmitter::particleDurationChanged,
290 this, &QQuickParticleEmitter::particleCountChanged);
291 }
else if (arg >= 0 && m_maxParticleCount < 0){
292 disconnect(
this, &QQuickParticleEmitter::particlesPerSecondChanged,
293 this, &QQuickParticleEmitter::particleCountChanged);
294 disconnect(
this, &QQuickParticleEmitter::particleDurationChanged,
295 this, &QQuickParticleEmitter::velocityFromMovementChanged);
297 m_overwrite = arg < 0;
298 m_maxParticleCount = arg;
299 emit maximumEmittedChanged(arg);
300 emit particleCountChanged();
317void QQuickParticleEmitter::emitWindow(
int timeStamp)
319 if (m_system ==
nullptr)
321 if ((!m_enabled || m_particlesPerSecond <= 0)&& !m_pulseLeft && m_burstQueue.isEmpty()){
327 m_last_emitter = m_last_last_emitter = QPointF(x(), y());
328 if (m_last_timestamp == -1)
329 m_last_timestamp = (timeStamp - m_startTime)/1000.;
331 m_last_timestamp = timeStamp/1000.;
332 m_last_emission = m_last_timestamp;
333 m_reset_last =
false;
338 m_pulseLeft -= timeStamp - m_last_timestamp * 1000.;
339 if (m_pulseLeft < 0){
341 timeStamp += m_pulseLeft;
345 qreal time = timeStamp / 1000.;
346 qreal particleRatio = 1. / m_particlesPerSecond;
347 qreal pt = m_last_emission;
348 qreal maxLife = (m_particleDuration + m_particleDurationVariation)/1000.0;
349 if (pt + maxLife < time)
353 qreal dt = time - m_last_timestamp;
358 qreal dex = (x() - m_last_emitter.x());
359 qreal dey = (y() - m_last_emitter.y());
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;
365 qreal by = m_last_emitter.y();
366 qreal cy = (y() + m_last_emitter.y()) / 2;
368 qreal sizeAtEnd = m_particleEndSize >= 0 ? m_particleEndSize : m_particleSize;
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)
374 QList<QQuickParticleData*> toEmit;
376 while ((pt < time && m_emitCap) || !m_burstQueue.isEmpty()) {
378 QQuickParticleData* datum = m_system->newDatum(m_system->groupIds[m_group], !m_overwrite);
380 qreal t = 1 - (pt - opt) / dt;
383 + 2 * bx * (1 - 2 * t)
387 + 2 * by * (1 - 2 * t)
395 + (QRandomGenerator::global()->bounded((m_particleDurationVariation*2) + 1) - m_particleDurationVariation))
398 if (datum->lifeSpan >= m_system->maxLife){
399 datum->lifeSpan = m_system->maxLife;
401 m_emitCap = particleCount();
407 if (!m_burstQueue.isEmpty()){
408 boundsRect = QRectF(m_burstQueue.first().second.x() - x(), m_burstQueue.first().second.y() - y(),
411 boundsRect = QRectF(emitter_x_offset + dex * (pt - opt) / dt, emitter_y_offset + dey * (pt - opt) / dt
412 , width(), height());
414 QPointF newPos = effectiveExtruder()->extrude(boundsRect);
415 datum->x = newPos.x();
416 datum->y = newPos.y();
419 const QPointF &velocity = m_velocity->sample(newPos);
420 datum->vx = velocity.x()
421 + m_velocity_from_movement * vx;
422 datum->vy = velocity.y()
423 + m_velocity_from_movement * vy;
426 const QPointF &accel = m_acceleration->sample(newPos);
427 datum->ax = accel.x();
428 datum->ay = accel.y();
431 float sizeVariation = -m_particleSizeVariation
432 + QRandomGenerator::global()->bounded(m_particleSizeVariation * 2);
434 float size = qMax((qreal)0.0 , m_particleSize + sizeVariation);
435 float endSize = qMax((qreal)0.0 , sizeAtEnd + sizeVariation);
438 datum->endSize = endSize;
442 if (m_burstQueue.isEmpty()){
445 m_burstQueue.first().first--;
446 if (m_burstQueue.first().first <= 0)
447 m_burstQueue.pop_front();
451 foreach (QQuickParticleData* d, toEmit)
452 m_system->emitParticle(d,
this);
454 if (isEmitConnected()) {
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));
463 emit emitParticles(particles);
466 m_last_emission = pt;
468 m_last_last_emitter = m_last_emitter;
469 m_last_emitter = QPointF(x(), y());
470 m_last_timestamp = time;