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 Declarative 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 Particle elements can be manipulated in custom emitters and affectors.
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
58 \qmlproperty real QtQuick.Particles2::Particle::initialX
59 The x coordinate of the particle at the beginning of its lifetime.
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.
67 \qmlproperty real QtQuick.Particles2::Particle::initialVX
68 The x velocity of the particle at the beginning of its lifetime.
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.
76 \qmlproperty real QtQuick.Particles2::Particle::initialAX
77 The x acceleration of the particle at the beginning of its lifetime.
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.
85 \qmlproperty real QtQuick.Particles2::Particle::initialY
86 The y coordinate of the particle at the beginning of its lifetime.
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.
94 \qmlproperty real QtQuick.Particles2::Particle::initialVY
95 The y velocity of the particle at the beginning of its lifetime.
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.
103 \qmlproperty real QtQuick.Particles2::Particle::initialAY
104 The y acceleration of the particle at the beginning of its lifetime.
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.
112 \qmlproperty real QtQuick.Particles2::Particle::x
113 The current x coordinate of the particle.
117 \qmlproperty real QtQuick.Particles2::Particle::vx
118 The current x velocity of the particle.
122 \qmlproperty real QtQuick.Particles2::Particle::ax
123 The current x acceleration of the particle.
127 \qmlproperty real QtQuick.Particles2::Particle::y
128 The current y coordinate of the particle.
132 \qmlproperty real QtQuick.Particles2::Particle::vy
133 The current y velocity of the particle.
137 \qmlproperty real QtQuick.Particles2::Particle::ay
138 The current y acceleration of the particle.
142 \qmlproperty real QtQuick.Particles2::Particle::t
143 The time, in seconds since the beginning of the simulation, that the particle was born.
148 \qmlproperty real QtQuick.Particles2::Particle::startSize
149 The size in pixels that the particle image is at the start
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
163 \qmlproperty real QtQuick.Particles2::Particle::lifeSpan
164 The time in seconds that the particle will live for.
168 \qmlproperty real QtQuick.Particles2::Particle::rotation
169 Degrees clockwise that the particle image is rotated at
170 the beginning of its life.
174 \qmlproperty real QtQuick.Particles2::Particle::rotationSpeed
175 Degrees clockwise per second that the particle image is rotated at while alive.
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.
185 \qmlproperty bool QtQuick.Particles2::Particle::update
187 Inside an Affector, the changes made to the particle will only be
188 applied if update is set to true.
191 \qmlproperty real QtQuick.Particles2::Particle::xDeformationVectorX
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.
199 \qmlproperty real QtQuick.Particles2::Particle::yDeformationVectorX
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.
207 \qmlproperty real QtQuick.Particles2::Particle::xDeformationVectorY
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.
215 \qmlproperty real QtQuick.Particles2::Particle::yDeformationVectorY
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.
223 \qmlproperty real QtQuick.Particles2::Particle::red
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.
228 Values are from 0.0 to 1.0.
232 \qmlproperty real QtQuick.Particles2::Particle::green
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.
237 Values are from 0.0 to 1.0.
241 \qmlproperty real QtQuick.Particles2::Particle::blue
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.
246 Values are from 0.0 to 1.0.
250 \qmlproperty real QtQuick.Particles2::Particle::alpha
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.
255 Values are from 0.0 to 1.0.
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.
263 \qmlmethod real QtQuick.Particles2::Particle::currentSize
264 The currentSize of the particle, interpolating between startSize and endSize based on the currentTime.
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
272 V8_RESOURCE_TYPE(ParticleDataType)
274 QV8ParticleDataResource(QV8Engine *e) : QV8ObjectResource(e) {}
275 QQuickParticleData* datum;//TODO: Guard needed?
278 class QV8ParticleDataDeletable : public QV8Engine::Deletable
281 QV8ParticleDataDeletable(QV8Engine *engine);
282 ~QV8ParticleDataDeletable();
284 v8::Persistent<v8::Function> constructor;
287 static v8::Handle<v8::Value> particleData_discard(const v8::Arguments &args)
289 QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(args.This());
292 V8THROW_ERROR("Not a valid ParticleData object");
294 r->datum->lifeSpan = 0; //Don't kill(), because it could still be in the middle of being created
295 return v8::Undefined();
298 static v8::Handle<v8::Value> particleData_lifeLeft(const v8::Arguments &args)
300 QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(args.This());
302 V8THROW_ERROR("Not a valid ParticleData object");
304 return v8::Number::New(r->datum->lifeLeft());
307 static v8::Handle<v8::Value> particleData_curSize(const v8::Arguments &args)
309 QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(args.This());
311 V8THROW_ERROR("Not a valid ParticleData object");
313 return v8::Number::New(r->datum->curSize());
315 #define COLOR_GETTER_AND_SETTER(VAR, NAME) static v8::Handle<v8::Value> particleData_get_ ## NAME (v8::Local<v8::String>, const v8::AccessorInfo &info) \
317 QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This()); \
318 if (!r || !r->datum) \
319 V8THROW_ERROR("Not a valid ParticleData object"); \
321 return v8::Number::New((r->datum->color. VAR )/255.0);\
324 static void particleData_set_ ## NAME (v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)\
326 QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This());\
327 if (!r || !r->datum)\
328 V8THROW_ERROR_SETTER("Not a valid ParticleData object");\
330 r->datum->color. VAR = qMin(255, qMax(0, (int)floor(value->NumberValue() * 255.0)));\
334 #define SEMIBOOL_GETTER_AND_SETTER(VARIABLE) static v8::Handle<v8::Value> particleData_get_ ## VARIABLE (v8::Local<v8::String>, const v8::AccessorInfo &info) \
336 QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This()); \
337 if (!r || !r->datum) \
338 V8THROW_ERROR("Not a valid ParticleData object"); \
340 return v8::Boolean::New(r->datum-> VARIABLE);\
343 static void particleData_set_ ## VARIABLE (v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)\
345 QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This());\
346 if (!r || !r->datum)\
347 V8THROW_ERROR_SETTER("Not a valid ParticleData object");\
349 r->datum-> VARIABLE = value->BooleanValue() ? 1.0 : 0.0;\
352 #define FLOAT_GETTER_AND_SETTER(VARIABLE) static v8::Handle<v8::Value> particleData_get_ ## VARIABLE (v8::Local<v8::String>, const v8::AccessorInfo &info) \
354 QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This()); \
355 if (!r || !r->datum) \
356 V8THROW_ERROR("Not a valid ParticleData object"); \
358 return v8::Number::New(r->datum-> VARIABLE);\
361 static void particleData_set_ ## VARIABLE (v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)\
363 QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This());\
364 if (!r || !r->datum)\
365 V8THROW_ERROR_SETTER("Not a valid ParticleData object");\
367 r->datum-> VARIABLE = value->NumberValue();\
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) \
372 QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This()); \
373 if (!r || !r->datum) \
374 V8THROW_ERROR("Not a valid ParticleData object"); \
376 return v8::Number::New(r->datum-> GETTER ());\
379 static void particleData_set_ ## VARIABLE (v8::Local<v8::String>, v8::Local<v8::Value> value, const v8::AccessorInfo &info)\
381 QV8ParticleDataResource *r = v8_resource_cast<QV8ParticleDataResource>(info.This());\
382 if (!r || !r->datum)\
383 V8THROW_ERROR_SETTER("Not a valid ParticleData object");\
385 r->datum-> SETTER ( value->NumberValue() );\
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))
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)
425 QV8ParticleDataDeletable::QV8ParticleDataDeletable(QV8Engine *engine)
427 v8::HandleScope handle_scope;
428 v8::Context::Scope scope(engine->context());
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);
470 constructor = qPersistentNew(ft->GetFunction());
473 QV8ParticleDataDeletable::~QV8ParticleDataDeletable()
475 qPersistentDispose(constructor);
478 V8_DEFINE_EXTENSION(QV8ParticleDataDeletable, particleV8Data);
481 QQuickV8ParticleData::QQuickV8ParticleData(QV8Engine* engine, QQuickParticleData* datum)
483 if (!engine || !datum)
485 v8::HandleScope handle_scope;
486 v8::Context::Scope scope(engine->context());
488 QV8ParticleDataDeletable *d = particleV8Data(engine);
489 m_v8Value = qPersistentNew(d->constructor->NewInstance());
490 QV8ParticleDataResource *r = new QV8ParticleDataResource(engine);
492 m_v8Value->SetExternalResource(r);
495 QQuickV8ParticleData::~QQuickV8ParticleData()
497 qPersistentDispose(m_v8Value);
500 QQmlV8Handle QQuickV8ParticleData::v8Value()
502 return QQmlV8Handle::fromHandle(m_v8Value);