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 "qquickv8particledata_p.h"
43 #include "qquickparticlesystem_p.h"//for QQuickParticleData
50 \inqmlmodule QtQuick.Particles 2
51 \brief Represents particles manipulated by emitters and affectors
52 \ingroup qtquick-particles
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
59 \qmlproperty real QtQuick.Particles2::Particle::initialX
60 The x coordinate of the particle at the beginning of its lifetime.
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.
68 \qmlproperty real QtQuick.Particles2::Particle::initialVX
69 The x velocity of the particle at the beginning of its lifetime.
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.
77 \qmlproperty real QtQuick.Particles2::Particle::initialAX
78 The x acceleration of the particle at the beginning of its lifetime.
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.
86 \qmlproperty real QtQuick.Particles2::Particle::initialY
87 The y coordinate of the particle at the beginning of its lifetime.
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.
95 \qmlproperty real QtQuick.Particles2::Particle::initialVY
96 The y velocity of the particle at the beginning of its lifetime.
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.
104 \qmlproperty real QtQuick.Particles2::Particle::initialAY
105 The y acceleration of the particle at the beginning of its lifetime.
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.
113 \qmlproperty real QtQuick.Particles2::Particle::x
114 The current x coordinate of the particle.
118 \qmlproperty real QtQuick.Particles2::Particle::vx
119 The current x velocity of the particle.
123 \qmlproperty real QtQuick.Particles2::Particle::ax
124 The current x acceleration of the particle.
128 \qmlproperty real QtQuick.Particles2::Particle::y
129 The current y coordinate of the particle.
133 \qmlproperty real QtQuick.Particles2::Particle::vy
134 The current y velocity of the particle.
138 \qmlproperty real QtQuick.Particles2::Particle::ay
139 The current y acceleration of the particle.
143 \qmlproperty real QtQuick.Particles2::Particle::t
144 The time, in seconds since the beginning of the simulation, that the particle was born.
149 \qmlproperty real QtQuick.Particles2::Particle::startSize
150 The size in pixels that the particle image is at the start
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
164 \qmlproperty real QtQuick.Particles2::Particle::lifeSpan
165 The time in seconds that the particle will live for.
169 \qmlproperty real QtQuick.Particles2::Particle::rotation
170 Degrees clockwise that the particle image is rotated at
171 the beginning of its life.
175 \qmlproperty real QtQuick.Particles2::Particle::rotationVelocity
176 Degrees clockwise per second that the particle image is rotated at while alive.
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.
186 \qmlproperty bool QtQuick.Particles2::Particle::update
188 Inside an Affector, the changes made to the particle will only be
189 applied if update is set to true.
192 \qmlproperty real QtQuick.Particles2::Particle::xDeformationVectorX
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.
200 \qmlproperty real QtQuick.Particles2::Particle::yDeformationVectorX
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.
208 \qmlproperty real QtQuick.Particles2::Particle::xDeformationVectorY
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.
216 \qmlproperty real QtQuick.Particles2::Particle::yDeformationVectorY
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.
224 \qmlproperty real QtQuick.Particles2::Particle::red
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.
229 Values are from 0.0 to 1.0.
233 \qmlproperty real QtQuick.Particles2::Particle::green
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.
238 Values are from 0.0 to 1.0.
242 \qmlproperty real QtQuick.Particles2::Particle::blue
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.
247 Values are from 0.0 to 1.0.
251 \qmlproperty real QtQuick.Particles2::Particle::alpha
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.
256 Values are from 0.0 to 1.0.
259 \qmlproperty real QtQuick.Particles2::Particle::lifeLeft
260 The time in seconds that the particle has left to live at
261 the current point in time.
264 \qmlproperty real QtQuick.Particles2::Particle::currentSize
265 The currentSize of the particle, interpolating between startSize and endSize based on the currentTime.
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
273 V8_RESOURCE_TYPE(ParticleDataType)
275 QV8ParticleDataResource(QV8Engine *e) : QV8ObjectResource(e) {}
276 QQuickParticleData* datum;//TODO: Guard needed?
279 class QV8ParticleDataDeletable : public QV8Engine::Deletable
282 QV8ParticleDataDeletable(QV8Engine *engine);
283 ~QV8ParticleDataDeletable();
285 v8::Persistent<v8::Function> constructor;
288 static v8::Handle<v8::Value> particleData_discard(const v8::Arguments &args)
290 QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(args.This());
293 V8THROW_ERROR("Not a valid ParticleData object");
295 r->datum->lifeSpan = 0; //Don't kill(), because it could still be in the middle of being created
296 return v8::Undefined();
299 static v8::Handle<v8::Value> particleData_lifeLeft(const v8::Arguments &args)
301 QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(args.This());
303 V8THROW_ERROR("Not a valid ParticleData object");
305 return v8::Number::New(r->datum->lifeLeft());
308 static v8::Handle<v8::Value> particleData_curSize(const v8::Arguments &args)
310 QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(args.This());
312 V8THROW_ERROR("Not a valid ParticleData object");
314 return v8::Number::New(r->datum->curSize());
316 #define COLOR_GETTER_AND_SETTER(VAR, NAME) static v8::Handle<v8::Value> particleData_get_ ## NAME (v8::Local<v8::String>, const v8::AccessorInfo &info) \
318 QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This()); \
319 if (!r || !r->datum) \
320 V8THROW_ERROR("Not a valid ParticleData object"); \
322 return v8::Number::New((r->datum->color. VAR )/255.0);\
325 static void particleData_set_ ## NAME (v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)\
327 QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This());\
328 if (!r || !r->datum)\
329 V8THROW_ERROR_SETTER("Not a valid ParticleData object");\
331 r->datum->color. VAR = qMin(255, qMax(0, (int)floor(value->NumberValue() * 255.0)));\
335 #define SEMIBOOL_GETTER_AND_SETTER(VARIABLE) static v8::Handle<v8::Value> particleData_get_ ## VARIABLE (v8::Local<v8::String>, const v8::AccessorInfo &info) \
337 QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This()); \
338 if (!r || !r->datum) \
339 V8THROW_ERROR("Not a valid ParticleData object"); \
341 return v8::Boolean::New(r->datum-> VARIABLE);\
344 static void particleData_set_ ## VARIABLE (v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)\
346 QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This());\
347 if (!r || !r->datum)\
348 V8THROW_ERROR_SETTER("Not a valid ParticleData object");\
350 r->datum-> VARIABLE = value->BooleanValue() ? 1.0 : 0.0;\
353 #define FLOAT_GETTER_AND_SETTER(VARIABLE) static v8::Handle<v8::Value> particleData_get_ ## VARIABLE (v8::Local<v8::String>, const v8::AccessorInfo &info) \
355 QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This()); \
356 if (!r || !r->datum) \
357 V8THROW_ERROR("Not a valid ParticleData object"); \
359 return v8::Number::New(r->datum-> VARIABLE);\
362 static void particleData_set_ ## VARIABLE (v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)\
364 QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This());\
365 if (!r || !r->datum)\
366 V8THROW_ERROR_SETTER("Not a valid ParticleData object");\
368 r->datum-> VARIABLE = value->NumberValue();\
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) \
373 QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This()); \
374 if (!r || !r->datum) \
375 V8THROW_ERROR("Not a valid ParticleData object"); \
377 return v8::Number::New(r->datum-> GETTER ());\
380 static void particleData_set_ ## VARIABLE (v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)\
382 QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This());\
383 if (!r || !r->datum)\
384 V8THROW_ERROR_SETTER("Not a valid ParticleData object");\
386 r->datum-> SETTER ( value->NumberValue() );\
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))
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)
426 QV8ParticleDataDeletable::QV8ParticleDataDeletable(QV8Engine *engine)
428 v8::HandleScope handle_scope;
429 v8::Context::Scope scope(engine->context());
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);
471 constructor = qPersistentNew(ft->GetFunction());
474 QV8ParticleDataDeletable::~QV8ParticleDataDeletable()
476 qPersistentDispose(constructor);
479 V8_DEFINE_EXTENSION(QV8ParticleDataDeletable, particleV8Data);
482 QQuickV8ParticleData::QQuickV8ParticleData(QV8Engine* engine, QQuickParticleData* datum)
484 if (!engine || !datum)
486 v8::HandleScope handle_scope;
487 v8::Context::Scope scope(engine->context());
489 QV8ParticleDataDeletable *d = particleV8Data(engine);
490 m_v8Value = qPersistentNew(d->constructor->NewInstance());
491 QV8ParticleDataResource *r = new QV8ParticleDataResource(engine);
493 m_v8Value->SetExternalResource(r);
496 QQuickV8ParticleData::~QQuickV8ParticleData()
498 qPersistentDispose(m_v8Value);
501 QQmlV8Handle QQuickV8ParticleData::v8Value()
503 return QQmlV8Handle::fromHandle(m_v8Value);