1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qquick3dparticleaffector_p.h"
5#include "qquick3dparticleutils_p.h"
6
7QT_BEGIN_NAMESPACE
8
9/*!
10 \qmltype Affector3D
11 \inherits Node
12 \inqmlmodule QtQuick3D.Particles3D
13 \brief Affectors modify the attributes of particles during their lifetime.
14 \since 6.2
15
16 The Affector3D is an abstract base class of affectors like \l Gravity3D, \l Wander3D, and \l PointRotator3D.
17
18 By default affectors affect all particles in the system, but this can be limited by defining
19 the \l particles list. If the system has multiple affectors, the order of affectors may
20 result in different outcome, as affectors are applied one after another.
21*/
22
23QQuick3DParticleAffector::QQuick3DParticleAffector(QQuick3DNode *parent)
24 : QQuick3DNode(parent)
25{
26}
27
28QQuick3DParticleAffector::~QQuick3DParticleAffector()
29{
30 for (const auto &connection : std::as_const(t&: m_connections))
31 QObject::disconnect(connection);
32 if (m_system)
33 m_system->unRegisterParticleAffector(a: this);
34}
35
36/*!
37 \qmlproperty ParticleSystem3D Affector3D::system
38
39 This property defines the \l ParticleSystem3D for the affector. If system is direct parent of the affector,
40 this property does not need to be defined.
41*/
42QQuick3DParticleSystem *QQuick3DParticleAffector::system() const
43{
44 return m_system;
45}
46
47void QQuick3DParticleAffector::setSystem(QQuick3DParticleSystem *system)
48{
49 if (m_system == system)
50 return;
51
52 if (m_system)
53 m_system->unRegisterParticleAffector(a: this);
54
55 m_system = system;
56 if (m_system)
57 m_system->registerParticleAffector(a: this);
58
59 m_systemSharedParent = getSharedParentNode(node: this, system: m_system);
60
61 Q_EMIT systemChanged();
62 Q_EMIT update();
63}
64
65/*!
66 \qmlproperty bool Affector3D::enabled
67
68 If enabled is set to \c false, this affector will not alter any particles.
69 Usually this is used to conditionally turn an affector on or off.
70
71 The default value is \c true.
72*/
73bool QQuick3DParticleAffector::enabled() const
74{
75 return m_enabled;
76}
77
78void QQuick3DParticleAffector::setEnabled(bool enabled)
79{
80 if (m_enabled == enabled)
81 return;
82
83 m_enabled = enabled;
84 Q_EMIT enabledChanged();
85 Q_EMIT update();
86}
87
88void QQuick3DParticleAffector::componentComplete()
89{
90 if (!m_system && qobject_cast<QQuick3DParticleSystem*>(object: parent()))
91 setSystem(qobject_cast<QQuick3DParticleSystem*>(object: parent()));
92}
93
94void QQuick3DParticleAffector::prepareToAffect()
95{
96}
97
98// Particles
99
100/*!
101 \qmlproperty List<Particle3D> Affector3D::particles
102
103 This list controls which logical particles will be affected.
104 When empty, all particles in the system are affected.
105*/
106QQmlListProperty<QQuick3DParticle> QQuick3DParticleAffector::particles()
107{
108 return {this, this,
109 &QQuick3DParticleAffector::appendParticle,
110 &QQuick3DParticleAffector::particleCount,
111 &QQuick3DParticleAffector::particle,
112 &QQuick3DParticleAffector::clearParticles,
113 &QQuick3DParticleAffector::replaceParticle,
114 &QQuick3DParticleAffector::removeLastParticle};
115}
116
117void QQuick3DParticleAffector::appendParticle(QQuick3DParticle *n) {
118 m_particles.append(t: n);
119 m_connections.insert(key: n, value: QObject::connect(sender: n, signal: &QObject::destroyed, slot: [this](QObject *obj) {
120 QQuick3DParticle *particle = qobject_cast<QQuick3DParticle *>(object: obj);
121 m_particles.removeAll(t: particle);
122 QObject::disconnect(m_connections[particle]);
123 m_connections.remove(key: particle);
124 }));
125}
126
127qsizetype QQuick3DParticleAffector::particleCount() const
128{
129 return m_particles.size();
130}
131
132QQuick3DParticle *QQuick3DParticleAffector::particle(qsizetype index) const
133{
134 return m_particles.at(i: index);
135}
136
137void QQuick3DParticleAffector::clearParticles() {
138 m_particles.clear();
139}
140
141void QQuick3DParticleAffector::replaceParticle(qsizetype index, QQuick3DParticle *n)
142{
143 QQuick3DParticle *remove = m_particles[index];
144 QObject::disconnect(m_connections[remove]);
145 m_connections.remove(key: remove);
146 m_particles[index] = n;
147 m_connections.insert(key: n, value: QObject::connect(sender: n, signal: &QObject::destroyed, slot: [this](QObject *obj) {
148 QQuick3DParticle *particle = qobject_cast<QQuick3DParticle *>(object: obj);
149 m_particles.removeAll(t: particle);
150 QObject::disconnect(m_connections[particle]);
151 m_connections.remove(key: particle);
152 }));
153}
154
155void QQuick3DParticleAffector::removeLastParticle()
156{
157 QQuick3DParticle *last = m_particles.last();
158 QObject::disconnect(m_connections[last]);
159 m_connections.remove(key: last);
160 m_particles.removeLast();
161}
162
163// Particles - static
164void QQuick3DParticleAffector::appendParticle(QQmlListProperty<QQuick3DParticle> *list, QQuick3DParticle *p) {
165 reinterpret_cast<QQuick3DParticleAffector *>(list->data)->appendParticle(n: p);
166}
167
168void QQuick3DParticleAffector::clearParticles(QQmlListProperty<QQuick3DParticle> *list) {
169 reinterpret_cast<QQuick3DParticleAffector *>(list->data)->clearParticles();
170}
171
172void QQuick3DParticleAffector::replaceParticle(QQmlListProperty<QQuick3DParticle> *list, qsizetype i, QQuick3DParticle *p)
173{
174 reinterpret_cast<QQuick3DParticleAffector *>(list->data)->replaceParticle(index: i, n: p);
175}
176
177void QQuick3DParticleAffector::removeLastParticle(QQmlListProperty<QQuick3DParticle> *list)
178{
179 reinterpret_cast<QQuick3DParticleAffector *>(list->data)->removeLastParticle();
180}
181
182QQuick3DParticle *QQuick3DParticleAffector::particle(QQmlListProperty<QQuick3DParticle> *list, qsizetype i) {
183 return reinterpret_cast<QQuick3DParticleAffector *>(list->data)->particle(index: i);
184}
185
186qsizetype QQuick3DParticleAffector::particleCount(QQmlListProperty<QQuick3DParticle> *list) {
187 return reinterpret_cast<QQuick3DParticleAffector *>(list->data)->particleCount();
188}
189
190QT_END_NAMESPACE
191

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