aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/particles
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@nokia.com>2011-08-25 11:47:24 +0200
committerGunnar Sletta <gunnar.sletta@nokia.com>2011-08-25 12:52:15 +0200
commit8e6ecb56e5d61ce661422779c9d9cbf22f081a34 (patch)
tree227aeb360800a49de58472bd39bc5f4c596c1b15 /src/declarative/particles
parentc9224b6cf5cceb7d5314f7504d44bfe72bc66950 (diff)
parent0d84e957297b4ffa6ab5b0b5bcf8b169d567d298 (diff)
Merge branch 'master' into refactor
Conflicts: src/declarative/items/qsgcanvas.cpp src/declarative/items/qsgitem.cpp src/declarative/items/qsgtextnode.cpp tests/auto/declarative/examples/examples.pro tools/qmlviewer/qmlviewer.pro Change-Id: Icbb0ef5dc79b658c62fd2b2c25a66c9bb3cbeb10
Diffstat (limited to 'src/declarative/particles')
-rw-r--r--src/declarative/particles/defaultshaders/coloredfragment.shader9
-rw-r--r--src/declarative/particles/defaultshaders/coloredvertex.shader (renamed from src/declarative/particles/defaultshaders/trailsvertex.shader)31
-rw-r--r--src/declarative/particles/defaultshaders/ctfragment.shader11
-rw-r--r--src/declarative/particles/defaultshaders/ctvertex.shader38
-rw-r--r--src/declarative/particles/defaultshaders/deformablefragment.shader5
-rw-r--r--src/declarative/particles/defaultshaders/deformablevertex.shader70
-rw-r--r--src/declarative/particles/defaultshaders/imagefragment.shader45
-rw-r--r--src/declarative/particles/defaultshaders/imagevertex.shader (renamed from src/declarative/particles/defaultshaders/ultravertex.shader)129
-rw-r--r--src/declarative/particles/defaultshaders/simplefragment.shader4
-rw-r--r--src/declarative/particles/defaultshaders/simplevertex.shader33
-rw-r--r--src/declarative/particles/defaultshaders/spritefragment.shader9
-rw-r--r--src/declarative/particles/defaultshaders/spritevertex.shader90
-rw-r--r--src/declarative/particles/defaultshaders/superfragment.shader11
-rw-r--r--src/declarative/particles/defaultshaders/tabledfragment.shader23
-rw-r--r--src/declarative/particles/defaultshaders/tabledvertex.shader (renamed from src/declarative/particles/defaultshaders/supervertex.shader)13
-rw-r--r--src/declarative/particles/defaultshaders/trailsfragment.shader8
-rw-r--r--src/declarative/particles/defaultshaders/ultrafragment.shader16
-rw-r--r--src/declarative/particles/particles.pri6
-rw-r--r--src/declarative/particles/particles.qrc16
-rw-r--r--src/declarative/particles/qsgangleddirection.cpp1
-rw-r--r--src/declarative/particles/qsgcumulativedirection.cpp1
-rw-r--r--src/declarative/particles/qsgcustomaffector.cpp73
-rw-r--r--src/declarative/particles/qsgcustomaffector_p.h69
-rw-r--r--src/declarative/particles/qsgcustomemitter.cpp189
-rw-r--r--src/declarative/particles/qsgcustomemitter_p.h76
-rw-r--r--src/declarative/particles/qsgcustomparticle.cpp5
-rw-r--r--src/declarative/particles/qsgellipseextruder.cpp1
-rw-r--r--src/declarative/particles/qsgemitter.cpp262
-rw-r--r--src/declarative/particles/qsgemitter_p.h104
-rw-r--r--src/declarative/particles/qsgfollowemitter.cpp88
-rw-r--r--src/declarative/particles/qsgfollowemitter_p.h2
-rw-r--r--src/declarative/particles/qsgfriction.cpp1
-rw-r--r--src/declarative/particles/qsggravity.cpp1
-rw-r--r--src/declarative/particles/qsgimageparticle.cpp923
-rw-r--r--src/declarative/particles/qsgimageparticle_p.h114
-rw-r--r--src/declarative/particles/qsgitemparticle.cpp1
-rw-r--r--src/declarative/particles/qsgkill.cpp1
-rw-r--r--src/declarative/particles/qsglineextruder.cpp1
-rw-r--r--src/declarative/particles/qsgmaskextruder.cpp1
-rw-r--r--src/declarative/particles/qsgmodelparticle.cpp1
-rw-r--r--src/declarative/particles/qsgparticleaffector.cpp28
-rw-r--r--src/declarative/particles/qsgparticleaffector_p.h2
-rw-r--r--src/declarative/particles/qsgparticleemitter.cpp307
-rw-r--r--src/declarative/particles/qsgparticleemitter_p.h58
-rw-r--r--src/declarative/particles/qsgparticleextruder.cpp1
-rw-r--r--src/declarative/particles/qsgparticlepainter.cpp1
-rw-r--r--src/declarative/particles/qsgparticlesmodule.cpp18
-rw-r--r--src/declarative/particles/qsgparticlesystem.cpp3
-rw-r--r--src/declarative/particles/qsgpointattractor.cpp1
-rw-r--r--src/declarative/particles/qsgpointattractor_p.h2
-rw-r--r--src/declarative/particles/qsgpointdirection.cpp1
-rw-r--r--src/declarative/particles/qsgspritegoal.cpp1
-rw-r--r--src/declarative/particles/qsgstochasticdirection.cpp1
-rw-r--r--src/declarative/particles/qsgtargeteddirection.cpp1
-rw-r--r--src/declarative/particles/qsgturbulence.cpp1
-rw-r--r--src/declarative/particles/qsgwander.cpp1
56 files changed, 1415 insertions, 1494 deletions
diff --git a/src/declarative/particles/defaultshaders/coloredfragment.shader b/src/declarative/particles/defaultshaders/coloredfragment.shader
new file mode 100644
index 0000000000..4ae2643598
--- /dev/null
+++ b/src/declarative/particles/defaultshaders/coloredfragment.shader
@@ -0,0 +1,9 @@
+uniform sampler2D texture;
+uniform lowp float qt_Opacity;
+
+varying lowp vec4 fColor;
+
+void main() {
+ gl_FragColor = (texture2D(texture, gl_PointCoord)) * fColor * qt_Opacity;
+}
+
diff --git a/src/declarative/particles/defaultshaders/trailsvertex.shader b/src/declarative/particles/defaultshaders/coloredvertex.shader
index 7bc1d66b71..5b8339276c 100644
--- a/src/declarative/particles/defaultshaders/trailsvertex.shader
+++ b/src/declarative/particles/defaultshaders/coloredvertex.shader
@@ -1,18 +1,15 @@
attribute highp vec2 vPos;
-attribute highp vec2 vTex;
attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize
attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration
attribute lowp vec4 vColor;
-uniform highp mat4 matrix;
+uniform highp mat4 qt_Matrix;
uniform highp float timestamp;
-uniform lowp float opacity;
+uniform highp float entry;
-varying highp vec2 fTex;
varying lowp vec4 fColor;
-void main() {
- fTex = vTex;
+void main() {
highp float size = vData.z;
highp float endSize = vData.w;
@@ -23,15 +20,25 @@ void main() {
if (t < 0. || t > 1.)
currentSize = 0.;
+ lowp float fFade = 1.;
+
+ if (entry == 1.){
+ highp float fadeIn = min(t * 10., 1.);
+ highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.));
+ fFade = fadeIn * fadeOut;
+ }else if(entry == 2.){
+ highp float sizeIn = min(t * 10., 1.);
+ highp float sizeOut = 1. - max(0., min((t - 0.75) * 4., 1.));
+ currentSize = currentSize * sizeIn * sizeOut;
+ }
+
+ gl_PointSize = currentSize;
+
highp vec2 pos = vPos
- - currentSize / 2. + currentSize * vTex // adjust size
+ vVec.xy * t * vData.y // apply speed vector..
+ 0.5 * vVec.zw * pow(t * vData.y, 2.);
- gl_Position = matrix * vec4(pos.x, pos.y, 0, 1);
-
- highp float fadeIn = min(t * 10., 1.);
- highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.));
+ gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);
- fColor = vColor * fadeIn * fadeOut * opacity;
+ fColor = vColor * (fFade);
}
diff --git a/src/declarative/particles/defaultshaders/ctfragment.shader b/src/declarative/particles/defaultshaders/ctfragment.shader
deleted file mode 100644
index a17f5841ca..0000000000
--- a/src/declarative/particles/defaultshaders/ctfragment.shader
+++ /dev/null
@@ -1,11 +0,0 @@
-uniform sampler2D texture;
-uniform sampler2D colortable;
-uniform sampler2D opacitytable;
-
-varying highp vec2 fTex;
-varying lowp vec4 fColor;
-varying lowp float tt;
-
-void main() {
- gl_FragColor = (texture2D(texture, fTex).w) * fColor * texture2D(colortable, vec2(tt, 0.5)) *( texture2D(opacitytable, vec2(tt, 0.5)).w);
-}
diff --git a/src/declarative/particles/defaultshaders/ctvertex.shader b/src/declarative/particles/defaultshaders/ctvertex.shader
deleted file mode 100644
index b20676cc49..0000000000
--- a/src/declarative/particles/defaultshaders/ctvertex.shader
+++ /dev/null
@@ -1,38 +0,0 @@
-attribute highp vec2 vPos;
-attribute highp vec2 vTex;
-attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize
-attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration
-attribute lowp vec4 vColor;
-
-uniform highp mat4 matrix;
-uniform highp float timestamp;
-uniform sampler2D sizetable;
-uniform sampler2D opacitytable;
-
-varying highp vec2 fTex;
-varying lowp vec4 fColor;
-varying lowp float tt;
-
-void main() {
- fTex = vTex;
- highp float size = vData.z;
- highp float endSize = vData.w;
-
- highp float t = (timestamp - vData.x) / vData.y;
-
- highp float currentSize = mix(size, endSize, t * t) * texture2D(sizetable, vec2(t,0.5)).w;
-
- if (t < 0. || t > 1.)
- currentSize = 0.;
-
- highp vec2 pos = vPos
- - currentSize / 2. + currentSize * vTex // adjust size
- + vVec.xy * t * vData.y // apply speed vector..
- + 0.5 * vVec.zw * pow(t * vData.y, 2.);
-
- gl_Position = matrix * vec4(pos.x, pos.y, 0, 1);
-
- fColor = vColor;
- tt = t;
-
-}
diff --git a/src/declarative/particles/defaultshaders/deformablefragment.shader b/src/declarative/particles/defaultshaders/deformablefragment.shader
index 494053e319..1ac25ba208 100644
--- a/src/declarative/particles/defaultshaders/deformablefragment.shader
+++ b/src/declarative/particles/defaultshaders/deformablefragment.shader
@@ -1,8 +1,9 @@
uniform sampler2D texture;
+uniform lowp float qt_Opacity;
varying highp vec2 fTex;
-varying lowp float fFade;
+varying lowp vec4 fColor;
void main() {
- gl_FragColor = (texture2D(texture, fTex)) * fFade;
+ gl_FragColor = (texture2D(texture, fTex)) * fColor * qt_Opacity;
}
diff --git a/src/declarative/particles/defaultshaders/deformablevertex.shader b/src/declarative/particles/defaultshaders/deformablevertex.shader
index 01570950b1..ab6acde36d 100644
--- a/src/declarative/particles/defaultshaders/deformablevertex.shader
+++ b/src/declarative/particles/defaultshaders/deformablevertex.shader
@@ -4,13 +4,14 @@ attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize
attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration
attribute highp vec4 vDeformVec; //x,y x unit vector; z,w = y unit vector
attribute highp vec3 vRotation; //x = radians of rotation, y=rotation speed, z= bool autoRotate
+attribute lowp vec4 vColor;
-uniform highp mat4 matrix;
+uniform highp mat4 qt_Matrix;
uniform highp float timestamp;
-uniform lowp float opacity;
+uniform highp float entry;
varying highp vec2 fTex;
-varying lowp float fFade;
+varying lowp vec4 fColor;
void main() {
fTex = vTex;
@@ -21,37 +22,44 @@ void main() {
highp float currentSize = mix(size, endSize, t * t);
- highp vec2 pos;
- if (t < 0. || t > 1.){
+ if (t < 0. || t > 1.)
currentSize = 0.;
- pos = vPos;
- }else{
- highp float rotation = vRotation.x + vRotation.y * t * vData.y;
- if(vRotation.z == 1.0){
- highp vec2 curVel = vVec.zw * t * vData.y + vVec.xy;
- rotation += atan(curVel.y, curVel.x);
- }
- highp vec2 trigCalcs = vec2(cos(rotation), sin(rotation));
- highp vec2 xDeform = vDeformVec.xy * currentSize * (vTex.x-0.5);
- highp vec2 yDeform = vDeformVec.zw * currentSize * (vTex.y-0.5);
- highp vec2 xRotatedDeform;
- xRotatedDeform.x = trigCalcs.x*xDeform.x - trigCalcs.y*xDeform.y;
- xRotatedDeform.y = trigCalcs.y*xDeform.x + trigCalcs.x*xDeform.y;
- highp vec2 yRotatedDeform;
- yRotatedDeform.x = trigCalcs.x*yDeform.x - trigCalcs.y*yDeform.y;
- yRotatedDeform.y = trigCalcs.y*yDeform.x + trigCalcs.x*yDeform.y;
- pos = vPos
- + xRotatedDeform
- + yRotatedDeform
- //- vec2(1,1) * currentSize * 0.5 // 'center'
- + vVec.xy * t * vData.y // apply speed
- + 0.5 * vVec.zw * pow(t * vData.y, 2.); // apply acceleration
+
+ lowp float fFade = 1.;
+
+ if (entry == 1.){
+ highp float fadeIn = min(t * 10., 1.);
+ highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.));
+ fFade = fadeIn * fadeOut;
+ }else if(entry == 2.){
+ highp float sizeIn = min(t * 10., 1.);
+ highp float sizeOut = 1. - max(0., min((t - 0.75) * 4., 1.));
+ currentSize = currentSize * sizeIn * sizeOut;
}
- gl_Position = matrix * vec4(pos.x, pos.y, 0, 1);
+ highp vec2 pos;
+ highp float rotation = vRotation.x + vRotation.y * t * vData.y;
+ if(vRotation.z == 1.0){
+ highp vec2 curVel = vVec.zw * t * vData.y + vVec.xy;
+ rotation += atan(curVel.y, curVel.x);
+ }
+ highp vec2 trigCalcs = vec2(cos(rotation), sin(rotation));
+ highp vec2 xDeform = vDeformVec.xy * currentSize * (vTex.x-0.5);
+ highp vec2 yDeform = vDeformVec.zw * currentSize * (vTex.y-0.5);
+ highp vec2 xRotatedDeform;
+ xRotatedDeform.x = trigCalcs.x*xDeform.x - trigCalcs.y*xDeform.y;
+ xRotatedDeform.y = trigCalcs.y*xDeform.x + trigCalcs.x*xDeform.y;
+ highp vec2 yRotatedDeform;
+ yRotatedDeform.x = trigCalcs.x*yDeform.x - trigCalcs.y*yDeform.y;
+ yRotatedDeform.y = trigCalcs.y*yDeform.x + trigCalcs.x*yDeform.y;
+ pos = vPos
+ + xRotatedDeform
+ + yRotatedDeform
+ //- vec2(1,1) * currentSize * 0.5 // 'center'
+ + vVec.xy * t * vData.y // apply speed
+ + 0.5 * vVec.zw * pow(t * vData.y, 2.); // apply acceleration
- highp float fadeIn = min(t * 10., 1.);
- highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.));
+ gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);
- fFade = fadeIn * fadeOut * opacity;
+ fColor = vColor * fFade;
}
diff --git a/src/declarative/particles/defaultshaders/imagefragment.shader b/src/declarative/particles/defaultshaders/imagefragment.shader
new file mode 100644
index 0000000000..c2341fe6ff
--- /dev/null
+++ b/src/declarative/particles/defaultshaders/imagefragment.shader
@@ -0,0 +1,45 @@
+uniform sampler2D texture;
+uniform lowp float qt_Opacity;
+
+#ifdef SPRITE
+varying highp vec4 fTexS;
+#else
+#ifdef DEFORM //First non-pointsprite
+varying highp vec2 fTex;
+#endif
+#endif
+#ifdef COLOR
+varying lowp vec4 fColor;
+#else
+varying lowp float fFade;
+#endif
+#ifdef TABLE
+varying lowp vec2 tt;
+uniform sampler2D colortable;
+#endif
+
+void main() {
+#ifdef SPRITE
+ gl_FragColor = mix(texture2D(texture, fTexS.xy), texture2D(texture, fTexS.zw), tt.y)
+ * fColor
+ * texture2D(colortable, tt)
+ * qt_Opacity;
+#else
+#ifdef TABLE
+ gl_FragColor = texture2D(texture, fTex)
+ * fColor
+ * texture2D(colortable, tt)
+ * qt_Opacity;
+#else
+#ifdef DEFORM
+ gl_FragColor = (texture2D(texture, fTex)) * fColor * qt_Opacity;
+#else
+#ifdef COLOR
+ gl_FragColor = (texture2D(texture, gl_PointCoord)) * fColor * qt_Opacity;
+#else
+ gl_FragColor = texture2D(texture, gl_PointCoord) * (fFade * qt_Opacity);
+#endif //COLOR
+#endif //DEFORM
+#endif //TABLE
+#endif //SPRITE
+}
diff --git a/src/declarative/particles/defaultshaders/ultravertex.shader b/src/declarative/particles/defaultshaders/imagevertex.shader
index 65a1a3077a..e1033c9165 100644
--- a/src/declarative/particles/defaultshaders/ultravertex.shader
+++ b/src/declarative/particles/defaultshaders/imagevertex.shader
@@ -1,76 +1,97 @@
attribute highp vec2 vPos;
-attribute highp vec2 vTex;
attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize
attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration
+uniform highp float entry;
+#ifdef COLOR
attribute lowp vec4 vColor;
+#endif
+#ifdef DEFORM
+attribute highp vec2 vTex;
attribute highp vec4 vDeformVec; //x,y x unit vector; z,w = y unit vector
attribute highp vec3 vRotation; //x = radians of rotation, y=rotation speed, z= bool autoRotate
+#endif
+#ifdef SPRITE
attribute highp vec4 vAnimData;// idx, duration, frameCount (this anim), timestamp (this anim)
-
-uniform highp mat4 matrix;
-uniform highp float timestamp;
uniform highp float framecount; //maximum of all anims
uniform highp float animcount;
-uniform sampler2D sizetable;
+#endif
-varying lowp float tt;
-varying highp vec2 fTexA;
-varying highp vec2 fTexB;
-varying lowp float progress;
+uniform highp mat4 qt_Matrix;
+uniform highp float timestamp;
+#ifdef TABLE
+varying lowp vec2 tt;//y is progress if Sprite mode
+uniform highp float sizetable[64];
+uniform highp float opacitytable[64];
+#endif
+#ifdef SPRITE
+varying highp vec4 fTexS;
+#else
+#ifdef DEFORM
+varying highp vec2 fTex;
+#endif
+#endif
+#ifdef COLOR
varying lowp vec4 fColor;
+#else
+varying lowp float fFade;
+#endif
void main() {
- highp float size = vData.z;
- highp float endSize = vData.w;
highp float t = (timestamp - vData.x) / vData.y;
-
+ if (t < 0. || t > 1.){
+#ifdef DEFORM //Not point sprites
+ gl_Position = qt_Matrix * vec4(vPos.x, vPos.y, 0., 1.);
+#else
+ gl_PointSize = 0.;
+#endif
+ return;
+ }
+#ifdef SPRITE
//Calculate frame location in texture
highp float frameIndex = mod((((timestamp - vAnimData.w)*1000.)/vAnimData.y),vAnimData.z);
- progress = mod((timestamp - vAnimData.w)*1000., vAnimData.y) / vAnimData.y;
+ tt.y = mod((timestamp - vAnimData.w)*1000., vAnimData.y) / vAnimData.y;
frameIndex = floor(frameIndex);
- highp vec2 frameTex = vTex;
- if(vTex.x == 0.)
- frameTex.x = (frameIndex/framecount);
- else
- frameTex.x = 1. * ((frameIndex + 1.)/framecount);
-
- if(vTex.y == 0.)
- frameTex.y = (vAnimData.x/animcount);
- else
- frameTex.y = 1. * ((vAnimData.x + 1.)/animcount);
+ fTexS.xy = vec2(((frameIndex + vTex.x) / framecount), ((vAnimData.x + vTex.y) / animcount));
- fTexA = frameTex;
//Next frame is also passed, for interpolation
//### Should the next anim be precalculated to allow for interpolation there?
if(frameIndex != vAnimData.z - 1.)//Can't do it for the last frame though, this anim may not loop
frameIndex = mod(frameIndex+1., vAnimData.z);
-
- if(vTex.x == 0.)
- frameTex.x = (frameIndex/framecount);
- else
- frameTex.x = 1. * ((frameIndex + 1.)/framecount);
-
- if(vTex.y == 0.)
- frameTex.y = (vAnimData.x/animcount);
- else
- frameTex.y = 1. * ((vAnimData.x + 1.)/animcount);
- fTexB = frameTex;
-
- highp float currentSize = mix(size, endSize, t * t) * texture2D(sizetable, vec2(t,0.5)).w;
-
- if (t < 0. || t > 1.)
- currentSize = 0.;
+ fTexS.zw = vec2(((frameIndex + vTex.x) / framecount), ((vAnimData.x + vTex.y) / animcount));
+#else
+#ifdef DEFORM
+ fTex = vTex;
+#endif
+#endif
+ highp float currentSize = mix(vData.z, vData.w, t * t);
+ lowp float fade = 1.;
+ highp float fadeIn = min(t * 10., 1.);
+ highp float fadeOut = 1. - clamp((t - 0.75) * 4.,0., 1.);
+
+#ifdef TABLE
+ currentSize = currentSize * sizetable[int(floor(t*64.))];
+ fade = fade * opacitytable[int(floor(t*64.))];
+#endif
+ if (entry == 1.)
+ fade = fadeIn * fadeOut;
+ else if(entry == 2.)
+ currentSize = currentSize * fadeIn * fadeOut;
highp vec2 pos;
+#ifdef DEFORM
highp float rotation = vRotation.x + vRotation.y * t * vData.y;
if(vRotation.z == 1.0){
highp vec2 curVel = vVec.zw * t * vData.y + vVec.xy;
rotation += atan(curVel.y, curVel.x);
}
highp vec2 trigCalcs = vec2(cos(rotation), sin(rotation));
+ highp vec4 deform = vDeformVec * currentSize * (vTex.xxyy - 0.5);
+ highp vec4 rotatedDeform = deform.xxzz * trigCalcs.xyxy;
+ rotatedDeform = rotatedDeform + (deform.yyww * trigCalcs.yxyx * vec4(-1.,1.,-1.,1.));
+ /* The readable version:
highp vec2 xDeform = vDeformVec.xy * currentSize * (vTex.x-0.5);
highp vec2 yDeform = vDeformVec.zw * currentSize * (vTex.y-0.5);
highp vec2 xRotatedDeform;
@@ -79,16 +100,26 @@ void main() {
highp vec2 yRotatedDeform;
yRotatedDeform.x = trigCalcs.x*yDeform.x - trigCalcs.y*yDeform.y;
yRotatedDeform.y = trigCalcs.y*yDeform.x + trigCalcs.x*yDeform.y;
+ */
pos = vPos
- + xRotatedDeform
- + yRotatedDeform
- //- vec2(1,1) * currentSize * 0.5 // 'center'
+ + rotatedDeform.xy
+ + rotatedDeform.zw
+ vVec.xy * t * vData.y // apply speed
+ 0.5 * vVec.zw * pow(t * vData.y, 2.); // apply acceleration
-
- gl_Position = matrix * vec4(pos.x, pos.y, 0, 1);
-
- fColor = vColor;
- tt = t;
-
+#else
+ pos = vPos
+ + vVec.xy * t * vData.y // apply speed vector..
+ + 0.5 * vVec.zw * pow(t * vData.y, 2.);
+ gl_PointSize = currentSize;
+#endif
+ gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);
+
+#ifdef COLOR
+ fColor = vColor * fade;
+#else
+ fFade = fade;
+#endif
+#ifdef TABLE
+ tt.x = t;
+#endif
}
diff --git a/src/declarative/particles/defaultshaders/simplefragment.shader b/src/declarative/particles/defaultshaders/simplefragment.shader
index 494053e319..9b445da52f 100644
--- a/src/declarative/particles/defaultshaders/simplefragment.shader
+++ b/src/declarative/particles/defaultshaders/simplefragment.shader
@@ -1,8 +1,8 @@
uniform sampler2D texture;
+uniform lowp float qt_Opacity;
-varying highp vec2 fTex;
varying lowp float fFade;
void main() {
- gl_FragColor = (texture2D(texture, fTex)) * fFade;
+ gl_FragColor = texture2D(texture, gl_PointCoord) * (fFade * qt_Opacity);
}
diff --git a/src/declarative/particles/defaultshaders/simplevertex.shader b/src/declarative/particles/defaultshaders/simplevertex.shader
index f185ef0700..c287e159a5 100644
--- a/src/declarative/particles/defaultshaders/simplevertex.shader
+++ b/src/declarative/particles/defaultshaders/simplevertex.shader
@@ -1,36 +1,39 @@
attribute highp vec2 vPos;
-attribute highp vec2 vTex;
attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize
attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration
-uniform highp mat4 matrix;
+uniform highp mat4 qt_Matrix;
uniform highp float timestamp;
-uniform lowp float opacity;
+uniform highp float entry;
-varying highp vec2 fTex;
varying lowp float fFade;
void main() {
- fTex = vTex;
- highp float size = vData.z;
- highp float endSize = vData.w;
-
highp float t = (timestamp - vData.x) / vData.y;
- highp float currentSize = mix(size, endSize, t * t);
+ highp float currentSize = mix(vData.z, vData.w, t * t);
if (t < 0. || t > 1.)
currentSize = 0.;
+ fFade = 1.;
+
+ if (entry == 1.){
+ highp float fadeIn = min(t * 10., 1.);
+ highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.));
+ fFade = fadeIn * fadeOut;
+ }else if(entry == 2.){
+ highp float sizeIn = min(t * 10., 1.);
+ highp float sizeOut = 1. - max(0., min((t - 0.75) * 4., 1.));
+ currentSize = currentSize * sizeIn * sizeOut;
+ }
+
+ gl_PointSize = currentSize;
+
highp vec2 pos = vPos
- - currentSize / 2. + currentSize * vTex // adjust size
+ vVec.xy * t * vData.y // apply speed vector..
+ 0.5 * vVec.zw * pow(t * vData.y, 2.);
- gl_Position = matrix * vec4(pos.x, pos.y, 0, 1);
-
- highp float fadeIn = min(t * 10., 1.);
- highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.));
+ gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);
- fFade = fadeIn * fadeOut * opacity;
}
diff --git a/src/declarative/particles/defaultshaders/spritefragment.shader b/src/declarative/particles/defaultshaders/spritefragment.shader
index 4d89d69c6a..86002f03fb 100644
--- a/src/declarative/particles/defaultshaders/spritefragment.shader
+++ b/src/declarative/particles/defaultshaders/spritefragment.shader
@@ -1,10 +1,17 @@
uniform sampler2D texture;
+uniform sampler2D colortable;
+uniform sampler2D opacitytable;
+uniform lowp float qt_Opacity;
varying highp vec2 fTexA;
varying highp vec2 fTexB;
varying lowp float progress;
varying lowp vec4 fColor;
+varying lowp float tt;
void main() {
- gl_FragColor = mix(texture2D(texture, fTexA), texture2D(texture, fTexB), progress) * fColor.w;
+ gl_FragColor = mix(texture2D(texture, fTexA), texture2D(texture, fTexB), progress)
+ * fColor
+ * texture2D(colortable, vec2(tt, 0.5))
+ * (texture2D(opacitytable, vec2(tt, 0.5)).w * qt_Opacity);
}
diff --git a/src/declarative/particles/defaultshaders/spritevertex.shader b/src/declarative/particles/defaultshaders/spritevertex.shader
index 78b8e36b3b..96ce3454b8 100644
--- a/src/declarative/particles/defaultshaders/spritevertex.shader
+++ b/src/declarative/particles/defaultshaders/spritevertex.shader
@@ -1,26 +1,41 @@
attribute highp vec2 vPos;
-attribute highp vec2 vTex;
attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize
attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration
+#ifdef COLOR
+attribute lowp vec4 vColor;
+#endif
+#ifdef DEFORM
+attribute highp vec2 vTex;
+attribute highp vec4 vDeformVec; //x,y x unit vector; z,w = y unit vector
+attribute highp vec3 vRotation; //x = radians of rotation, y=rotation speed, z= bool autoRotate
+#endif
+#ifdef SPRITE
attribute highp vec4 vAnimData;// idx, duration, frameCount (this anim), timestamp (this anim)
-
-uniform highp mat4 matrix;
-uniform highp float timestamp;
-uniform lowp float opacity;
uniform highp float framecount; //maximum of all anims
uniform highp float animcount;
-
+#endif
+
+uniform highp mat4 qt_Matrix;
+uniform highp float timestamp;
+#ifdef TABLE
+varying lowp float tt;
+#endif
+#ifdef SPRITE
+varying lowp float progress;
varying highp vec2 fTexA;
varying highp vec2 fTexB;
-varying lowp float progress;
+#elseif DEFORM
+varying highp vec2 fTex;
+#endif
+#ifdef COLOR
varying lowp vec4 fColor;
+#endif
-void main() {
- highp float size = vData.z;
- highp float endSize = vData.w;
- highp float t = (timestamp - vData.x) / vData.y;
+void main() {
+ highp float t = (timestamp - vData.x) / vData.y;
+#ifdef SPRITE
//Calculate frame location in texture
highp float frameIndex = mod((((timestamp - vAnimData.w)*1000.)/vAnimData.y),vAnimData.z);
progress = mod((timestamp - vAnimData.w)*1000., vAnimData.y) / vAnimData.y;
@@ -53,25 +68,46 @@ void main() {
else
frameTex.y = 1. * ((vAnimData.x + 1.)/animcount);
fTexB = frameTex;
+#endif
- //Applying Size here seems to screw with RockingAffector?
- highp float currentSize = mix(size, endSize, t * t);
+ highp float currentSize = mix(vData.z, vData.w, t * t);
if (t < 0. || t > 1.)
currentSize = 0.;
- //If affector is mananging pos, they don't set speed?
- highp vec2 pos = vPos
- - currentSize / 2. + currentSize * vTex // adjust size
- + vVec.xy * t * vData.y // apply speed vector..
- + 0.5 * vVec.zw * pow(t * vData.y, 2.);
-
- gl_Position = matrix * vec4(pos.x, pos.y, 0, 1);
-
- // calculate opacity
- highp float fadeIn = min(t * 10., 1.);
- highp float fadeOut = 1. - max(0., min((t - 0.75) * 4., 1.));
-
- lowp vec4 white = vec4(1.);
- fColor = white * fadeIn * fadeOut * opacity;
+ highp vec2 pos;
+#ifdef DEFORM
+ highp float rotation = vRotation.x + vRotation.y * t * vData.y;
+ if(vRotation.z == 1.0){
+ highp vec2 curVel = vVec.zw * t * vData.y + vVec.xy;
+ rotation += atan(curVel.y, curVel.x);
+ }
+ highp vec2 trigCalcs = vec2(cos(rotation), sin(rotation));
+ highp vec2 xDeform = vDeformVec.xy * currentSize * (vTex.x-0.5);
+ highp vec2 yDeform = vDeformVec.zw * currentSize * (vTex.y-0.5);
+ highp vec2 xRotatedDeform;
+ xRotatedDeform.x = trigCalcs.x*xDeform.x - trigCalcs.y*xDeform.y;
+ xRotatedDeform.y = trigCalcs.y*xDeform.x + trigCalcs.x*xDeform.y;
+ highp vec2 yRotatedDeform;
+ yRotatedDeform.x = trigCalcs.x*yDeform.x - trigCalcs.y*yDeform.y;
+ yRotatedDeform.y = trigCalcs.y*yDeform.x + trigCalcs.x*yDeform.y;
+ pos = vPos
+ + xRotatedDeform
+ + yRotatedDeform
+ //- vec2(1,1) * currentSize * 0.5 // 'center'
+ + vVec.xy * t * vData.y // apply speed
+ + 0.5 * vVec.zw * pow(t * vData.y, 2.); // apply acceleration
+#else
+ pos = vPos
+ + vVec.xy * t * vData.y // apply speed vector..
+ + 0.5 * vVec.zw * pow(t * vData.y, 2.);
+#endif
+ gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);
+
+#ifdef COLOR
+ fColor = vColor;
+#endif
+#ifdef TABLE
+ tt = t;
+#endif
}
diff --git a/src/declarative/particles/defaultshaders/superfragment.shader b/src/declarative/particles/defaultshaders/superfragment.shader
deleted file mode 100644
index a17f5841ca..0000000000
--- a/src/declarative/particles/defaultshaders/superfragment.shader
+++ /dev/null
@@ -1,11 +0,0 @@
-uniform sampler2D texture;
-uniform sampler2D colortable;
-uniform sampler2D opacitytable;
-
-varying highp vec2 fTex;
-varying lowp vec4 fColor;
-varying lowp float tt;
-
-void main() {
- gl_FragColor = (texture2D(texture, fTex).w) * fColor * texture2D(colortable, vec2(tt, 0.5)) *( texture2D(opacitytable, vec2(tt, 0.5)).w);
-}
diff --git a/src/declarative/particles/defaultshaders/tabledfragment.shader b/src/declarative/particles/defaultshaders/tabledfragment.shader
new file mode 100644
index 0000000000..e92d8050eb
--- /dev/null
+++ b/src/declarative/particles/defaultshaders/tabledfragment.shader
@@ -0,0 +1,23 @@
+uniform sampler2D texture;
+uniform sampler2D colortable;
+uniform sampler2D opacitytable;
+uniform sampler2D sizetable;
+uniform lowp float qt_Opacity;
+
+varying highp vec2 fTex;
+varying lowp vec4 fColor;
+varying lowp float tt;
+
+void main() {
+ highp vec2 tex = (((fTex - 0.5) / texture2D(sizetable, vec2(tt, 0.5)).w) + 0.5);
+ lowp vec4 color;
+ if(tex.x < 1.0 && tex.x > 0.0 && tex.y < 1.0 && tex.y > 0.0){//No CLAMP_TO_BORDER in ES2, so have to do it ourselves
+ color = texture2D(texture, tex);
+ }else{
+ color = vec4(0.,0.,0.,0.);
+ }
+ gl_FragColor = color
+ * fColor
+ * texture2D(colortable, vec2(tt, 0.5))
+ * (texture2D(opacitytable, vec2(tt, 0.5)).w * qt_Opacity);
+}
diff --git a/src/declarative/particles/defaultshaders/supervertex.shader b/src/declarative/particles/defaultshaders/tabledvertex.shader
index 432a23ce05..ef3c35da82 100644
--- a/src/declarative/particles/defaultshaders/supervertex.shader
+++ b/src/declarative/particles/defaultshaders/tabledvertex.shader
@@ -6,14 +6,14 @@ attribute lowp vec4 vColor;
attribute highp vec4 vDeformVec; //x,y x unit vector; z,w = y unit vector
attribute highp vec3 vRotation; //x = radians of rotation, y=rotation speed, z= bool autoRotate
-uniform highp mat4 matrix;
+uniform highp mat4 qt_Matrix;
uniform highp float timestamp;
-uniform sampler2D sizetable;
-uniform sampler2D opacitytable;
+varying lowp float tt;
varying highp vec2 fTex;
+varying lowp float progress;
varying lowp vec4 fColor;
-varying lowp float tt;
+
void main() {
fTex = vTex;
@@ -22,8 +22,7 @@ void main() {
highp float t = (timestamp - vData.x) / vData.y;
- highp float currentSize = mix(size, endSize, t * t) * texture2D(sizetable, vec2(t,0.5)).w;
-
+ highp float currentSize = mix(size, endSize, t * t);
if (t < 0. || t > 1.)
currentSize = 0.;
@@ -49,7 +48,7 @@ void main() {
+ vVec.xy * t * vData.y // apply speed
+ 0.5 * vVec.zw * pow(t * vData.y, 2.); // apply acceleration
- gl_Position = matrix * vec4(pos.x, pos.y, 0, 1);
+ gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);
fColor = vColor;
tt = t;
diff --git a/src/declarative/particles/defaultshaders/trailsfragment.shader b/src/declarative/particles/defaultshaders/trailsfragment.shader
deleted file mode 100644
index d3db87fa30..0000000000
--- a/src/declarative/particles/defaultshaders/trailsfragment.shader
+++ /dev/null
@@ -1,8 +0,0 @@
-uniform sampler2D texture;
-
-varying highp vec2 fTex;
-varying lowp vec4 fColor;
-
-void main() {
- gl_FragColor = (texture2D(texture, fTex).w) * fColor;
-}
diff --git a/src/declarative/particles/defaultshaders/ultrafragment.shader b/src/declarative/particles/defaultshaders/ultrafragment.shader
deleted file mode 100644
index 0627d0f1e8..0000000000
--- a/src/declarative/particles/defaultshaders/ultrafragment.shader
+++ /dev/null
@@ -1,16 +0,0 @@
-uniform sampler2D texture;
-uniform sampler2D colortable;
-uniform sampler2D opacitytable;
-
-varying highp vec2 fTexA;
-varying highp vec2 fTexB;
-varying lowp float progress;
-varying lowp vec4 fColor;
-varying lowp float tt;
-
-void main() {
- gl_FragColor = mix(texture2D(texture, fTexA), texture2D(texture, fTexB), progress)
- * fColor
- * texture2D(colortable, vec2(tt, 0.5))
- *( texture2D(opacitytable, vec2(tt, 0.5)).w);
-}
diff --git a/src/declarative/particles/particles.pri b/src/declarative/particles/particles.pri
index 582e1d3f8c..9f63cd81b9 100644
--- a/src/declarative/particles/particles.pri
+++ b/src/declarative/particles/particles.pri
@@ -4,7 +4,6 @@ HEADERS += \
$$PWD/qsgangleddirection_p.h \
$$PWD/qsgcustomparticle_p.h \
$$PWD/qsgellipseextruder_p.h \
- $$PWD/qsgemitter_p.h \
$$PWD/qsgfollowemitter_p.h \
$$PWD/qsgfriction_p.h \
$$PWD/qsggravity_p.h \
@@ -29,15 +28,12 @@ HEADERS += \
$$PWD/qsgwander_p.h \
$$PWD/qsgtargetaffector_p.h \
$$PWD/qsgcumulativedirection_p.h \
- $$PWD/qsgcustomemitter_p.h \
- $$PWD/qsgcustomaffector_p.h \
$$PWD/qsgv8particledata_p.h
SOURCES += \
$$PWD/qsgangleddirection.cpp \
$$PWD/qsgcustomparticle.cpp \
$$PWD/qsgellipseextruder.cpp \
- $$PWD/qsgemitter.cpp \
$$PWD/qsgfollowemitter.cpp \
$$PWD/qsgfriction.cpp \
$$PWD/qsggravity.cpp \
@@ -62,8 +58,6 @@ SOURCES += \
$$PWD/qsgwander.cpp \
$$PWD/qsgtargetaffector.cpp \
$$PWD/qsgcumulativedirection.cpp \
- $$PWD/qsgcustomemitter.cpp \
- $$PWD/qsgcustomaffector.cpp \
$$PWD/qsgv8particledata.cpp
RESOURCES += \
diff --git a/src/declarative/particles/particles.qrc b/src/declarative/particles/particles.qrc
index 85931ec9ce..5403f55266 100644
--- a/src/declarative/particles/particles.qrc
+++ b/src/declarative/particles/particles.qrc
@@ -1,22 +1,10 @@
<RCC>
<qresource prefix="/">
- <file>defaultshaders/spritefragment.shader</file>
- <file>defaultshaders/spritevertex.shader</file>
- <file>defaultshaders/ctfragment.shader</file>
- <file>defaultshaders/ctvertex.shader</file>
- <file>defaultshaders/trailsfragment.shader</file>
- <file>defaultshaders/trailsvertex.shader</file>
+ <file>defaultshaders/imagefragment.shader</file>
+ <file>defaultshaders/imagevertex.shader</file>
<file>defaultshaders/spriteimagefragment.shader</file>
<file>defaultshaders/spriteimagevertex.shader</file>
<file>defaultshaders/identitytable.png</file>
<file>defaultshaders/defaultFadeInOut.png</file>
- <file>defaultshaders/deformablefragment.shader</file>
- <file>defaultshaders/deformablevertex.shader</file>
- <file>defaultshaders/ultravertex.shader</file>
- <file>defaultshaders/ultrafragment.shader</file>
- <file>defaultshaders/supervertex.shader</file>
- <file>defaultshaders/superfragment.shader</file>
- <file>defaultshaders/simplevertex.shader</file>
- <file>defaultshaders/simplefragment.shader</file>
</qresource>
</RCC>
diff --git a/src/declarative/particles/qsgangleddirection.cpp b/src/declarative/particles/qsgangleddirection.cpp
index ffd434f980..ab39b8a575 100644
--- a/src/declarative/particles/qsgangleddirection.cpp
+++ b/src/declarative/particles/qsgangleddirection.cpp
@@ -46,7 +46,6 @@ const qreal CONV = 0.017453292519943295;
/*!
\qmlclass AngledDirection QSGAngledDirection
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits StochasticDirection
\brief The AngledDirection element allows you to specify a direction that varies in angle
diff --git a/src/declarative/particles/qsgcumulativedirection.cpp b/src/declarative/particles/qsgcumulativedirection.cpp
index 5ffdef6327..1d7523972b 100644
--- a/src/declarative/particles/qsgcumulativedirection.cpp
+++ b/src/declarative/particles/qsgcumulativedirection.cpp
@@ -45,7 +45,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass CumulativeDirection QSGCumulativeDirection
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits StochasticDirection
\brief The CumulativeDirection element allows you to specify a direction made of other directions
diff --git a/src/declarative/particles/qsgcustomaffector.cpp b/src/declarative/particles/qsgcustomaffector.cpp
deleted file mode 100644
index 9832399661..0000000000
--- a/src/declarative/particles/qsgcustomaffector.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsgcustomaffector_p.h"
-QT_BEGIN_NAMESPACE
-/*!
- \qmlclass CustomAffector QSGCustomAffector
- \inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
- \inherits Affector
- \brief The Custom affector allows you to modify affected particles
-
-*/
-
-//TODO: Document particle 'type'
-/*!
- \qmlsignal Timer::affecting(particle, dt)
-
- This handler is called when a particle is selected to be affected.
-
- dt is the time since the last time it was affected. Use dt to normalize
- trajectory manipulations to real time.
-*/
-QSGCustomAffector::QSGCustomAffector(QSGItem *parent) :
- QSGParticleAffector(parent)
-{
-}
-
-
-bool QSGCustomAffector::affectParticle(QSGParticleData *d, qreal dt)
-{
- emit affectParticle(d->v8Value(), dt);
- return true;//TODO: Work it out (best added alongside autoTimeScaling)
-}
-QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgcustomaffector_p.h b/src/declarative/particles/qsgcustomaffector_p.h
deleted file mode 100644
index b4d0ca7417..0000000000
--- a/src/declarative/particles/qsgcustomaffector_p.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef CUSTOMAFFECTOR_H
-#define CUSTOMAFFECTOR_H
-#include "qsgparticleaffector_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-
-class QSGCustomAffector : public QSGParticleAffector
-{
- Q_OBJECT
-public:
- explicit QSGCustomAffector(QSGItem *parent = 0);
-protected:
- virtual bool affectParticle(QSGParticleData *d, qreal dt);
-signals:
- void affectParticle(QDeclarativeV8Handle particle, qreal dt);
-
-public slots:
-
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // CUSTOMAFFECTOR_H
diff --git a/src/declarative/particles/qsgcustomemitter.cpp b/src/declarative/particles/qsgcustomemitter.cpp
deleted file mode 100644
index 0500e0c75e..0000000000
--- a/src/declarative/particles/qsgcustomemitter.cpp
+++ /dev/null
@@ -1,189 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsgcustomemitter_p.h"
-#include "qsgparticlesystem_p.h"
-QT_BEGIN_NAMESPACE
-/*!
- \qmlclass CustomEmitter QSGCustomEmitter
- \inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
- \inherits Emitter
- \brief The Custom emitter allows you to modify particles as they are emitted
-
-*/
-
-//TODO: Document particle 'type'
-/*!
- \qmlsignal CustomEmitter::emitting(particle)
-
- This handler is called when a particle is emitted. You can modify particle
- attributes from within the handler.
-*/
-
-QSGCustomEmitter::QSGCustomEmitter(QSGItem* parent)
- : QSGParticleEmitter(parent)
- , m_particle_count(0)
- , m_reset_last(true)
- , m_last_timestamp(0)
- , m_last_emission(0)
-{
-}
-
-void QSGCustomEmitter::reset()
-{
- m_reset_last = true;
-}
-
-void QSGCustomEmitter::emitWindow(int timeStamp)
-{
- if (m_system == 0)
- return;
- if ((!m_emitting || !m_particlesPerSecond)&& !m_burstLeft && m_burstQueue.isEmpty()){
- m_reset_last = true;
- return;
- }
-
- if (m_reset_last) {
- m_last_emitter = m_last_last_emitter = QPointF(x(), y());
- m_last_timestamp = timeStamp/1000.;
- m_last_emission = m_last_timestamp;
- m_reset_last = false;
- }
-
- if (m_burstLeft){
- m_burstLeft -= timeStamp - m_last_timestamp * 1000.;
- if (m_burstLeft < 0){
- if (!m_emitting)
- timeStamp += m_burstLeft;
- m_burstLeft = 0;
- }
- }
-
- qreal time = timeStamp / 1000.;
-
- qreal particleRatio = 1. / m_particlesPerSecond;
- qreal pt = m_last_emission;
-
- qreal opt = pt; // original particle time
- qreal dt = time - m_last_timestamp; // timestamp delta...
- if (!dt)
- dt = 0.000001;
-
- // emitter difference since last...
- qreal dex = (x() - m_last_emitter.x());
- qreal dey = (y() - m_last_emitter.y());
-
- qreal sizeAtEnd = m_particleEndSize >= 0 ? m_particleEndSize : m_particleSize;
- qreal emitter_x_offset = m_last_emitter.x() - x();
- qreal emitter_y_offset = m_last_emitter.y() - y();
- if (!m_burstQueue.isEmpty() && !m_burstLeft && !m_emitting)//'outside time' emissions only
- pt = time;
- while (pt < time || !m_burstQueue.isEmpty()) {
- //int pos = m_last_particle % m_particle_count;
- QSGParticleData* datum = m_system->newDatum(m_system->m_groupIds[m_particle]);
- if (datum){//actually emit(otherwise we've been asked to skip this one)
- datum->e = this;//###useful?
- qreal t = 1 - (pt - opt) / dt;
-
-
- // Particle timestamp
- datum->t = pt;
- datum->lifeSpan = //TODO:Promote to base class?
- (m_particleDuration
- + ((rand() % ((m_particleDurationVariation*2) + 1)) - m_particleDurationVariation))
- / 1000.0;
-
- // Particle position
- QRectF boundsRect;
- if (!m_burstQueue.isEmpty()){
- boundsRect = QRectF(m_burstQueue.first().second.x() - x(), m_burstQueue.first().second.y() - y(),
- width(), height());
- } else {
- boundsRect = QRectF(emitter_x_offset + dex * (pt - opt) / dt, emitter_y_offset + dey * (pt - opt) / dt
- , width(), height());
- }
- QPointF newPos = effectiveExtruder()->extrude(boundsRect);
- datum->x = newPos.x();
- datum->y = newPos.y();
-
- // Particle speed
- const QPointF &speed = m_speed->sample(newPos);
- datum->vx = speed.x();
- datum->vy = speed.y();
-
- // Particle acceleration
- const QPointF &accel = m_acceleration->sample(newPos);
- datum->ax = accel.x();
- datum->ay = accel.y();
-
- // Particle size
- float sizeVariation = -m_particleSizeVariation
- + rand() / float(RAND_MAX) * m_particleSizeVariation * 2;
-
- float size = qMax((qreal)0.0 , m_particleSize + sizeVariation);
- float endSize = qMax((qreal)0.0 , sizeAtEnd + sizeVariation);
-
- datum->size = size;
- datum->endSize = endSize;
-
- emitParticle(datum->v8Value());//A chance for arbitrary JS changes
-
- m_system->emitParticle(datum);
- }
- if (m_burstQueue.isEmpty()){
- pt += particleRatio;
- }else{
- m_burstQueue.first().first--;
- if (m_burstQueue.first().first <= 0)
- m_burstQueue.pop_front();
- }
- }
- m_last_emission = pt;
-
- m_last_last_last_emitter = m_last_last_emitter;
- m_last_last_emitter = m_last_emitter;
- m_last_emitter = QPointF(x(), y());
- m_last_timestamp = time;
-}
-
-
-QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgcustomemitter_p.h b/src/declarative/particles/qsgcustomemitter_p.h
deleted file mode 100644
index 4d22490fb6..0000000000
--- a/src/declarative/particles/qsgcustomemitter_p.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSGCUSTOMEMITTER_H
-#define QSGCUSTOMEMITTER_H
-#include "qsgparticleemitter_p.h"
-#include <private/qv8engine_p.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QSGCustomEmitter : public QSGParticleEmitter
-{
- Q_OBJECT
-public:
- explicit QSGCustomEmitter(QSGItem* parent=0);
- virtual ~QSGCustomEmitter(){}
- virtual void emitWindow(int timeStamp);
- virtual void reset();
-Q_SIGNALS:
- void emitParticle(QDeclarativeV8Handle particle);
-private:
- int m_particle_count;
- bool m_reset_last;
- qreal m_last_timestamp;
- qreal m_last_emission;
-
- QPointF m_last_emitter;
- QPointF m_last_last_emitter;
- QPointF m_last_last_last_emitter;
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // QSGCUSTOMEMITTER_H
diff --git a/src/declarative/particles/qsgcustomparticle.cpp b/src/declarative/particles/qsgcustomparticle.cpp
index 53cb131bc5..db544d20e8 100644
--- a/src/declarative/particles/qsgcustomparticle.cpp
+++ b/src/declarative/particles/qsgcustomparticle.cpp
@@ -122,7 +122,6 @@ struct PlainVertices {
/*!
\qmlclass CustomParticle QSGCustomParticle
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits ParticlePainter
\brief The CustomParticle element allows you to specify your own shader to paint particles.
@@ -420,10 +419,12 @@ void QSGCustomParticle::prepareNextFrame(){
QSGShaderEffectNode* QSGCustomParticle::buildCustomNodes()
{
+#ifdef QT_OPENGL_ES_2
if (m_count * 4 > 0xffff) {
- printf("CustomParticle: Too many particles... \n");//####Why is this here?
+ printf("CustomParticle: Too many particles... \n");
return 0;
}
+#endif
if (m_count <= 0) {
printf("CustomParticle: Too few particles... \n");
diff --git a/src/declarative/particles/qsgellipseextruder.cpp b/src/declarative/particles/qsgellipseextruder.cpp
index 59e8803b28..29fa3c8841 100644
--- a/src/declarative/particles/qsgellipseextruder.cpp
+++ b/src/declarative/particles/qsgellipseextruder.cpp
@@ -45,7 +45,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass EllipseShape QSGEllipseExtruder
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits Shape
\brief The EllipseShape represents an ellipse to other particle system elements
diff --git a/src/declarative/particles/qsgemitter.cpp b/src/declarative/particles/qsgemitter.cpp
deleted file mode 100644
index 10d59dfaf8..0000000000
--- a/src/declarative/particles/qsgemitter.cpp
+++ /dev/null
@@ -1,262 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsgemitter_p.h"
-#include "qsgparticlesystem_p.h"
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmlclass Emitter QSGBasicEmitter
- \inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
- \brief The Emitter element allows you to emit logical particles.
-
- This element emits logical particles into the ParticleSystem, with the
- given starting attributes.
-
- Note that logical particles are not
- automatically rendered, you will need to have one or more
- ParticlePainter elements visualizing them.
-
- Note that the given starting attributes can be modified at any point
- in the particle's lifetime by any Affector element in the same
- ParticleSystem. This includes attributes like lifespan.
-*/
-
-QSGBasicEmitter::QSGBasicEmitter(QSGItem* parent)
- : QSGParticleEmitter(parent)
- , m_speed_from_movement(0)
- , m_particle_count(0)
- , m_reset_last(true)
- , m_last_timestamp(0)
- , m_last_emission(0)
-{
-// setFlag(ItemHasContents);
-}
-
-/*!
- \qmlproperty ParticleSystem QtQuick.Particles2::Emitter::system
-
- This is the Particle system that the Emitter will emit into.
- This can be omitted if the Emitter is a direct child of the ParticleSystem
-*/
-/*!
- \qmlproperty string QtQuick.Particles2::Emitter::particle
-*/
-/*!
- \qmlproperty Shape QtQuick.Particles2::Emitter::shape
-*/
-/*!
- \qmlproperty bool QtQuick.Particles2::Emitter::emitting
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::Emitter::emitRate
-*/
-/*!
- \qmlproperty int QtQuick.Particles2::Emitter::lifeSpan
-*/
-/*!
- \qmlproperty int QtQuick.Particles2::Emitter::lifeSpanVariation
-*/
-/*!
- \qmlproperty int QtQuick.Particles2::Emitter::emitCap
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::Emitter::size
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::Emitter::endSize
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::Emitter::sizeVariation
-*/
-/*!
- \qmlproperty StochasticDirection QtQuick.Particles2::Emitter::speed
-*/
-/*!
- \qmlproperty StochasticDirection QtQuick.Particles2::Emitter::acceleration
-*/
-/*!
- \qmlproperty qreal QtQuick.Particles2::Emitter::speedFromMovement
-*/
-
-void QSGBasicEmitter::setSpeedFromMovement(qreal t)
-{
- if (t == m_speed_from_movement)
- return;
- m_speed_from_movement = t;
- emit speedFromMovementChanged();
-}
-
-void QSGBasicEmitter::reset()
-{
- m_reset_last = true;
-}
-
-void QSGBasicEmitter::emitWindow(int timeStamp)
-{
- if (m_system == 0)
- return;
- if ((!m_emitting || !m_particlesPerSecond)&& !m_burstLeft && m_burstQueue.isEmpty()){
- m_reset_last = true;
- return;
- }
-
- if (m_reset_last) {
- m_last_emitter = m_last_last_emitter = QPointF(x(), y());
- m_last_timestamp = timeStamp/1000.;
- m_last_emission = m_last_timestamp;
- m_reset_last = false;
- }
-
- if (m_burstLeft){
- m_burstLeft -= timeStamp - m_last_timestamp * 1000.;
- if (m_burstLeft < 0){
- if (!m_emitting)
- timeStamp += m_burstLeft;
- m_burstLeft = 0;
- }
- }
-
- qreal time = timeStamp / 1000.;
-
- qreal particleRatio = 1. / m_particlesPerSecond;
- qreal pt = m_last_emission;
-
- qreal opt = pt; // original particle time
- qreal dt = time - m_last_timestamp; // timestamp delta...
- if (!dt)
- dt = 0.000001;
-
- // emitter difference since last...
- qreal dex = (x() - m_last_emitter.x());
- qreal dey = (y() - m_last_emitter.y());
-
- qreal ax = (m_last_last_emitter.x() + m_last_emitter.x()) / 2;
- qreal bx = m_last_emitter.x();
- qreal cx = (x() + m_last_emitter.x()) / 2;
- qreal ay = (m_last_last_emitter.y() + m_last_emitter.y()) / 2;
- qreal by = m_last_emitter.y();
- qreal cy = (y() + m_last_emitter.y()) / 2;
-
- qreal sizeAtEnd = m_particleEndSize >= 0 ? m_particleEndSize : m_particleSize;
- qreal emitter_x_offset = m_last_emitter.x() - x();
- qreal emitter_y_offset = m_last_emitter.y() - y();
- if (!m_burstQueue.isEmpty() && !m_burstLeft && !m_emitting)//'outside time' emissions only
- pt = time;
- while (pt < time || !m_burstQueue.isEmpty()) {
- //int pos = m_last_particle % m_particle_count;
- QSGParticleData* datum = m_system->newDatum(m_system->m_groupIds[m_particle]);
- if (datum){//actually emit(otherwise we've been asked to skip this one)
- datum->e = this;//###useful?
- qreal t = 1 - (pt - opt) / dt;
- qreal vx =
- - 2 * ax * (1 - t)
- + 2 * bx * (1 - 2 * t)
- + 2 * cx * t;
- qreal vy =
- - 2 * ay * (1 - t)
- + 2 * by * (1 - 2 * t)
- + 2 * cy * t;
-
-
- // Particle timestamp
- datum->t = pt;
- datum->lifeSpan = //TODO:Promote to base class?
- (m_particleDuration
- + ((rand() % ((m_particleDurationVariation*2) + 1)) - m_particleDurationVariation))
- / 1000.0;
-
- // Particle position
- QRectF boundsRect;
- if (!m_burstQueue.isEmpty()){
- boundsRect = QRectF(m_burstQueue.first().second.x() - x(), m_burstQueue.first().second.y() - y(),
- width(), height());
- } else {
- boundsRect = QRectF(emitter_x_offset + dex * (pt - opt) / dt, emitter_y_offset + dey * (pt - opt) / dt
- , width(), height());
- }
- QPointF newPos = effectiveExtruder()->extrude(boundsRect);
- datum->x = newPos.x();
- datum->y = newPos.y();
-
- // Particle speed
- const QPointF &speed = m_speed->sample(newPos);
- datum->vx = speed.x()
- + m_speed_from_movement * vx;
- datum->vy = speed.y()
- + m_speed_from_movement * vy;
-
- // Particle acceleration
- const QPointF &accel = m_acceleration->sample(newPos);
- datum->ax = accel.x();
- datum->ay = accel.y();
-
- // Particle size
- float sizeVariation = -m_particleSizeVariation
- + rand() / float(RAND_MAX) * m_particleSizeVariation * 2;
-
- float size = qMax((qreal)0.0 , m_particleSize + sizeVariation);
- float endSize = qMax((qreal)0.0 , sizeAtEnd + sizeVariation);
-
- datum->size = size;// * float(m_emitting);
- datum->endSize = endSize;// * float(m_emitting);
-
- m_system->emitParticle(datum);
- }
- if (m_burstQueue.isEmpty()){
- pt += particleRatio;
- }else{
- m_burstQueue.first().first--;
- if (m_burstQueue.first().first <= 0)
- m_burstQueue.pop_front();
- }
- }
- m_last_emission = pt;
-
- m_last_last_last_emitter = m_last_last_emitter;
- m_last_last_emitter = m_last_emitter;
- m_last_emitter = QPointF(x(), y());
- m_last_timestamp = time;
-}
-
-
-QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgemitter_p.h b/src/declarative/particles/qsgemitter_p.h
deleted file mode 100644
index f61da15012..0000000000
--- a/src/declarative/particles/qsgemitter_p.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef TRAILSEMITTER_H
-#define TRAILSEMITTER_H
-
-#include <QtCore>//FIXME
-#include <QtGui>
-
-#include "qsgparticleemitter_p.h"
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-
-class QSGGeometryNode;
-
-class QSGBasicEmitter : public QSGParticleEmitter
-{
- Q_OBJECT
-
- Q_PROPERTY(qreal speedFromMovement READ speedFromMovement WRITE setSpeedFromMovement NOTIFY speedFromMovementChanged)
-
-public:
- explicit QSGBasicEmitter(QSGItem* parent=0);
- virtual ~QSGBasicEmitter(){}
- virtual void emitWindow(int timeStamp);
-
-
- qreal speedFromMovement() const { return m_speed_from_movement; }
- void setSpeedFromMovement(qreal s);
-
- qreal renderOpacity() const { return m_render_opacity; }
-
-signals:
-
- void speedFromMovementChanged();
-
-public slots:
-public:
- virtual void reset();
-protected:
-
-private:
-
- qreal m_speed_from_movement;
-
- // derived values...
- int m_particle_count;
- bool m_reset_last;
- qreal m_last_timestamp;
- qreal m_last_emission;
-
- QPointF m_last_emitter;
- QPointF m_last_last_emitter;
- QPointF m_last_last_last_emitter;
-
- qreal m_render_opacity;
-};
-
-QT_END_NAMESPACE
-QT_END_HEADER
-#endif // TRAILSEMITTER_H
diff --git a/src/declarative/particles/qsgfollowemitter.cpp b/src/declarative/particles/qsgfollowemitter.cpp
index 0d4e7f73fd..68f0f6bf75 100644
--- a/src/declarative/particles/qsgfollowemitter.cpp
+++ b/src/declarative/particles/qsgfollowemitter.cpp
@@ -45,21 +45,13 @@
QT_BEGIN_NAMESPACE
/*!
- \qmlclass Emitter QSGBasicEmitter
+ \qmlclass FollowEmitter QSGFollowEmitter
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
- \brief The Emitter element allows you to emit logical particles.
+ \inherits QSGParticleEmitter
+ \brief The FollowEmitter element allows you to emit logical particles from other logical particles.
This element emits logical particles into the ParticleSystem, with the
- given starting attributes.
-
- Note that logical particles are not
- automatically rendered, you will need to have one or more
- ParticlePainter elements visualizing them.
-
- Note that the given starting attributes can be modified at any point
- in the particle's lifetime by any Affector element in the same
- ParticleSystem. This includes attributes like lifespan.
+ starting positions based on those of other logical particles.
*/
QSGFollowEmitter::QSGFollowEmitter(QSGItem *parent) :
QSGParticleEmitter(parent)
@@ -80,24 +72,17 @@ QSGFollowEmitter::QSGFollowEmitter(QSGItem *parent) :
this, SLOT(recalcParticlesPerSecond()));
}
-
-/*!
- \qmlproperty ParticleSystem QtQuick.Particles2::FollowEmitter::system
-
- This is the Particle system that the FollowEmitter will emit into.
- This can be omitted if the FollowEmitter is a direct child of the ParticleSystem
-*/
-/*!
- \qmlproperty string QtQuick.Particles2::FollowEmitter::particle
-*/
/*!
\qmlproperty string QtQuick.Particles2::FollowEmitter::follow
+
+ The type of logical particle which this is emitting from.
*/
-/*!
- \qmlproperty Shape QtQuick.Particles2::FollowEmitter::shape
-*/
+
/*!
\qmlproperty Shape QtQuick.Particles2::FollowEmitter::emitShape
+
+ As the area of a FollowEmitter is the area it follows, a separate shape can be provided
+ to be the shape it emits out of.
*/
/*!
\qmlproperty real QtQuick.Particles2::FollowEmitter::emitWidth
@@ -106,39 +91,24 @@ QSGFollowEmitter::QSGFollowEmitter(QSGItem *parent) :
\qmlproperty real QtQuick.Particles2::FollowEmitter::emitHeight
*/
/*!
- \qmlproperty bool QtQuick.Particles2::FollowEmitter::emitting
-*/
-/*!
\qmlproperty real QtQuick.Particles2::FollowEmitter::emitRatePerParticle
*/
/*!
- \qmlproperty int QtQuick.Particles2::FollowEmitter::lifeSpan
-*/
-/*!
- \qmlproperty int QtQuick.Particles2::FollowEmitter::lifeSpanVariation
-*/
-/*!
- \qmlproperty int QtQuick.Particles2::FollowEmitter::emitCap
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::FollowEmitter::size
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::FollowEmitter::endSize
-*/
-/*!
- \qmlproperty real QtQuick.Particles2::FollowEmitter::sizeVariation
-*/
-/*!
- \qmlproperty StochasticDirection QtQuick.Particles2::FollowEmitter::speed
-*/
-/*!
- \qmlproperty StochasticDirection QtQuick.Particles2::FollowEmitter::acceleration
-*/
-/*!
- \qmlproperty qreal QtQuick.Particles2::FollowEmitter::speedFromMovement
+ \qmlsignal QtQuick.Particles2::FollowEmitter::emitFollowParticle(particle, followed)
+
+ This handler is called when a particle is emitted. You can modify particle
+ attributes from within the handler. followed is the particle that this is being
+ emitted off of.
+
+ If you use this signal handler, emitParticle will not be emitted.
*/
+bool QSGFollowEmitter::isEmitFollowConnected()
+{
+ static int idx = QObjectPrivate::get(this)->signalIndex("emitFollowParticle(QDeclarativeV8Handle,QDeclarativeV8Handle)");
+ return QObjectPrivate::get(this)->isSignalConnected(idx);
+}
+
void QSGFollowEmitter::recalcParticlesPerSecond(){
if (!m_system)
return;
@@ -178,6 +148,7 @@ void QSGFollowEmitter::emitWindow(int timeStamp)
}
}
+ //TODO: Implement startTime and speedFromMovement
qreal time = timeStamp / 1000.;
qreal particleRatio = 1. / m_particlesPerParticlePerSecond;
qreal pt;
@@ -202,7 +173,7 @@ void QSGFollowEmitter::emitWindow(int timeStamp)
continue;
}
while (pt < time || !m_burstQueue.isEmpty()){
- QSGParticleData* datum = m_system->newDatum(gId2);
+ QSGParticleData* datum = m_system->newDatum(gId2, !m_overwrite);
if (datum){//else, skip this emission
datum->e = this;//###useful?
@@ -236,8 +207,10 @@ void QSGFollowEmitter::emitWindow(int timeStamp)
// Particle speed
const QPointF &speed = m_speed->sample(newPos);
- datum->vx = speed.x();
+ datum->vx = speed.x()
+ + m_speed_from_movement * d->vx;
datum->vy = speed.y();
+ + m_speed_from_movement * d->vy;
// Particle acceleration
const QPointF &accel = m_acceleration->sample(newPos);
@@ -254,6 +227,11 @@ void QSGFollowEmitter::emitWindow(int timeStamp)
datum->size = size * float(m_emitting);
datum->endSize = endSize * float(m_emitting);
+ if (isEmitFollowConnected())
+ emitFollowParticle(datum->v8Value(), d->v8Value());//A chance for many arbitrary JS changes
+ else if (isEmitConnected())
+ emitParticle(datum->v8Value());//A chance for arbitrary JS changes
+
m_system->emitParticle(datum);
}
if (!m_burstQueue.isEmpty()){
diff --git a/src/declarative/particles/qsgfollowemitter_p.h b/src/declarative/particles/qsgfollowemitter_p.h
index 3fd5f1c2f8..d26435df6a 100644
--- a/src/declarative/particles/qsgfollowemitter_p.h
+++ b/src/declarative/particles/qsgfollowemitter_p.h
@@ -95,6 +95,7 @@ public:
}
signals:
+ void emitFollowParticle(QDeclarativeV8Handle particle, QDeclarativeV8Handle followed);
void particlesPerParticlePerSecondChanged(int arg);
@@ -161,6 +162,7 @@ private:
int m_followCount;
QSGParticleExtruder* m_emissionExtruder;
QSGParticleExtruder* m_defaultEmissionExtruder;
+ bool isEmitFollowConnected();
};
QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgfriction.cpp b/src/declarative/particles/qsgfriction.cpp
index e6a43013e8..6baeaf6c3b 100644
--- a/src/declarative/particles/qsgfriction.cpp
+++ b/src/declarative/particles/qsgfriction.cpp
@@ -44,7 +44,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass Friction QSGFrictionAffector
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits Affector
\brief The Friction affector slows down movement proportional to the particle's current speed.
diff --git a/src/declarative/particles/qsggravity.cpp b/src/declarative/particles/qsggravity.cpp
index 1639588917..1de2a0e014 100644
--- a/src/declarative/particles/qsggravity.cpp
+++ b/src/declarative/particles/qsggravity.cpp
@@ -46,7 +46,6 @@ const qreal CONV = 0.017453292520444443;
/*!
\qmlclass Gravity QSGGravityAffector
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits Affector
\brief The Gravity element allows you to set a constant accleration in an angle
diff --git a/src/declarative/particles/qsgimageparticle.cpp b/src/declarative/particles/qsgimageparticle.cpp
index cf1f48e036..57461a414b 100644
--- a/src/declarative/particles/qsgimageparticle.cpp
+++ b/src/declarative/particles/qsgimageparticle.cpp
@@ -54,238 +54,395 @@
QT_BEGIN_NAMESPACE
+//###Switch to define later, for now user-friendly (no compilation) debugging is worth it
+DEFINE_BOOL_CONFIG_OPTION(qmlParticlesDebug, QML_PARTICLES_DEBUG)
+
+#ifdef Q_WS_MAC
+#define SHADER_DEFINES "#version 120\n"
+#else
+#define SHADER_DEFINES ""
+#endif
+
+//TODO: Make it larger on desktop? Requires fixing up shader code with the same define
+#define UNIFORM_ARRAY_SIZE 64
+
const float CONV = 0.017453292519943295;
-class UltraMaterial : public QSGMaterial
+class ImageMaterialData
{
-public:
- UltraMaterial(bool withSprites=false)
- : texture(0)
- , colortable(0)
- , sizetable(0)
- , opacitytable(0)
- , timestamp(0)
- , framecount(1)
- , animcount(1)
- , usesSprites(withSprites)
- {
- setFlag(Blending, true);
- }
+ public:
+ ImageMaterialData()
+ : texture(0), colorTable(0)
+ {}
- ~UltraMaterial()
- {
+ ~ImageMaterialData(){
delete texture;
- delete colortable;
- delete sizetable;
- delete opacitytable;
- }
-
- virtual QSGMaterialType *type() const { static QSGMaterialType type; return &type; }
- virtual QSGMaterialShader *createShader() const;
- virtual int compare(const QSGMaterial *other) const
- {
- return this - static_cast<const UltraMaterial *>(other);
+ delete colorTable;
}
QSGTexture *texture;
- QSGTexture *colortable;
- QSGTexture *sizetable;
- QSGTexture *opacitytable;
+ QSGTexture *colorTable;
+ float sizeTable[UNIFORM_ARRAY_SIZE];
+ float opacityTable[UNIFORM_ARRAY_SIZE];
qreal timestamp;
- int framecount;
- int animcount;
- bool usesSprites;
+ qreal entry;
+ qreal framecount;
+ qreal animcount;
};
-class UltraMaterialData : public QSGMaterialShader
+
+//TODO: Move shaders inline once they've stablilized
+class TabledMaterialData : public ImageMaterialData {};
+class TabledMaterial : public QSGSimpleMaterialShader<TabledMaterialData>
{
+ QSG_DECLARE_SIMPLE_SHADER(TabledMaterial, TabledMaterialData)
+
public:
- UltraMaterialData(const char *vertexFile = 0, const char *fragmentFile = 0)
+ TabledMaterial()
{
- QFile vf(vertexFile ? vertexFile : ":defaultshaders/ultravertex.shader");
+ QFile vf(":defaultshaders/imagevertex.shader");
vf.open(QFile::ReadOnly);
- m_vertex_code = vf.readAll();
+ m_vertex_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define TABLE\n#define DEFORM\n#define COLOR\n")
+ + vf.readAll();
- QFile ff(fragmentFile ? fragmentFile : ":defaultshaders/ultrafragment.shader");
+ QFile ff(":defaultshaders/imagefragment.shader");
ff.open(QFile::ReadOnly);
- m_fragment_code = ff.readAll();
+ m_fragment_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define TABLE\n#define DEFORM\n#define COLOR\n")
+ + ff.readAll();
Q_ASSERT(!m_vertex_code.isNull());
Q_ASSERT(!m_fragment_code.isNull());
}
- void deactivate() {
- QSGMaterialShader::deactivate();
+ const char *vertexShader() const { return m_vertex_code.constData(); }
+ const char *fragmentShader() const { return m_fragment_code.constData(); }
- for (int i=0; i<8; ++i) {
- program()->setAttributeArray(i, GL_FLOAT, chunkOfBytes, 1, 0);
- }
+ QList<QByteArray> attributes() const {
+ return QList<QByteArray>() << "vPos" << "vTex" << "vData" << "vVec"
+ << "vColor" << "vDeformVec" << "vRotation";
+ };
+
+ void initialize() {
+ QSGSimpleMaterialShader<TabledMaterialData>::initialize();
+ program()->bind();
+ program()->setUniformValue("texture", 0);
+ program()->setUniformValue("colortable", 1);
+ glFuncs = QGLContext::currentContext()->functions();
+ m_timestamp_id = program()->uniformLocation("timestamp");
+ m_entry_id = program()->uniformLocation("entry");
+ m_sizetable_id = program()->uniformLocation("sizetable");
+ m_opacitytable_id = program()->uniformLocation("opacitytable");
+ }
+
+ void updateState(const TabledMaterialData* d, const TabledMaterialData*) {
+ glFuncs->glActiveTexture(GL_TEXTURE1);
+ d->colorTable->bind();
+
+ glFuncs->glActiveTexture(GL_TEXTURE0);
+ d->texture->bind();
+
+ program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
+ program()->setUniformValue("framecount", (float) 1);
+ program()->setUniformValue("animcount", (float) 1);
+ program()->setUniformValue(m_entry_id, (float) d->entry);
+ program()->setUniformValueArray(m_sizetable_id, (float*) d->sizeTable, UNIFORM_ARRAY_SIZE, 1);
+ program()->setUniformValueArray(m_opacitytable_id, (float*) d->opacityTable, UNIFORM_ARRAY_SIZE, 1);
}
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *)
+ int m_entry_id;
+ int m_timestamp_id;
+ int m_sizetable_id;
+ int m_opacitytable_id;
+ QByteArray m_vertex_code;
+ QByteArray m_fragment_code;
+ QGLFunctions* glFuncs;
+};
+
+class DeformableMaterialData : public ImageMaterialData {};
+class DeformableMaterial : public QSGSimpleMaterialShader<DeformableMaterialData>
+{
+ QSG_DECLARE_SIMPLE_SHADER(DeformableMaterial, DeformableMaterialData)
+
+public:
+ DeformableMaterial()
{
- UltraMaterial *m = static_cast<UltraMaterial *>(newEffect);
- state.context()->functions()->glActiveTexture(GL_TEXTURE1);
- m->colortable->bind();
+ QFile vf(":defaultshaders/imagevertex.shader");
+ vf.open(QFile::ReadOnly);
+ m_vertex_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define DEFORM\n#define COLOR\n")
+ + vf.readAll();
+
+ QFile ff(":defaultshaders/imagefragment.shader");
+ ff.open(QFile::ReadOnly);
+ m_fragment_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define DEFORM\n#define COLOR\n")
+ + ff.readAll();
+
+ Q_ASSERT(!m_vertex_code.isNull());
+ Q_ASSERT(!m_fragment_code.isNull());
+ }
- state.context()->functions()->glActiveTexture(GL_TEXTURE2);
- m->sizetable->bind();
+ const char *vertexShader() const { return m_vertex_code.constData(); }
+ const char *fragmentShader() const { return m_fragment_code.constData(); }
- state.context()->functions()->glActiveTexture(GL_TEXTURE3);
- m->opacitytable->bind();
+ QList<QByteArray> attributes() const {
+ return QList<QByteArray>() << "vPos" << "vTex" << "vData" << "vVec"
+ << "vColor" << "vDeformVec" << "vRotation";
+ };
- // make sure we end by setting GL_TEXTURE0 as active texture
- state.context()->functions()->glActiveTexture(GL_TEXTURE0);
- m->texture->bind();
+ void initialize() {
+ QSGSimpleMaterialShader<DeformableMaterialData>::initialize();
+ program()->bind();
+ program()->setUniformValue("texture", 0);
+ glFuncs = QGLContext::currentContext()->functions();
+ m_timestamp_id = program()->uniformLocation("timestamp");
+ m_entry_id = program()->uniformLocation("entry");
+ }
+
+ void updateState(const DeformableMaterialData* d, const DeformableMaterialData*) {
+ glFuncs->glActiveTexture(GL_TEXTURE0);
+ d->texture->bind();
+
+ program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
+ program()->setUniformValue(m_entry_id, (float) d->entry);
+ }
+
+ int m_entry_id;
+ int m_timestamp_id;
+ QByteArray m_vertex_code;
+ QByteArray m_fragment_code;
+ QGLFunctions* glFuncs;
+};
+
+class SpriteMaterialData : public ImageMaterialData {};
+class SpriteMaterial : public QSGSimpleMaterialShader<SpriteMaterialData>
+{
+ QSG_DECLARE_SIMPLE_SHADER(SpriteMaterial, SpriteMaterialData)
+
+public:
+ SpriteMaterial()
+ {
+ QFile vf(":defaultshaders/imagevertex.shader");
+ vf.open(QFile::ReadOnly);
+ m_vertex_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define SPRITE\n#define TABLE\n#define DEFORM\n#define COLOR\n")
+ + vf.readAll();
- program()->setUniformValue(m_opacity_id, state.opacity());
- program()->setUniformValue(m_timestamp_id, (float) m->timestamp);
- program()->setUniformValue(m_framecount_id, (float) m->framecount);
- program()->setUniformValue(m_animcount_id, (float) m->animcount);
+ QFile ff(":defaultshaders/imagefragment.shader");
+ ff.open(QFile::ReadOnly);
+ m_fragment_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define SPRITE\n#define TABLE\n#define DEFORM\n#define COLOR\n")
+ + ff.readAll();
- if (state.isMatrixDirty())
- program()->setUniformValue(m_matrix_id, state.combinedMatrix());
+ Q_ASSERT(!m_vertex_code.isNull());
+ Q_ASSERT(!m_fragment_code.isNull());
}
- virtual void initialize() {
+ const char *vertexShader() const { return m_vertex_code.constData(); }
+ const char *fragmentShader() const { return m_fragment_code.constData(); }
+
+ QList<QByteArray> attributes() const {
+ return QList<QByteArray>() << "vPos" << "vTex" << "vData" << "vVec"
+ << "vColor" << "vDeformVec" << "vRotation" << "vAnimData";
+ };
+
+ void initialize() {
+ QSGSimpleMaterialShader<SpriteMaterialData>::initialize();
program()->bind();
program()->setUniformValue("texture", 0);
program()->setUniformValue("colortable", 1);
- program()->setUniformValue("sizetable", 2);
- program()->setUniformValue("opacitytable", 3);
- m_matrix_id = program()->uniformLocation("matrix");
- m_opacity_id = program()->uniformLocation("opacity");
+ glFuncs = QGLContext::currentContext()->functions();
m_timestamp_id = program()->uniformLocation("timestamp");
m_framecount_id = program()->uniformLocation("framecount");
m_animcount_id = program()->uniformLocation("animcount");
+ m_entry_id = program()->uniformLocation("entry");
+ m_sizetable_id = program()->uniformLocation("sizetable");
+ m_opacitytable_id = program()->uniformLocation("sizetable");
}
- virtual const char *vertexShader() const { return m_vertex_code.constData(); }
- virtual const char *fragmentShader() const { return m_fragment_code.constData(); }
-
- virtual char const *const *attributeNames() const {
- static const char *attr[] = {
- "vPos",
- "vTex",
- "vData",
- "vVec",
- "vColor",
- "vDeformVec",
- "vRotation",
- "vAnimData",
- 0
- };
- return attr;
- }
+ void updateState(const SpriteMaterialData* d, const SpriteMaterialData*) {
+ glFuncs->glActiveTexture(GL_TEXTURE1);
+ d->colorTable->bind();
- virtual bool isColorTable() const { return false; }
+ // make sure we end by setting GL_TEXTURE0 as active texture
+ glFuncs->glActiveTexture(GL_TEXTURE0);
+ d->texture->bind();
+
+ program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
+ program()->setUniformValue(m_framecount_id, (float) d->framecount);
+ program()->setUniformValue(m_animcount_id, (float) d->animcount);
+ program()->setUniformValue(m_entry_id, (float) d->entry);
+ program()->setUniformValueArray(m_sizetable_id, (float*) d->sizeTable, 64, 1);
+ program()->setUniformValueArray(m_opacitytable_id, (float*) d->opacityTable, UNIFORM_ARRAY_SIZE, 1);
+ }
- int m_matrix_id;
- int m_opacity_id;
int m_timestamp_id;
int m_framecount_id;
int m_animcount_id;
-
+ int m_entry_id;
+ int m_sizetable_id;
+ int m_opacitytable_id;
QByteArray m_vertex_code;
QByteArray m_fragment_code;
-
- static float chunkOfBytes[1024];
+ QGLFunctions* glFuncs;
};
-float UltraMaterialData::chunkOfBytes[1024];
-QSGMaterialShader *UltraMaterial::createShader() const
+class ColoredMaterialData : public ImageMaterialData {};
+class ColoredMaterial : public QSGSimpleMaterialShader<ColoredMaterialData>
{
- if (usesSprites)//TODO: Perhaps just swap the shaders, and don't mind the extra vector?
- return new UltraMaterialData;
- else
- return new UltraMaterialData;
-}
+ QSG_DECLARE_SIMPLE_SHADER(ColoredMaterial, ColoredMaterialData)
+
+public:
+ ColoredMaterial()
+ {
+ QFile vf(":defaultshaders/imagevertex.shader");
+ vf.open(QFile::ReadOnly);
+ m_vertex_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define COLOR\n")
+ + vf.readAll();
+ QFile ff(":defaultshaders/imagefragment.shader");
+ ff.open(QFile::ReadOnly);
+ m_fragment_code = QByteArray(SHADER_DEFINES)
+ + QByteArray("#define COLOR\n")
+ + ff.readAll();
-class SimpleMaterial : public UltraMaterial
-{
- virtual QSGMaterialShader *createShader() const;
- virtual QSGMaterialType *type() const { static QSGMaterialType type; return &type; }
+ Q_ASSERT(!m_vertex_code.isNull());
+ Q_ASSERT(!m_fragment_code.isNull());
+ }
+
+ const char *vertexShader() const { return m_vertex_code.constData(); }
+ const char *fragmentShader() const { return m_fragment_code.constData(); }
+
+ void activate() {
+ QSGSimpleMaterialShader<ColoredMaterialData>::activate();
+#ifndef QT_OPENGL_ES_2
+ glEnable(GL_POINT_SPRITE);
+ glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
+#endif
+ }
+
+ void deactivate() {
+ QSGSimpleMaterialShader<ColoredMaterialData>::deactivate();
+#ifndef QT_OPENGL_ES_2
+ glDisable(GL_POINT_SPRITE);
+ glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
+#endif
+ }
+
+ QList<QByteArray> attributes() const {
+ return QList<QByteArray>() << "vPos" << "vData" << "vVec" << "vColor";
+ }
+
+ void initialize() {
+ QSGSimpleMaterialShader<ColoredMaterialData>::initialize();
+ program()->bind();
+ program()->setUniformValue("texture", 0);
+ glFuncs = QGLContext::currentContext()->functions();
+ m_timestamp_id = program()->uniformLocation("timestamp");
+ m_entry_id = program()->uniformLocation("entry");
+ }
+
+ void updateState(const ColoredMaterialData* d, const ColoredMaterialData*) {
+ glFuncs->glActiveTexture(GL_TEXTURE0);
+ d->texture->bind();
+
+ program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
+ program()->setUniformValue(m_entry_id, (float) d->entry);
+ }
+
+ int m_timestamp_id;
+ int m_entry_id;
+ QByteArray m_vertex_code;
+ QByteArray m_fragment_code;
+ QGLFunctions* glFuncs;
};
-class SimpleMaterialData : public QSGMaterialShader
+class SimpleMaterialData : public ImageMaterialData {};
+class SimpleMaterial : public QSGSimpleMaterialShader<SimpleMaterialData>
{
+ QSG_DECLARE_SIMPLE_SHADER(SimpleMaterial, SimpleMaterialData)
+
public:
- SimpleMaterialData(const char *vertexFile = 0, const char *fragmentFile = 0)
+ SimpleMaterial()
{
- QFile vf(vertexFile ? vertexFile : ":defaultshaders/simplevertex.shader");
+ QFile vf(":defaultshaders/imagevertex.shader");
vf.open(QFile::ReadOnly);
- m_vertex_code = vf.readAll();
+ m_vertex_code = QByteArray(SHADER_DEFINES)
+ + vf.readAll();
- QFile ff(fragmentFile ? fragmentFile : ":defaultshaders/simplefragment.shader");
+ QFile ff(":defaultshaders/imagefragment.shader");
ff.open(QFile::ReadOnly);
- m_fragment_code = ff.readAll();
+ m_fragment_code = QByteArray(SHADER_DEFINES)
+ + ff.readAll();
Q_ASSERT(!m_vertex_code.isNull());
Q_ASSERT(!m_fragment_code.isNull());
}
- void deactivate() {
- QSGMaterialShader::deactivate();
+ const char *vertexShader() const { return m_vertex_code.constData(); }
+ const char *fragmentShader() const { return m_fragment_code.constData(); }
- for (int i=0; i<8; ++i) {
- program()->setAttributeArray(i, GL_FLOAT, chunkOfBytes, 1, 0);
- }
+ void activate() {
+ QSGSimpleMaterialShader<SimpleMaterialData>::activate();
+#ifndef QT_OPENGL_ES_2
+ glEnable(GL_POINT_SPRITE);
+ glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
+#endif
}
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *)
- {
- UltraMaterial *m = static_cast<UltraMaterial *>(newEffect);
- state.context()->functions()->glActiveTexture(GL_TEXTURE0);
- m->texture->bind();
-
- program()->setUniformValue(m_opacity_id, state.opacity());
- program()->setUniformValue(m_timestamp_id, (float) m->timestamp);
+ void deactivate() {
+ QSGSimpleMaterialShader<SimpleMaterialData>::deactivate();
+#ifndef QT_OPENGL_ES_2
+ glDisable(GL_POINT_SPRITE);
+ glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
+#endif
+ }
- if (state.isMatrixDirty())
- program()->setUniformValue(m_matrix_id, state.combinedMatrix());
+ QList<QByteArray> attributes() const {
+ return QList<QByteArray>() << "vPos" << "vData" << "vVec";
}
- virtual void initialize() {
- m_matrix_id = program()->uniformLocation("matrix");
- m_opacity_id = program()->uniformLocation("opacity");
+ void initialize() {
+ QSGSimpleMaterialShader<SimpleMaterialData>::initialize();
+ program()->bind();
+ program()->setUniformValue("texture", 0);
+ glFuncs = QGLContext::currentContext()->functions();
m_timestamp_id = program()->uniformLocation("timestamp");
+ m_entry_id = program()->uniformLocation("entry");
}
- virtual const char *vertexShader() const { return m_vertex_code.constData(); }
- virtual const char *fragmentShader() const { return m_fragment_code.constData(); }
-
- virtual char const *const *attributeNames() const {
- static const char *attr[] = {
- "vPos",
- "vTex",
- "vData",
- "vVec",
- 0
- };
- return attr;
- }
+ void updateState(const SimpleMaterialData* d, const SimpleMaterialData*) {
+ glFuncs->glActiveTexture(GL_TEXTURE0);
+ d->texture->bind();
- virtual bool isColorTable() const { return false; }
+ program()->setUniformValue(m_timestamp_id, (float) d->timestamp);
+ program()->setUniformValue(m_entry_id, (float) d->entry);
+ }
- int m_matrix_id;
- int m_opacity_id;
int m_timestamp_id;
-
+ int m_entry_id;
QByteArray m_vertex_code;
QByteArray m_fragment_code;
-
- static float chunkOfBytes[1024];
+ QGLFunctions* glFuncs;
};
-float SimpleMaterialData::chunkOfBytes[1024];
-QSGMaterialShader *SimpleMaterial::createShader() const {
- return new SimpleMaterialData;
+void fillUniformArrayFromImage(float* array, const QImage& img, int size)
+{
+ if (img.isNull()){
+ for (int i=0; i<size; i++)
+ array[i] = 1;
+ return;
+ }
+ QImage scaled = img.scaled(size,1);
+ for (int i=0; i<size; i++)
+ array[i] = qAlpha(scaled.pixel(i,0))/255.0;
}
/*!
\qmlclass ImageParticle QSGImageParticle
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits ParticlePainter
\brief The ImageParticle element visualizes logical particles using an image
@@ -303,6 +460,8 @@ QSGMaterialShader *SimpleMaterial::createShader() const {
*/
/*!
\qmlproperty url QtQuick.Particles2::ImageParticle::sizeTable
+
+ Note that currently sizeTable is ignored for sprite particles.
*/
/*!
\qmlproperty url QtQuick.Particles2::ImageParticle::opacityTable
@@ -352,6 +511,21 @@ QSGMaterialShader *SimpleMaterial::createShader() const {
/*!
\qmlproperty list<Sprite> QtQuick.Particles2::ImageParticle::sprites
*/
+/*!
+ \qmlproperty EntryEffect QtQuick.Particles2::ImageParticle::entryEffect
+
+ This property provides basic and cheap entrance and exit effects for the particles.
+ For fine-grained control, see sizeTable and opacityTable.
+
+ Acceptable values are
+ \list
+ \o None: Particles just appear and disappear.
+ \o Fade: Particles fade in from 0. opacity at the start of their life, and fade out to 0. at the end.
+ \o Scale: Particles scale in from 0 size at the start of their life, and scale back to 0 at the end.
+ \endlist
+
+ Default value is Fade.
+*/
QSGImageParticle::QSGImageParticle(QSGItem* parent)
@@ -376,8 +550,16 @@ QSGImageParticle::QSGImageParticle(QSGItem* parent)
, m_bloat(false)
, perfLevel(Unknown)
, m_lastLevel(Unknown)
+ , m_debugMode(false)
+ , m_entryEffect(Fade)
{
setFlag(ItemHasContents);
+ m_debugMode = qmlParticlesDebug();
+}
+
+QSGImageParticle::~QSGImageParticle()
+{
+ delete m_material;
}
QDeclarativeListProperty<QSGSprite> QSGImageParticle::sprites()
@@ -572,6 +754,16 @@ void QSGImageParticle::setBloat(bool arg)
reset();
}
+void QSGImageParticle::setEntryEffect(EntryEffect arg)
+{
+ if (m_entryEffect != arg) {
+ m_entryEffect = arg;
+ if (m_material)
+ getState<ImageMaterialData>(m_material)->entry = (qreal) m_entryEffect;
+ emit entryEffectChanged(arg);
+ }
+}
+
void QSGImageParticle::reset()
{
QSGParticlePainter::reset();
@@ -592,19 +784,49 @@ void QSGImageParticle::createEngine()
static QSGGeometry::Attribute SimpleParticle_Attributes[] = {
{ 0, 2, GL_FLOAT }, // Position
- { 1, 2, GL_FLOAT }, // TexCoord
- { 2, 4, GL_FLOAT }, // Data
- { 3, 4, GL_FLOAT } // Vectors
+ { 1, 4, GL_FLOAT }, // Data
+ { 2, 4, GL_FLOAT } // Vectors
};
static QSGGeometry::AttributeSet SimpleParticle_AttributeSet =
{
- 4, // Attribute Count
- (2 + 2 + 4 + 4 ) * sizeof(float),
+ 3, // Attribute Count
+ ( 2 + 4 + 4 ) * sizeof(float),
SimpleParticle_Attributes
};
-static QSGGeometry::Attribute UltraParticle_Attributes[] = {
+static QSGGeometry::Attribute ColoredParticle_Attributes[] = {
+ { 0, 2, GL_FLOAT }, // Position
+ { 1, 4, GL_FLOAT }, // Data
+ { 2, 4, GL_FLOAT }, // Vectors
+ { 3, 4, GL_UNSIGNED_BYTE }, // Colors
+};
+
+static QSGGeometry::AttributeSet ColoredParticle_AttributeSet =
+{
+ 4, // Attribute Count
+ ( 2 + 4 + 4 ) * sizeof(float) + 4 * sizeof(uchar),
+ ColoredParticle_Attributes
+};
+
+static QSGGeometry::Attribute DeformableParticle_Attributes[] = {
+ { 0, 2, GL_FLOAT }, // Position
+ { 1, 2, GL_FLOAT }, // TexCoord
+ { 2, 4, GL_FLOAT }, // Data
+ { 3, 4, GL_FLOAT }, // Vectors
+ { 4, 4, GL_UNSIGNED_BYTE }, // Colors
+ { 5, 4, GL_FLOAT }, // DeformationVectors
+ { 6, 3, GL_FLOAT }, // Rotation
+};
+
+static QSGGeometry::AttributeSet DeformableParticle_AttributeSet =
+{
+ 7, // Attribute Count
+ (2 + 2 + 4 + 4 + 4 + 3) * sizeof(float) + 4 * sizeof(uchar),
+ DeformableParticle_Attributes
+};
+
+static QSGGeometry::Attribute SpriteParticle_Attributes[] = {
{ 0, 2, GL_FLOAT }, // Position
{ 1, 2, GL_FLOAT }, // TexCoord
{ 2, 4, GL_FLOAT }, // Data
@@ -615,159 +837,100 @@ static QSGGeometry::Attribute UltraParticle_Attributes[] = {
{ 7, 4, GL_FLOAT } // Anim Data
};
-static QSGGeometry::AttributeSet UltraParticle_AttributeSet =
+static QSGGeometry::AttributeSet SpriteParticle_AttributeSet =
{
8, // Attribute Count
(2 + 2 + 4 + 4 + 4 + 4 + 3) * sizeof(float) + 4 * sizeof(uchar),
- UltraParticle_Attributes
+ SpriteParticle_Attributes
};
-QSGGeometryNode* QSGImageParticle::buildSimpleParticleNodes()
-{
- perfLevel = Simple;//TODO: Intermediate levels
- QImage image = QImage(m_image_name.toLocalFile());
- if (image.isNull()) {
- printf("UltraParticle: loading image failed... '%s'\n", qPrintable(m_image_name.toLocalFile()));
- return 0;
- }
-
- if (m_material) {
- delete m_material;
- m_material = 0;
- }
-
- m_material = new SimpleMaterial();
- m_material->texture = sceneGraphEngine()->createTextureFromImage(image);
- m_material->texture->setFiltering(QSGTexture::Linear);
- m_material->framecount = 1;
-
- foreach (const QString &str, m_particles){
- int gIdx = m_system->m_groupIds[str];
- int count = m_system->m_groupData[gIdx]->size();
-
- QSGGeometryNode* node = new QSGGeometryNode();
- m_nodes.insert(gIdx, node);
- node->setMaterial(m_material);
-
- int vCount = count * 4;
- int iCount = count * 6;
-
- QSGGeometry *g = new QSGGeometry(SimpleParticle_AttributeSet, vCount, iCount);
- node->setGeometry(g);
- g->setDrawingMode(GL_TRIANGLES);
-
- SimpleVertex *vertices = (SimpleVertex *) g->vertexData();
- for (int p=0; p < count; ++p){
- commit(gIdx, p);
- vertices[0].tx = 0;
- vertices[0].ty = 0;
-
- vertices[1].tx = 1;
- vertices[1].ty = 0;
-
- vertices[2].tx = 0;
- vertices[2].ty = 1;
-
- vertices[3].tx = 1;
- vertices[3].ty = 1;
-
- vertices += 4;
- }
-
- quint16 *indices = g->indexDataAsUShort();
- for (int i=0; i < count; ++i) {
- int o = i * 4;
- indices[0] = o;
- indices[1] = o + 1;
- indices[2] = o + 2;
- indices[3] = o + 1;
- indices[4] = o + 3;
- indices[5] = o + 2;
- indices += 6;
- }
- }
-
- foreach (QSGGeometryNode* node, m_nodes){
- if (node == *(m_nodes.begin()))
- continue;
- (*(m_nodes.begin()))->appendChildNode(node);
- }
-
- return *(m_nodes.begin());
-}
-
QSGGeometryNode* QSGImageParticle::buildParticleNodes()
{
+#ifdef QT_OPENGL_ES_2
if (m_count * 4 > 0xffff) {
- printf("UltraParticle: Too many particles... \n");//### Why is this here?
+ printf("ImageParticle: Too many particles - maximum 16,000 per ImageParticle.\n");//ES 2 vertex count limit is ushort
return 0;
}
+#endif
if (count() <= 0)
return 0;
- if (!m_sprites.count() && !m_bloat
- && m_colortable_name.isEmpty()
- && m_sizetable_name.isEmpty()
- && m_opacitytable_name.isEmpty()
- && !m_autoRotation
- && !m_rotation && !m_rotationVariation
- && !m_rotationSpeed && !m_rotationSpeedVariation
- && !m_alphaVariation && m_alpha == 1.0
- && !m_redVariation && !m_blueVariation && !m_greenVariation
- && !m_color.isValid()
- )
- return buildSimpleParticleNodes();
- perfLevel = Sprites;//TODO: intermediate levels
- if (!m_color.isValid())//But we're in colored level (or higher)
- m_color = QColor(Qt::white);
+ if (m_sprites.count() || m_bloat) {
+ perfLevel = Sprites;
+ } else if (!m_colortable_name.isEmpty() || !m_sizetable_name.isEmpty()
+ || !m_opacitytable_name.isEmpty()) {
+ perfLevel = Tabled;
+ } else if (m_autoRotation || m_rotation || m_rotationVariation
+ || m_rotationSpeed || m_rotationSpeedVariation) {
+ perfLevel = Deformable;
+ } else if (m_alphaVariation || m_alpha != 1.0 || m_color.isValid()
+ || m_redVariation || m_blueVariation || m_greenVariation) {
+ perfLevel = Colored;
+ } else {
+ perfLevel = Simple;
+ }
+
+ if (perfLevel >= Colored && !m_color.isValid())
+ m_color = QColor(Qt::white);//Hidden default, but different from unset
QImage image;
- if (m_sprites.count()){
+ if (perfLevel >= Sprites){
if (!m_spriteEngine) {
- qWarning() << "UltraParticle: No sprite engine...";
+ qWarning() << "ImageParticle: No sprite engine...";
return 0;
}
image = m_spriteEngine->assembledImage();
if (image.isNull())//Warning is printed in engine
return 0;
- }else{
+ } else {
image = QImage(m_image_name.toLocalFile());
if (image.isNull()) {
- printf("UltraParticle: loading image failed... '%s'\n", qPrintable(m_image_name.toLocalFile()));
+ printf("ImageParticle: loading image failed '%s'\n", qPrintable(m_image_name.toLocalFile()));
return 0;
}
}
+
if (m_material) {
delete m_material;
m_material = 0;
}
- QImage colortable(m_colortable_name.toLocalFile());
- QImage sizetable(m_sizetable_name.toLocalFile());
- QImage opacitytable(m_opacitytable_name.toLocalFile());
- m_material = new UltraMaterial();
- if (colortable.isNull())
- colortable = QImage(":defaultshaders/identitytable.png");
- if (sizetable.isNull())
- sizetable = QImage(":defaultshaders/identitytable.png");
- if (opacitytable.isNull())
- opacitytable = QImage(":defaultshaders/defaultFadeInOut.png");
- Q_ASSERT(!colortable.isNull());
- Q_ASSERT(!sizetable.isNull());
- Q_ASSERT(!opacitytable.isNull());
- m_material->colortable = sceneGraphEngine()->createTextureFromImage(colortable);
- m_material->sizetable = sceneGraphEngine()->createTextureFromImage(sizetable);
- m_material->opacitytable = sceneGraphEngine()->createTextureFromImage(opacitytable);
-
- m_material->texture = sceneGraphEngine()->createTextureFromImage(image);
- m_material->texture->setFiltering(QSGTexture::Linear);
-
- m_material->framecount = 1;
- if (m_spriteEngine){
- m_material->framecount = m_spriteEngine->maxFrames();
+ //Setup material
+ QImage colortable;
+ QImage sizetable;
+ QImage opacitytable;
+ switch (perfLevel) {//Fallthrough intended
+ case Sprites:
+ m_material = SpriteMaterial::createMaterial();
+ getState<ImageMaterialData>(m_material)->framecount = m_spriteEngine->maxFrames();
m_spriteEngine->setCount(m_count);
+ case Tabled:
+ if (!m_material)
+ m_material = TabledMaterial::createMaterial();
+ colortable = QImage(m_colortable_name.toLocalFile());
+ sizetable = QImage(m_sizetable_name.toLocalFile());
+ opacitytable = QImage(m_opacitytable_name.toLocalFile());
+ if (colortable.isNull())
+ colortable = QImage(":defaultshaders/identitytable.png");
+ Q_ASSERT(!colortable.isNull());
+ getState<ImageMaterialData>(m_material)->colorTable = sceneGraphEngine()->createTextureFromImage(colortable);
+ fillUniformArrayFromImage(getState<ImageMaterialData>(m_material)->sizeTable, sizetable, UNIFORM_ARRAY_SIZE);
+ fillUniformArrayFromImage(getState<ImageMaterialData>(m_material)->opacityTable, opacitytable, UNIFORM_ARRAY_SIZE);
+ case Deformable:
+ if (!m_material)
+ m_material = DeformableMaterial::createMaterial();
+ case Colored:
+ if (!m_material)
+ m_material = ColoredMaterial::createMaterial();
+ default://Also Simple
+ if (!m_material)
+ m_material = SimpleMaterial::createMaterial();
+ getState<ImageMaterialData>(m_material)->texture = sceneGraphEngine()->createTextureFromImage(image);
+ getState<ImageMaterialData>(m_material)->texture->setFiltering(QSGTexture::Linear);
+ getState<ImageMaterialData>(m_material)->entry = (qreal) m_entryEffect;
+ m_material->setFlag(QSGMaterial::Blending);
}
foreach (const QString &str, m_particles){
@@ -784,39 +947,51 @@ QSGGeometryNode* QSGImageParticle::buildParticleNodes()
int vCount = count * 4;
int iCount = count * 6;
- QSGGeometry *g = new QSGGeometry(UltraParticle_AttributeSet, vCount, iCount);
- node->setGeometry(g);
- g->setDrawingMode(GL_TRIANGLES);
-
- UltraVertex *vertices = (UltraVertex *) g->vertexData();
- for (int p=0; p < count; ++p) {
- commit(gIdx, p);//commit sets geometry for the node
-
- vertices[0].tx = 0;
- vertices[0].ty = 0;
-
- vertices[1].tx = 1;
- vertices[1].ty = 0;
-
- vertices[2].tx = 0;
- vertices[2].ty = 1;
-
- vertices[3].tx = 1;
- vertices[3].ty = 1;
-
- vertices += 4;
- }
+ QSGGeometry *g;
+ if (perfLevel == Sprites)
+ g = new QSGGeometry(SpriteParticle_AttributeSet, vCount, iCount);
+ else if (perfLevel == Tabled)
+ g = new QSGGeometry(DeformableParticle_AttributeSet, vCount, iCount);
+ else if (perfLevel == Deformable)
+ g = new QSGGeometry(DeformableParticle_AttributeSet, vCount, iCount);
+ else if (perfLevel == Colored)
+ g = new QSGGeometry(ColoredParticle_AttributeSet, count, 0);
+ else //Simple
+ g = new QSGGeometry(SimpleParticle_AttributeSet, count, 0);
- quint16 *indices = g->indexDataAsUShort();
- for (int i=0; i < count; ++i) {
- int o = i * 4;
- indices[0] = o;
- indices[1] = o + 1;
- indices[2] = o + 2;
- indices[3] = o + 1;
- indices[4] = o + 3;
- indices[5] = o + 2;
- indices += 6;
+ node->setGeometry(g);
+ if (perfLevel <= Colored){
+ g->setDrawingMode(GL_POINTS);
+ if (m_debugMode){
+ GLfloat pointSizeRange[2];
+ glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, pointSizeRange);
+ qDebug() << "Using point sprites, GL_ALIASED_POINT_SIZE_RANGE " <<pointSizeRange[0] << ":" << pointSizeRange[1];
+ }
+ }else
+ g->setDrawingMode(GL_TRIANGLES);
+
+ for (int p=0; p < count; ++p)
+ commit(gIdx, p);//commit sets geometry for the node, has its own perfLevel switch
+
+ if (perfLevel == Sprites)
+ initTexCoords<SpriteVertex>((SpriteVertex*)g->vertexData(), vCount);
+ else if (perfLevel == Tabled)
+ initTexCoords<DeformableVertex>((DeformableVertex*)g->vertexData(), vCount);
+ else if (perfLevel == Deformable)
+ initTexCoords<DeformableVertex>((DeformableVertex*)g->vertexData(), vCount);
+
+ if (perfLevel > Colored){
+ quint16 *indices = g->indexDataAsUShort();
+ for (int i=0; i < count; ++i) {
+ int o = i * 4;
+ indices[0] = o;
+ indices[1] = o + 1;
+ indices[2] = o + 2;
+ indices[3] = o + 1;
+ indices[4] = o + 3;
+ indices[5] = o + 2;
+ indices += 6;
+ }
}
}
@@ -867,26 +1042,34 @@ void QSGImageParticle::prepareNextFrame()
m_rootNode = buildParticleNodes();
if (m_rootNode == 0)
return;
- //qDebug() << "Feature level: " << perfLevel;
+ if(m_debugMode){
+ qDebug() << "QSGImageParticle Feature level: " << perfLevel;
+ qDebug() << "QSGImageParticle Nodes: ";
+ int count = 0;
+ foreach(int i, m_nodes.keys()){
+ qDebug() << "Group " << i << " (" << m_system->m_groupData[i]->size() << " particles)";
+ count += m_system->m_groupData[i]->size();
+ }
+ qDebug() << "Total count: " << count;
+ }
}
qint64 timeStamp = m_system->systemSync(this);
qreal time = timeStamp / 1000.;
- m_material->timestamp = time;
-
- //Advance State
- if (m_spriteEngine){//perfLevel == Sprites?//TODO: use signals?
- m_material->animcount = m_spriteEngine->spriteCount();
+ switch (perfLevel){//Fall-through intended
+ case Sprites:
+ //Advance State
+ getState<ImageMaterialData>(m_material)->animcount = m_spriteEngine->spriteCount();
m_spriteEngine->updateSprites(timeStamp);
foreach (const QString &str, m_particles){
int gIdx = m_system->m_groupIds[str];
int count = m_system->m_groupData[gIdx]->size();
- UltraVertices *particles = (UltraVertices *) m_nodes[gIdx]->geometry()->vertexData();
+ Vertices<SpriteVertex>* particles = (Vertices<SpriteVertex> *) m_nodes[gIdx]->geometry()->vertexData();
for (int i=0; i < count; i++){
int spriteIdx = m_idxStarts[gIdx] + i;
- UltraVertices &p = particles[i];
+ Vertices<SpriteVertex> &p = particles[i];
int curIdx = m_spriteEngine->spriteState(spriteIdx);
if (curIdx != p.v1.animIdx){
p.v1.animIdx = p.v2.animIdx = p.v3.animIdx = p.v4.animIdx = curIdx;
@@ -896,9 +1079,15 @@ void QSGImageParticle::prepareNextFrame()
}
}
}
- }else{
- m_material->animcount = 1;
+ case Tabled:
+ case Deformable:
+ case Colored:
+ case Simple:
+ default: //Also Simple
+ getState<ImageMaterialData>(m_material)->timestamp = time;
+ break;
}
+
}
void QSGImageParticle::reloadColor(const Color4ub &c, QSGParticleData* d)
@@ -967,47 +1156,91 @@ void QSGImageParticle::commit(int gIdx, int pIdx)
if (!node)
return;
QSGParticleData* datum = m_system->m_groupData[gIdx]->data[pIdx];
-
node->setFlag(QSGNode::OwnsGeometry, false);
- UltraVertex *ultraVertices = (UltraVertex *) node->geometry()->vertexData();
+ SpriteVertex *spriteVertices = (SpriteVertex *) node->geometry()->vertexData();
+ DeformableVertex *deformableVertices = (DeformableVertex *) node->geometry()->vertexData();
+ ColoredVertex *coloredVertices = (ColoredVertex *) node->geometry()->vertexData();
SimpleVertex *simpleVertices = (SimpleVertex *) node->geometry()->vertexData();
- switch (perfLevel){
+ switch (perfLevel){//No automatic fall through intended on this one
case Sprites:
- ultraVertices += pIdx*4;
+ spriteVertices += pIdx*4;
for (int i=0; i<4; i++){
- ultraVertices[i].x = datum->x - m_systemOffset.x();
- ultraVertices[i].y = datum->y - m_systemOffset.y();
- ultraVertices[i].t = datum->t;
- ultraVertices[i].lifeSpan = datum->lifeSpan;
- ultraVertices[i].size = datum->size;
- ultraVertices[i].endSize = datum->endSize;
- ultraVertices[i].vx = datum->vx;
- ultraVertices[i].vy = datum->vy;
- ultraVertices[i].ax = datum->ax;
- ultraVertices[i].ay = datum->ay;
- ultraVertices[i].xx = datum->xx;
- ultraVertices[i].xy = datum->xy;
- ultraVertices[i].yx = datum->yx;
- ultraVertices[i].yy = datum->yy;
- ultraVertices[i].rotation = datum->rotation;
- ultraVertices[i].rotationSpeed = datum->rotationSpeed;
- ultraVertices[i].autoRotate = datum->autoRotate;
- ultraVertices[i].animIdx = datum->animIdx;
- ultraVertices[i].frameDuration = datum->frameDuration;
- ultraVertices[i].frameCount = datum->frameCount;
- ultraVertices[i].animT = datum->animT;
- ultraVertices[i].color.r = datum->color.r;
- ultraVertices[i].color.g = datum->color.g;
- ultraVertices[i].color.b = datum->color.b;
- ultraVertices[i].color.a = datum->color.a;
+ spriteVertices[i].x = datum->x - m_systemOffset.x();
+ spriteVertices[i].y = datum->y - m_systemOffset.y();
+ spriteVertices[i].t = datum->t;
+ spriteVertices[i].lifeSpan = datum->lifeSpan;
+ spriteVertices[i].size = datum->size;
+ spriteVertices[i].endSize = datum->endSize;
+ spriteVertices[i].vx = datum->vx;
+ spriteVertices[i].vy = datum->vy;
+ spriteVertices[i].ax = datum->ax;
+ spriteVertices[i].ay = datum->ay;
+ spriteVertices[i].xx = datum->xx;
+ spriteVertices[i].xy = datum->xy;
+ spriteVertices[i].yx = datum->yx;
+ spriteVertices[i].yy = datum->yy;
+ spriteVertices[i].rotation = datum->rotation;
+ spriteVertices[i].rotationSpeed = datum->rotationSpeed;
+ spriteVertices[i].autoRotate = datum->autoRotate;
+ spriteVertices[i].animIdx = datum->animIdx;
+ spriteVertices[i].frameDuration = datum->frameDuration;
+ spriteVertices[i].frameCount = datum->frameCount;
+ spriteVertices[i].animT = datum->animT;
+ spriteVertices[i].color.r = datum->color.r;
+ spriteVertices[i].color.g = datum->color.g;
+ spriteVertices[i].color.b = datum->color.b;
+ spriteVertices[i].color.a = datum->color.a;
}
break;
- case Tabled://TODO: Us
+ case Tabled: //Fall through until it has its own vertex class
case Deformable:
+ deformableVertices += pIdx*4;
+ for (int i=0; i<4; i++){
+ deformableVertices[i].x = datum->x - m_systemOffset.x();
+ deformableVertices[i].y = datum->y - m_systemOffset.y();
+ deformableVertices[i].t = datum->t;
+ deformableVertices[i].lifeSpan = datum->lifeSpan;
+ deformableVertices[i].size = datum->size;
+ deformableVertices[i].endSize = datum->endSize;
+ deformableVertices[i].vx = datum->vx;
+ deformableVertices[i].vy = datum->vy;
+ deformableVertices[i].ax = datum->ax;
+ deformableVertices[i].ay = datum->ay;
+ deformableVertices[i].xx = datum->xx;
+ deformableVertices[i].xy = datum->xy;
+ deformableVertices[i].yx = datum->yx;
+ deformableVertices[i].yy = datum->yy;
+ deformableVertices[i].rotation = datum->rotation;
+ deformableVertices[i].rotationSpeed = datum->rotationSpeed;
+ deformableVertices[i].autoRotate = datum->autoRotate;
+ deformableVertices[i].color.r = datum->color.r;
+ deformableVertices[i].color.g = datum->color.g;
+ deformableVertices[i].color.b = datum->color.b;
+ deformableVertices[i].color.a = datum->color.a;
+ }
+ break;
case Colored:
+ coloredVertices += pIdx*1;
+ for (int i=0; i<1; i++){
+ coloredVertices[i].x = datum->x - m_systemOffset.x();
+ coloredVertices[i].y = datum->y - m_systemOffset.y();
+ coloredVertices[i].t = datum->t;
+ coloredVertices[i].lifeSpan = datum->lifeSpan;
+ coloredVertices[i].size = datum->size;
+ coloredVertices[i].endSize = datum->endSize;
+ coloredVertices[i].vx = datum->vx;
+ coloredVertices[i].vy = datum->vy;
+ coloredVertices[i].ax = datum->ax;
+ coloredVertices[i].ay = datum->ay;
+ coloredVertices[i].color.r = datum->color.r;
+ coloredVertices[i].color.g = datum->color.g;
+ coloredVertices[i].color.b = datum->color.b;
+ coloredVertices[i].color.a = datum->color.a;
+ }
+ break;
case Simple:
- simpleVertices += pIdx*4;
- for (int i=0; i<4; i++){
+ simpleVertices += pIdx*1;
+ for (int i=0; i<1; i++){
simpleVertices[i].x = datum->x - m_systemOffset.x();
simpleVertices[i].y = datum->y - m_systemOffset.y();
simpleVertices[i].t = datum->t;
diff --git a/src/declarative/particles/qsgimageparticle_p.h b/src/declarative/particles/qsgimageparticle_p.h
index 1ac840ca9f..eb890e285c 100644
--- a/src/declarative/particles/qsgimageparticle_p.h
+++ b/src/declarative/particles/qsgimageparticle_p.h
@@ -44,6 +44,7 @@
#include "qsgparticlepainter_p.h"
#include "qsgstochasticdirection_p.h"
#include <QDeclarativeListProperty>
+#include <qsgsimplematerial.h>
QT_BEGIN_HEADER
@@ -51,7 +52,7 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
-class UltraMaterial;
+class ImageMaterialData;
class QSGGeometryNode;
class QSGSprite;
@@ -60,8 +61,6 @@ class QSGSpriteEngine;
struct SimpleVertex {
float x;
float y;
- float tx;
- float ty;
float t;
float lifeSpan;
float size;
@@ -72,14 +71,44 @@ struct SimpleVertex {
float ay;
};
-struct SimpleVertices {
- SimpleVertex v1;
- SimpleVertex v2;
- SimpleVertex v3;
- SimpleVertex v4;
+struct ColoredVertex {
+ float x;
+ float y;
+ float t;
+ float lifeSpan;
+ float size;
+ float endSize;
+ float vx;
+ float vy;
+ float ax;
+ float ay;
+ Color4ub color;
+};
+
+struct DeformableVertex {
+ float x;
+ float y;
+ float tx;
+ float ty;
+ float t;
+ float lifeSpan;
+ float size;
+ float endSize;
+ float vx;
+ float vy;
+ float ax;
+ float ay;
+ Color4ub color;
+ float xx;
+ float xy;
+ float yx;
+ float yy;
+ float rotation;
+ float rotationSpeed;
+ float autoRotate;//Assumed that GPUs prefer floats to bools
};
-struct UltraVertex {
+struct SpriteVertex {
float x;
float y;
float tx;
@@ -99,25 +128,19 @@ struct UltraVertex {
float yy;
float rotation;
float rotationSpeed;
- float autoRotate;//Assume that GPUs prefer floats to bools
+ float autoRotate;//Assumed that GPUs prefer floats to bools
float animIdx;
float frameDuration;
float frameCount;
float animT;
};
-struct UltraVertices {
- UltraVertex v1;
- UltraVertex v2;
- UltraVertex v3;
- UltraVertex v4;
-};
-
-struct IntermediateVertices {
- UltraVertex* v1;
- UltraVertex* v2;
- UltraVertex* v3;
- UltraVertex* v4;
+template <typename Vertex>
+struct Vertices {
+ Vertex v1;
+ Vertex v2;
+ Vertex v3;
+ Vertex v4;
};
class QSGImageParticle : public QSGParticlePainter
@@ -153,15 +176,24 @@ class QSGImageParticle : public QSGParticlePainter
//yVector is the same, but top-left to bottom-left. The particle is always a parallelogram.
Q_PROPERTY(QSGStochasticDirection* yVector READ yVector WRITE setYVector NOTIFY yVectorChanged)
Q_PROPERTY(QDeclarativeListProperty<QSGSprite> sprites READ sprites)
+
+ Q_PROPERTY(EntryEffect entryEffect READ entryEffect WRITE setEntryEffect NOTIFY entryEffectChanged)
Q_PROPERTY(bool bloat READ bloat WRITE setBloat NOTIFY bloatChanged)//Just a debugging property to bypass optimizations
+ Q_ENUMS(EntryEffect)
public:
explicit QSGImageParticle(QSGItem *parent = 0);
- virtual ~QSGImageParticle(){}
+ virtual ~QSGImageParticle();
QDeclarativeListProperty<QSGSprite> sprites();
QSGSpriteEngine* spriteEngine() {return m_spriteEngine;}
+ enum EntryEffect {
+ None = 0,
+ Fade = 1,
+ Scale = 2
+ };
+
enum PerformanceLevel{//TODO: Expose?
Unknown = 0,
Simple,
@@ -217,6 +249,8 @@ public:
bool bloat() const { return m_bloat; }
+ EntryEffect entryEffect() const { return m_entryEffect; }
+
signals:
void imageChanged();
@@ -254,6 +288,8 @@ signals:
void bloatChanged(bool arg);
+ void entryEffectChanged(EntryEffect arg);
+
public slots:
void reloadColor(const Color4ub &c, QSGParticleData* d);
void setAlphaVariation(qreal arg);
@@ -282,6 +318,8 @@ public slots:
void setBloat(bool arg);
+ void setEntryEffect(EntryEffect arg);
+
protected:
void reset();
virtual void initialize(int gIdx, int pIdx);
@@ -290,7 +328,6 @@ protected:
QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
void prepareNextFrame();
QSGGeometryNode* buildParticleNodes();
- QSGGeometryNode* buildSimpleParticleNodes();
private slots:
void createEngine(); //### method invoked by sprite list changing (in engine.h) - pretty nasty
@@ -312,7 +349,7 @@ private:
QHash<int, QSGGeometryNode *> m_nodes;
QHash<int, int> m_idxStarts;//TODO: Proper resizing will lead to needing a spriteEngine per particle - do this after sprite engine gains transparent sharing?
int m_lastIdxStart;
- UltraMaterial *m_material;
+ QSGMaterial *m_material;
// derived values...
@@ -337,6 +374,33 @@ private:
PerformanceLevel perfLevel;
PerformanceLevel m_lastLevel;
+ bool m_debugMode;
+
+ template<class Vertex>
+ void initTexCoords(Vertex* v, int count){
+ Vertex* end = v + count;
+ while (v < end){
+ v[0].tx = 0;
+ v[0].ty = 0;
+
+ v[1].tx = 1;
+ v[1].ty = 0;
+
+ v[2].tx = 0;
+ v[2].ty = 1;
+
+ v[3].tx = 1;
+ v[3].ty = 1;
+
+ v += 4;
+ }
+ }
+
+ template<class MaterialData>
+ MaterialData* getState(QSGMaterial* m){
+ return static_cast<QSGSimpleMaterial<MaterialData> *>(m)->state();
+ }
+ EntryEffect m_entryEffect;
};
QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgitemparticle.cpp b/src/declarative/particles/qsgitemparticle.cpp
index 19d921a10d..65407fabf8 100644
--- a/src/declarative/particles/qsgitemparticle.cpp
+++ b/src/declarative/particles/qsgitemparticle.cpp
@@ -51,7 +51,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass ItemParticle QSGItemParticle
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits ParticlePainter
\brief The ItemParticle element allows you to specify your own delegate to paint particles.
diff --git a/src/declarative/particles/qsgkill.cpp b/src/declarative/particles/qsgkill.cpp
index 9d4bc940bd..dfd26e3f39 100644
--- a/src/declarative/particles/qsgkill.cpp
+++ b/src/declarative/particles/qsgkill.cpp
@@ -45,7 +45,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass Kill QSGKillAffector
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits Affector
\brief The Kill affector allows you to expire affected particles
diff --git a/src/declarative/particles/qsglineextruder.cpp b/src/declarative/particles/qsglineextruder.cpp
index a08d052c20..6581cf23ee 100644
--- a/src/declarative/particles/qsglineextruder.cpp
+++ b/src/declarative/particles/qsglineextruder.cpp
@@ -44,7 +44,6 @@
/*!
\qmlclass LineShape QSGLineExtruder
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits Shape
\brief The LineShape represents a line to Affectors and Emitter
diff --git a/src/declarative/particles/qsgmaskextruder.cpp b/src/declarative/particles/qsgmaskextruder.cpp
index e76280378b..4f8b89a639 100644
--- a/src/declarative/particles/qsgmaskextruder.cpp
+++ b/src/declarative/particles/qsgmaskextruder.cpp
@@ -46,7 +46,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass MaskShape QSGMaskExtruder
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits Shape
\brief The MaskShape element allows you to represent an image as a shape to affectors and emitters.
diff --git a/src/declarative/particles/qsgmodelparticle.cpp b/src/declarative/particles/qsgmodelparticle.cpp
index 19815aa8f4..2646864283 100644
--- a/src/declarative/particles/qsgmodelparticle.cpp
+++ b/src/declarative/particles/qsgmodelparticle.cpp
@@ -49,7 +49,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass ModelParticle QSGModelParticle
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits ParticlePainter
\brief The ModelParticle element allows you to specify a model and delegate pair to paint particles.
diff --git a/src/declarative/particles/qsgparticleaffector.cpp b/src/declarative/particles/qsgparticleaffector.cpp
index bf268efc9d..4cb3e49403 100644
--- a/src/declarative/particles/qsgparticleaffector.cpp
+++ b/src/declarative/particles/qsgparticleaffector.cpp
@@ -45,7 +45,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass Affector QSGParticleAffector
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\brief Affector elements can alter the attributes of logical particles at any point in their lifetime.
The base Affector does not alter any attributes, but can be used to emit a signal
@@ -95,11 +94,24 @@ QT_BEGIN_NAMESPACE
/*!
\qmlproperty bool QtQuick.Particles2::Affector::signal
If this is set to true, then an affected(x,y) signal will be emitted each
- time this affector affects a particle.
+ time this affector would affect a particle.
+
+ For Affector only, this will happen irrespective of whether any changes
+ are made to the particle, for other Affectors the signal will only fire
+ if the particle is actually affected.
Default value is false.
*/
+//TODO: Document particle 'type'
+/*!
+ \qmlsignal QtQuick.Particles2::Affector::affectParticle(particle, dt)
+
+ This handler is called when a particle is selected to be affected.
+
+ dt is the time since the last time it was affected. Use dt to normalize
+ trajectory manipulations to real time.
+*/
QSGParticleAffector::QSGParticleAffector(QSGItem *parent) :
QSGItem(parent), m_needsReset(false), m_system(0), m_active(true)
, m_updateIntSet(false), m_shape(new QSGParticleExtruder(this)), m_signal(false)
@@ -112,6 +124,12 @@ QSGParticleAffector::QSGParticleAffector(QSGItem *parent) :
this, SLOT(updateOffsets()));//TODO: in componentComplete and all relevant signals
}
+bool QSGParticleAffector::isAffectConnected()
+{
+ static int idx = QObjectPrivate::get(this)->signalIndex("affectParticle(QDeclarativeV8Handle, qreal)");
+ return QObjectPrivate::get(this)->isSignalConnected(idx);
+}
+
void QSGParticleAffector::componentComplete()
{
if (!m_system && qobject_cast<QSGParticleSystem*>(parentItem()))
@@ -162,8 +180,10 @@ void QSGParticleAffector::affectSystem(qreal dt)
bool QSGParticleAffector::affectParticle(QSGParticleData *d, qreal dt)
{
- Q_UNUSED(d);
- Q_UNUSED(dt);
+ if (isAffectConnected()){
+ emit affectParticle(d->v8Value(), dt);
+ return true;
+ }
return m_signal;//If signalling, then we always 'null affect' it.
}
diff --git a/src/declarative/particles/qsgparticleaffector_p.h b/src/declarative/particles/qsgparticleaffector_p.h
index 4479f5d131..dd279c07b9 100644
--- a/src/declarative/particles/qsgparticleaffector_p.h
+++ b/src/declarative/particles/qsgparticleaffector_p.h
@@ -103,6 +103,7 @@ public:
}
signals:
+ void affectParticle(QDeclarativeV8Handle particle, qreal dt);
void systemChanged(QSGParticleSystem* arg);
@@ -189,6 +190,7 @@ protected:
bool m_active;
virtual void componentComplete();
QPointF m_offset;
+ bool isAffectConnected();
private:
QSet<int> m_groups;
QSet<QPair<int, int> > m_onceOffed;
diff --git a/src/declarative/particles/qsgparticleemitter.cpp b/src/declarative/particles/qsgparticleemitter.cpp
index dfd1618088..bf4f5701e5 100644
--- a/src/declarative/particles/qsgparticleemitter.cpp
+++ b/src/declarative/particles/qsgparticleemitter.cpp
@@ -41,7 +41,153 @@
#include "qsgparticleemitter_p.h"
QT_BEGIN_NAMESPACE
-//Not visible from QML, so not documented. Document subclasses.
+
+
+/*!
+ \qmlclass Emitter QSGParticleEmitter
+ \inqmlmodule QtQuick.Particles 2
+ \brief The Emitter element allows you to emit logical particles.
+
+ This element emits logical particles into the ParticleSystem, with the
+ given starting attributes.
+
+ Note that logical particles are not
+ automatically rendered, you will need to have one or more
+ ParticlePainter elements visualizing them.
+
+ Note that the given starting attributes can be modified at any point
+ in the particle's lifetime by any Affector element in the same
+ ParticleSystem. This includes attributes like lifespan.
+*/
+
+
+/*!
+ \qmlproperty ParticleSystem QtQuick.Particles2::Emitter::system
+
+ This is the Particle system that the Emitter will emit into.
+ This can be omitted if the Emitter is a direct child of the ParticleSystem
+*/
+/*!
+ \qmlproperty string QtQuick.Particles2::Emitter::particle
+
+ This is the type of logical particle which it will emit.
+
+ Default value is "" (empty string).
+*/
+/*!
+ \qmlproperty Shape QtQuick.Particles2::Emitter::shape
+
+ This shape is applied to the bounding box of the emitter. Particles are then emitting
+ from inside the area of the shape.
+
+*/
+/*!
+ \qmlproperty bool QtQuick.Particles2::Emitter::emitting
+
+ If set to false, the emitter will cease emissions until it is set to true.
+
+ Default value is true.
+*/
+/*!
+ \qmlproperty real QtQuick.Particles2::Emitter::emitRate
+
+ Number of particles emitted per second.
+
+ Default value is 10 particles per second.
+*/
+/*!
+ \qmlproperty int QtQuick.Particles2::Emitter::lifeSpan
+
+ The time in milliseconds each emitted particle should last for.
+
+ Default value is 1000 (one second).
+*/
+/*!
+ \qmlproperty int QtQuick.Particles2::Emitter::lifeSpanVariation
+
+ Particle lifespans will vary by up to this much in either direction.
+
+ Default value is 0.
+*/
+
+/*!
+ \qmlproperty int QtQuick.Particles2::Emitter::emitCap
+
+ The maximum number of particles at a time that this emitter will have alive.
+
+ This can be set as a performance optimization (when using burst and pulse) or
+ to stagger emissions. The default value is emitRate * lifeSpan in seconds, which
+ is the number of particles that would be alive at any one time given the default settings.
+*/
+/*!
+ \qmlproperty bool QtQuick.Particles2::Emitter::noCap
+
+ If set to true, the emitCap will be ignored and this emitter will never skip emitting
+ a particle based on how many it has alive.
+
+ Default value is false.
+*/
+/*!
+ \qmlproperty int QtQuick.Particles2::Emitter::startTime
+
+ If this value is set when the emitter is loaded, then it will emit particles from the
+ past, up to startTime milliseconds ago. These will simulate as if they were emitted then,
+ but will not have any affectors applied to them. Affectors will take effect from the present time.
+*/
+/*!
+ \qmlproperty real QtQuick.Particles2::Emitter::size
+
+ The size in pixels of the particles at the start of their life.
+
+ Default value is 16.
+*/
+/*!
+ \qmlproperty real QtQuick.Particles2::Emitter::endSize
+
+ The size in pixels of the particles at the end of their life. Size will
+ be linearly interpolated during the life of the particle from this value and
+ size. If endSize is -1, then the size of the particle will remain constant at
+ the starting size.
+
+ Default value is -1.
+*/
+/*!
+ \qmlproperty real QtQuick.Particles2::Emitter::sizeVariation
+
+ The size of a particle can vary by this much up or down from size/endSize. The same
+ random addition is made to both size and endSize for a single particle.
+
+ Default value is 0.
+*/
+/*!
+ \qmlproperty StochasticDirection QtQuick.Particles2::Emitter::speed
+
+ The starting speed of the particles emitted.
+*/
+/*!
+ \qmlproperty StochasticDirection QtQuick.Particles2::Emitter::acceleration
+
+ The starting acceleraton of the particles emitted.
+*/
+/*!
+ \qmlproperty qreal QtQuick.Particles2::Emitter::speedFromMovement
+
+ If this value is non-zero, then any movement of the emitter will provide additional
+ starting velocity to the particles based on the movement. The additional vector will be the
+ same angle as the emitter's movement, with a magnitude that is the magnitude of the emitters
+ movement multiplied by speedFromMovement.
+
+ Default value is 0.
+*/
+//TODO: Document particle 'type'
+/*!
+ \qmlsignal QtQuick.Particles2::Emitter::emitParticle(particle)
+
+ This handler is called when a particle is emitted. You can modify particle
+ attributes from within the handler.
+*/
+
+
QSGParticleEmitter::QSGParticleEmitter(QSGItem *parent) :
QSGItem(parent)
, m_particlesPerSecond(10)
@@ -58,6 +204,13 @@ QSGParticleEmitter::QSGParticleEmitter(QSGItem *parent) :
, m_particleSizeVariation(0)
, m_maxParticleCount(-1)
, m_burstLeft(0)
+ , m_speed_from_movement(0)
+ , m_particle_count(0)
+ , m_reset_last(true)
+ , m_last_timestamp(-1)
+ , m_last_emission(0)
+ , m_startTime(0)
+ , m_overwrite(false)
{
//TODO: Reset speed/acc back to null vector? Or allow null pointer?
@@ -75,6 +228,12 @@ QSGParticleEmitter::~QSGParticleEmitter()
delete m_defaultExtruder;
}
+bool QSGParticleEmitter::isEmitConnected()
+{
+ static int idx = QObjectPrivate::get(this)->signalIndex("emitParticle(QDeclarativeV8Handle)");
+ return QObjectPrivate::get(this)->isSignalConnected(idx);
+}
+
void QSGParticleEmitter::componentComplete()
{
if (!m_system && qobject_cast<QSGParticleSystem*>(parentItem()))
@@ -83,11 +242,6 @@ void QSGParticleEmitter::componentComplete()
qWarning() << "Emitter created without a particle system specified";//TODO: useful QML warnings, like line number?
QSGItem::componentComplete();
}
-void QSGParticleEmitter::emitWindow(int timeStamp)
-{
- Q_UNUSED(timeStamp);
-}
-
void QSGParticleEmitter::setEmitting(bool arg)
{
@@ -155,4 +309,145 @@ int QSGParticleEmitter::particleCount() const
return m_particlesPerSecond*((m_particleDuration+m_particleDurationVariation)/1000.0);
}
+void QSGParticleEmitter::setSpeedFromMovement(qreal t)
+{
+ if (t == m_speed_from_movement)
+ return;
+ m_speed_from_movement = t;
+ emit speedFromMovementChanged();
+}
+
+void QSGParticleEmitter::emitWindow(int timeStamp)
+{
+ if (m_system == 0)
+ return;
+ if ((!m_emitting || !m_particlesPerSecond)&& !m_burstLeft && m_burstQueue.isEmpty()){
+ m_reset_last = true;
+ return;
+ }
+
+ if (m_reset_last) {
+ m_last_emitter = m_last_last_emitter = QPointF(x(), y());
+ if (m_last_timestamp == -1)
+ m_last_timestamp = timeStamp/1000. - m_startTime;
+ else
+ m_last_timestamp = timeStamp/1000.;
+ m_last_emission = m_last_timestamp;
+ m_reset_last = false;
+ }
+
+ if (m_burstLeft){
+ m_burstLeft -= timeStamp - m_last_timestamp * 1000.;
+ if (m_burstLeft < 0){
+ if (!m_emitting)
+ timeStamp += m_burstLeft;
+ m_burstLeft = 0;
+ }
+ }
+
+ qreal time = timeStamp / 1000.;
+
+ qreal particleRatio = 1. / m_particlesPerSecond;
+ qreal pt = m_last_emission;
+
+ qreal opt = pt; // original particle time
+ qreal dt = time - m_last_timestamp; // timestamp delta...
+ if (!dt)
+ dt = 0.000001;
+
+ // emitter difference since last...
+ qreal dex = (x() - m_last_emitter.x());
+ qreal dey = (y() - m_last_emitter.y());
+
+ qreal ax = (m_last_last_emitter.x() + m_last_emitter.x()) / 2;
+ qreal bx = m_last_emitter.x();
+ qreal cx = (x() + m_last_emitter.x()) / 2;
+ qreal ay = (m_last_last_emitter.y() + m_last_emitter.y()) / 2;
+ qreal by = m_last_emitter.y();
+ qreal cy = (y() + m_last_emitter.y()) / 2;
+
+ qreal sizeAtEnd = m_particleEndSize >= 0 ? m_particleEndSize : m_particleSize;
+ qreal emitter_x_offset = m_last_emitter.x() - x();
+ qreal emitter_y_offset = m_last_emitter.y() - y();
+ if (!m_burstQueue.isEmpty() && !m_burstLeft && !m_emitting)//'outside time' emissions only
+ pt = time;
+ while (pt < time || !m_burstQueue.isEmpty()) {
+ //int pos = m_last_particle % m_particle_count;
+ QSGParticleData* datum = m_system->newDatum(m_system->m_groupIds[m_particle], !m_overwrite);
+ if (datum){//actually emit(otherwise we've been asked to skip this one)
+ datum->e = this;//###useful?
+ qreal t = 1 - (pt - opt) / dt;
+ qreal vx =
+ - 2 * ax * (1 - t)
+ + 2 * bx * (1 - 2 * t)
+ + 2 * cx * t;
+ qreal vy =
+ - 2 * ay * (1 - t)
+ + 2 * by * (1 - 2 * t)
+ + 2 * cy * t;
+
+
+ // Particle timestamp
+ datum->t = pt;
+ datum->lifeSpan = //TODO:Promote to base class?
+ (m_particleDuration
+ + ((rand() % ((m_particleDurationVariation*2) + 1)) - m_particleDurationVariation))
+ / 1000.0;
+
+ // Particle position
+ QRectF boundsRect;
+ if (!m_burstQueue.isEmpty()){
+ boundsRect = QRectF(m_burstQueue.first().second.x() - x(), m_burstQueue.first().second.y() - y(),
+ width(), height());
+ } else {
+ boundsRect = QRectF(emitter_x_offset + dex * (pt - opt) / dt, emitter_y_offset + dey * (pt - opt) / dt
+ , width(), height());
+ }
+ QPointF newPos = effectiveExtruder()->extrude(boundsRect);
+ datum->x = newPos.x();
+ datum->y = newPos.y();
+
+ // Particle speed
+ const QPointF &speed = m_speed->sample(newPos);
+ datum->vx = speed.x()
+ + m_speed_from_movement * vx;
+ datum->vy = speed.y()
+ + m_speed_from_movement * vy;
+
+ // Particle acceleration
+ const QPointF &accel = m_acceleration->sample(newPos);
+ datum->ax = accel.x();
+ datum->ay = accel.y();
+
+ // Particle size
+ float sizeVariation = -m_particleSizeVariation
+ + rand() / float(RAND_MAX) * m_particleSizeVariation * 2;
+
+ float size = qMax((qreal)0.0 , m_particleSize + sizeVariation);
+ float endSize = qMax((qreal)0.0 , sizeAtEnd + sizeVariation);
+
+ datum->size = size;// * float(m_emitting);
+ datum->endSize = endSize;// * float(m_emitting);
+
+ if (isEmitConnected())
+ emitParticle(datum->v8Value());//A chance for arbitrary JS changes
+ m_system->emitParticle(datum);
+ }
+ if (m_burstQueue.isEmpty()){
+ pt += particleRatio;
+ }else{
+ m_burstQueue.first().first--;
+ if (m_burstQueue.first().first <= 0)
+ m_burstQueue.pop_front();
+ }
+ }
+ m_last_emission = pt;
+
+ m_last_last_last_emitter = m_last_last_emitter;
+ m_last_last_emitter = m_last_emitter;
+ m_last_emitter = QPointF(x(), y());
+ m_last_timestamp = time;
+}
+
+
QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgparticleemitter_p.h b/src/declarative/particles/qsgparticleemitter_p.h
index 9cf130d40d..2c75fbfe22 100644
--- a/src/declarative/particles/qsgparticleemitter_p.h
+++ b/src/declarative/particles/qsgparticleemitter_p.h
@@ -64,6 +64,8 @@ class QSGParticleEmitter : public QSGItem
Q_PROPERTY(QString particle READ particle WRITE setParticle NOTIFY particleChanged)
Q_PROPERTY(QSGParticleExtruder* shape READ extruder WRITE setExtruder NOTIFY extruderChanged)
Q_PROPERTY(bool emitting READ emitting WRITE setEmitting NOTIFY emittingChanged)
+ Q_PROPERTY(int startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged)
+ Q_PROPERTY(bool noCap READ overwrite WRITE setOverWrite NOTIFY overwriteChanged)
Q_PROPERTY(qreal emitRate READ particlesPerSecond WRITE setParticlesPerSecond NOTIFY particlesPerSecondChanged)
Q_PROPERTY(int lifeSpan READ particleDuration WRITE setParticleDuration NOTIFY particleDurationChanged)
@@ -76,6 +78,8 @@ class QSGParticleEmitter : public QSGItem
Q_PROPERTY(QSGStochasticDirection *speed READ speed WRITE setSpeed NOTIFY speedChanged)
Q_PROPERTY(QSGStochasticDirection *acceleration READ acceleration WRITE setAcceleration NOTIFY accelerationChanged)
+ Q_PROPERTY(qreal speedFromMovement READ speedFromMovement WRITE setSpeedFromMovement NOTIFY speedFromMovementChanged)
+
public:
explicit QSGParticleEmitter(QSGItem *parent = 0);
virtual ~QSGParticleEmitter();
@@ -111,8 +115,11 @@ public:
return m_particleDurationVariation;
}
+ qreal speedFromMovement() const { return m_speed_from_movement; }
+ void setSpeedFromMovement(qreal s);
virtual void componentComplete();
signals:
+ void emitParticle(QDeclarativeV8Handle particle);
void particlesPerSecondChanged(qreal);
void particleDurationChanged(int);
void emittingChanged(bool);
@@ -138,6 +145,12 @@ signals:
void maxParticleCountChanged(int arg);
void particleCountChanged();
+ void speedFromMovementChanged();
+
+ void startTimeChanged(int arg);
+
+ void overwriteChanged(bool arg);
+
public slots:
void pulse(qreal seconds);
void burst(int num);
@@ -235,6 +248,22 @@ public slots:
void setMaxParticleCount(int arg);
+ void setStartTime(int arg)
+ {
+ if (m_startTime != arg) {
+ m_startTime = arg;
+ emit startTimeChanged(arg);
+ }
+ }
+
+ void setOverWrite(bool arg)
+{
+ if (m_overwrite != arg) {
+ m_overwrite = arg;
+emit overwriteChanged(arg);
+}
+}
+
public:
int particleCount() const;
@@ -274,6 +303,16 @@ public:
return m_maxParticleCount;
}
+ int startTime() const
+ {
+ return m_startTime;
+ }
+
+ bool overwrite() const
+ {
+ return m_overwrite;
+ }
+
protected:
qreal m_particlesPerSecond;
int m_particleDuration;
@@ -290,11 +329,30 @@ protected:
qreal m_particleEndSize;
qreal m_particleSizeVariation;
+ qreal m_speedFromMovement;
+ int m_startTime;
+ bool m_overwrite;
+
int m_burstLeft;//TODO: Rename to pulse
QList<QPair<int, QPointF > > m_burstQueue;
int m_maxParticleCount;
+
+ //Used in default implementation, but might be useful
+ qreal m_speed_from_movement;
+
+ int m_particle_count;
+ bool m_reset_last;
+ qreal m_last_timestamp;
+ qreal m_last_emission;
+
+ QPointF m_last_emitter;
+ QPointF m_last_last_emitter;
+ QPointF m_last_last_last_emitter;
+
+ bool isEmitConnected();
private:
QSGStochasticDirection m_nullVector;
+
};
QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgparticleextruder.cpp b/src/declarative/particles/qsgparticleextruder.cpp
index b51ab8b467..a390bb92ac 100644
--- a/src/declarative/particles/qsgparticleextruder.cpp
+++ b/src/declarative/particles/qsgparticleextruder.cpp
@@ -46,7 +46,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass Shape QSGParticleExtruder
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\brief The Shape element allows you to specify an area for affectors and emitter.
The base class is just a rectangle.
diff --git a/src/declarative/particles/qsgparticlepainter.cpp b/src/declarative/particles/qsgparticlepainter.cpp
index 4d795999a0..97333ff20b 100644
--- a/src/declarative/particles/qsgparticlepainter.cpp
+++ b/src/declarative/particles/qsgparticlepainter.cpp
@@ -45,7 +45,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass ParticlePainter QSGParticlePainter
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits ParticlePainter
\brief ParticlePainter elements allow you to specify how to paint particles.
diff --git a/src/declarative/particles/qsgparticlesmodule.cpp b/src/declarative/particles/qsgparticlesmodule.cpp
index 1bb06eae35..e6076b925f 100644
--- a/src/declarative/particles/qsgparticlesmodule.cpp
+++ b/src/declarative/particles/qsgparticlesmodule.cpp
@@ -42,7 +42,6 @@
#include "qsgangleddirection_p.h"
#include "qsgcustomparticle_p.h"
#include "qsgellipseextruder_p.h"
-#include "qsgemitter_p.h"
#include "qsgfollowemitter_p.h"
#include "qsgfriction_p.h"
#include "qsggravity_p.h"
@@ -67,20 +66,12 @@
#include "qsgwander_p.h"
#include "qsgtargetaffector_p.h"
#include "qsgcumulativedirection_p.h"
-#include "qsgcustomemitter_p.h"
-#include "qsgcustomaffector_p.h"
QT_BEGIN_NAMESPACE
void QSGParticlesModule::defineModule()
{
const char* uri = "QtQuick.Particles";
- //Debugging only exposition
- qmlRegisterType<QSGParticlePainter>(uri, 2, 0, "ParticlePainter");
- qmlRegisterType<QSGParticleEmitter>(uri, 2, 0, "ParticleEmitter");
- qmlRegisterType<QSGParticleExtruder>(uri, 2, 0, "ParticleExtruder");
- qmlRegisterType<QSGStochasticDirection>(uri, 2, 0, "NullVector");
- //Probably should be nocreate types
qmlRegisterType<QSGParticleSystem>(uri, 2, 0, "ParticleSystem");
@@ -89,8 +80,7 @@ void QSGParticlesModule::defineModule()
qmlRegisterType<QSGItemParticle>(uri, 2, 0, "ItemParticle");
qmlRegisterType<QSGModelParticle>(uri, 2, 0, "ModelParticle");
- qmlRegisterType<QSGBasicEmitter>(uri, 2, 0, "Emitter");//TODO: Rename BasicEmitter?
- qmlRegisterType<QSGCustomEmitter>(uri, 2, 0, "CustomEmitter");
+ qmlRegisterType<QSGParticleEmitter>(uri, 2, 0, "Emitter");
qmlRegisterType<QSGFollowEmitter>(uri, 2, 0, "FollowEmitter");
qmlRegisterType<QSGEllipseExtruder>(uri, 2, 0, "EllipseShape");
@@ -103,7 +93,6 @@ void QSGParticlesModule::defineModule()
qmlRegisterType<QSGCumulativeDirection>(uri, 2, 0, "CumulativeDirection");
qmlRegisterType<QSGParticleAffector>(uri, 2, 0, "Affector");//useful for the triggered signal
- qmlRegisterType<QSGCustomAffector>(uri, 2, 0, "CustomAffector");
qmlRegisterType<QSGWanderAffector>(uri, 2, 0, "Wander");
qmlRegisterType<QSGFrictionAffector>(uri, 2, 0, "Friction");
qmlRegisterType<QSGPointAttractorAffector>(uri, 2, 0, "PointAttractor");
@@ -112,6 +101,11 @@ void QSGParticlesModule::defineModule()
qmlRegisterType<QSGSpriteGoalAffector>(uri, 2, 0, "SpriteGoal");
qmlRegisterType<QSGTurbulenceAffector>(uri, 2, 0 , "Turbulence");
qmlRegisterType<QSGTargetAffector>(uri, 2, 0 , "Target");
+
+ //Exposed just for completeness
+ qmlRegisterType<QSGParticlePainter>(uri, 2, 0, "ParticlePainter");
+ qmlRegisterType<QSGParticleExtruder>(uri, 2, 0, "ParticleExtruder");
+ qmlRegisterType<QSGStochasticDirection>(uri, 2, 0, "NullVector");
}
QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgparticlesystem.cpp b/src/declarative/particles/qsgparticlesystem.cpp
index f48156315c..efd6c22bd9 100644
--- a/src/declarative/particles/qsgparticlesystem.cpp
+++ b/src/declarative/particles/qsgparticlesystem.cpp
@@ -57,7 +57,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass ParticleSystem QSGParticleSystem
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\brief The ParticleSystem brings together ParticlePainter, Emitter and Affector elements.
*/
@@ -478,7 +477,7 @@ float QSGParticleData::curSize()
{
if (!system || !lifeSpan)
return 0.0f;
- return size + (endSize - size) * (lifeLeft() / lifeSpan);
+ return size + (endSize - size) * (1 - (lifeLeft() / lifeSpan));
}
float QSGParticleData::lifeLeft()
diff --git a/src/declarative/particles/qsgpointattractor.cpp b/src/declarative/particles/qsgpointattractor.cpp
index cc4cac66a4..1a3c3c25c5 100644
--- a/src/declarative/particles/qsgpointattractor.cpp
+++ b/src/declarative/particles/qsgpointattractor.cpp
@@ -46,7 +46,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass PointAttractor QSGPointAttractorAffector
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits Affector
\brief The PointAttractor allows you to attract particles towards a specific point.
diff --git a/src/declarative/particles/qsgpointattractor_p.h b/src/declarative/particles/qsgpointattractor_p.h
index 932a3081d6..95716483ed 100644
--- a/src/declarative/particles/qsgpointattractor_p.h
+++ b/src/declarative/particles/qsgpointattractor_p.h
@@ -55,7 +55,7 @@ class QSGPointAttractorAffector : public QSGParticleAffector
//Like Gravitational singularity, but linear to distance instead of quadratic
//And affects ds/dt, not da/dt
Q_PROPERTY(qreal strength READ strength WRITE setStrength NOTIFY strengthChanged)
- Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
+ Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)//TODO: Change to pointX, pointY
Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
Q_PROPERTY(PhysicsAffects physics READ physics WRITE setPhysics NOTIFY physicsChanged)
Q_PROPERTY(Proportion proportionalToDistance READ proportionalToDistance WRITE setProportionalToDistance NOTIFY proportionalToDistanceChanged)
diff --git a/src/declarative/particles/qsgpointdirection.cpp b/src/declarative/particles/qsgpointdirection.cpp
index 0448ac9a7e..7cc0823eec 100644
--- a/src/declarative/particles/qsgpointdirection.cpp
+++ b/src/declarative/particles/qsgpointdirection.cpp
@@ -46,7 +46,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass PointDirection QSGPointDirection
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits StochasticDirection
\brief The PointDirection element allows you to specify a direction that varies in x and y components
diff --git a/src/declarative/particles/qsgspritegoal.cpp b/src/declarative/particles/qsgspritegoal.cpp
index 79fcf8188c..1837167813 100644
--- a/src/declarative/particles/qsgspritegoal.cpp
+++ b/src/declarative/particles/qsgspritegoal.cpp
@@ -50,7 +50,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass SpriteGoal QSGSpriteGoalAffector
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits Affector
\brief The SpriteGoal Affector allows you to change the state of a sprite or group of a particle.
diff --git a/src/declarative/particles/qsgstochasticdirection.cpp b/src/declarative/particles/qsgstochasticdirection.cpp
index f44b941578..cdbc9f15ad 100644
--- a/src/declarative/particles/qsgstochasticdirection.cpp
+++ b/src/declarative/particles/qsgstochasticdirection.cpp
@@ -45,7 +45,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass StochasticDirection QSGStochasticDirection
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\brief The StochasticDirection elements allow you to specify a vector space.
*/
diff --git a/src/declarative/particles/qsgtargeteddirection.cpp b/src/declarative/particles/qsgtargeteddirection.cpp
index 3e5d3e1628..696cdfa915 100644
--- a/src/declarative/particles/qsgtargeteddirection.cpp
+++ b/src/declarative/particles/qsgtargeteddirection.cpp
@@ -48,7 +48,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass TargetedDirection QSGTargetedDirection
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits StochasticDirection
\brief The TargetedDirection element allows you to specify a direction towards the target point
diff --git a/src/declarative/particles/qsgturbulence.cpp b/src/declarative/particles/qsgturbulence.cpp
index e9812d7825..003f3c12b6 100644
--- a/src/declarative/particles/qsgturbulence.cpp
+++ b/src/declarative/particles/qsgturbulence.cpp
@@ -49,7 +49,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass Turbulence QSGTurbulenceAffector
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits Affector
\brief The TurbulenceAffector is a bit of a hack and probably shouldn't be used yet.
diff --git a/src/declarative/particles/qsgwander.cpp b/src/declarative/particles/qsgwander.cpp
index 2d04d62eba..a4a4d2c9c5 100644
--- a/src/declarative/particles/qsgwander.cpp
+++ b/src/declarative/particles/qsgwander.cpp
@@ -45,7 +45,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass Wander QSGWanderAffector
\inqmlmodule QtQuick.Particles 2
- \since QtQuick.Particles 2.0
\inherits Affector
\brief The Wander affector allows particles to randomly vary their trajectory.