Rename speed -> velocity in the particle system
[profile/ivi/qtdeclarative.git] / src / particles / qquickv8particledata.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 QtQuick 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 "qquickv8particledata_p.h"
43 #include "qquickparticlesystem_p.h"//for QQuickParticleData
44 #include <QDebug>
45
46 QT_BEGIN_NAMESPACE
47
48 /*!
49     \qmlclass Particle
50     \inqmlmodule QtQuick.Particles 2
51     \brief Represents particles manipulated by emitters and affectors
52     \ingroup qtquick-particles
53
54     Particle elements are always managed internally by the ParticleSystem and cannot be created in QML.
55     However, sometimes they are exposed via signals so as to allow arbitrary changes to the particle state
56 */
57
58 /*!
59     \qmlproperty real QtQuick.Particles2::Particle::initialX
60     The x coordinate of the particle at the beginning of its lifetime.
61
62     The method of simulation prefers to have the initial values changed, rather
63     than determining and changing the value at a given time. Change initial
64     values in CustomEmitters instead of the current values.
65 */
66
67 /*!
68     \qmlproperty real QtQuick.Particles2::Particle::initialVX
69     The x velocity of the particle at the beginning of its lifetime.
70
71     The method of simulation prefers to have the initial values changed, rather
72     than determining and changing the value at a given time. Change initial
73     values in CustomEmitters instead of the current values.
74 */
75
76 /*!
77     \qmlproperty real QtQuick.Particles2::Particle::initialAX
78     The x acceleration of the particle at the beginning of its lifetime.
79
80     The method of simulation prefers to have the initial values changed, rather
81     than determining and changing the value at a given time. Change initial
82     values in CustomEmitters instead of the current values.
83 */
84
85 /*!
86     \qmlproperty real QtQuick.Particles2::Particle::initialY
87     The y coordinate of the particle at the beginning of its lifetime.
88
89     The method of simulation prefers to have the initial values changed, rather
90     than determining and changing the value at a given time. Change initial
91     values in CustomEmitters instead of the current values.
92 */
93
94 /*!
95     \qmlproperty real QtQuick.Particles2::Particle::initialVY
96     The y velocity of the particle at the beginning of its lifetime.
97
98     The method of simulation prefers to have the initial values changed, rather
99     than determining and changing the value at a given time. Change initial
100     values in CustomEmitters instead of the current values.
101 */
102
103 /*!
104     \qmlproperty real QtQuick.Particles2::Particle::initialAY
105     The y acceleration of the particle at the beginning of its lifetime.
106
107     The method of simulation prefers to have the initial values changed, rather
108     than determining and changing the value at a given time. Change initial
109     values in CustomEmitters instead of the current values.
110 */
111
112 /*!
113     \qmlproperty real QtQuick.Particles2::Particle::x
114     The current x coordinate of the particle.
115 */
116
117 /*!
118     \qmlproperty real QtQuick.Particles2::Particle::vx
119     The current x velocity of the particle.
120 */
121
122 /*!
123     \qmlproperty real QtQuick.Particles2::Particle::ax
124     The current x acceleration of the particle.
125 */
126
127 /*!
128     \qmlproperty real QtQuick.Particles2::Particle::y
129     The current y coordinate of the particle.
130 */
131
132 /*!
133     \qmlproperty real QtQuick.Particles2::Particle::vy
134     The current y velocity of the particle.
135 */
136
137 /*!
138     \qmlproperty real QtQuick.Particles2::Particle::ay
139     The current y acceleration of the particle.
140 */
141
142 /*!
143     \qmlproperty real QtQuick.Particles2::Particle::t
144     The time, in seconds since the beginning of the simulation, that the particle was born.
145 */
146
147
148 /*!
149     \qmlproperty real QtQuick.Particles2::Particle::startSize
150     The size in pixels that the particle image is at the start
151     of its life.
152 */
153
154
155 /*!
156     \qmlproperty real QtQuick.Particles2::Particle::endSize
157     The size in pixels that the particle image is at the end
158     of its life. If this value is less than 0, then it is
159     disregarded and the particle will have its startSize for the
160     entire lifetime.
161 */
162
163 /*!
164     \qmlproperty real QtQuick.Particles2::Particle::lifeSpan
165     The time in seconds that the particle will live for.
166 */
167
168 /*!
169     \qmlproperty real QtQuick.Particles2::Particle::rotation
170     Degrees clockwise that the particle image is rotated at
171     the beginning of its life.
172 */
173
174 /*!
175     \qmlproperty real QtQuick.Particles2::Particle::rotationVelocity
176     Degrees clockwise per second that the particle image is rotated at while alive.
177 */
178 /*!
179     \qmlproperty bool QtQuick.Particles2::Particle::autoRotate
180     If autoRotate is true, then the particle's rotation will be
181     set so that it faces the direction of travel, plus any
182     rotation from the rotation or rotationVelocity properties.
183 */
184
185 /*!
186     \qmlproperty bool QtQuick.Particles2::Particle::update
187
188     Inside an Affector, the changes made to the particle will only be
189     applied if update is set to true.
190 */
191 /*!
192     \qmlproperty real QtQuick.Particles2::Particle::xDeformationVectorX
193
194     The x component of the deformation vector along the X axis. ImageParticle
195     can draw particles across non-square shapes. It will draw the texture rectangle
196     across the parallelogram drawn with the x and y deformation vectors.
197 */
198
199 /*!
200     \qmlproperty real QtQuick.Particles2::Particle::yDeformationVectorX
201
202     The y component of the deformation vector along the X axis. ImageParticle
203     can draw particles across non-square shapes. It will draw the texture rectangle
204     across the parallelogram drawn with the x and y deformation vectors.
205 */
206
207 /*!
208     \qmlproperty real QtQuick.Particles2::Particle::xDeformationVectorY
209
210     The x component of the deformation vector along the X axis. ImageParticle
211     can draw particles across non-square shapes. It will draw the texture rectangle
212     across the parallelogram drawn with the x and y deformation vectors.
213 */
214
215 /*!
216     \qmlproperty real QtQuick.Particles2::Particle::yDeformationVectorY
217
218     The y component of the deformation vector along the Y axis. ImageParticle
219     can draw particles across non-square shapes. It will draw the texture rectangle
220     across the parallelogram drawn with the x and y deformation vectors.
221 */
222
223 /*!
224     \qmlproperty real QtQuick.Particles2::Particle::red
225
226     ImageParticle can draw colorized particles. When it does so, red is used
227     as the red channel of the color applied to the source image.
228
229     Values are from 0.0 to 1.0.
230 */
231
232 /*!
233     \qmlproperty real QtQuick.Particles2::Particle::green
234
235     ImageParticle can draw colorized particles. When it does so, green is used
236     as the green channel of the color applied to the source image.
237
238     Values are from 0.0 to 1.0.
239 */
240
241 /*!
242     \qmlproperty real QtQuick.Particles2::Particle::blue
243
244     ImageParticle can draw colorized particles. When it does so, blue is used
245     as the blue channel of the color applied to the source image.
246
247     Values are from 0.0 to 1.0.
248 */
249
250 /*!
251     \qmlproperty real QtQuick.Particles2::Particle::alpha
252
253     ImageParticle can draw colorized particles. When it does so, alpha is used
254     as the alpha channel of the color applied to the source image.
255
256     Values are from 0.0 to 1.0.
257 */
258 /*!
259     \qmlmethod real QtQuick.Particles2::Particle::lifeLeft
260     The time in seconds that the particle has left to live at
261     the current point in time.
262 */
263 /*!
264     \qmlmethod real QtQuick.Particles2::Particle::currentSize
265     The currentSize of the particle, interpolating between startSize and endSize based on the currentTime.
266 */
267
268
269
270 //### Particle data handles are not locked to within certain scopes like QQuickContext2D, but there's no way to reload either...
271 class QV8ParticleDataResource : public QV8ObjectResource
272 {
273     V8_RESOURCE_TYPE(ParticleDataType)
274 public:
275     QV8ParticleDataResource(QV8Engine *e) : QV8ObjectResource(e) {}
276     QQuickParticleData* datum;//TODO: Guard needed?
277 };
278
279 class QV8ParticleDataDeletable : public QV8Engine::Deletable
280 {
281 public:
282     QV8ParticleDataDeletable(QV8Engine *engine);
283     ~QV8ParticleDataDeletable();
284
285     v8::Persistent<v8::Function> constructor;
286 };
287
288 static v8::Handle<v8::Value> particleData_discard(const v8::Arguments &args)
289 {
290     QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(args.This());
291
292     if (!r || !r->datum)
293         V8THROW_ERROR("Not a valid ParticleData object");
294
295     r->datum->lifeSpan = 0; //Don't kill(), because it could still be in the middle of being created
296     return v8::Undefined();
297 }
298
299 static v8::Handle<v8::Value> particleData_lifeLeft(const v8::Arguments &args)
300 {
301     QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(args.This());
302     if (!r || !r->datum)
303         V8THROW_ERROR("Not a valid ParticleData object");
304
305     return v8::Number::New(r->datum->lifeLeft());
306 }
307
308 static v8::Handle<v8::Value> particleData_curSize(const v8::Arguments &args)
309 {
310     QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(args.This());
311     if (!r || !r->datum)
312         V8THROW_ERROR("Not a valid ParticleData object");
313
314     return v8::Number::New(r->datum->curSize());
315 }
316 #define COLOR_GETTER_AND_SETTER(VAR, NAME) static v8::Handle<v8::Value> particleData_get_ ## NAME (v8::Local<v8::String>, const v8::AccessorInfo &info) \
317 { \
318     QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This()); \
319     if (!r || !r->datum) \
320         V8THROW_ERROR("Not a valid ParticleData object"); \
321 \
322     return v8::Number::New((r->datum->color. VAR )/255.0);\
323 }\
324 \
325 static void particleData_set_ ## NAME (v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)\
326 {\
327     QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This());\
328     if (!r || !r->datum)\
329         V8THROW_ERROR_SETTER("Not a valid ParticleData object");\
330 \
331     r->datum->color. VAR = qMin(255, qMax(0, (int)floor(value->NumberValue() * 255.0)));\
332 }
333
334
335 #define SEMIBOOL_GETTER_AND_SETTER(VARIABLE) static v8::Handle<v8::Value> particleData_get_ ## VARIABLE (v8::Local<v8::String>, const v8::AccessorInfo &info) \
336 { \
337     QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This()); \
338     if (!r || !r->datum) \
339         V8THROW_ERROR("Not a valid ParticleData object"); \
340 \
341     return v8::Boolean::New(r->datum-> VARIABLE);\
342 }\
343 \
344 static void particleData_set_ ## VARIABLE (v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)\
345 {\
346     QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This());\
347     if (!r || !r->datum)\
348         V8THROW_ERROR_SETTER("Not a valid ParticleData object");\
349 \
350     r->datum-> VARIABLE = value->BooleanValue() ? 1.0 : 0.0;\
351 }
352
353 #define FLOAT_GETTER_AND_SETTER(VARIABLE) static v8::Handle<v8::Value> particleData_get_ ## VARIABLE (v8::Local<v8::String>, const v8::AccessorInfo &info) \
354 { \
355     QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This()); \
356     if (!r || !r->datum) \
357         V8THROW_ERROR("Not a valid ParticleData object"); \
358 \
359     return v8::Number::New(r->datum-> VARIABLE);\
360 }\
361 \
362 static void particleData_set_ ## VARIABLE (v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)\
363 {\
364     QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This());\
365     if (!r || !r->datum)\
366         V8THROW_ERROR_SETTER("Not a valid ParticleData object");\
367 \
368     r->datum-> VARIABLE = value->NumberValue();\
369 }
370
371 #define FAKE_FLOAT_GETTER_AND_SETTER(VARIABLE, GETTER, SETTER) static v8::Handle<v8::Value> particleData_get_ ## VARIABLE (v8::Local<v8::String>, const v8::AccessorInfo &info) \
372 { \
373     QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This()); \
374     if (!r || !r->datum) \
375         V8THROW_ERROR("Not a valid ParticleData object"); \
376 \
377     return v8::Number::New(r->datum-> GETTER ());\
378 }\
379 \
380 static void particleData_set_ ## VARIABLE (v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)\
381 {\
382     QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This());\
383     if (!r || !r->datum)\
384         V8THROW_ERROR_SETTER("Not a valid ParticleData object");\
385 \
386     r->datum-> SETTER ( value->NumberValue() );\
387 }
388
389 #define REGISTER_ACCESSOR(FT, ENGINE, VARIABLE, NAME) FT ->PrototypeTemplate()->SetAccessor( v8::String::New( #NAME ), particleData_get_ ## VARIABLE , particleData_set_ ## VARIABLE , v8::External::Wrap(ENGINE))
390
391 COLOR_GETTER_AND_SETTER(r, red)
392 COLOR_GETTER_AND_SETTER(g, green)
393 COLOR_GETTER_AND_SETTER(b, blue)
394 COLOR_GETTER_AND_SETTER(a, alpha)
395 SEMIBOOL_GETTER_AND_SETTER(autoRotate)
396 SEMIBOOL_GETTER_AND_SETTER(update)
397 FLOAT_GETTER_AND_SETTER(x)
398 FLOAT_GETTER_AND_SETTER(y)
399 FLOAT_GETTER_AND_SETTER(t)
400 FLOAT_GETTER_AND_SETTER(lifeSpan)
401 FLOAT_GETTER_AND_SETTER(size)
402 FLOAT_GETTER_AND_SETTER(endSize)
403 FLOAT_GETTER_AND_SETTER(vx)
404 FLOAT_GETTER_AND_SETTER(vy)
405 FLOAT_GETTER_AND_SETTER(ax)
406 FLOAT_GETTER_AND_SETTER(ay)
407 FLOAT_GETTER_AND_SETTER(xx)
408 FLOAT_GETTER_AND_SETTER(xy)
409 FLOAT_GETTER_AND_SETTER(yx)
410 FLOAT_GETTER_AND_SETTER(yy)
411 FLOAT_GETTER_AND_SETTER(rotation)
412 FLOAT_GETTER_AND_SETTER(rotationVelocity)
413 FLOAT_GETTER_AND_SETTER(animIdx)
414 FLOAT_GETTER_AND_SETTER(frameDuration)
415 FLOAT_GETTER_AND_SETTER(frameAt)
416 FLOAT_GETTER_AND_SETTER(frameCount)
417 FLOAT_GETTER_AND_SETTER(animT)
418 FLOAT_GETTER_AND_SETTER(r)
419 FAKE_FLOAT_GETTER_AND_SETTER(curX, curX, setInstantaneousX)
420 FAKE_FLOAT_GETTER_AND_SETTER(curVX, curVX, setInstantaneousVX)
421 FAKE_FLOAT_GETTER_AND_SETTER(curAX, curAX, setInstantaneousAX)
422 FAKE_FLOAT_GETTER_AND_SETTER(curY, curY, setInstantaneousY)
423 FAKE_FLOAT_GETTER_AND_SETTER(curVY, curVY, setInstantaneousVY)
424 FAKE_FLOAT_GETTER_AND_SETTER(curAY, curAY, setInstantaneousAY)
425
426 QV8ParticleDataDeletable::QV8ParticleDataDeletable(QV8Engine *engine)
427 {
428     v8::HandleScope handle_scope;
429     v8::Context::Scope scope(engine->context());
430
431     v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
432     ft->InstanceTemplate()->SetHasExternalResource(true);
433     ft->PrototypeTemplate()->Set(v8::String::New("discard"), V8FUNCTION(particleData_discard, engine));
434     ft->PrototypeTemplate()->Set(v8::String::New("lifeLeft"), V8FUNCTION(particleData_lifeLeft, engine));
435     ft->PrototypeTemplate()->Set(v8::String::New("currentSize"), V8FUNCTION(particleData_curSize, engine));
436     REGISTER_ACCESSOR(ft, engine, x, initialX);
437     REGISTER_ACCESSOR(ft, engine, y, initialY);
438     REGISTER_ACCESSOR(ft, engine, t, t);
439     REGISTER_ACCESSOR(ft, engine, lifeSpan, lifeSpan);
440     REGISTER_ACCESSOR(ft, engine, size, startSize);
441     REGISTER_ACCESSOR(ft, engine, endSize, endSize);
442     REGISTER_ACCESSOR(ft, engine, vx, initialVX);
443     REGISTER_ACCESSOR(ft, engine, vy, initialVY);
444     REGISTER_ACCESSOR(ft, engine, ax, initialAX);
445     REGISTER_ACCESSOR(ft, engine, ay, initialAY);
446     REGISTER_ACCESSOR(ft, engine, xx, xDeformationVectorX);
447     REGISTER_ACCESSOR(ft, engine, xy, xDeformationVectorY);
448     REGISTER_ACCESSOR(ft, engine, yx, yDeformationVectorX);
449     REGISTER_ACCESSOR(ft, engine, yy, yDeformationVectorY);
450     REGISTER_ACCESSOR(ft, engine, rotation, rotation);
451     REGISTER_ACCESSOR(ft, engine, rotationVelocity, rotationVelocity);
452     REGISTER_ACCESSOR(ft, engine, autoRotate, autoRotate);
453     REGISTER_ACCESSOR(ft, engine, animIdx, animationIndex);
454     REGISTER_ACCESSOR(ft, engine, frameDuration, frameDuration);
455     REGISTER_ACCESSOR(ft, engine, frameAt, frameAt);
456     REGISTER_ACCESSOR(ft, engine, frameCount, frameCount);
457     REGISTER_ACCESSOR(ft, engine, animT, animationT);
458     REGISTER_ACCESSOR(ft, engine, r, r);
459     REGISTER_ACCESSOR(ft, engine, update, update);
460     REGISTER_ACCESSOR(ft, engine, curX, x);
461     REGISTER_ACCESSOR(ft, engine, curVX, vx);
462     REGISTER_ACCESSOR(ft, engine, curAX, ax);
463     REGISTER_ACCESSOR(ft, engine, curY, y);
464     REGISTER_ACCESSOR(ft, engine, curVY, vy);
465     REGISTER_ACCESSOR(ft, engine, curAY, ay);
466     REGISTER_ACCESSOR(ft, engine, red, red);
467     REGISTER_ACCESSOR(ft, engine, green, green);
468     REGISTER_ACCESSOR(ft, engine, blue, blue);
469     REGISTER_ACCESSOR(ft, engine, alpha, alpha);
470
471     constructor = qPersistentNew(ft->GetFunction());
472 }
473
474 QV8ParticleDataDeletable::~QV8ParticleDataDeletable()
475 {
476     qPersistentDispose(constructor);
477 }
478
479 V8_DEFINE_EXTENSION(QV8ParticleDataDeletable, particleV8Data);
480
481
482 QQuickV8ParticleData::QQuickV8ParticleData(QV8Engine* engine, QQuickParticleData* datum)
483 {
484     if (!engine || !datum)
485         return;
486     v8::HandleScope handle_scope;
487     v8::Context::Scope scope(engine->context());
488
489     QV8ParticleDataDeletable *d = particleV8Data(engine);
490     m_v8Value = qPersistentNew(d->constructor->NewInstance());
491     QV8ParticleDataResource *r = new QV8ParticleDataResource(engine);
492     r->datum = datum;
493     m_v8Value->SetExternalResource(r);
494 }
495
496 QQuickV8ParticleData::~QQuickV8ParticleData()
497 {
498     qPersistentDispose(m_v8Value);
499 }
500
501 QQmlV8Handle QQuickV8ParticleData::v8Value()
502 {
503     return QQmlV8Handle::fromHandle(m_v8Value);
504 }
505
506 QT_END_NAMESPACE