6#include <QtQuick3D/private/qquick3dquaternionutils_p.h>
12#include <private/qqmldelegatemodel_p.h>
17#include <QtQuick3DUtils/private/qquick3dprofiler_p.h>
18#include <qtquick3d_tracepoints_p.h>
20#include <QtGui/qquaternion.h>
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
69QQuick3DParticleSystem::QQuick3DParticleSystem(QQuick3DNode *parent)
70 : QQuick3DNode(parent)
73 , m_initialized(
false)
74 , m_componentComplete(
false)
75 , m_animation(
new QQuick3DParticleSystemAnimation(
this))
76 , m_updateAnimation(
new QQuick3DParticleSystemUpdate(
this))
78 , m_loggingData(
new QQuick3DParticleSystemLogging(
this))
80 connect(m_loggingData, &QQuick3DParticleSystemLogging::loggingIntervalChanged, &m_loggingTimer, [
this]() {
81 m_loggingTimer.setInterval(m_loggingData->m_loggingInterval);
85 connect(
this, &QQuick3DNode::layersChanged,
this, [
this]() {
86 for (
auto *particle : std::as_const(m_particles))
87 particle->updateNodeLayers();
91QQuick3DParticleSystem::~QQuick3DParticleSystem()
94 m_updateAnimation->stop();
96 for (
const auto &connection : std::as_const(m_connections))
97 QObject::disconnect(connection);
99 const auto particles = m_particles;
100 const auto emitters = m_emitters;
101 const auto trailEmitters = m_trailEmitters;
102 const auto affectors = m_affectors;
103 for (
auto *particle : particles)
104 particle->setSystem(
nullptr);
105 for (
auto *emitter : emitters)
106 emitter->setSystem(
nullptr);
107 for (
auto *emitter : trailEmitters)
108 emitter->setSystem(
nullptr);
109 for (
auto *affector : affectors)
110 affector->setSystem(
nullptr);
114
115
116
117
118
119
120
121
122
123
124bool QQuick3DParticleSystem::isRunning()
const
130
131
132
133
134
135
136
137
138bool QQuick3DParticleSystem::isPaused()
const
144
145
146
147
148
149
150
151
152
153int QQuick3DParticleSystem::startTime()
const
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179int QQuick3DParticleSystem::time()
const
185
186
187
188
189
190
191
192
193
194
195
196
197bool QQuick3DParticleSystem::useRandomSeed()
const
199 return m_useRandomSeed;
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217int QQuick3DParticleSystem::seed()
const
223
224
225
226
227
228
229
230
231
232
233bool QQuick3DParticleSystem::logging()
const
239
240
241
242
243
244
245
246
247
248
249
250QQuick3DParticleSystemLogging *QQuick3DParticleSystem::loggingData()
const
252 return m_loggingData;
256
257
258
259
260
261
262
263
264void QQuick3DParticleSystem::reset()
266 for (
auto emitter : std::as_const(m_emitters))
268 for (
auto emitter : std::as_const(m_trailEmitters))
270 for (
auto particle : std::as_const(m_particles))
272 m_particleIdIndex = 0;
276
277
278
279int QQuick3DParticleSystem::currentTime()
const
281 return m_currentTime;
284void QQuick3DParticleSystem::setRunning(
bool running)
286 if (m_running != running) {
288 Q_EMIT runningChanged();
294 if (m_componentComplete && !m_running && m_useRandomSeed)
295 doSeedRandomization();
297 (m_running && !isEditorModeOn()) ? m_animation->start() : m_animation->stop();
301void QQuick3DParticleSystem::setPaused(
bool paused)
303 if (m_paused != paused) {
305 if (m_animation->state() != QAbstractAnimation::Stopped)
306 m_paused ? m_animation->pause() : m_animation->resume();
307 Q_EMIT pausedChanged();
311void QQuick3DParticleSystem::setStartTime(
int startTime)
313 if (m_startTime == startTime)
316 m_startTime = startTime;
317 m_updateAnimation->setDirty(
true);
318 Q_EMIT startTimeChanged();
321void QQuick3DParticleSystem::setTime(
int time)
328 m_updateAnimation->setDirty(
true);
330 Q_EMIT timeChanged();
333void QQuick3DParticleSystem::setUseRandomSeed(
bool randomize)
335 if (m_useRandomSeed == randomize)
338 m_useRandomSeed = randomize;
342 doSeedRandomization();
343 m_rand.setDeterministic(!m_useRandomSeed);
344 Q_EMIT useRandomSeedChanged();
347void QQuick3DParticleSystem::setSeed(
int seed)
354 Q_EMIT seedChanged();
357void QQuick3DParticleSystem::setLogging(
bool logging)
359 if (m_logging == logging)
364 resetLoggingVariables();
365 m_loggingData->resetData();
368 m_loggingTimer.start();
370 m_loggingTimer.stop();
372 Q_EMIT loggingChanged();
376
377
378
379void QQuick3DParticleSystem::setEditorTime(
int time)
381 if (m_editorTime == time)
386 m_updateAnimation->setDirty(
true);
389void QQuick3DParticleSystem::componentComplete()
391 QQuick3DNode::componentComplete();
392 m_componentComplete =
true;
393 m_updateAnimation->start();
395 connect(&m_loggingTimer, &QTimer::timeout,
this, &QQuick3DParticleSystem::updateLoggingData);
396 m_loggingTimer.setInterval(m_loggingData->m_loggingInterval);
399 doSeedRandomization();
407 Q_EMIT timeChanged();
410 if (m_animation->state() == QAbstractAnimation::Running)
412 if (m_running && !isEditorModeOn())
413 m_animation->start();
415 m_animation->pause();
417 m_initialized =
true;
420void QQuick3DParticleSystem::refresh()
425 if (!m_running || m_paused || isEditorModeOn())
426 m_animation->setCurrentTime(isEditorModeOn() ? m_editorTime : m_time);
429void QQuick3DParticleSystem::markDirty()
432 m_updateAnimation->setDirty(
true);
435int QQuick3DParticleSystem::particleCount()
const
438 for (
auto particle : std::as_const(m_particles))
439 pCount += particle->maxAmount();
443void QQuick3DParticleSystem::registerParticle(QQuick3DParticle *particle)
445 m_particles << particle;
448void QQuick3DParticleSystem::unRegisterParticle(QQuick3DParticle *particle)
450 m_particles.removeAll(particle);
453void QQuick3DParticleSystem::registerParticleEmitter(QQuick3DParticleEmitter *e)
455 auto te = qobject_cast<QQuick3DParticleTrailEmitter *>(e);
457 m_trailEmitters << te;
462void QQuick3DParticleSystem::unRegisterParticleEmitter(QQuick3DParticleEmitter *e)
464 auto te = qobject_cast<QQuick3DParticleTrailEmitter *>(e);
466 m_trailEmitters.removeAll(te);
468 m_emitters.removeAll(e);
471void QQuick3DParticleSystem::registerParticleAffector(QQuick3DParticleAffector *a)
474 m_connections.insert(a, connect(a, &QQuick3DParticleAffector::update,
this, &QQuick3DParticleSystem::markDirty));
477void QQuick3DParticleSystem::unRegisterParticleAffector(QQuick3DParticleAffector *a)
479 QObject::disconnect(m_connections[a]);
480 m_connections.remove(a);
481 m_affectors.removeAll(a);
484void QQuick3DParticleSystem::updateCurrentTime(
int currentTime)
486 if (!m_initialized || isGloballyDisabled() || (isEditorModeOn() && !visible()))
489 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DParticleUpdate);
491 Q_TRACE(QSSG_particleUpdate_entry);
493 m_currentTime = currentTime;
494 const float timeS =
float(m_currentTime / 1000.0f);
503 for (
auto emitter : std::as_const(m_emitters))
504 emitter->emitParticles();
507 for (
auto affector : std::as_const(m_affectors)) {
508 if (affector->m_enabled)
509 affector->prepareToAffect();
513 for (
auto particle : std::as_const(m_particles)) {
516 QVector<TrailEmits> trailEmits;
517 for (
auto emitter : std::as_const(m_trailEmitters)) {
518 if (emitter->follow() == particle) {
519 int emitAmount = emitter->getEmitAmount();
520 if (emitAmount > 0 || emitter->hasBursts()) {
523 e.amount = emitAmount;
529 m_particlesMax += particle->maxAmount();
531 QQuick3DParticleSpriteParticle *spriteParticle = qobject_cast<QQuick3DParticleSpriteParticle *>(particle);
532 if (spriteParticle) {
533 processSpriteParticle(spriteParticle, trailEmits, timeS);
536 QQuick3DParticleModelParticle *modelParticle = qobject_cast<QQuick3DParticleModelParticle *>(particle);
538 processModelParticle(modelParticle, trailEmits, timeS);
541 QQuick3DParticleModelBlendParticle *mbp = qobject_cast<QQuick3DParticleModelBlendParticle *>(particle);
543 processModelBlendParticle(mbp, trailEmits, timeS);
549 for (
auto emitter : std::as_const(m_trailEmitters))
550 emitter->clearBursts();
552 m_timeAnimation += m_perfTimer.nsecsElapsed();
553 m_updateAnimation->setDirty(
false);
554 Q_QUICK3D_PROFILE_END_WITH_ID(QQuick3DProfiler::Quick3DParticleUpdate, m_particlesUsed, Q_QUICK3D_PROFILE_GET_ID(
this));
556 Q_TRACE(QSSG_particleUpdate_exit, m_particlesUsed);
560void QQuick3DParticleSystem::processModelParticle(QQuick3DParticleModelParticle *modelParticle,
const QVector<TrailEmits> &trailEmits,
float timeS)
562 modelParticle->clearInstanceTable();
564 const int c = modelParticle->maxAmount();
566 for (
int i = 0; i < c; i++) {
567 const auto d = &modelParticle->m_particleData.at(i);
569 const float particleTimeEnd = d->startTime + d->lifetime;
571 if (timeS < d->startTime || timeS > particleTimeEnd) {
572 if (timeS > particleTimeEnd && d->lifetime > 0.0f) {
573 const auto pos = d->reversed ? d->startPosition : d->startPosition + (d->startVelocity * (particleTimeEnd - d->startTime));
574 for (
auto trailEmit : std::as_const(trailEmits))
575 trailEmit.emitter->emitTrailParticles(pos, 0, QQuick3DParticleDynamicBurst::TriggerEnd, d->surfaceNormal, d->startVelocity.normalized());
581 QQuick3DParticleDataCurrent currentData;
582 if (timeS >= d->startTime && d->lifetime <= 0.0f) {
583 for (
auto trailEmit : std::as_const(trailEmits))
584 trailEmit.emitter->emitTrailParticles(d->startPosition, 0, QQuick3DParticleDynamicBurst::TriggerStart, d->surfaceNormal, d->startVelocity.normalized());
588 const float particleTimeS = d->reversed ? particleTimeEnd - timeS : timeS - d->startTime;
591 processParticleCommon(currentData, d, particleTimeS);
594 if (modelParticle->m_alignMode != QQuick3DParticle::AlignNone)
595 processParticleAlignment(currentData, modelParticle, d);
598 const float timeChange = std::max(0.0f, std::min(1.0f, particleTimeS / d->lifetime));
601 currentData.scale = modelParticle->m_initialScale * (d->endSize * timeChange + d->startSize * (1.0f - timeChange));
604 const float particleTimeLeftS = d->lifetime - particleTimeS;
605 processParticleFadeInOut(currentData, modelParticle, particleTimeS, particleTimeLeftS);
608 for (
auto affector : std::as_const(m_affectors)) {
610 if (affector->m_enabled && (affector->m_particles.isEmpty() || affector->m_particles.contains(modelParticle)))
611 affector->affectParticle(*d, ¤tData, particleTimeS);
615 for (
auto trailEmit : std::as_const(trailEmits))
616 trailEmit.emitter->emitTrailParticles(currentData.position, trailEmit.amount, QQuick3DParticleDynamicBurst::TriggerTime, d->surfaceNormal, d->startVelocity.normalized());
618 const QColor color(currentData.color.r, currentData.color.g, currentData.color.b, currentData.color.a);
620 modelParticle->addInstance(currentData.position, currentData.scale, currentData.rotation, color, timeChange);
622 modelParticle->commitInstance();
627 return (b - a) * f + a;
630void QQuick3DParticleSystem::processModelBlendParticle(QQuick3DParticleModelBlendParticle *particle,
const QVector<TrailEmits> &trailEmits,
float timeS)
632 const int c = particle->maxAmount();
634 for (
int i = 0; i < c; i++) {
635 const auto d = &particle->m_particleData.at(i);
637 const float particleTimeEnd = d->startTime + d->lifetime;
639 if (timeS < d->startTime || timeS > particleTimeEnd) {
640 if (timeS > particleTimeEnd && d->lifetime > 0.0f) {
641 const auto pos = d->reversed ? d->startPosition : d->startPosition + (d->startVelocity * (particleTimeEnd - d->startTime));
642 for (
auto trailEmit : std::as_const(trailEmits))
643 trailEmit.emitter->emitTrailParticles(pos, 0, QQuick3DParticleDynamicBurst::TriggerEnd, d->surfaceNormal, d->startVelocity.normalized());
650 QVector4D color(
float(d->startColor.r)/ 255.0f,
651 float(d->startColor.g)/ 255.0f,
652 float(d->startColor.b)/ 255.0f,
653 float(d->startColor.a)/ 255.0f);
654 if (d->startTime > 0.0f && timeS > particleTimeEnd
655 && (particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Construct ||
656 particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Transfer)) {
659 pos = particle->particleEndPosition(i);
660 rot = particle->particleEndRotation(i);
661 if (particle->fadeOutEffect() == QQuick3DParticle::FadeOpacity)
663 }
else if (particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Explode ||
664 particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Transfer) {
667 pos = particle->particleCenter(i);
668 if (particle->fadeInEffect() == QQuick3DParticle::FadeOpacity)
671 particle->setParticleData(i, pos, rot, color, size, age);
675 QQuick3DParticleDataCurrent currentData;
676 if (timeS >= d->startTime && d->lifetime <= 0.0f) {
677 for (
auto trailEmit : std::as_const(trailEmits))
678 trailEmit.emitter->emitTrailParticles(d->startPosition, 0, QQuick3DParticleDynamicBurst::TriggerStart, d->surfaceNormal, d->startVelocity.normalized());
682 const float particleTimeS = d->reversed ? particleTimeEnd - timeS : timeS - d->startTime;
685 processParticleCommon(currentData, d, particleTimeS);
688 const float timeChange = std::max(0.0f, std::min(1.0f, particleTimeS / d->lifetime));
691 const float scale = d->endSize * timeChange + d->startSize * (1.0f - timeChange);
692 currentData.scale = QVector3D(scale, scale, scale);
695 const float particleTimeLeftS = d->lifetime - particleTimeS;
696 processParticleFadeInOut(currentData, particle, particleTimeS, particleTimeLeftS);
699 for (
auto affector : std::as_const(m_affectors)) {
701 if (affector->m_enabled && (affector->m_particles.isEmpty() || affector->m_particles.contains(particle)))
702 affector->affectParticle(*d, ¤tData, particleTimeS);
706 for (
auto trailEmit : std::as_const(trailEmits))
707 trailEmit.emitter->emitTrailParticles(currentData.position, trailEmit.amount, QQuick3DParticleDynamicBurst::TriggerTime, d->surfaceNormal, d->startVelocity.normalized());
710 const QVector4D color(
float(currentData.color.r) / 255.0f,
711 float(currentData.color.g) / 255.0f,
712 float(currentData.color.b) / 255.0f,
713 float(currentData.color.a) / 255.0f);
714 float endTimeS = particle->endTime() * 0.001f;
715 if ((particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Construct ||
716 particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Transfer)
717 && particleTimeLeftS < endTimeS) {
718 QVector3D endPosition = particle->particleEndPosition(i);
719 QVector3D endRotation = particle->particleEndRotation(i);
720 float factor = 1.0f - particleTimeLeftS / endTimeS;
721 currentData.position = mix(currentData.position, endPosition, factor);
722 currentData.rotation = mix(currentData.rotation, endRotation, factor);
724 particle->setParticleData(i, currentData.position, currentData.rotation,
725 color, currentData.scale.x(), timeChange);
727 particle->commitParticles();
730void QQuick3DParticleSystem::processSpriteParticle(QQuick3DParticleSpriteParticle *spriteParticle,
const QVector<TrailEmits> &trailEmits,
float timeS)
732 const int c = spriteParticle->maxAmount();
734 for (
int i = 0; i < c; i++) {
735 const auto d = &spriteParticle->m_particleData.at(i);
737 const float particleTimeEnd = d->startTime + d->lifetime;
738 auto &particleData = spriteParticle->m_spriteParticleData[i];
739 if (timeS < d->startTime || timeS > particleTimeEnd) {
740 if (timeS > particleTimeEnd && particleData.age > 0.0f) {
741 const auto pos = d->reversed ? d->startPosition : d->startPosition + (d->startVelocity * (particleTimeEnd - d->startTime));
742 for (
auto trailEmit : std::as_const(trailEmits))
743 trailEmit.emitter->emitTrailParticles(pos, 0, QQuick3DParticleDynamicBurst::TriggerEnd, d->surfaceNormal, d->startVelocity.normalized());
744 auto *lineParticle = qobject_cast<QQuick3DParticleLineParticle *>(spriteParticle);
746 lineParticle->saveLineSegment(i, timeS);
749 spriteParticle->resetParticleData(i);
753 QQuick3DParticleDataCurrent currentData;
754 if (timeS >= d->startTime && timeS < particleTimeEnd && particleData.age == 0.0f) {
755 for (
auto trailEmit : std::as_const(trailEmits))
756 trailEmit.emitter->emitTrailParticles(d->startPosition, 0, QQuick3DParticleDynamicBurst::TriggerStart, d->surfaceNormal, d->startVelocity.normalized());
760 const float particleTimeS = d->reversed ? particleTimeEnd - timeS : timeS - d->startTime;
763 processParticleCommon(currentData, d, particleTimeS);
766 if (!spriteParticle->m_billboard && spriteParticle->m_alignMode != QQuick3DParticle::AlignNone)
767 processParticleAlignment(currentData, spriteParticle, d);
770 const float timeChange = std::max(0.0f, std::min(1.0f, particleTimeS / d->lifetime));
773 const float scale = d->endSize * timeChange + d->startSize * (1.0f - timeChange);
774 currentData.scale = QVector3D(scale, scale, scale);
777 const float particleTimeLeftS = d->lifetime - particleTimeS;
778 processParticleFadeInOut(currentData, spriteParticle, particleTimeS, particleTimeLeftS);
780 float animationFrame = 0.0f;
781 if (
auto sequence = spriteParticle->m_spriteSequence) {
784 const bool isSingleFrame = (sequence->animationDirection() == QQuick3DParticleSpriteSequence::SingleFrame);
785 float startFrame = sequence->firstFrame(d->index, isSingleFrame);
786 if (sequence->animationDirection() == QQuick3DParticleSpriteSequence::Normal) {
787 animationFrame = fmodf(startFrame + particleTimeS / d->animationTime, 1.0f);
788 }
else if (sequence->animationDirection() == QQuick3DParticleSpriteSequence::Reverse) {
789 animationFrame = fmodf(startFrame + 0.9999f - fmodf(particleTimeS / d->animationTime, 1.0f), 1.0f);
790 }
else if (sequence->animationDirection() == QQuick3DParticleSpriteSequence::Alternate) {
791 animationFrame = startFrame + particleTimeS / d->animationTime;
792 animationFrame = fabsf(fmodf(1.0f + animationFrame, 2.0f) - 1.0f);
793 }
else if (sequence->animationDirection() == QQuick3DParticleSpriteSequence::AlternateReverse) {
794 animationFrame = fmodf(startFrame + 0.9999f, 1.0f) - particleTimeS / d->animationTime;
795 animationFrame = fabsf(fmodf(fabsf(1.0f + animationFrame), 2.0f) - 1.0f);
798 animationFrame = startFrame;
800 animationFrame = std::clamp(animationFrame, 0.0f, 0.9999f);
804 for (
auto affector : std::as_const(m_affectors)) {
806 if (affector->m_enabled && (affector->m_particles.isEmpty() || affector->m_particles.contains(spriteParticle)))
807 affector->affectParticle(*d, ¤tData, particleTimeS);
811 for (
auto trailEmit : std::as_const(trailEmits))
812 trailEmit.emitter->emitTrailParticles(currentData.position, trailEmit.amount, QQuick3DParticleDynamicBurst::TriggerTime, d->surfaceNormal, d->startVelocity.normalized());
816 const QVector4D color(
float(currentData.color.r) / 255.0f,
817 float(currentData.color.g) / 255.0f,
818 float(currentData.color.b) / 255.0f,
819 float(currentData.color.a) / 255.0f);
820 const QVector3D offset(spriteParticle->offsetX(), spriteParticle->offsetY(), 0);
821 spriteParticle->setParticleData(i, currentData.position + (offset * currentData.scale.x()),
822 currentData.rotation, color, currentData.scale.x(), timeChange,
825 spriteParticle->commitParticles(timeS);
828void QQuick3DParticleSystem::processParticleCommon(QQuick3DParticleDataCurrent ¤tData,
const QQuick3DParticleData *d,
float particleTimeS)
832 currentData.position = d->startPosition;
835 currentData.color = d->startColor;
838 currentData.position += d->startVelocity * particleTimeS;
841 constexpr float step = 360.0f / 127.0f;
842 currentData.rotation = QVector3D(
843 d->startRotation.x * step + abs(d->startRotationVelocity.x) * d->startRotationVelocity.x * particleTimeS,
844 d->startRotation.y * step + abs(d->startRotationVelocity.y) * d->startRotationVelocity.y * particleTimeS,
845 d->startRotation.z * step + abs(d->startRotationVelocity.z) * d->startRotationVelocity.z * particleTimeS);
848void QQuick3DParticleSystem::processParticleFadeInOut(QQuick3DParticleDataCurrent ¤tData,
const QQuick3DParticle *particle,
float particleTimeS,
float particleTimeLeftS)
850 const float fadeInS = particle->m_fadeInDuration / 1000.0f;
851 const float fadeOutS = particle->m_fadeOutDuration / 1000.0f;
852 if (particleTimeS < fadeInS) {
854 const float fadeIn = particleTimeS / fadeInS;
855 if (particle->m_fadeInEffect == QQuick3DParticleModelParticle::FadeOpacity)
856 currentData.color.a *= fadeIn;
857 else if (particle->m_fadeInEffect == QQuick3DParticleModelParticle::FadeScale)
858 currentData.scale *= fadeIn;
860 if (particleTimeLeftS < fadeOutS) {
862 const float fadeOut = particleTimeLeftS / fadeOutS;
863 if (particle->m_fadeOutEffect == QQuick3DParticleModelParticle::FadeOpacity)
864 currentData.color.a *= fadeOut;
865 else if (particle->m_fadeOutEffect == QQuick3DParticleModelParticle::FadeScale)
866 currentData.scale *= fadeOut;
870void QQuick3DParticleSystem::processParticleAlignment(QQuick3DParticleDataCurrent ¤tData,
const QQuick3DParticle *particle,
const QQuick3DParticleData *d)
872 if (particle->m_alignMode == QQuick3DParticle::AlignTowardsTarget) {
873 QQuaternion alignQuat = QQuick3DQuaternionUtils::lookAt(particle->alignTargetPosition(), currentData.position);
874 currentData.rotation = (alignQuat * QQuaternion::fromEulerAngles(currentData.rotation)).toEulerAngles();
875 }
else if (particle->m_alignMode == QQuick3DParticle::AlignTowardsStartVelocity) {
876 QQuaternion alignQuat = QQuick3DQuaternionUtils::lookAt(d->startVelocity, QVector3D());
877 currentData.rotation = (alignQuat * QQuaternion::fromEulerAngles(currentData.rotation)).toEulerAngles();
881bool QQuick3DParticleSystem::isGloballyDisabled()
883 static const bool disabled = qEnvironmentVariableIntValue(
"QT_QUICK3D_DISABLE_PARTICLE_SYSTEMS");
887bool QQuick3DParticleSystem::isEditorModeOn()
889 static const bool editorMode = qEnvironmentVariableIntValue(
"QT_QUICK3D_EDITOR_PARTICLE_SYSTEMS");
893void QQuick3DParticleSystem::updateLoggingData()
898 if (m_loggingData->m_particlesMax != m_particlesMax) {
899 m_loggingData->m_particlesMax = m_particlesMax;
900 Q_EMIT m_loggingData->particlesMaxChanged();
902 if (m_loggingData->m_particlesUsed != m_particlesUsed) {
903 m_loggingData->m_particlesUsed = m_particlesUsed;
904 Q_EMIT m_loggingData->particlesUsedChanged();
906 if (m_loggingData->m_updates != m_updates) {
907 m_loggingData->m_updates = m_updates;
908 Q_EMIT m_loggingData->updatesChanged();
911 m_loggingData->updateTimes(m_timeAnimation);
913 Q_EMIT loggingDataChanged();
914 resetLoggingVariables();
917void QQuick3DParticleSystem::resetLoggingVariables()
925QPRand *QQuick3DParticleSystem::rand()
930void QQuick3DParticleSystem::doSeedRandomization()
933 setSeed(QRandomGenerator::global()->bounded(1 + (INT32_MAX - 1)));
936bool QQuick3DParticleSystem::isShared(
const QQuick3DParticle *particle)
const
939 for (
auto emitter : std::as_const(m_emitters)) {
940 count += emitter->particle() == particle;
944 for (
auto emitter : std::as_const(m_trailEmitters)) {
945 count += emitter->particle() == particle;
Q_TRACE_POINT(qtcore, QCoreApplication_postEvent_exit)
Q_TRACE_POINT(qtquick3d, QSSG_particleUpdate_exit, int particleCount)
static QVector3D mix(const QVector3D &a, const QVector3D &b, float f)