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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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