1 | // Copyright (C) 2021 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | #include "qquick3dparticletrailemitter_p.h" |
5 | |
6 | QT_BEGIN_NAMESPACE |
7 | |
8 | /*! |
9 | \qmltype TrailEmitter3D |
10 | \inherits ParticleEmitter3D |
11 | \inqmlmodule QtQuick3D.Particles3D |
12 | \brief Emitter for logical particles from other particles. |
13 | \since 6.2 |
14 | |
15 | TrailEmitter3D is a special emitter for emitting particles with starting positions inherited from |
16 | other logical particles. |
17 | */ |
18 | |
19 | QQuick3DParticleTrailEmitter::QQuick3DParticleTrailEmitter(QQuick3DNode *parent) |
20 | : QQuick3DParticleEmitter(parent) |
21 | { |
22 | } |
23 | |
24 | /*! |
25 | \qmlproperty Particle3D TrailEmitter3D::follow |
26 | |
27 | This property defines the logical particle which this emitter follows. |
28 | When the TrailEmitter3D emits particles, center position of those particles |
29 | will become from the \l Particle3D the emitter follows. |
30 | */ |
31 | QQuick3DParticle *QQuick3DParticleTrailEmitter::follow() const |
32 | { |
33 | return m_follow; |
34 | } |
35 | |
36 | void QQuick3DParticleTrailEmitter::setFollow(QQuick3DParticle *follow) |
37 | { |
38 | if (m_follow == follow) |
39 | return; |
40 | |
41 | m_follow = follow; |
42 | Q_EMIT followChanged(); |
43 | } |
44 | |
45 | /*! |
46 | \qmlmethod vector3d TrailEmitter3D::burst(int count) |
47 | |
48 | This method emits \a count amount of particles from this emitter immediately. |
49 | |
50 | \note TrailEmitter3D doesn't support other bursting methods. Position always comes |
51 | from the particle defined with the \l follow property. |
52 | */ |
53 | void QQuick3DParticleTrailEmitter::burst(int count) |
54 | { |
55 | if (!system()) |
56 | return; |
57 | QQuick3DParticleEmitBurstData burst; |
58 | burst.time = system()->currentTime(); |
59 | burst.amount = count; |
60 | m_bursts << burst; |
61 | } |
62 | |
63 | // Returns true if there are any dynamic bursts |
64 | bool QQuick3DParticleTrailEmitter::hasBursts() const |
65 | { |
66 | bool dynamicBursts = false; |
67 | for (auto *burst : std::as_const(t: m_emitBursts)) { |
68 | if (qobject_cast<QQuick3DParticleDynamicBurst *>(object: burst)) { |
69 | dynamicBursts = true; |
70 | break; |
71 | } |
72 | } |
73 | return !m_bursts.empty() || dynamicBursts; |
74 | } |
75 | |
76 | // Called to emit set of particles |
77 | void QQuick3DParticleTrailEmitter::emitTrailParticles(const QVector3D ¢erPos, int emitAmount, int triggerType) |
78 | { |
79 | if (!system()) |
80 | return; |
81 | |
82 | if (!enabled()) |
83 | return; |
84 | |
85 | const int systemTime = system()->currentTime(); |
86 | for (auto particle : std::as_const(t&: m_system->m_particles)) { |
87 | if (particle == m_particle) { |
88 | emitAmount += getEmitAmountFromDynamicBursts(triggerType); |
89 | emitAmount = std::min(a: emitAmount, b: int(particle->maxAmount())); |
90 | float addTime = ((systemTime - m_prevEmitTime) / 1000.0f) / emitAmount; |
91 | for (int i = 0; i < emitAmount; i++) { |
92 | // Distribute evenly between previous and current time, important especially |
93 | // when time has jumped a lot (like a starttime). |
94 | float startTime = (m_prevEmitTime / 1000.0f) + addTime * float(i); |
95 | emitParticle(particle, startTime, transform: QMatrix4x4(), parentRotation: QQuaternion(), centerPos); |
96 | } |
97 | // Emit bursts, if any |
98 | for (auto burst : std::as_const(t&: m_bursts)) { |
99 | int burstAmount = std::min(a: burst.amount, b: int(particle->maxAmount())); |
100 | float burstTime = float(burst.time / 1000.0f); |
101 | for (int i = 0; i < burstAmount; i++) |
102 | emitParticle(particle, startTime: burstTime, transform: QMatrix4x4(), parentRotation: QQuaternion(), centerPos); |
103 | } |
104 | } |
105 | } |
106 | |
107 | m_prevEmitTime = systemTime; |
108 | } |
109 | |
110 | void QQuick3DParticleTrailEmitter::clearBursts() |
111 | { |
112 | // After bursts have been emitted, clear the list |
113 | m_bursts.clear(); |
114 | } |
115 | |
116 | QT_END_NAMESPACE |
117 | |