1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qquickcustomaffector_p.h"
5
6#include <private/qquickv4particledata_p.h>
7#include <private/qqmlglobal_p.h>
8
9#include <QtCore/qdebug.h>
10
11QT_BEGIN_NAMESPACE
12
13//TODO: Move docs (and inheritence) to real base when docs can propagate. Currently this pretends to be the base class!
14/*!
15 \qmlsignal QtQuick.Particles::Affector::affectParticles(Array particles, real dt)
16
17 This signal is emitted when particles are selected to be affected.
18 \a particles is an array of particle objects which can be directly
19 manipulated.
20
21 \a dt is the time since the last time it was affected. Use \a dt to
22 normalize trajectory manipulations to real time.
23
24 \note JavaScript is slower to execute, so it is not recommended to use
25 this in high-volume particle systems.
26*/
27
28/*!
29 \qmlproperty StochasticDirection QtQuick.Particles::Affector::position
30
31 Affected particles will have their position set to this direction,
32 relative to the ParticleSystem. When interpreting directions as points,
33 imagine it as an arrow with the base at the 0,0 of the ParticleSystem and the
34 tip at where the specified position will be.
35*/
36
37/*!
38 \qmlproperty StochasticDirection QtQuick.Particles::Affector::velocity
39
40 Affected particles will have their velocity set to this direction.
41*/
42
43
44/*!
45 \qmlproperty StochasticDirection QtQuick.Particles::Affector::acceleration
46
47 Affected particles will have their acceleration set to this direction.
48*/
49
50
51/*!
52 \qmlproperty bool QtQuick.Particles::Affector::relative
53
54 Whether the affected particles have their existing position/velocity/acceleration added
55 to the new one.
56
57 Default is true.
58*/
59QQuickCustomAffector::QQuickCustomAffector(QQuickItem *parent) :
60 QQuickParticleAffector(parent)
61 , m_position(&m_nullVector)
62 , m_velocity(&m_nullVector)
63 , m_acceleration(&m_nullVector)
64 , m_relative(true)
65{
66}
67
68bool QQuickCustomAffector::isAffectConnected()
69{
70 IS_SIGNAL_CONNECTED(
71 this, QQuickCustomAffector, affectParticles,
72 (const QList<QQuickV4ParticleData> &, qreal));
73}
74
75void QQuickCustomAffector::affectSystem(qreal dt)
76{
77 //Acts a bit differently, just emits affected for everyone it might affect, when the only thing is connecting to affected(x,y)
78 bool justAffected = (m_acceleration == &m_nullVector
79 && m_velocity == &m_nullVector
80 && m_position == &m_nullVector
81 && isAffectedConnected());
82 if (!isAffectConnected() && !justAffected) {
83 QQuickParticleAffector::affectSystem(dt);
84 return;
85 }
86 if (!m_enabled)
87 return;
88 updateOffsets();
89
90 QList<QQuickParticleData*> toAffect;
91 for (const QQuickParticleGroupData *gd : std::as_const(t&: m_system->groupData)) {
92 if (activeGroup(g: gd->index)) {
93 for (QQuickParticleData *d : gd->data) {
94 if (shouldAffect(datum: d)) {
95 toAffect << d;
96 }
97 }
98 }
99 }
100
101 if (toAffect.isEmpty())
102 return;
103
104 if (justAffected) {
105 for (const QQuickParticleData *d : std::as_const(t&: toAffect)) {//Not postAffect to avoid saying the particle changed
106 if (m_onceOff)
107 m_onceOffed << qMakePair(value1: d->groupId, value2: d->index);
108 emit affected(x: d->curX(particleSystem: m_system), y: d->curY(particleSystem: m_system));
109 }
110 return;
111 }
112
113 if (m_onceOff)
114 dt = 1.0;
115
116 QList<QQuickV4ParticleData> particles;
117 particles.reserve(asize: toAffect.size());
118 for (QQuickParticleData *data: std::as_const(t&: toAffect))
119 particles.push_back(t: data->v4Value(particleSystem: m_system));
120
121 const auto doAffect = [&](qreal dt) {
122 affectProperties(particles: toAffect, dt);
123 emit affectParticles(particles, dt);
124 };
125
126 if (dt >= simulationCutoff || dt <= simulationDelta) {
127 doAffect(dt);
128 } else {
129 int realTime = m_system->timeInt;
130 m_system->timeInt -= dt * 1000.0;
131 while (dt > simulationDelta) {
132 m_system->timeInt += simulationDelta * 1000.0;
133 dt -= simulationDelta;
134 doAffect(simulationDelta);
135 }
136 m_system->timeInt = realTime;
137 if (dt > 0.0)
138 doAffect(dt);
139 }
140
141 for (QQuickParticleData *d : std::as_const(t&: toAffect))
142 if (d->update == 1.0)
143 postAffect(datum: d);
144}
145
146bool QQuickCustomAffector::affectParticle(QQuickParticleData *d, qreal dt)
147{
148 //This does the property based affecting, called by superclass if signal isn't hooked up.
149 bool changed = false;
150 QPointF curPos(d->curX(particleSystem: m_system), d->curY(particleSystem: m_system));
151
152 if (m_acceleration != &m_nullVector){
153 QPointF pos = m_acceleration->sample(from: curPos);
154 QPointF curAcc = QPointF(d->curAX(), d->curAY());
155 if (m_relative) {
156 pos *= dt;
157 pos += curAcc;
158 }
159 if (pos != curAcc) {
160 d->setInstantaneousAX(ax: pos.x(), particleSystem: m_system);
161 d->setInstantaneousAY(ay: pos.y(), particleSystem: m_system);
162 changed = true;
163 }
164 }
165
166 if (m_velocity != &m_nullVector){
167 QPointF pos = m_velocity->sample(from: curPos);
168 QPointF curVel = QPointF(d->curVX(particleSystem: m_system), d->curVY(particleSystem: m_system));
169 if (m_relative) {
170 pos *= dt;
171 pos += curVel;
172 }
173 if (pos != curVel) {
174 d->setInstantaneousVX(vx: pos.x(), particleSystem: m_system);
175 d->setInstantaneousVY(vy: pos.y(), particleSystem: m_system);
176 changed = true;
177 }
178 }
179
180 if (m_position != &m_nullVector){
181 QPointF pos = m_position->sample(from: curPos);
182 if (m_relative) {
183 pos *= dt;
184 pos += curPos;
185 }
186 if (pos != curPos) {
187 d->setInstantaneousX(x: pos.x(), particleSystem: m_system);
188 d->setInstantaneousY(y: pos.y(), particleSystem: m_system);
189 changed = true;
190 }
191 }
192
193 return changed;
194}
195
196void QQuickCustomAffector::affectProperties(const QList<QQuickParticleData*> &particles, qreal dt)
197{
198 for (QQuickParticleData *d : particles)
199 if ( affectParticle(d, dt) )
200 d->update = 1.0;
201}
202
203QT_END_NAMESPACE
204
205#include "moc_qquickcustomaffector_p.cpp"
206

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

source code of qtdeclarative/src/particles/qquickcustomaffector.cpp