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 | |
6 | QT_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 | |
24 | QQuick3DParticle::QQuick3DParticle(QQuick3DObject *parent) |
25 | : QQuick3DObject(parent) |
26 | , m_color(255, 255, 255, 255) |
27 | , m_colorVariation(0, 0, 0, 0) |
28 | { |
29 | } |
30 | |
31 | QQuick3DParticle::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 | |
39 | QQuick3DParticle::~QQuick3DParticle() |
40 | { |
41 | if (m_system) |
42 | m_system->unRegisterParticle(particle: this); |
43 | } |
44 | |
45 | QQuick3DParticleSystem *QQuick3DParticle::system() const |
46 | { |
47 | return m_system; |
48 | } |
49 | |
50 | void 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 | */ |
77 | int QQuick3DParticle::maxAmount() const |
78 | { |
79 | return m_maxAmount; |
80 | } |
81 | |
82 | void QQuick3DParticle::setMaxAmount(int maxAmount) |
83 | { |
84 | if (m_maxAmount == maxAmount) |
85 | return; |
86 | |
87 | doSetMaxAmount(amount: maxAmount); |
88 | } |
89 | |
90 | void 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 | */ |
103 | QColor QQuick3DParticle::color() const |
104 | { |
105 | return m_color; |
106 | } |
107 | |
108 | float QQuick3DParticle::opacity() const |
109 | { |
110 | return m_color.alphaF(); |
111 | } |
112 | |
113 | |
114 | void 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 |
125 | void 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 | */ |
153 | QVector4D QQuick3DParticle::colorVariation() const |
154 | { |
155 | return m_colorVariation; |
156 | } |
157 | |
158 | void 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 | */ |
191 | bool QQuick3DParticle::unifiedColorVariation() const |
192 | { |
193 | return m_unifiedColorVariation; |
194 | } |
195 | |
196 | void 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 | */ |
227 | QQuick3DParticle::FadeType QQuick3DParticle::fadeInEffect() const |
228 | { |
229 | return m_fadeInEffect; |
230 | } |
231 | |
232 | void 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 | */ |
251 | QQuick3DParticle::FadeType QQuick3DParticle::fadeOutEffect() const |
252 | { |
253 | return m_fadeOutEffect; |
254 | } |
255 | |
256 | void 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 | */ |
279 | int QQuick3DParticle::fadeInDuration() const |
280 | { |
281 | return m_fadeInDuration; |
282 | } |
283 | |
284 | void 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 | */ |
302 | int QQuick3DParticle::fadeOutDuration() const |
303 | { |
304 | return m_fadeOutDuration; |
305 | } |
306 | |
307 | void 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 | */ |
343 | QQuick3DParticle::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 | */ |
357 | QVector3D 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 | */ |
375 | bool QQuick3DParticle::hasTransparency() const |
376 | { |
377 | return m_hasTransparency; |
378 | } |
379 | |
380 | void QQuick3DParticle::setHasTransparency(bool transparency) |
381 | { |
382 | if (m_hasTransparency == transparency) |
383 | return; |
384 | |
385 | m_hasTransparency = transparency; |
386 | Q_EMIT hasTransparencyChanged(); |
387 | } |
388 | |
389 | void QQuick3DParticle::setAlignMode(AlignMode alignMode) |
390 | { |
391 | if (m_alignMode == alignMode) |
392 | return; |
393 | |
394 | m_alignMode = alignMode; |
395 | Q_EMIT alignModeChanged(); |
396 | } |
397 | |
398 | void 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 | */ |
431 | QQuick3DParticle::SortMode QQuick3DParticle::sortMode() const |
432 | { |
433 | return m_sortMode; |
434 | } |
435 | |
436 | void QQuick3DParticle::setSortMode(QQuick3DParticle::SortMode mode) |
437 | { |
438 | if (m_sortMode == mode) |
439 | return; |
440 | m_sortMode = mode; |
441 | Q_EMIT sortModeChanged(); |
442 | } |
443 | |
444 | void QQuick3DParticle::updateBurstIndex(int amount) |
445 | { |
446 | m_lastBurstIndex += amount; |
447 | } |
448 | |
449 | int QQuick3DParticle::nextCurrentIndex(const QQuick3DParticleEmitter *) |
450 | { |
451 | m_currentIndex = (m_currentIndex < m_maxAmount - 1) ? m_currentIndex + 1 : m_lastBurstIndex; |
452 | return m_currentIndex; |
453 | } |
454 | |
455 | void 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 | |
462 | void QQuick3DParticle::reset() { |
463 | m_currentIndex = -1; |
464 | m_lastBurstIndex = 0; |
465 | |
466 | // Reset all particles data |
467 | m_particleData.fill(t: {}); |
468 | } |
469 | |
470 | QT_END_NAMESPACE |
471 | |