1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qquick3dparticle_p.h"
5
6QT_BEGIN_NAMESPACE
7
8/*!
9 \qmltype Particle3D
10 \inherits Object3D
11 \inqmlmodule QtQuick3D.Particles3D
12 \brief Abstract logical particle.
13 \since 6.2
14
15 This element defines the common properties of the logical particles.
16 Particle3D is an abstract base class of particles, use \l ModelParticle3D or \l SpriteParticle3D instead.
17
18 \note Unlike the materials used with the models, particles default to being rendered with assuming
19 semi-transparency, and so with blending enabled. This is the desired behavior most of the time due
20 to particle textures, color (alpha) variations, fadings etc. If you don't need the blending,
21 set the \l hasTransparency to \c false for possible performance gains.
22*/
23
24QQuick3DParticle::QQuick3DParticle(QQuick3DObject *parent)
25 : QQuick3DObject(parent)
26 , m_color(255, 255, 255, 255)
27 , m_colorVariation(0, 0, 0, 0)
28{
29}
30
31QQuick3DParticle::QQuick3DParticle(QQuick3DObjectPrivate &dd, QQuick3DNode *parent)
32 : QQuick3DObject(dd, parent)
33 , m_color(255, 255, 255, 255)
34 , m_colorVariation(0, 0, 0, 0)
35{
36
37}
38
39QQuick3DParticle::~QQuick3DParticle()
40{
41 if (m_system)
42 m_system->unRegisterParticle(particle: this);
43}
44
45QQuick3DParticleSystem *QQuick3DParticle::system() const
46{
47 return m_system;
48}
49
50void QQuick3DParticle::setSystem(QQuick3DParticleSystem *system)
51{
52 if (m_system == system)
53 return;
54
55 if (m_system)
56 m_system->unRegisterParticle(particle: this);
57
58 m_system = system;
59 if (m_system)
60 m_system->registerParticle(particle: this);
61 Q_EMIT systemChanged();
62}
63
64/*!
65 \qmlproperty int Particle3D::maxAmount
66
67 This property defines the maximum amount of particles that can exist at the same time.
68 You can use \l {ParticleSystem3DLogging::particlesUsed}{particlesUsed} for debugging how
69 efficiently the allocated particles are used. If the maxAmount is too small, particles
70 are reused before they reach the end of their \l {ParticleEmitter3D::lifeSpan}{lifeSpan}.
71 If the maxAmount is too big, unnecessary memory is allocated for the particles.
72
73 \note Changing the maxAmount resets all the particles in the particle system.
74
75 The default value is \c 100.
76*/
77int QQuick3DParticle::maxAmount() const
78{
79 return m_maxAmount;
80}
81
82void QQuick3DParticle::setMaxAmount(int maxAmount)
83{
84 if (m_maxAmount == maxAmount)
85 return;
86
87 doSetMaxAmount(amount: maxAmount);
88}
89
90void QQuick3DParticle::doSetMaxAmount(int amount)
91{
92 m_maxAmount = amount;
93 Q_EMIT maxAmountChanged();
94}
95
96/*!
97 \qmlproperty color Particle3D::color
98
99 This property defines the base color that is used for colorizing the particles.
100
101 The default value is \c "#FFFFFF" (white).
102*/
103QColor QQuick3DParticle::color() const
104{
105 return m_color;
106}
107
108float QQuick3DParticle::opacity() const
109{
110 return m_color.alphaF();
111}
112
113
114void QQuick3DParticle::setColor(QColor color)
115{
116 if (m_color == color)
117 return;
118
119 m_color = color;
120 Q_EMIT colorChanged();
121}
122
123// When setting color to undefined, reset particle
124// to use its own color instead
125void QQuick3DParticle::resetColor()
126{
127 m_color = QColor(255, 255, 255, 255);
128 m_colorVariation = QVector4D(0, 0, 0, 0);
129}
130
131/*!
132 \qmlproperty vector4d Particle3D::colorVariation
133
134 This property defines the color variation that is used for colorizing the particles.
135 The values are in RGBA order and each value should be between 0.0 (no variation) and 1.0
136 (full variation).
137
138 For example, to create particles which will have translucent red colors between
139 \c #ff0000 and \c #e50000, with 40% to 60% opacity:
140
141 \qml
142 ModelParticle3D {
143 ...
144 color: "#7fff0000"
145 colorVariation: Qt.vector4d(0.1, 0.0, 0.0, 0.2)
146 }
147 \endqml
148
149 The default value is \c (0, 0, 0, 0) (no variation).
150
151 \sa unifiedColorVariation
152*/
153QVector4D QQuick3DParticle::colorVariation() const
154{
155 return m_colorVariation;
156}
157
158void QQuick3DParticle::setColorVariation(QVector4D colorVariation)
159{
160 if (m_colorVariation == colorVariation)
161 return;
162
163 m_colorVariation = colorVariation;
164 Q_EMIT colorVariationChanged();
165}
166
167/*!
168 \qmlproperty bool Particle3D::unifiedColorVariation
169
170 This property defines if the \l colorVariation should be applied uniformly for all
171 the color channels. This means that all variations are applied with the same
172 random amount.
173
174 For example, to create particles which will have yellow colors between
175 \c #ffff00 and \c #7f7f00, so that the values of \c R and \c G color channels are
176 always the same:
177
178 \qml
179 ModelParticle3D {
180 ...
181 color: "#ffff00"
182 colorVariation: Qt.vector4d(0.5, 0.5, 0.0, 0.0)
183 unifiedColorVariation: true
184 }
185 \endqml
186
187 The default value is \c false.
188
189 \sa colorVariation
190*/
191bool QQuick3DParticle::unifiedColorVariation() const
192{
193 return m_unifiedColorVariation;
194}
195
196void QQuick3DParticle::setUnifiedColorVariation(bool unified)
197{
198 if (m_unifiedColorVariation == unified)
199 return;
200
201 m_unifiedColorVariation = unified;
202 Q_EMIT unifiedColorVariationChanged();
203}
204
205/*!
206 \qmlproperty enumeration Particle3D::FadeType
207
208 Defines the type of the fading effect.
209
210 \value Particle3D.FadeNone
211 No fading.
212 \value Particle3D.FadeOpacity
213 Fade the particle opacity from/to 0.0.
214 \value Particle3D.FadeScale
215 Fade the particle scale from/to 0.0.
216*/
217
218/*!
219 \qmlproperty FadeType Particle3D::fadeInEffect
220
221 This property defines the fading effect used when the particles appear.
222
223 The default value is \c Particle3D.FadeOpacity.
224
225 \sa fadeInDuration, fadeOutEffect
226*/
227QQuick3DParticle::FadeType QQuick3DParticle::fadeInEffect() const
228{
229 return m_fadeInEffect;
230}
231
232void QQuick3DParticle::setFadeInEffect(FadeType fadeInEffect)
233{
234 if (m_fadeInEffect == fadeInEffect)
235 return;
236
237 m_fadeInEffect = fadeInEffect;
238 Q_EMIT fadeInEffectChanged();
239}
240
241/*!
242 \qmlproperty FadeType Particle3D::fadeOutEffect
243
244 This property defines the fading effect used when the particles reach their
245 \l {ParticleEmitter3D::lifeSpan}{lifeSpan} and disappear.
246
247 The default value is \c Particle3D.FadeOpacity.
248
249 \sa fadeOutDuration, fadeInEffect
250*/
251QQuick3DParticle::FadeType QQuick3DParticle::fadeOutEffect() const
252{
253 return m_fadeOutEffect;
254}
255
256void QQuick3DParticle::setFadeOutEffect(FadeType fadeOutEffect)
257{
258 if (m_fadeOutEffect == fadeOutEffect)
259 return;
260
261 m_fadeOutEffect = fadeOutEffect;
262 Q_EMIT fadeOutEffectChanged();
263}
264
265/*!
266 \qmlproperty int Particle3D::fadeInDuration
267
268 This property defines the duration in milliseconds for the fading in effect.
269
270 \note The fading durations are part of the particles
271 \l {ParticleEmitter3D::lifeSpan}{lifeSpan}. So e.g. if \c lifeSpan is 3000,
272 \c fadeInDuration is 500 and \c fadeOutDuration is 500, the fully visible
273 time of the particle is 2000ms.
274
275 The default value is \c 250.
276
277 \sa fadeInEffect, fadeOutDuration
278*/
279int QQuick3DParticle::fadeInDuration() const
280{
281 return m_fadeInDuration;
282}
283
284void QQuick3DParticle::setFadeInDuration(int fadeInDuration)
285{
286 if (m_fadeInDuration == fadeInDuration)
287 return;
288
289 m_fadeInDuration = fadeInDuration;
290 Q_EMIT fadeInDurationChanged();
291}
292
293/*!
294 \qmlproperty int Particle3D::fadeOutDuration
295
296 This property defines the duration in milliseconds for the fading out effect.
297
298 The default value is \c 250.
299
300 \sa fadeOutEffect, fadeInDuration
301*/
302int QQuick3DParticle::fadeOutDuration() const
303{
304 return m_fadeOutDuration;
305}
306
307void QQuick3DParticle::setFadeOutDuration(int fadeOutDuration)
308{
309 if (m_fadeOutDuration == fadeOutDuration)
310 return;
311
312 m_fadeOutDuration = fadeOutDuration;
313 Q_EMIT fadeOutDurationChanged();
314}
315
316/*!
317 \qmlproperty enumeration Particle3D::AlignMode
318
319 Defines the type of the alignment.
320
321 \value Particle3D.AlignNone
322 No alignment. Particles rotation can be defined with \l {ParticleEmitter3D::particleRotation}{particleRotation}.
323 \value Particle3D.AlignTowardsTarget
324 Align the particles towards \l alignTargetPosition direction.
325 \value Particle3D.AlignTowardsStartVelocity
326 Align the particles towards their starting \l {ParticleEmitter3D::velocity}{velocity}
327 direction.
328*/
329
330/*!
331 \qmlproperty AlignMode Particle3D::alignMode
332
333 This property defines the align mode used for the particles.
334 Particle alignment means the direction that particles face.
335
336 \note When the \l SpriteParticle3D \l {SpriteParticle3D::billboard}{billboard}
337 property is set to \c true, alignMode does not have an effect.
338
339 The default value is \c Particle3D.AlignNone.
340
341 \sa alignTargetPosition
342*/
343QQuick3DParticle::AlignMode QQuick3DParticle::alignMode() const
344{
345 return m_alignMode;
346}
347
348/*!
349 \qmlproperty vector3d Particle3D::alignTargetPosition
350
351 This property defines the position particles are aligned to.
352 This property has effect only when the \l alignMode is set to
353 \c Particle3D.AlignTowardsTarget.
354
355 \sa alignMode
356*/
357QVector3D QQuick3DParticle::alignTargetPosition() const
358{
359 return m_alignTarget;
360}
361
362/*!
363 \qmlproperty bool Particle3D::hasTransparency
364
365 This property defines if the particle has any transparency and should
366 be blended with the background. Usually this should be true, like when
367 the particle color doesn't have full alpha, texture contains semi-transparent
368 pixels or particles opacity is faded in or out. Setting this to false can be
369 an optimization in specific cases.
370
371 The default value is \c true.
372
373 \sa color, fadeInEffect, fadeOutEffect
374*/
375bool QQuick3DParticle::hasTransparency() const
376{
377 return m_hasTransparency;
378}
379
380void QQuick3DParticle::setHasTransparency(bool transparency)
381{
382 if (m_hasTransparency == transparency)
383 return;
384
385 m_hasTransparency = transparency;
386 Q_EMIT hasTransparencyChanged();
387}
388
389void QQuick3DParticle::setAlignMode(AlignMode alignMode)
390{
391 if (m_alignMode == alignMode)
392 return;
393
394 m_alignMode = alignMode;
395 Q_EMIT alignModeChanged();
396}
397
398void QQuick3DParticle::setAlignTargetPosition(const QVector3D &alignPosition)
399{
400 if (m_alignTarget == alignPosition)
401 return;
402
403 m_alignTarget = alignPosition;
404 Q_EMIT alignTargetPositionChanged();
405}
406
407/*!
408 \qmlproperty enumeration Particle3D::SortMode
409
410 Defines the sorting mode of the particle. The sorting mode determines
411 the order in which the particles are drawn.
412
413 \value Particle3D.SortNone
414 No sorting.
415 \value Particle3D.SortNewest
416 Sort based on particle lifetime, newest first.
417 \value Particle3D.SortOldest
418 Sort based on particle lifetime, oldest first.
419 \value Particle3D.SortDistance
420 Sort based on distance to the camera, farthest first.
421*/
422
423
424/*!
425 \qmlproperty SortMode Particle3D::sortMode
426
427 This property defines the sort mode used for the particles.
428
429 The default value is \c Particle3D.SortNone.
430*/
431QQuick3DParticle::SortMode QQuick3DParticle::sortMode() const
432{
433 return m_sortMode;
434}
435
436void QQuick3DParticle::setSortMode(QQuick3DParticle::SortMode mode)
437{
438 if (m_sortMode == mode)
439 return;
440 m_sortMode = mode;
441 Q_EMIT sortModeChanged();
442}
443
444void QQuick3DParticle::updateBurstIndex(int amount)
445{
446 m_lastBurstIndex += amount;
447}
448
449int QQuick3DParticle::nextCurrentIndex(const QQuick3DParticleEmitter *)
450{
451 m_currentIndex = (m_currentIndex < m_maxAmount - 1) ? m_currentIndex + 1 : m_lastBurstIndex;
452 return m_currentIndex;
453}
454
455void QQuick3DParticle::componentComplete()
456{
457 QQuick3DObject::componentComplete();
458 // Make sure the default amount gets initialized, even if user doesn't set it
459 Q_EMIT maxAmountChanged();
460}
461
462void QQuick3DParticle::reset() {
463 m_currentIndex = -1;
464 m_lastBurstIndex = 0;
465
466 // Reset all particles data
467 m_particleData.fill(t: {});
468}
469
470QT_END_NAMESPACE
471

source code of qtquick3d/src/quick3dparticles/qquick3dparticle.cpp