1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
7 ** This file is part of the Declarative module of the Qt Toolkit.
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.
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.
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.
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.
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(frameCount)
415 FLOAT_GETTER_AND_SETTER(animT)
416 FLOAT_GETTER_AND_SETTER(r)
417 FAKE_FLOAT_GETTER_AND_SETTER(curX, curX, setInstantaneousX)
418 FAKE_FLOAT_GETTER_AND_SETTER(curVX, curVX, setInstantaneousVX)
419 FAKE_FLOAT_GETTER_AND_SETTER(curAX, curAX, setInstantaneousAX)
420 FAKE_FLOAT_GETTER_AND_SETTER(curY, curY, setInstantaneousY)
421 FAKE_FLOAT_GETTER_AND_SETTER(curVY, curVY, setInstantaneousVY)
422 FAKE_FLOAT_GETTER_AND_SETTER(curAY, curAY, setInstantaneousAY)
424 QV8ParticleDataDeletable::QV8ParticleDataDeletable(QV8Engine *engine)
426 v8::HandleScope handle_scope;
427 v8::Context::Scope scope(engine->context());
429 v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
430 ft->InstanceTemplate()->SetHasExternalResource(true);
431 ft->PrototypeTemplate()->Set(v8::String::New("discard"), V8FUNCTION(particleData_discard, engine));
432 ft->PrototypeTemplate()->Set(v8::String::New("lifeLeft"), V8FUNCTION(particleData_lifeLeft, engine));
433 ft->PrototypeTemplate()->Set(v8::String::New("currentSize"), V8FUNCTION(particleData_curSize, engine));
434 REGISTER_ACCESSOR(ft, engine, x, initialX);
435 REGISTER_ACCESSOR(ft, engine, y, initialY);
436 REGISTER_ACCESSOR(ft, engine, t, t);
437 REGISTER_ACCESSOR(ft, engine, lifeSpan, lifeSpan);
438 REGISTER_ACCESSOR(ft, engine, size, startSize);
439 REGISTER_ACCESSOR(ft, engine, endSize, endSize);
440 REGISTER_ACCESSOR(ft, engine, vx, initialVX);
441 REGISTER_ACCESSOR(ft, engine, vy, initialVY);
442 REGISTER_ACCESSOR(ft, engine, ax, initialAX);
443 REGISTER_ACCESSOR(ft, engine, ay, initialAY);
444 REGISTER_ACCESSOR(ft, engine, xx, xDeformationVectorX);
445 REGISTER_ACCESSOR(ft, engine, xy, xDeformationVectorY);
446 REGISTER_ACCESSOR(ft, engine, yx, yDeformationVectorX);
447 REGISTER_ACCESSOR(ft, engine, yy, yDeformationVectorY);
448 REGISTER_ACCESSOR(ft, engine, rotation, rotation);
449 REGISTER_ACCESSOR(ft, engine, rotationSpeed, rotationSpeed);
450 REGISTER_ACCESSOR(ft, engine, autoRotate, autoRotate);
451 REGISTER_ACCESSOR(ft, engine, animIdx, animationIndex);
452 REGISTER_ACCESSOR(ft, engine, frameDuration, frameDuration);
453 REGISTER_ACCESSOR(ft, engine, frameCount, frameCount);
454 REGISTER_ACCESSOR(ft, engine, animT, animationT);
455 REGISTER_ACCESSOR(ft, engine, r, r);
456 REGISTER_ACCESSOR(ft, engine, update, update);
457 REGISTER_ACCESSOR(ft, engine, curX, x);
458 REGISTER_ACCESSOR(ft, engine, curVX, vx);
459 REGISTER_ACCESSOR(ft, engine, curAX, ax);
460 REGISTER_ACCESSOR(ft, engine, curY, y);
461 REGISTER_ACCESSOR(ft, engine, curVY, vy);
462 REGISTER_ACCESSOR(ft, engine, curAY, ay);
463 REGISTER_ACCESSOR(ft, engine, red, red);
464 REGISTER_ACCESSOR(ft, engine, green, green);
465 REGISTER_ACCESSOR(ft, engine, blue, blue);
466 REGISTER_ACCESSOR(ft, engine, alpha, alpha);
468 constructor = qPersistentNew(ft->GetFunction());
471 QV8ParticleDataDeletable::~QV8ParticleDataDeletable()
473 qPersistentDispose(constructor);
476 V8_DEFINE_EXTENSION(QV8ParticleDataDeletable, particleV8Data);
479 QQuickV8ParticleData::QQuickV8ParticleData(QV8Engine* engine, QQuickParticleData* datum)
481 if (!engine || !datum)
483 v8::HandleScope handle_scope;
484 v8::Context::Scope scope(engine->context());
486 QV8ParticleDataDeletable *d = particleV8Data(engine);
487 m_v8Value = qPersistentNew(d->constructor->NewInstance());
488 QV8ParticleDataResource *r = new QV8ParticleDataResource(engine);
490 m_v8Value->SetExternalResource(r);
493 QQuickV8ParticleData::~QQuickV8ParticleData()
495 qPersistentDispose(m_v8Value);
498 QDeclarativeV8Handle QQuickV8ParticleData::v8Value()
500 return QDeclarativeV8Handle::fromHandle(m_v8Value);