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