1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQuick module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qquickcustomaffector_p.h"
43 #include <private/qv8engine_p.h>
44 #include <private/qqmlengine_p.h>
45 #include <private/qqmlglobal_p.h>
50 //TODO: Move docs (and inheritence) to real base when docs can propagate. Currently this pretends to be the base class!
52 \qmlsignal QtQuick.Particles2::Affector::affectParticles(Array particles, real dt)
54 This handler is called when particles are selected to be affected. particles contains
55 an array of particle objects which can be directly manipulated.
57 dt is the time since the last time it was affected. Use dt to normalize
58 trajectory manipulations to real time.
60 Note that JS is slower to execute, so it is not recommended to use this in
61 high-volume particle systems.
65 \qmlproperty StochasticDirection QtQuick.Particles2::Affector::position
67 Affected particles will have their position set to this direction,
68 relative to the ParticleSystem. When interpreting directions as points,
69 imagine it as an arrow with the base at the 0,0 of the ParticleSystem and the
70 tip at where the specified position will be.
74 \qmlproperty StochasticDirection QtQuick.Particles2::Affector::speed
76 Affected particles will have their speed set to this direction.
81 \qmlproperty StochasticDirection QtQuick.Particles2::Affector::acceleration
83 Affected particles will have their acceleration set to this direction.
88 \qmlproperty bool QtQuick.Particles2::Affector::relative
90 Whether the affected particles have their existing position/speed/acceleration added
95 QQuickCustomAffector::QQuickCustomAffector(QQuickItem *parent) :
96 QQuickParticleAffector(parent)
97 , m_position(&m_nullVector)
98 , m_speed(&m_nullVector)
99 , m_acceleration(&m_nullVector)
104 bool QQuickCustomAffector::isAffectConnected()
106 IS_SIGNAL_CONNECTED(this, QQuickCustomAffector, affectParticles, (QQmlV8Handle,qreal));
109 void QQuickCustomAffector::affectSystem(qreal dt)
111 //Acts a bit differently, just emits affected for everyone it might affect, when the only thing is connecting to affected(x,y)
112 bool justAffected = (m_acceleration == &m_nullVector
113 && m_speed == &m_nullVector
114 && m_position == &m_nullVector
115 && isAffectedConnected());
116 if (!isAffectConnected() && !justAffected) {
117 QQuickParticleAffector::affectSystem(dt);
124 QList<QQuickParticleData*> toAffect;
125 foreach (QQuickParticleGroupData* gd, m_system->groupData)
126 if (activeGroup(m_system->groupData.key(gd)))
127 foreach (QQuickParticleData* d, gd->data)
131 if (toAffect.isEmpty())
135 foreach (QQuickParticleData* d, toAffect) {//Not postAffect to avoid saying the particle changed
137 m_onceOffed << qMakePair(d->group, d->index);
138 emit affected(d->curX(), d->curY());
146 v8::HandleScope handle_scope;
147 v8::Context::Scope scope(QQmlEnginePrivate::getV8Engine(qmlEngine(this))->context());
148 v8::Handle<v8::Array> array = v8::Array::New(toAffect.size());
149 for (int i=0; i<toAffect.size(); i++)
150 array->Set(i, toAffect[i]->v8Value().toHandle());
152 if (dt >= simulationCutoff || dt <= simulationDelta) {
153 affectProperties(toAffect, dt);
154 emit affectParticles(QQmlV8Handle::fromHandle(array), dt);
156 int realTime = m_system->timeInt;
157 m_system->timeInt -= dt * 1000.0;
158 while (dt > simulationDelta) {
159 m_system->timeInt += simulationDelta * 1000.0;
160 dt -= simulationDelta;
161 affectProperties(toAffect, simulationDelta);
162 emit affectParticles(QQmlV8Handle::fromHandle(array), simulationDelta);
164 m_system->timeInt = realTime;
166 affectProperties(toAffect, dt);
167 emit affectParticles(QQmlV8Handle::fromHandle(array), dt);
171 foreach (QQuickParticleData* d, toAffect)
172 if (d->update == 1.0)
176 bool QQuickCustomAffector::affectParticle(QQuickParticleData *d, qreal dt)
178 //This does the property based affecting, called by superclass if signal isn't hooked up.
179 bool changed = false;
180 QPointF curPos(d->curX(), d->curY());
182 if (m_acceleration != &m_nullVector){
183 QPointF pos = m_acceleration->sample(curPos);
184 QPointF curAcc = QPointF(d->curAX(), d->curAY());
190 d->setInstantaneousAX(pos.x());
191 d->setInstantaneousAY(pos.y());
196 if (m_speed != &m_nullVector){
197 QPointF pos = m_speed->sample(curPos);
198 QPointF curVel = QPointF(d->curVX(), d->curVY());
204 d->setInstantaneousVX(pos.x());
205 d->setInstantaneousVY(pos.y());
210 if (m_position != &m_nullVector){
211 QPointF pos = m_position->sample(curPos);
217 d->setInstantaneousX(pos.x());
218 d->setInstantaneousY(pos.y());
226 void QQuickCustomAffector::affectProperties(const QList<QQuickParticleData*> particles, qreal dt)
228 foreach (QQuickParticleData* d, particles)
229 if ( affectParticle(d, dt) )