Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / src / quick / particles / qquickcustomaffector.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the Declarative module of the Qt Toolkit.
7 **
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.
16 **
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.
20 **
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.
28 **
29 ** Other Usage
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.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qquickcustomaffector_p.h"
43 #include <private/qv8engine_p.h>
44 #include <private/qdeclarativeengine_p.h>
45 #include <QDeclarativeEngine>
46 #include <QDebug>
47 QT_BEGIN_NAMESPACE
48
49 //TODO: Move docs (and inheritence) to real base when docs can propagate. Currently this pretends to be the base class!
50 /*!
51     \qmlsignal QtQuick.Particles2::Affector::affectParticles(Array particles, real dt)
52
53     This handler is called when particles are selected to be affected. particles contains
54     an array of particle objects which can be directly manipulated.
55
56     dt is the time since the last time it was affected. Use dt to normalize
57     trajectory manipulations to real time.
58
59     Note that JS is slower to execute, so it is not recommended to use this in
60     high-volume particle systems.
61 */
62
63 /*!
64     \qmlproperty StochasticDirection QtQuick.Particles2::Affector::position
65
66     Affected particles will have their position set to this direction,
67     relative to the ParticleSystem. When interpreting directions as points,
68     imagine it as an arrow with the base at the 0,0 of the ParticleSystem and the
69     tip at where the specified position will be.
70 */
71
72 /*!
73     \qmlproperty StochasticDirection QtQuick.Particles2::Affector::speed
74
75     Affected particles will have their speed set to this direction.
76 */
77
78
79 /*!
80     \qmlproperty StochasticDirection QtQuick.Particles2::Affector::acceleration
81
82     Affected particles will have their acceleration set to this direction.
83 */
84
85
86 /*!
87     \qmlproperty bool QtQuick.Particles2::Affector::relative
88
89     Whether the affected particles have their existing position/speed/acceleration added
90     to the new one.
91
92     Default is true.
93 */
94 QQuickCustomAffector::QQuickCustomAffector(QQuickItem *parent) :
95     QQuickParticleAffector(parent)
96     , m_position(&m_nullVector)
97     , m_speed(&m_nullVector)
98     , m_acceleration(&m_nullVector)
99     , m_relative(true)
100 {
101 }
102
103 bool QQuickCustomAffector::isAffectConnected()
104 {
105     static int idx = QObjectPrivate::get(this)->signalIndex("affectParticles(QDeclarativeV8Handle,qreal)");
106     return QObjectPrivate::get(this)->isSignalConnected(idx);
107 }
108
109 void QQuickCustomAffector::affectSystem(qreal dt)
110 {
111     if (!isAffectConnected()) {
112         QQuickParticleAffector::affectSystem(dt);
113         return;
114     }
115     if (!m_enabled)
116         return;
117     updateOffsets();
118
119     QList<QQuickParticleData*> toAffect;
120     foreach (QQuickParticleGroupData* gd, m_system->groupData)
121         if (activeGroup(m_system->groupData.key(gd)))
122             foreach (QQuickParticleData* d, gd->data)
123                 if (shouldAffect(d))
124                     toAffect << d;
125
126     if (toAffect.isEmpty())
127         return;
128
129     if (m_onceOff)
130         dt = 1.0;
131
132     v8::HandleScope handle_scope;
133     v8::Context::Scope scope(QDeclarativeEnginePrivate::getV8Engine(qmlEngine(this))->context());
134     v8::Handle<v8::Array> array = v8::Array::New(toAffect.size());
135     for (int i=0; i<toAffect.size(); i++)
136         array->Set(i, toAffect[i]->v8Value().toHandle());
137
138     if (dt >= simulationCutoff || dt <= simulationDelta) {
139         affectProperties(toAffect, dt);
140         emit affectParticles(QDeclarativeV8Handle::fromHandle(array), dt);
141     } else {
142         int realTime = m_system->timeInt;
143         m_system->timeInt -= dt * 1000.0;
144         while (dt > simulationDelta) {
145             m_system->timeInt += simulationDelta * 1000.0;
146             dt -= simulationDelta;
147             affectProperties(toAffect, simulationDelta);
148             emit affectParticles(QDeclarativeV8Handle::fromHandle(array), simulationDelta);
149         }
150         m_system->timeInt = realTime;
151         if (dt > 0.0) {
152             affectProperties(toAffect, dt);
153             emit affectParticles(QDeclarativeV8Handle::fromHandle(array), dt);
154         }
155     }
156
157     foreach (QQuickParticleData* d, toAffect)
158         if (d->update == 1.0)
159             postAffect(d);
160 }
161
162 bool QQuickCustomAffector::affectParticle(QQuickParticleData *d, qreal dt)
163 {
164     //This does the property based affecting, called by superclass if signal isn't hooked up.
165     bool changed = false;
166     QPointF curPos(d->curX(), d->curY());
167
168     if (m_acceleration != &m_nullVector){
169         QPointF pos = m_acceleration->sample(curPos);
170         if (m_relative) {
171             pos *= dt;
172             pos += QPointF(d->curAX(), d->curAY());
173         }
174         d->setInstantaneousAX(pos.x());
175         d->setInstantaneousAY(pos.y());
176         changed = true;
177     }
178
179     if (m_speed != &m_nullVector){
180         QPointF pos = m_speed->sample(curPos);
181         if (m_relative) {
182             pos *= dt;
183             pos += QPointF(d->curVX(), d->curVY());
184         }
185         d->setInstantaneousVX(pos.x());
186         d->setInstantaneousVY(pos.y());
187         changed = true;
188     }
189
190     if (m_position != &m_nullVector){
191         QPointF pos = m_position->sample(curPos);
192         if (m_relative) {
193             pos *= dt;
194             pos += curPos;
195         }
196         d->setInstantaneousX(pos.x());
197         d->setInstantaneousY(pos.y());
198         changed = true;
199     }
200
201     return changed;
202 }
203
204 void QQuickCustomAffector::affectProperties(const QList<QQuickParticleData*> particles, qreal dt)
205 {
206     foreach (QQuickParticleData* d, particles)
207         if ( affectParticle(d, dt) )
208             d->update = 1.0;
209 }
210
211 QT_END_NAMESPACE