Refactor SpriteEngine out of StochasticEngine
authorAlan Alpert <alan.alpert@nokia.com>
Mon, 12 Sep 2011 23:39:11 +0000 (09:39 +1000)
committerQt by Nokia <qt-info@nokia.com>
Tue, 13 Sep 2011 02:53:33 +0000 (04:53 +0200)
Also add ParticleGroups which use only StochasticStates
Simplistic change for now, just to focus the API for the
particle system. ParticleGroup elements replace the particleStates
property on the system, and the term "group" is now used more
consistently.

Change-Id: I6456f9c521b8166ccd94ea953275557bcfbf6423
Reviewed-on: http://codereview.qt-project.org/4699
Reviewed-by: Alan Alpert <alan.alpert@nokia.com>
50 files changed:
examples/declarative/animation/basics/color-animation.qml
examples/declarative/flickr/flickr.qml
examples/declarative/minehunt/MinehuntCore/Explosion.qml
examples/declarative/particles/allsmiles/smilefactory.qml
examples/declarative/particles/allsmiles/spriteparticles.qml
examples/declarative/particles/asteroid/asteroid.qml
examples/declarative/particles/asteroid/blackhole.qml
examples/declarative/particles/trails/combustion.qml
examples/declarative/particles/trails/fireballs.qml
examples/declarative/particles/trails/fireworks.qml
examples/declarative/particles/trails/portal.qml
examples/declarative/particles/trails/turbulence.qml
examples/declarative/plasmapatrol/content/BlasterHardpoint.qml
examples/declarative/plasmapatrol/content/CannonHardpoint.qml
examples/declarative/plasmapatrol/content/Cruiser.qml
examples/declarative/plasmapatrol/content/Frigate.qml
examples/declarative/plasmapatrol/content/LaserHardpoint.qml
examples/declarative/plasmapatrol/content/PlasmaPatrolParticles.qml
examples/declarative/plasmapatrol/content/Sloop.qml
examples/declarative/plasmapatrol/plasmapatrol.qml
examples/declarative/samegame/SamegameCore/BoomBlock.qml
examples/declarative/samegame/SamegameCore/GameArea.qml
examples/declarative/snake/content/Cookie.qml
examples/declarative/snake/content/Link.qml
examples/declarative/toys/dynamicscene/dynamicscene.qml
src/declarative/items/qsgsprite.cpp
src/declarative/items/qsgsprite_p.h
src/declarative/items/qsgspriteengine.cpp
src/declarative/items/qsgspriteengine_p.h
src/declarative/items/qsgspriteimage.cpp
src/declarative/particles/particles.pri
src/declarative/particles/qsgcustomparticle.cpp
src/declarative/particles/qsgimageparticle.cpp
src/declarative/particles/qsgimageparticle_p.h
src/declarative/particles/qsgitemparticle.cpp
src/declarative/particles/qsgparticleaffector.cpp
src/declarative/particles/qsgparticleaffector_p.h
src/declarative/particles/qsgparticleemitter.cpp
src/declarative/particles/qsgparticleemitter_p.h
src/declarative/particles/qsgparticlegroup.cpp [new file with mode: 0644]
src/declarative/particles/qsgparticlegroup_p.h [new file with mode: 0644]
src/declarative/particles/qsgparticlepainter.cpp
src/declarative/particles/qsgparticlepainter_p.h
src/declarative/particles/qsgparticlesmodule.cpp
src/declarative/particles/qsgparticlesystem.cpp
src/declarative/particles/qsgparticlesystem_p.h
src/declarative/particles/qsgspritegoal.cpp
src/declarative/particles/qsgspritegoal_p.h
src/declarative/particles/qsgtrailemitter.cpp
src/declarative/particles/qsgtrailemitter_p.h

index a83dbab..9e0f29c 100644 (file)
@@ -86,7 +86,7 @@ Item {
             width: parent.width; height: parent.height/2
             ImageParticle {
                 source: "images/star.png"
-                particles: ["star"]
+                groups: ["star"]
                 color: "#00333333"
                 SequentialAnimation on opacity {
                     loops: Animation.Infinite
@@ -95,7 +95,7 @@ Item {
                 }
             }
             Emitter {
-                particle: "star"
+                group: "star"
                 anchors.fill: parent
                 emitRate: parent.width / 50
                 lifeSpan: 5000
index 14e4fca..4397d0a 100644 (file)
@@ -56,7 +56,7 @@ Item {
             id: bgParticles
             anchors.fill: parent
             ImageParticle {
-                particles: ["trail"]
+                groups: ["trail"]
                 source: "content/images/particle.png"
                 color: "#1A1A6F"
                 alpha: 0.1
@@ -64,7 +64,7 @@ Item {
                 blueVariation: 0.8
             }
             Emitter {
-                particle: "drops"
+                group: "drops"
                 width: parent.width
                 emitRate: 0.5
                 lifeSpan: 20000
@@ -75,7 +75,7 @@ Item {
             }
             TrailEmitter {
                 follow: "drops"
-                particle: "trail"
+                group: "trail"
                 emitRatePerParticle: 18
                 size: 32
                 endSize: 0
index 225c19d..af98ad1 100644 (file)
@@ -48,14 +48,14 @@ Item {
         width: 40
         height: 40
         ImageParticle {
-            particles: ["star"]
+            groups: ["star"]
             source: "file:MinehuntCore/pics/star.png" // TODO: Use qrc path once QTBUG-21129 is fixed
         }
         Emitter {
             id: particles
             emitting: false
             anchors.centerIn: parent
-            particle: "star"
+            group: "star"
             speed: AngledDirection { angleVariation: 360; magnitude: 150; magnitudeVariation: 50 }
             emitRate: 200
             z: 100
index fe65149..4b01862 100644 (file)
@@ -48,7 +48,7 @@ Rectangle{
     ParticleSystem{id:sys}
     ImageParticle{
         system: sys
-        particles: ["goingLeft", "goingRight"]
+        groups: ["goingLeft", "goingRight"]
         source: "content/singlesmile.png"
         rotation: 90
         rotationSpeed: 90
@@ -56,7 +56,7 @@ Rectangle{
     }
     ImageParticle{
         system: sys
-        particles: ["goingDown"]
+        groups: ["goingDown"]
         source: "content/squarefacespriteXX.png"
         yVector: PointDirection{ y: 0.5; yVariation: 0.25; xVariation: 0.25; }
         rotation: 180
@@ -85,7 +85,7 @@ Rectangle{
         y: 120
         system: sys
         enabled: false
-        particle: "goingRight"
+        group: "goingRight"
         speed: PointDirection{ x: 100 }
         lifeSpan: 4000
         emitRate: 2
@@ -97,7 +97,7 @@ Rectangle{
         y: 240
         system: sys
         enabled: false
-        particle: "goingLeft"
+        group: "goingLeft"
         speed: PointDirection{ x: -100 }
         lifeSpan: 4000
         emitRate: 2
@@ -109,7 +109,7 @@ Rectangle{
         y: 360
         system: sys
         enabled: false
-        particle: "goingDown"
+        group: "goingDown"
         speed: PointDirection{ x: 100 }
         lifeSpan: 4000
         emitRate: 2
index 705016e..0586dfd 100644 (file)
@@ -47,7 +47,7 @@ Rectangle{
     height: 400
     ImageParticle{
         id: test
-        particles: ["Test"]
+        groups: ["Test"]
         source: "content/particle.png"
         system: sys
         z: 2
@@ -57,7 +57,7 @@ Rectangle{
     }
     ImageParticle{
         id: single
-        particles: ["Face"]
+        groups: ["Face"]
         system: sys
         z: 2
         anchors.fill: parent
@@ -73,7 +73,7 @@ Rectangle{
     }
     Emitter{
         system: sys
-        particle: "Test"
+        group: "Test"
         anchors.fill: parent
         id: particles2
         emitRate: 6000
@@ -83,7 +83,7 @@ Rectangle{
     }
     Emitter{
         system: sys
-        particle: "Face"
+        group: "Face"
         anchors.fill: parent
         id: particles
         emitRate: 60
index ea2fabd..6d55699 100644 (file)
@@ -67,7 +67,7 @@ Item {
     }
     ImageParticle {
         system: sys
-        particles: ["starfield"]
+        groups: ["starfield"]
         source: "content/star.png"
         colorVariation: 0.3
         color: "white"
@@ -75,7 +75,7 @@ Item {
     Emitter {
         id: starField
         system: sys
-        particle: "starfield"
+        group: "starfield"
 
         emitRate: 80
         lifeSpan: 2500
@@ -91,7 +91,7 @@ Item {
     }
     Emitter{
         system: sys
-        particle: "meteor"
+        group: "meteor"
         emitRate: 12
         lifeSpan: 5000
         acceleration: PointDirection{ xVariation: 80; yVariation: 80; }
@@ -101,7 +101,7 @@ Item {
      }
     ImageParticle{
         system: sys
-        particles: ["meteor"]
+        groups: ["meteor"]
         sprites:[Sprite{
                 id: spinState
                 name: "spinning"
@@ -126,7 +126,7 @@ Item {
         ]
     }
     SpriteGoal{
-        particles: ["meteor"]
+        groups: ["meteor"]
         system: sys
         goalState: "explode"
         jump: true
@@ -170,7 +170,7 @@ Item {
     ImageParticle{
         z:0 
         system: sys
-        particles: ["exhaust"]
+        groups: ["exhaust"]
         source: "content/particle4.png"
 
         color: "orange"
@@ -193,7 +193,7 @@ Item {
     Emitter{
         id: trailsNormal2
         system: sys
-        particle: "exhaust"
+        group: "exhaust"
 
         emitRate: 300
         lifeSpan: 500
index 7e8a7a9..00fca7e 100644 (file)
@@ -66,7 +66,7 @@ Rectangle{
     }
 
     Emitter{
-        particle: "stars"
+        group: "stars"
         system: particles
         emitRate: 40
         lifeSpan: 4000
@@ -77,7 +77,7 @@ Rectangle{
         height: parent.height
     }
     Emitter{
-        particle: "roids"
+        group: "roids"
         system: particles
         emitRate: 10
         lifeSpan: 4000
@@ -93,7 +93,7 @@ Rectangle{
     }
     ImageParticle{
         id: stars
-        particles: ["stars"]
+        groups: ["stars"]
         system: particles
         source: "content/star.png"
         color: "white"
@@ -102,7 +102,7 @@ Rectangle{
     }
     ImageParticle{
         id: roids
-        particles: ["roids"]
+        groups: ["roids"]
         system: particles
         sprites: Sprite{
             id: spinState
@@ -115,7 +115,7 @@ Rectangle{
     }
     ImageParticle{
         id: shot
-        particles: ["shot"]
+        groups: ["shot"]
         system: particles
         source: "content/star.png"
 
@@ -124,7 +124,7 @@ Rectangle{
     }
     ImageParticle{
         id: engine
-        particles: ["engine"]
+        groups: ["engine"]
         system: particles
         source: "content/particle4.png"
 
@@ -170,7 +170,7 @@ Rectangle{
             drag.target: ship
         }
         Emitter{
-            particle: "engine"
+            group: "engine"
             system: particles
             emitRate: 200
             lifeSpan: 1000
@@ -182,7 +182,7 @@ Rectangle{
             width: 20
         }
         Emitter{
-            particle: "shot"
+            group: "shot"
             system: particles
             emitRate: 32
             lifeSpan: 2000
index e4a21e9..238dbe8 100644 (file)
@@ -57,71 +57,67 @@ Rectangle {
     ParticleSystem{
         id: particles
         anchors.fill: parent
+        ParticleGroup{
+            name: "unlit"
+            duration: 1000
+            to: {"lighting":1, "unlit":99}
+            ImageParticle{
+                source: "content/particleA.png"
+                colorVariation: 0.1
+                color: "#2060160f"
+            }
+            SpriteGoal{
+                whenCollidingWith: ["lit"]
+                goalState: "lighting"
+                jump: true
+                systemStates: true
+            }
+        }
+        ParticleGroup{
+            name: "lighting"
+            duration: 100
+            to: {"lit":1}
+        }
+        ParticleGroup{
+            name: "lit"
+            duration: 10000
+            onEntered: score++;
+            TrailEmitter{
+                id: fireballFlame
+                group: "flame"
 
+                emitRatePerParticle: 48
+                lifeSpan: 200
+                emitWidth: 8
+                emitHeight: 8
 
-        particleStates:[
-            Sprite{
-                name: "unlit"
-                duration: 1000
-                to: {"lighting":1, "unlit":99}
-                ImageParticle{
-                    source: "content/particleA.png"
-                    colorVariation: 0.1
-                    color: "#2060160f"
-                }
-                SpriteGoal{
-                    whenCollidingWith: ["lit"]
-                    goalState: "lighting"
-                    jump: true
-                    systemStates: true
-                }
-            },
-            Sprite{
-                name: "lighting"
-                duration: 100
-                to: {"lit":1}
-            },
-            Sprite{
-                name: "lit"
-                duration: 10000
-                onEntered: score++;
-                TrailEmitter{
-                    id: fireballFlame
-                    particle: "flame"
-
-                    emitRatePerParticle: 48
-                    lifeSpan: 200
-                    emitWidth: 8
-                    emitHeight: 8
-
-                    size: 24
-                    sizeVariation: 8
-                    endSize: 4
-                }
+                size: 24
+                sizeVariation: 8
+                endSize: 4
+            }
 
-                TrailEmitter{
-                    id: fireballSmoke
-                    particle: "smoke"
+            TrailEmitter{
+                id: fireballSmoke
+                group: "smoke"
 
-                    emitRatePerParticle: 120
-                    lifeSpan: 2000
-                    emitWidth: 16
-                    emitHeight: 16
+                emitRatePerParticle: 120
+                lifeSpan: 2000
+                emitWidth: 16
+                emitHeight: 16
 
-                    speed: PointDirection{yVariation: 16; xVariation: 16}
-                    acceleration: PointDirection{y: -16}
+                speed: PointDirection{yVariation: 16; xVariation: 16}
+                acceleration: PointDirection{y: -16}
 
-                    size: 24
-                    sizeVariation: 8
-                    endSize: 8
-                }
+                size: 24
+                sizeVariation: 8
+                endSize: 8
             }
-        ]
+        }
 
         ImageParticle{
             id: smoke
             anchors.fill: parent
-            particles: ["smoke"]
+            groups: ["smoke"]
             source: "content/particle.png"
             colorVariation: 0
             color: "#00111111"
@@ -129,7 +125,7 @@ Rectangle {
         ImageParticle{
             id: pilot
             anchors.fill: parent
-            particles: ["pilot"]
+            groups: ["pilot"]
             source: "content/particle.png"
             redVariation: 0.01
             blueVariation: 0.4
@@ -138,7 +134,7 @@ Rectangle {
         ImageParticle{
             id: flame
             anchors.fill: parent
-            particles: ["flame", "lit", "lighting"]
+            groups: ["flame", "lit", "lighting"]
             source: "content/particleA.png"
             colorVariation: 0.1
             color: "#00ff400f"
@@ -152,14 +148,14 @@ Rectangle {
             sizeVariation: 4
             speed: PointDirection{x:120; xVariation: 80; yVariation: 50}
             acceleration: PointDirection{y:120}
-            particle: "unlit"
+            group: "unlit"
         }
 
         Emitter{
             id: flamer
             x: 100
             y: 300
-            particle: "pilot"
+            group: "pilot"
             emitRate: 80
             lifeSpan: 600
             size: 24
@@ -167,7 +163,7 @@ Rectangle {
             endSize: 0
             speed: PointDirection{ y:-100; yVariation: 4; xVariation: 4 }
             SpriteGoal{
-                particles: ["unlit"]
+                groups: ["unlit"]
                 goalState: "lit"
                 jump: true
                 systemStates: true
@@ -181,7 +177,7 @@ Rectangle {
         }
         //Click to enflame
         SpriteGoal{//TODO: Aux emiiters in the state definition (which allows the occasional ball to spontaneously combust)
-            particles: ["unlit"]
+            groups: ["unlit"]
             goalState: "lighting"
             jump: true
             systemStates: true
index 97a0c0a..c7c0420 100644 (file)
@@ -55,7 +55,7 @@ Rectangle {
     ImageParticle{
         id: fireball
         anchors.fill: parent
-        particles: ["E"]
+        groups: ["E"]
         system: particles
         source: "content/particleA.png"
         colorVariation: 0.2
@@ -66,7 +66,7 @@ Rectangle {
         id: smoke
         system: particles
         anchors.fill: parent
-        particles: ["A", "B"]
+        groups: ["A", "B"]
         source: "content/particle.png"
         colorVariation: 0
         color: "#00111111"
@@ -75,7 +75,7 @@ Rectangle {
         id: flame
         anchors.fill: parent
         system: particles
-        particles: ["C", "D"]
+        groups: ["C", "D"]
         source: "content/particle.png"
         colorVariation: 0.1
         color: "#00ff400f"
@@ -83,7 +83,7 @@ Rectangle {
     Emitter{
         id: fire
         system: particles
-        particle: "C"
+        group: "C"
 
         y: parent.height
         width: parent.width
@@ -100,7 +100,7 @@ Rectangle {
     }
     TrailEmitter{
         id: fireSmoke
-        particle: "B"
+        group: "B"
         system: particles
         follow: "C"
         width: root.width
@@ -120,7 +120,7 @@ Rectangle {
         id: fireballFlame
         anchors.fill: parent
         system: particles
-        particle: "D"
+        group: "D"
         follow: "E"
 
         emitRatePerParticle: 120
@@ -137,7 +137,7 @@ Rectangle {
         id: fireballSmoke
         anchors.fill: parent
         system: particles
-        particle: "A"
+        group: "A"
         follow: "E"
 
         emitRatePerParticle: 128
@@ -155,7 +155,7 @@ Rectangle {
     Emitter{
         id: balls
         system: particles
-        particle: "E"
+        group: "E"
 
         y: parent.height
         width: parent.width
index 437d9ee..6b370b3 100644 (file)
@@ -48,36 +48,34 @@ Rectangle{
     ParticleSystem{
         anchors.fill: parent
         id: syssy
-        particleStates:[
-            Sprite{
-                name: "fire"
-                duration: 2000
-                durationVariation: 2000
-                to: {"splode":1}
-            },
-            Sprite{
-                name: "splode"
-                duration: 400
-                to: {"dead":1}
-                TrailEmitter{
-                    particle: "works"
-                    emitRatePerParticle: 100
-                    lifeSpan: 1000
-                    maximumEmitted: 1200
-                    size: 8
-                    speed: AngleDirection{angle: 270; angleVariation: 45; magnitude: 20; magnitudeVariation: 20;}
-                    acceleration: PointDirection{y:100; yVariation: 20}
-                }
-            },
-            Sprite{
-                name: "dead"
-                duration: 1000
-                Affector{
-                    once: true
-                    onAffected: worksEmitter.burst(400,x,y)
-                }
+        ParticleGroup{
+            name: "fire"
+            duration: 2000
+            durationVariation: 2000
+            to: {"splode":1}
+        }
+        ParticleGroup{
+            name: "splode"
+            duration: 400
+            to: {"dead":1}
+            TrailEmitter{
+                group: "works"
+                emitRatePerParticle: 100
+                lifeSpan: 1000
+                maximumEmitted: 1200
+                size: 8
+                speed: AngleDirection{angle: 270; angleVariation: 45; magnitude: 20; magnitudeVariation: 20;}
+                acceleration: PointDirection{y:100; yVariation: 20}
+            }
+        }
+        ParticleGroup{
+            name: "dead"
+            duration: 1000
+            Affector{
+                once: true
+                onAffected: worksEmitter.burst(400,x,y)
             }
-        ]
+        }
         Timer{
             interval: 6000
             running: true
@@ -87,7 +85,7 @@ Rectangle{
         }
         Emitter{
             id: startingEmitter
-            particle: "fire"
+            group: "fire"
             width: parent.width
             y: parent.height
             enabled: false
@@ -98,7 +96,7 @@ Rectangle{
         }
         Emitter{
             id: worksEmitter
-            particle: "works"
+            group: "works"
             enabled: false
             emitRate: 100
             lifeSpan: 1600
@@ -111,7 +109,7 @@ Rectangle{
             acceleration: PointDirection{y:100; yVariation: 20}
         }
         ImageParticle{
-            particles: ["works", "fire", "splode"]
+            groups: ["works", "fire", "splode"]
             source: "content/particle.png"
             entryEffect: ImageParticle.Scale
         }
index 85efd9a..adf620f 100644 (file)
@@ -54,7 +54,7 @@ Rectangle{
         id: particles 
     }
     ImageParticle{
-        particles: ["center","edge"]
+        groups: ["center","edge"]
         anchors.fill: parent
         system: particles
         source: "content/particle.png"
@@ -63,7 +63,7 @@ Rectangle{
     }
     Emitter{
         anchors.fill: parent
-        particle: "center"
+        group: "center"
         system: particles
         emitRate: 200
         lifeSpan: 2000
@@ -80,7 +80,7 @@ Rectangle{
     }
     Emitter{
         anchors.fill: parent
-        particle: "edge"
+        group: "edge"
         startTime: 2000
         system: particles
         emitRate: 4000
index 104bb10..13eae16 100644 (file)
@@ -71,14 +71,14 @@ Rectangle{
         strength: 32
     }
     ImageParticle{
-        particles: ["smoke"]
+        groups: ["smoke"]
         system: ps
         source: "content/particle.png"
         color: "#11111111"
         colorVariation: 0
     }
     ImageParticle{
-        particles: ["flame"]
+        groups: ["flame"]
         system: ps
         source: "content/particle.png"
         color: "#11ff400f"
@@ -87,7 +87,7 @@ Rectangle{
     Emitter{
         anchors.centerIn: parent
         system: ps
-        particle: "flame"
+        group: "flame"
         
         emitRate: 120
         lifeSpan: 1200
@@ -102,7 +102,7 @@ Rectangle{
         width: root.width
         height: root.height/2 - 20
         system: ps
-        particle: "smoke"
+        group: "smoke"
         follow: "flame"
 
         emitRatePerParticle: 1
@@ -119,7 +119,7 @@ Rectangle{
         width: root.width
         height: root.height/2 - 40
         system: ps
-        particle: "smoke"
+        group: "smoke"
         follow: "flame"
         
         emitRatePerParticle: 4
index 384275f..3e751f4 100644 (file)
@@ -55,7 +55,7 @@ Item {
     height: 24
     Emitter{
         id: visualization
-        particle: "blaster"
+        group: "blaster"
         system: container.system
         enabled: show
         anchors.fill: parent
@@ -114,7 +114,7 @@ Item {
     }
     Emitter{
         id: emitter
-        particle: "blaster"
+        group: "blaster"
         enabled: false
         system: container.system
         anchors.centerIn: parent
index b2c7aca..dc15f0c 100644 (file)
@@ -51,7 +51,7 @@ Item {
     height: 24
     Emitter{
         id: visualization
-        particle: "cannon"
+        group: "cannon"
         enabled: container.show
         system: container.system
         anchors.centerIn: parent
@@ -80,7 +80,7 @@ Item {
     }
     Emitter{
         id: emitter
-        particle: "cannon"
+        group: "cannon"
         enabled: false
         system: container.system
         anchors.centerIn: parent
index b0d2002..a4983fc 100644 (file)
@@ -58,7 +58,7 @@ Item {
         //TODO: Cooler would be an 'orbiting' affector
         //TODO: On the subject, opacity and size should be grouped type 'overLife' if we can cram that in the particles
         system: container.system
-        particle: container.shipParticle
+        group: container.shipParticle
         anchors.centerIn: parent
         width: 64
         height: 64
@@ -76,7 +76,7 @@ Item {
     }
     Emitter{
         system: container.system
-        particle: "cruiserArmor"
+        group: "cruiserArmor"
         anchors.fill: parent
         shape: EllipseShape{ fill: false }
         enabled: hp>0
@@ -92,7 +92,7 @@ Item {
             system: container.system
             enabled: container.hp <=0
             anchors.fill: parent
-            particles: ["cruiserArmor"]
+            groups: ["cruiserArmor"]
             goalState: "death"
 //            jump: true
             once: true
index 8d493b8..f26e7e8 100644 (file)
@@ -56,7 +56,7 @@ Item {
     height: 128
     Emitter{
         system: container.system
-        particle: "frigateShield"
+        group: "frigateShield"
         anchors.centerIn: parent
         size: 92
         emitRate: 1
@@ -65,7 +65,7 @@ Item {
     }
     Emitter{
         system: container.system
-        particle: container.shipParticle
+        group: container.shipParticle
         anchors.centerIn: parent
         width: 64 
         height: 16
index 45712bf..56fd91b 100644 (file)
@@ -51,7 +51,7 @@ Item {
     height: 24
     Emitter{
         id: visualization
-        particle: "laser"
+        group: "laser"
         system: container.system
         anchors.fill: parent
         enabled: container.show
@@ -86,7 +86,7 @@ Item {
     }
     Emitter{
         id: emitter
-        particle: "laser"
+        group: "laser"
         enabled: false
         system: container.system
         x: Math.min(container.width/2, target.x);
index 792ba7a..7a8c3e6 100644 (file)
@@ -45,7 +45,7 @@ Item{
     property ParticleSystem sys
     ImageParticle{
         system: sys
-        particles: ["default"]
+        groups: ["default"]
         source: "pics/blur-circle3.png"
         color: "#003A3A3A"
         colorVariation: 0.1
@@ -53,7 +53,7 @@ Item{
     }
     ImageParticle{
         system: sys
-        particles: ["redTeam"]
+        groups: ["redTeam"]
         source: "pics/blur-circle3.png"
         color: "#0028060A"
         colorVariation: 0.1
@@ -61,7 +61,7 @@ Item{
     }
     ImageParticle{
         system: sys
-        particles: ["greenTeam"]
+        groups: ["greenTeam"]
         source: "pics/blur-circle3.png"
         color: "#0006280A"
         colorVariation: 0.1
@@ -69,7 +69,7 @@ Item{
     }
     ImageParticle{
         system: sys
-        particles: ["blaster"]
+        groups: ["blaster"]
         source: "pics/star2.png"
         //color: "#0F282406"
         color: "#0F484416"
@@ -78,7 +78,7 @@ Item{
     }
     ImageParticle{
         system: sys
-        particles: ["laser"]
+        groups: ["laser"]
         source: "pics/star3.png"
         //color: "#00123F68"
         color: "#00428FF8"
@@ -87,7 +87,7 @@ Item{
     }
     ImageParticle{
         system: sys
-        particles: ["cannon"]
+        groups: ["cannon"]
         source: "pics/particle.png"
         color: "#80FFAAFF"
         colorVariation: 0.1
@@ -95,7 +95,7 @@ Item{
     }
     ImageParticle{
         system: sys
-        particles: ["cannonCore"]
+        groups: ["cannonCore"]
         source: "pics/particle.png"
         color: "#00666666"
         colorVariation: 0.8
@@ -103,7 +103,7 @@ Item{
     }
     ImageParticle{
         system: sys
-        particles: ["cannonWake"]
+        groups: ["cannonWake"]
         source: "pics/star.png"
         color: "#00CCCCCC"
         colorVariation: 0.2
@@ -111,7 +111,7 @@ Item{
     }
     ImageParticle{
         system: sys
-        particles: ["frigateShield"]
+        groups: ["frigateShield"]
         source: "pics/blur-circle2.png"
         color: "#00000000"
         colorVariation: 0.05
@@ -121,7 +121,7 @@ Item{
     }
     ImageParticle{
         system: sys
-        particles: ["cruiserArmor"]
+        groups: ["cruiserArmor"]
         z: 1
         sprites:[Sprite{
                 id: spinState
@@ -146,7 +146,7 @@ Item{
     }
     TrailEmitter{
         system: sys
-        particle: "cannonWake"
+        group: "cannonWake"
         follow: "cannon"
         emitRatePerParticle: 64
         lifeSpan: 600
@@ -160,7 +160,7 @@ Item{
     }
     TrailEmitter{
         system: sys
-        particle: "cannonCore"
+        group: "cannonCore"
         follow: "cannon"
         emitRatePerParticle: 256
         lifeSpan: 128
index 82e57f5..59678a7 100644 (file)
@@ -60,7 +60,7 @@ Item {
         //TODO: Cooler would be an 'orbiting' affector
         //TODO: On the subject, opacity and size should be grouped type 'overLife' if we can cram that in the particles
         system: container.system
-        particle: container.shipParticle
+        group: container.shipParticle
         shape: EllipseShape{}
 
         emitRate: hp > 0 ?  hp + 20 : 0 
index 4ea464b..2fa9f44 100644 (file)
@@ -97,7 +97,7 @@ Rectangle {
                         anchors.fill: parent
                         system: particles
                         enabled: true
-                        particle: "default"
+                        group: "default"
                         emitRate: 1200
                         lifeSpan: 1200
                         shape: MaskShape{source:"content/pics/TitleText.png"}
index 1c84fa8..df3e9bd 100644 (file)
@@ -75,7 +75,7 @@ Item {
     Emitter {
         id: particles
         system: particleSystem
-        particle: { 
+        group: { 
             if(type == 0){
                 "red";
             } else if (type == 1) {
index 967e299..9a8f68a 100644 (file)
@@ -65,21 +65,21 @@ Item {
         id: particleSystem;
         z:2
         ImageParticle {
-            particles: ["red"]
+            groups: ["red"]
             color: Qt.darker("red");//Actually want desaturated...
             source: "pics/particle.png"
             colorVariation: 0.4
             alpha: 0.1
         }
         ImageParticle {
-            particles: ["green"]
+            groups: ["green"]
             color: Qt.darker("green");//Actually want desaturated...
             source: "pics/particle.png"
             colorVariation: 0.4
             alpha: 0.1
         }
         ImageParticle {
-            particles: ["blue"]
+            groups: ["blue"]
             color: Qt.darker("blue");//Actually want desaturated...
             source: "pics/particle.png"
             colorVariation: 0.4
index e3b3bbf..d9fedd9 100644 (file)
@@ -71,13 +71,13 @@ Item  {
     ParticleSystem {
         width:1; height:1; anchors.centerIn: parent;
         ImageParticle {
-            particles: ["star"]
+            groups: ["star"]
             source: "pics/yellowStar.png"
         }
         Emitter {
             id: particles
             anchors.fill: parent
-            particle: "star"
+            group: "star"
             emitRate: 50
             emitting: false
             lifeSpan: 700
index 82e0359..31ad622 100644 (file)
@@ -96,13 +96,13 @@ Item { id:link
     ParticleSystem {
         width:1; height:1; anchors.centerIn: parent;
         ImageParticle {
-            particles: ["star"]
+            groups: ["star"]
             source: type == 1 ? "pics/blueStar.png" : "pics/redStar.png"
         }
         Emitter {
             id: particles
             anchors.fill: parent
-            particle: "star"
+            group: "star"
             emitRate: 50
             emitting: false
             lifeSpan: 700
index 5670aac..179d633 100644 (file)
@@ -104,7 +104,7 @@ Item {
         ImageParticle {
             id: stars
             source: "content/images/star.png"
-            particles: ["stars"]
+            groups: ["stars"]
             opacity: .5
         }
 
@@ -113,7 +113,7 @@ Item {
             anchors.fill: parent
             emitRate: parent.width / 50
             lifeSpan: 5000
-            particle: "stars"
+            group: "stars"
         }
     }
 
index 806f7a9..63d1951 100644 (file)
 ****************************************************************************/
 
 #include "qsgsprite_p.h"
-//TODO: Split out particle system dependency
-#include "qsgparticlesystem_p.h"
 #include <QDebug>
 
 QT_BEGIN_NAMESPACE
 
 QSGSprite::QSGSprite(QObject *parent) :
-    QObject(parent)
+    QSGStochasticState(parent)
     , m_generatedCount(0)
     , m_framesPerRow(0)
-    , m_frames(1)
     , m_frameHeight(0)
     , m_frameWidth(0)
-    , m_duration(1000)
 {
 }
 
-void redirectError(QDeclarativeListProperty<QObject> *prop, QObject *value)
-{
-    qWarning() << "Could not add " << value << " to state" << prop->object << "as it is not associated with a particle system.";
-}
-
-QDeclarativeListProperty<QObject> QSGSprite::particleChildren()
-{
-    QSGParticleSystem* system = qobject_cast<QSGParticleSystem*>(parent());
-    if (system)
-        return QDeclarativeListProperty<QObject>(this, 0, &QSGParticleSystem::stateRedirect);
-    else
-        return QDeclarativeListProperty<QObject>(this, 0, &redirectError);
-}
-
-int QSGSprite::variedDuration() const
-{
-    return m_duration
-            + (m_durationVariance * ((qreal)qrand()/RAND_MAX) * 2)
-            - m_durationVariance;
-}
-
 QT_END_NAMESPACE
index c18e9b4..ed7c6c4 100644 (file)
@@ -46,6 +46,7 @@
 #include <QUrl>
 #include <QVariantMap>
 #include <QDeclarativeListProperty>
+#include "qsgspriteengine_p.h"
 
 QT_BEGIN_HEADER
 
@@ -54,38 +55,23 @@ QT_BEGIN_NAMESPACE
 QT_MODULE(Declarative)
 
 
-class QSGSprite : public QObject
+class QSGSprite : public QSGStochasticState
 {
     Q_OBJECT
-    Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
     Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
-    Q_PROPERTY(int frames READ frames WRITE setFrames NOTIFY framesChanged)
-    //If frame height or width is not specified, it is assumed to be a single long row of frames.
+    //If frame height or width is not specified, it is assumed to be a single long row of square frames.
     //Otherwise, it can be multiple contiguous rows, when one row runs out the next will be used.
     Q_PROPERTY(int frameHeight READ frameHeight WRITE setFrameHeight NOTIFY frameHeightChanged)
     Q_PROPERTY(int frameWidth READ frameWidth WRITE setFrameWidth NOTIFY frameWidthChanged)
-    Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
-    Q_PROPERTY(int durationVariation READ durationVariance WRITE setDurationVariance NOTIFY durationVarianceChanged)
-    Q_PROPERTY(qreal speedModifiesDuration READ speedModifer WRITE setSpeedModifier NOTIFY speedModifierChanged)
-    Q_PROPERTY(QVariantMap to READ to WRITE setTo NOTIFY toChanged)
 
-    Q_PROPERTY(QDeclarativeListProperty<QObject> particleChildren READ particleChildren DESIGNABLE false)//### Hidden property for in-state system definitions - ought not to be used in actual "Sprite" states
-    Q_CLASSINFO("DefaultProperty", "particleChildren")
 public:
     explicit QSGSprite(QObject *parent = 0);
 
-    QDeclarativeListProperty<QObject> particleChildren();
-
     QUrl source() const
     {
         return m_source;
     }
 
-    int frames() const
-    {
-        return m_frames;
-    }
-
     int frameHeight() const
     {
         return m_frameHeight;
@@ -96,55 +82,15 @@ public:
         return m_frameWidth;
     }
 
-    int duration() const
-    {
-        return m_duration;
-    }
-
-    QString name() const
-    {
-        return m_name;
-    }
-
-    QVariantMap to() const
-    {
-        return m_to;
-    }
-
-    qreal speedModifer() const
-    {
-        return m_speedModifier;
-    }
-
-    int durationVariance() const
-    {
-        return m_durationVariance;
-    }
-
-    int variedDuration() const;
 
 signals:
 
     void sourceChanged(QUrl arg);
 
-    void framesChanged(int arg);
-
     void frameHeightChanged(int arg);
 
     void frameWidthChanged(int arg);
 
-    void durationChanged(int arg);
-
-    void nameChanged(QString arg);
-
-    void toChanged(QVariantMap arg);
-
-    void speedModifierChanged(qreal arg);
-
-    void durationVarianceChanged(int arg);
-
-    void entered();//### Just playing around - don't expect full state API
-
 public slots:
 
     void setSource(QUrl arg)
@@ -155,14 +101,6 @@ public slots:
         }
     }
 
-    void setFrames(int arg)
-    {
-        if (m_frames != arg) {
-            m_frames = arg;
-            emit framesChanged(arg);
-        }
-    }
-
     void setFrameHeight(int arg)
     {
         if (m_frameHeight != arg) {
@@ -179,60 +117,16 @@ public slots:
         }
     }
 
-    void setDuration(int arg)
-    {
-        if (m_duration != arg) {
-            m_duration = arg;
-            emit durationChanged(arg);
-        }
-    }
-
-    void setName(QString arg)
-    {
-        if (m_name != arg) {
-            m_name = arg;
-            emit nameChanged(arg);
-        }
-    }
-
-    void setTo(QVariantMap arg)
-    {
-        if (m_to != arg) {
-            m_to = arg;
-            emit toChanged(arg);
-        }
-    }
-
-    void setSpeedModifier(qreal arg)
-    {
-        if (m_speedModifier != arg) {
-            m_speedModifier = arg;
-            emit speedModifierChanged(arg);
-        }
-    }
-
-    void setDurationVariance(int arg)
-    {
-        if (m_durationVariance != arg) {
-            m_durationVariance = arg;
-            emit durationVarianceChanged(arg);
-        }
-    }
 
 private:
     friend class QSGImageParticle;
     friend class QSGSpriteEngine;
+    friend class QSGStochasticEngine;
     int m_generatedCount;
     int m_framesPerRow;
     QUrl m_source;
-    int m_frames;
     int m_frameHeight;
     int m_frameWidth;
-    int m_duration;
-    QString m_name;
-    QVariantMap m_to;
-    qreal m_speedModifier;
-    int m_durationVariance;
 
 };
 
index 1915db6..0391ce1 100644 (file)
@@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE
    Also solve the state data initialization/transfer issue so as to not need to make friends
 */
 
-QSGSpriteEngine::QSGSpriteEngine(QObject *parent) :
+QSGStochasticEngine::QSGStochasticEngine(QObject *parent) :
     QObject(parent), m_timeOffset(0)
 {
     //Default size 1
@@ -61,7 +61,7 @@ QSGSpriteEngine::QSGSpriteEngine(QObject *parent) :
     m_advanceTime.start();
 }
 
-QSGSpriteEngine::QSGSpriteEngine(QList<QSGSprite*> states, QObject *parent) :
+QSGStochasticEngine::QSGStochasticEngine(QList<QSGStochasticState*> states, QObject *parent) :
     QObject(parent), m_states(states), m_timeOffset(0)
 {
     //Default size 1
@@ -69,10 +69,27 @@ QSGSpriteEngine::QSGSpriteEngine(QList<QSGSprite*> states, QObject *parent) :
     m_advanceTime.start();
 }
 
+QSGStochasticEngine::~QSGStochasticEngine()
+{
+}
+
+QSGSpriteEngine::QSGSpriteEngine(QObject *parent)
+    : QSGStochasticEngine(parent)
+{
+}
+
+QSGSpriteEngine::QSGSpriteEngine(QList<QSGSprite*> sprites, QObject *parent)
+    : QSGStochasticEngine(parent)
+{
+    foreach (QSGSprite* sprite, sprites)
+        m_states << (QSGStochasticState*)sprite;
+}
+
 QSGSpriteEngine::~QSGSpriteEngine()
 {
 }
 
+
 int QSGSpriteEngine::maxFrames()
 {
     return m_maxFrames;
@@ -87,46 +104,46 @@ TODO: Above idea needs to have the varying duration offset added to it
 */
 int QSGSpriteEngine::spriteState(int sprite)
 {
-    int state = m_sprites[sprite];
-    if (!m_states[state]->m_generatedCount)
+    int state = m_things[sprite];
+    if (!m_sprites[state]->m_generatedCount)
         return state;
-    int rowDuration = m_duration[sprite] * m_states[state]->m_framesPerRow;
+    int rowDuration = m_duration[sprite] * m_sprites[state]->m_framesPerRow;
     int extra = (m_timeOffset - m_startTimes[sprite])/rowDuration;
     return state + extra;
 }
 
 int QSGSpriteEngine::spriteStart(int sprite)
 {
-    int state = m_sprites[sprite];
-    if (!m_states[state]->m_generatedCount)
+    int state = m_things[sprite];
+    if (!m_sprites[state]->m_generatedCount)
         return m_startTimes[sprite];
-    int rowDuration = m_duration[sprite] * m_states[state]->m_framesPerRow;
+    int rowDuration = m_duration[sprite] * m_sprites[state]->m_framesPerRow;
     int extra = (m_timeOffset - m_startTimes[sprite])/rowDuration;
     return state + extra*rowDuration;
 }
 
 int QSGSpriteEngine::spriteFrames(int sprite)
 {
-    int state = m_sprites[sprite];
-    if (!m_states[state]->m_generatedCount)
-        return m_states[state]->frames();
-    int rowDuration = m_duration[sprite] * m_states[state]->m_framesPerRow;
+    int state = m_things[sprite];
+    if (!m_sprites[state]->m_generatedCount)
+        return m_sprites[state]->frames();
+    int rowDuration = m_duration[sprite] * m_sprites[state]->m_framesPerRow;
     int extra = (m_timeOffset - m_startTimes[sprite])/rowDuration;
-    if (extra == m_states[state]->m_generatedCount - 1)//last state
-        return m_states[state]->frames() % m_states[state]->m_framesPerRow;
+    if (extra == m_sprites[state]->m_generatedCount - 1)//last state
+        return m_sprites[state]->frames() % m_sprites[state]->m_framesPerRow;
     else
-        return m_states[state]->m_framesPerRow;
+        return m_sprites[state]->m_framesPerRow;
 }
 
 int QSGSpriteEngine::spriteDuration(int sprite)
 {
-    int state = m_sprites[sprite];
-    if (!m_states[state]->m_generatedCount)
+    int state = m_things[sprite];
+    if (!m_sprites[state]->m_generatedCount)
         return m_duration[sprite];
-    int rowDuration = m_duration[sprite] * m_states[state]->m_framesPerRow;
+    int rowDuration = m_duration[sprite] * m_sprites[state]->m_framesPerRow;
     int extra = (m_timeOffset - m_startTimes[sprite])/rowDuration;
-    if (extra == m_states[state]->m_generatedCount - 1)//last state
-        return (m_duration[sprite] * m_states[state]->frames()) % rowDuration;
+    if (extra == m_sprites[state]->m_generatedCount - 1)//last state
+        return (m_duration[sprite] * m_sprites[state]->frames()) % rowDuration;
     else
         return rowDuration;
 }
@@ -136,21 +153,21 @@ int QSGSpriteEngine::spriteCount()//TODO: Actually image state count, need to re
     return m_imageStateCount;
 }
 
-void QSGSpriteEngine::setGoal(int state, int sprite, bool jump)
+void QSGStochasticEngine::setGoal(int state, int sprite, bool jump)
 {
-    if (sprite >= m_sprites.count() || state >= m_states.count())
+    if (sprite >= m_things.count() || state >= m_states.count())
         return;
     if (!jump){
         m_goals[sprite] = state;
         return;
     }
 
-    if (m_sprites[sprite] == state)
+    if (m_things[sprite] == state)
         return;//Already there
-    m_sprites[sprite] = state;
+    m_things[sprite] = state;
     m_duration[sprite] = m_states[state]->variedDuration();
     m_goals[sprite] = -1;
-    restartSprite(sprite);
+    restart(sprite);
     emit stateChanged(sprite);
     emit m_states[state]->entered();
     return;
@@ -165,8 +182,15 @@ QImage QSGSpriteEngine::assembledImage()
 
     int maxSize;
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
+    foreach (QSGStochasticState* s, m_states){
+        QSGSprite* sprite = qobject_cast<QSGSprite*>(s);
+        if (sprite)
+            m_sprites << sprite;
+        else
+            qDebug() << "Error: Non-sprite in QSGSpriteEngine";
+    }
 
-    foreach (QSGSprite* state, m_states){
+    foreach (QSGSprite* state, m_sprites){
         if (state->frames() > m_maxFrames)
             m_maxFrames = state->frames();
 
@@ -224,7 +248,7 @@ QImage QSGSpriteEngine::assembledImage()
     image.fill(0);
     QPainter p(&image);
     int y = 0;
-    foreach (QSGSprite* state, m_states){
+    foreach (QSGSprite* state, m_sprites){
         QImage img(state->source().toLocalFile());
         if (img.height() == frameHeight && img.width() <  maxSize){//Simple case
             p.drawImage(0,y,img);
@@ -271,51 +295,51 @@ QImage QSGSpriteEngine::assembledImage()
     return image;
 }
 
-void QSGSpriteEngine::setCount(int c)
+void QSGStochasticEngine::setCount(int c)
 {
-    m_sprites.resize(c);
+    m_things.resize(c);
     m_goals.resize(c);
     m_duration.resize(c);
     m_startTimes.resize(c);
 }
 
-void QSGSpriteEngine::startSprite(int index, int state)
+void QSGStochasticEngine::start(int index, int state)
 {
-    if (index >= m_sprites.count())
+    if (index >= m_things.count())
         return;
-    m_sprites[index] = state;
+    m_things[index] = state;
     m_duration[index] = m_states[state]->variedDuration();
     m_goals[index] = -1;
-    restartSprite(index);
+    restart(index);
 }
 
-void QSGSpriteEngine::stopSprite(int index)
+void QSGStochasticEngine::stop(int index)
 {
-    if (index >= m_sprites.count())
+    if (index >= m_things.count())
         return;
     //Will never change until start is called again with a new state - this is not a 'pause'
     for (int i=0; i<m_stateUpdates.count(); i++)
         m_stateUpdates[i].second.removeAll(index);
 }
 
-void QSGSpriteEngine::restartSprite(int index)
+void QSGStochasticEngine::restart(int index)
 {
     m_startTimes[index] = m_timeOffset + m_advanceTime.elapsed();
-    int time = m_duration[index] * m_states[m_sprites[index]]->frames() + m_startTimes[index];
+    int time = m_duration[index] * m_states[m_things[index]]->frames() + m_startTimes[index];
     for (int i=0; i<m_stateUpdates.count(); i++)
         m_stateUpdates[i].second.removeAll(index);
     addToUpdateList(time, index);
 }
 
-uint QSGSpriteEngine::updateSprites(uint time)//### would returning a list of changed idxs be faster than signals?
+uint QSGStochasticEngine::updateSprites(uint time)//### would returning a list of changed idxs be faster than signals?
 {
     //Sprite State Update;
     QSet<int> changedIndexes;
     while (!m_stateUpdates.isEmpty() && time >= m_stateUpdates.first().first){
         foreach (int idx, m_stateUpdates.first().second){
-            if (idx >= m_sprites.count())
+            if (idx >= m_things.count())
                 continue;//TODO: Proper fix(because this does happen and I'm just ignoring it)
-            int stateIdx = m_sprites[idx];
+            int stateIdx = m_things[idx];
             int nextIdx = -1;
             int goalPath = goalSeek(stateIdx, idx);
             if (goalPath == -1){//Random
@@ -347,7 +371,7 @@ uint QSGSpriteEngine::updateSprites(uint time)//### would returning a list of ch
             if (nextIdx == -1)//No to states means stay here
                 nextIdx = stateIdx;
 
-            m_sprites[idx] = nextIdx;
+            m_things[idx] = nextIdx;
             m_duration[idx] = m_states[nextIdx]->variedDuration();
             m_startTimes[idx] = time;
             if (nextIdx != stateIdx){
@@ -370,7 +394,7 @@ uint QSGSpriteEngine::updateSprites(uint time)//### would returning a list of ch
     return m_stateUpdates.first().first;
 }
 
-int QSGSpriteEngine::goalSeek(int curIdx, int spriteIdx, int dist)
+int QSGStochasticEngine::goalSeek(int curIdx, int spriteIdx, int dist)
 {
     QString goalName;
     if (m_goals[spriteIdx] != -1)
@@ -386,7 +410,7 @@ int QSGSpriteEngine::goalSeek(int curIdx, int spriteIdx, int dist)
             return curIdx;
     if (dist < 0)
         dist = m_states.count();
-    QSGSprite* curState = m_states[curIdx];
+    QSGStochasticState* curState = m_states[curIdx];
     for (QVariantMap::const_iterator iter = curState->m_to.constBegin();
         iter!=curState->m_to.constEnd(); iter++){
         if (iter.key() == goalName)
@@ -445,7 +469,7 @@ int QSGSpriteEngine::goalSeek(int curIdx, int spriteIdx, int dist)
     return -1;
 }
 
-void QSGSpriteEngine::addToUpdateList(uint t, int idx)
+void QSGStochasticEngine::addToUpdateList(uint t, int idx)
 {
     for (int i=0; i<m_stateUpdates.count(); i++){
         if (m_stateUpdates[i].first==t){
index 10860a5..b2a06f2 100644 (file)
@@ -58,48 +58,171 @@ QT_BEGIN_NAMESPACE
 QT_MODULE(Declarative)
 
 class QSGSprite;
+class QSGStochasticState : public QObject //For internal use
+{
+    Q_OBJECT
+    Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
+    Q_PROPERTY(int durationVariation READ durationVariance WRITE setDurationVariance NOTIFY durationVarianceChanged)
+    Q_PROPERTY(QVariantMap to READ to WRITE setTo NOTIFY toChanged)
+    Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+    Q_PROPERTY(qreal speedModifiesDuration READ speedModifer WRITE setSpeedModifier NOTIFY speedModifierChanged)
+    Q_PROPERTY(int frames READ frames WRITE setFrames NOTIFY framesChanged)
+
+public:
+    QSGStochasticState(QObject* parent = 0)
+        : QObject(parent)
+        , m_frames(1)
+        , m_duration(1000)
+    {
+    }
+
+    int duration() const
+    {
+        return m_duration;
+    }
+
+    QString name() const
+    {
+        return m_name;
+    }
+
+    QVariantMap to() const
+    {
+        return m_to;
+    }
+
+    qreal speedModifer() const
+    {
+        return m_speedModifier;
+    }
+
+    int durationVariance() const
+    {
+        return m_durationVariance;
+    }
+
+
+    int variedDuration() const
+    {
+        return m_duration
+                + (m_durationVariance * ((qreal)qrand()/RAND_MAX) * 2)
+                - m_durationVariance;
+    }
 
-class QSGSpriteEngine : public QObject
+    int frames() const
+    {
+        return m_frames;
+    }
+
+signals:
+    void durationChanged(int arg);
+
+    void nameChanged(QString arg);
+
+    void toChanged(QVariantMap arg);
+
+    void speedModifierChanged(qreal arg);
+
+    void durationVarianceChanged(int arg);
+
+    void entered();//### Just playing around - don't expect full state API
+    void framesChanged(int arg);
+
+public slots:
+    void setDuration(int arg)
+    {
+        if (m_duration != arg) {
+            m_duration = arg;
+            emit durationChanged(arg);
+        }
+    }
+
+    void setName(QString arg)
+    {
+        if (m_name != arg) {
+            m_name = arg;
+            emit nameChanged(arg);
+        }
+    }
+
+    void setTo(QVariantMap arg)
+    {
+        if (m_to != arg) {
+            m_to = arg;
+            emit toChanged(arg);
+        }
+    }
+
+    void setSpeedModifier(qreal arg)
+    {
+        if (m_speedModifier != arg) {
+            m_speedModifier = arg;
+            emit speedModifierChanged(arg);
+        }
+    }
+
+    void setDurationVariance(int arg)
+    {
+        if (m_durationVariance != arg) {
+            m_durationVariance = arg;
+            emit durationVarianceChanged(arg);
+        }
+    }
+
+    void setFrames(int arg)
+    {
+        if (m_frames != arg) {
+            m_frames = arg;
+            emit framesChanged(arg);
+        }
+    }
+
+private:
+    QString m_name;
+    int m_frames;
+    QVariantMap m_to;
+    int m_duration;
+    qreal m_speedModifier;
+    int m_durationVariance;
+
+    friend class QSGStochasticEngine;
+};
+
+class QSGStochasticEngine : public QObject
 {
     Q_OBJECT
-    //TODO: Optimize single sprite case
-    Q_PROPERTY(QDeclarativeListProperty<QSGSprite> sprites READ sprites)
+    //TODO: Optimize single state case?
     Q_PROPERTY(QString globalGoal READ globalGoal WRITE setGlobalGoal NOTIFY globalGoalChanged)
+    Q_PROPERTY(QDeclarativeListProperty<QSGStochasticState> states READ states)
 public:
-    explicit QSGSpriteEngine(QObject *parent = 0);
-    QSGSpriteEngine(QList<QSGSprite*> sprites, QObject *parent=0);
-    ~QSGSpriteEngine();
+    explicit QSGStochasticEngine(QObject *parent = 0);
+    QSGStochasticEngine(QList<QSGStochasticState*> states, QObject *parent=0);
+    ~QSGStochasticEngine();
 
-    QDeclarativeListProperty<QSGSprite> sprites()
+    QDeclarativeListProperty<QSGStochasticState> states()
     {
-        return QDeclarativeListProperty<QSGSprite>(this, m_states);
+        return QDeclarativeListProperty<QSGStochasticState>(this, m_states);
     }
+
     QString globalGoal() const
     {
         return m_globalGoal;
     }
 
-    int count() const {return m_sprites.count();}
+    int count() const {return m_things.count();}
     void setCount(int c);
 
-    int spriteState(int sprite=0);// {return m_sprites[sprite];}
-    int spriteStart(int sprite=0);// {return m_startTimes[sprite];}
-    int spriteFrames(int sprite=0);
-    int spriteDuration(int sprite=0);
-    int spriteCount();//Like state count, but for the image states
-    int maxFrames();
 
-    void setGoal(int state, int sprite=0, bool jump=false);
-    QImage assembledImage();
 
-    void startSprite(int index=0, int state=0);
-    void stopSprite(int index=0);
+    void setGoal(int state, int sprite=0, bool jump=false);
+    void start(int index=0, int state=0);
+    void stop(int index=0);
+    int curState(int index=0) {return m_things[index];}
 
-private://Nothing outside should use this?
-    friend class QSGSpriteGoalAffector;//XXX: Fix interface
+    QSGStochasticState* state(int idx){return m_states[idx];}
+    int stateIndex(QSGStochasticState* s){return m_states.indexOf(s);}
     int stateCount() {return m_states.count();}
-    int stateIndex(QSGSprite* s){return m_states.indexOf(s);}//TODO: Does this need to be hidden?
-    QSGSprite* state(int idx){return m_states[idx];}//Used by spritegoal affector
+private:
 signals:
 
     void globalGoalChanged(QString arg);
@@ -116,14 +239,14 @@ public slots:
 
     uint updateSprites(uint time);
 
-private:
+protected:
     friend class QSGParticleSystem;
-    void restartSprite(int sprite);
+    void restart(int index);
     void addToUpdateList(uint t, int idx);
-    int goalSeek(int curState, int spriteIdx, int dist=-1);
-    QList<QSGSprite*> m_states;
+    int goalSeek(int curState, int idx, int dist=-1);
+    QList<QSGStochasticState*> m_states;
     //### Consider struct or class for the four data variables?
-    QVector<int> m_sprites;//int is the index in m_states of the current state
+    QVector<int> m_things;//int is the index in m_states of the current state
     QVector<int> m_goals;
     QVector<int> m_duration;
     QVector<int> m_startTimes;
@@ -136,6 +259,31 @@ private:
     int m_imageStateCount;
 };
 
+class QSGSpriteEngine : public QSGStochasticEngine
+{
+    Q_OBJECT
+    Q_PROPERTY(QDeclarativeListProperty<QSGSprite> sprites READ sprites)
+public:
+    explicit QSGSpriteEngine(QObject *parent = 0);
+    QSGSpriteEngine(QList<QSGSprite*> sprites, QObject *parent=0);
+    ~QSGSpriteEngine();
+    QDeclarativeListProperty<QSGSprite> sprites()
+    {
+        return QDeclarativeListProperty<QSGSprite>(this, m_sprites);
+    }
+
+
+    int spriteState(int sprite=0);
+    int spriteStart(int sprite=0);
+    int spriteFrames(int sprite=0);
+    int spriteDuration(int sprite=0);
+    int spriteCount();//Like state count, but for the image states
+    int maxFrames();
+    QImage assembledImage();
+private:
+    QList<QSGSprite*> m_sprites;
+};
+
 //Common use is to have your own list property which is transparently an engine
 inline void spriteAppend(QDeclarativeListProperty<QSGSprite> *p, QSGSprite* s)
 {
index afa80e4..5557ea5 100644 (file)
@@ -263,7 +263,7 @@ QSGGeometryNode* QSGSpriteImage::buildNode()
     g->setDrawingMode(GL_TRIANGLES);
 
     SpriteVertices *p = (SpriteVertices *) g->vertexData();
-    m_spriteEngine->startSprite(0);
+    m_spriteEngine->start(0);
     p->v1.animT = p->v2.animT = p->v3.animT = p->v4.animT = 0;
     p->v1.animIdx = p->v2.animIdx = p->v3.animIdx = p->v4.animIdx = 0;
     p->v1.frameCount = p->v2.frameCount = p->v3.frameCount = p->v4.frameCount = m_spriteEngine->spriteFrames();
index 527bd9a..8676e52 100644 (file)
@@ -29,7 +29,8 @@ HEADERS += \
     $$PWD/qsgtargetaffector_p.h \
     $$PWD/qsgcumulativedirection_p.h \
     $$PWD/qsgv8particledata_p.h \
-    $$PWD/qsgrectangleextruder_p.h
+    $$PWD/qsgrectangleextruder_p.h \
+    $$PWD/qsgparticlegroup_p.h
 
 SOURCES += \
     $$PWD/qsgangledirection.cpp \
@@ -60,7 +61,8 @@ SOURCES += \
     $$PWD/qsgtargetaffector.cpp \
     $$PWD/qsgcumulativedirection.cpp \
     $$PWD/qsgv8particledata.cpp \
-    $$PWD/qsgrectangleextruder.cpp
+    $$PWD/qsgrectangleextruder.cpp \
+    $$PWD/qsgparticlegroup.cpp
 
 RESOURCES += \
     $$PWD/particles.qrc
index ab4cfa0..a1d65a5 100644 (file)
@@ -465,7 +465,7 @@ QSGShaderEffectNode* QSGCustomParticle::buildCustomNodes()
         s.vertexCode = qt_particles_default_vertex_code;
     s.vertexCode = qt_particles_template_vertex_code + s.vertexCode;
     m_material.setProgramSource(s);
-    foreach (const QString &str, m_particles){
+    foreach (const QString &str, m_groups){
         int gIdx = m_system->m_groupIds[str];
         int count = m_system->m_groupData[gIdx]->size();
         //Create Particle Geometry
index 581024d..b1aef78 100644 (file)
@@ -1021,7 +1021,7 @@ QSGGeometryNode* QSGImageParticle::buildParticleNodes()
         m_material->setFlag(QSGMaterial::Blending);
     }
 
-    foreach (const QString &str, m_particles){
+    foreach (const QString &str, m_groups){
         int gIdx = m_system->m_groupIds[str];
         int count = m_system->m_groupData[gIdx]->size();
         QSGGeometryNode* node = new QSGGeometryNode();
@@ -1151,7 +1151,7 @@ void QSGImageParticle::prepareNextFrame()
         //Advance State
         getState<ImageMaterialData>(m_material)->animcount = m_spriteEngine->spriteCount();
         m_spriteEngine->updateSprites(timeStamp);
-        foreach (const QString &str, m_particles){
+        foreach (const QString &str, m_groups){
             int gIdx = m_system->m_groupIds[str];
             int count = m_system->m_groupData[gIdx]->size();
 
@@ -1199,7 +1199,7 @@ void QSGImageParticle::initialize(int gIdx, int pIdx)
             datum->animT = datum->t;
             datum->animIdx = 0;
             if (m_spriteEngine){
-                m_spriteEngine->startSprite(spriteIdx);
+                m_spriteEngine->start(spriteIdx);
                 datum->frameCount = m_spriteEngine->spriteFrames(spriteIdx);
                 datum->frameDuration = m_spriteEngine->spriteDuration(spriteIdx);
             }else{
index 01eacba..1f87b16 100644 (file)
@@ -56,7 +56,7 @@ class ImageMaterialData;
 class QSGGeometryNode;
 
 class QSGSprite;
-class QSGSpriteEngine;
+class QSGStochasticEngine;
 
 struct SimpleVertex {
     float x;
@@ -186,7 +186,7 @@ public:
 
 
     QDeclarativeListProperty<QSGSprite> sprites();
-    QSGSpriteEngine* spriteEngine() {return m_spriteEngine;}
+    QSGStochasticEngine* spriteEngine() {return m_spriteEngine;}
 
     enum EntryEffect {
         None = 0,
index c330880..2572d67 100644 (file)
@@ -226,7 +226,7 @@ void QSGItemParticle::prepareNextFrame()
         return;
 
     //TODO: Size, better fade?
-    foreach (const QString &str, m_particles){
+    foreach (const QString &str, m_groups){
         int gIdx = m_system->m_groupIds[str];
         int count = m_system->m_groupData[gIdx]->size();
 
index cff3c29..7cb4869 100644 (file)
@@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE
     If the Affector is a direct child of a ParticleSystem, it will automatically be associated with it.
 */
 /*!
-    \qmlproperty list<string> QtQuick.Particles2::Affector::particles
+    \qmlproperty list<string> QtQuick.Particles2::Affector::groups
     Which logical particle groups will be affected.
 
     If empty, it will affect all particles.
@@ -100,9 +100,9 @@ QT_BEGIN_NAMESPACE
     x,y are the coordinates of the affected particle, relative to the ParticleSystem.
 
 */
-//TODO: Document particle 'type'
+
 /*!
-    \qmlsignal QtQuick.Particles2::Affector::affectParticle(particle, dt)
+    \qmlsignal QtQuick.Particles2::Affector::affectParticle(particle particle, real dt)
 
     This handler is called when particles are selected to be affected.
 
@@ -113,7 +113,7 @@ QT_BEGIN_NAMESPACE
     high-volume particle systems.
 */
 /*!
-    \qmlsignal QtQuick.Particles2::Affector::affected(x, y)
+    \qmlsignal QtQuick.Particles2::Affector::affected(real x, real y)
 
     This handler is called when a particle is selected to be affected. It will
     only be called if signal is set to true.
@@ -142,12 +142,12 @@ void QSGParticleAffector::componentComplete()
 
 bool QSGParticleAffector::activeGroup(int g) {
     if (m_updateIntSet){
-        m_groups.clear();
-        foreach (const QString &p, m_particles)
-            m_groups << m_system->m_groupIds[p];//###Can this occur before group ids are properly assigned?
+        m_groupIds.clear();
+        foreach (const QString &p, m_groups)
+            m_groupIds << m_system->m_groupIds[p];//###Can this occur before group ids are properly assigned?
         m_updateIntSet = false;
     }
-    return m_groups.isEmpty() || m_groups.contains(g);
+    return m_groupIds.isEmpty() || m_groupIds.contains(g);
 }
 
 void QSGParticleAffector::affectSystem(qreal dt)
@@ -195,7 +195,7 @@ bool QSGParticleAffector::affectParticle(QSGParticleData *, qreal )
 void QSGParticleAffector::reset(QSGParticleData* pd)
 {//TODO: This, among other ones, should be restructured so they don't all need to remember to call the superclass
     if (m_onceOff)
-        if (m_groups.isEmpty() || m_groups.contains(pd->group))
+        if (m_groups.isEmpty() || m_groupIds.contains(pd->group))
             m_onceOffed.remove(qMakePair(pd->group, pd->index));
 }
 
index 5700969..0dadeff 100644 (file)
@@ -56,7 +56,7 @@ class QSGParticleAffector : public QSGItem
 {
     Q_OBJECT
     Q_PROPERTY(QSGParticleSystem* system READ system WRITE setSystem NOTIFY systemChanged)
-    Q_PROPERTY(QStringList particles READ particles WRITE setParticles NOTIFY particlesChanged)
+    Q_PROPERTY(QStringList groups READ groups WRITE setGroups NOTIFY groupsChanged)
     Q_PROPERTY(QStringList whenCollidingWith READ whenCollidingWith WRITE setWhenCollidingWith NOTIFY whenCollidingWithChanged)
     Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
     Q_PROPERTY(bool once READ onceOff WRITE setOnceOff NOTIFY onceChanged)
@@ -71,9 +71,9 @@ public:
         return m_system;
     }
 
-    QStringList particles() const
+    QStringList groups() const
     {
-        return m_particles;
+        return m_groups;
     }
 
     bool enabled() const
@@ -100,7 +100,7 @@ signals:
 
     void systemChanged(QSGParticleSystem* arg);
 
-    void particlesChanged(QStringList arg);
+    void groupsChanged(QStringList arg);
 
     void enabledChanged(bool arg);
 
@@ -122,12 +122,12 @@ void setSystem(QSGParticleSystem* arg)
     }
 }
 
-void setParticles(QStringList arg)
+void setGroups(QStringList arg)
 {
-    if (m_particles != arg) {
-        m_particles = arg;
+    if (m_groups != arg) {
+        m_groups = arg;
         m_updateIntSet = true;
-        emit particlesChanged(arg);
+        emit groupsChanged(arg);
     }
 }
 
@@ -169,14 +169,14 @@ protected:
     virtual bool affectParticle(QSGParticleData *d, qreal dt);
     bool m_needsReset;//### What is this really saving?
     QSGParticleSystem* m_system;
-    QStringList m_particles;
+    QStringList m_groups;
     bool activeGroup(int g);
     bool m_enabled;
     virtual void componentComplete();
     QPointF m_offset;
     bool isAffectedConnected();
 private:
-    QSet<int> m_groups;
+    QSet<int> m_groupIds;
     QSet<QPair<int, int> > m_onceOffed;
     bool m_updateIntSet;
 
index 13ab3e6..fdba3de 100644 (file)
@@ -68,9 +68,9 @@ QT_BEGIN_NAMESPACE
     This can be omitted if the Emitter is a direct child of the ParticleSystem
 */
 /*!
-    \qmlproperty string QtQuick.Particles2::Emitter::particle
+    \qmlproperty string QtQuick.Particles2::Emitter::group
 
-    This is the type of logical particle which it will emit.
+    This is the logical particle group which it will emit into.
 
     Default value is "" (empty string).
 */
@@ -396,7 +396,7 @@ void QSGParticleEmitter::emitWindow(int timeStamp)
         pt = time;
     while ((pt < time && m_emitCap) || !m_burstQueue.isEmpty()) {
         //int pos = m_last_particle % m_particle_count;
-        QSGParticleData* datum = m_system->newDatum(m_system->m_groupIds[m_particle], !m_overwrite);
+        QSGParticleData* datum = m_system->newDatum(m_system->m_groupIds[m_group], !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;
index 8ed7ee7..8bd205b 100644 (file)
@@ -61,7 +61,7 @@ class QSGParticleEmitter : public QSGItem
 {
     Q_OBJECT
     Q_PROPERTY(QSGParticleSystem* system READ system WRITE setSystem NOTIFY systemChanged)
-    Q_PROPERTY(QString particle READ particle WRITE setParticle NOTIFY particleChanged)
+    Q_PROPERTY(QString group READ group WRITE setGroup NOTIFY groupChanged)
     Q_PROPERTY(QSGParticleExtruder* shape READ extruder WRITE setExtruder NOTIFY extruderChanged)
     Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
     Q_PROPERTY(int startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged)
@@ -109,9 +109,9 @@ public:
         return m_system;
     }
 
-    QString particle() const
+    QString group() const
     {
-        return m_particle;
+        return m_group;
     }
 
     int particleDurationVariation() const
@@ -130,7 +130,7 @@ signals:
 
     void systemChanged(QSGParticleSystem* arg);
 
-    void particleChanged(QString arg);
+    void groupChanged(QString arg);
 
     void particleDurationVariationChanged(int arg);
 
@@ -185,11 +185,11 @@ public slots:
         }
     }
 
-    void setParticle(QString arg)
+    void setGroup(QString arg)
     {
-        if (m_particle != arg) {
-            m_particle = arg;
-            emit particleChanged(arg);
+        if (m_group != arg) {
+            m_group = arg;
+            emit groupChanged(arg);
         }
     }
 
@@ -308,7 +308,7 @@ protected:
        int m_particleDurationVariation;
        bool m_enabled;
        QSGParticleSystem* m_system;
-       QString m_particle;
+       QString m_group;
        QSGParticleExtruder* m_extruder;
        QSGParticleExtruder* m_defaultExtruder;
        QSGParticleExtruder* effectiveExtruder();
diff --git a/src/declarative/particles/qsgparticlegroup.cpp b/src/declarative/particles/qsgparticlegroup.cpp
new file mode 100644 (file)
index 0000000..28eb4d2
--- /dev/null
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** 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 "qsgparticlegroup_p.h"
+
+/*!
+    \qmlclass ParticleGroup QSGParticleGroup
+    \inqmlmodule QtQuick.Particles 2
+    \brief ParticleGroup elements allow you to set attributes on a logical particle group.
+
+    This element allows you to set timed transitions on particle groups.
+
+    You can also use this element to group particle system elements related to the logical
+    particle group. Emitters, Affectors and Painters set as direct children of a ParticleGroup
+    will automatically apply to that logical particle group. TrailEmitters will automatically follow
+    the group.
+
+    If a ParticleGroup element is not defined for a group, the group will function normally as if
+    none of the transition properties were set.
+*/
+/*!
+    \qmlproperty ParticleSystem QtQuick.Particles2::ParticleGroup::system
+    This is the system which will contain the group.
+
+    If the ParticleGroup is a direct child of a ParticleSystem, it will automatically be associated with it.
+*/
+/*!
+    \qmlproperty string QtQuick.Particles2::ParticleGroup::name
+    This is the name of the particle group, and how it is generally referred to by other elements.
+
+    If elements refer to a name which does not have an explicit ParticleGroup created, it will
+    work normally (with no transitions specified for the group). If you do not need to assign
+    duration based transitions to a group, you do not need to create a ParticleGroup with that name (although you may).
+*/
+/*!
+    \qmlproperty int QtQuick.Particles2::ParticleGroup::duration
+    The time in milliseconds before the group will attempt to transition.
+
+*/
+/*!
+    \qmlproperty ParticleSystem QtQuick.Particles2::ParticleGroup::durationVariation
+    The maximum number of milliseconds that the duration of the transition cycle varies per particle in the group.
+
+    Default value is zero.
+*/
+/*!
+    \qmlproperty ParticleSystem QtQuick.Particles2::ParticleGroup::to
+    The weighted list of transitions valid for this group.
+
+    If the chosen transition stays in this group, another duration (+/- up to durationVariation)
+    milliseconds will occur before another transition is attempted.
+*/
+
+QSGParticleGroup::QSGParticleGroup(QObject* parent)
+    : QSGStochasticState(parent)
+{
+
+}
+
+void delayedRedirect(QDeclarativeListProperty<QObject> *prop, QObject *value)
+{
+    QSGParticleGroup* pg = qobject_cast<QSGParticleGroup*>(prop->object);
+    if (pg)
+        pg->delayRedirect(value);
+}
+
+QDeclarativeListProperty<QObject> QSGParticleGroup::particleChildren()
+{
+    QSGParticleSystem* system = qobject_cast<QSGParticleSystem*>(parent());
+    if (system)
+        return QDeclarativeListProperty<QObject>(this, 0, &QSGParticleSystem::statePropertyRedirect);
+    else
+        return QDeclarativeListProperty<QObject>(this, 0, &delayedRedirect);
+}
+
+void QSGParticleGroup::setSystem(QSGParticleSystem* arg)
+{
+    if (m_system != arg) {
+        m_system = arg;
+        m_system->registerParticleGroup(this);
+        performDelayedRedirects();
+        emit systemChanged(arg);
+    }
+}
+
+void QSGParticleGroup::delayRedirect(QObject *obj)
+{
+    m_delayedRedirects << obj;
+}
+
+void QSGParticleGroup::performDelayedRedirects()
+{
+    if (!m_system)
+        return;
+    foreach (QObject* obj, m_delayedRedirects)
+        m_system->stateRedirect(this, m_system, obj);
+
+    m_delayedRedirects.clear();
+}
+
+void QSGParticleGroup::componentComplete(){
+    if (!m_system && qobject_cast<QSGParticleSystem*>(parent()))
+        setSystem(qobject_cast<QSGParticleSystem*>(parent()));
+}
diff --git a/src/declarative/particles/qsgparticlegroup_p.h b/src/declarative/particles/qsgparticlegroup_p.h
new file mode 100644 (file)
index 0000000..346b4ab
--- /dev/null
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** 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 QSGPARTICLEGROUP
+#define QSGPARTICLEGROUP
+#include "qsgspriteengine_p.h"
+#include "qsgparticlesystem_p.h"
+#include "qdeclarativeparserstatus.h"
+
+class QSGParticleGroup : public QSGStochasticState, public QDeclarativeParserStatus
+{
+    Q_OBJECT
+    //### Would setting limits per group be useful? Or clutter the API?
+    //Q_PROPERTY(int maximumAlive READ maximumAlive WRITE setMaximumAlive NOTIFY maximumAliveChanged)
+
+    Q_PROPERTY(QSGParticleSystem* system READ system WRITE setSystem NOTIFY systemChanged)
+
+    //Intercept children requests and assign to the group & system
+    Q_PROPERTY(QDeclarativeListProperty<QObject> particleChildren READ particleChildren DESIGNABLE false)//### Hidden property for in-state system definitions - ought not to be used in actual "Sprite" states
+    Q_CLASSINFO("DefaultProperty", "particleChildren")
+
+public:
+    explicit QSGParticleGroup(QObject* parent = 0);
+
+    QDeclarativeListProperty<QObject> particleChildren();
+
+    int maximumAlive() const
+    {
+        return m_maximumAlive;
+    }
+
+    QSGParticleSystem* system() const
+    {
+        return m_system;
+    }
+
+public slots:
+
+    void setMaximumAlive(int arg)
+    {
+        if (m_maximumAlive != arg) {
+            m_maximumAlive = arg;
+            emit maximumAliveChanged(arg);
+        }
+    }
+
+    void setSystem(QSGParticleSystem* arg);
+
+    void delayRedirect(QObject* obj);
+
+signals:
+
+    void maximumAliveChanged(int arg);
+
+    void systemChanged(QSGParticleSystem* arg);
+
+protected:
+    virtual void componentComplete();
+    virtual void classBegin(){;}
+
+private:
+
+    void performDelayedRedirects();
+
+    int m_maximumAlive;
+    QSGParticleSystem* m_system;
+    QList<QObject*> m_delayedRedirects;
+};
+
+#endif
index f4639c2..670c1f2 100644 (file)
@@ -58,10 +58,10 @@ QT_BEGIN_NAMESPACE
     If the ParticlePainter is a direct child of a ParticleSystem, it will automatically be associated with it.
 */
 /*!
-    \qmlproperty list<string> QtQuick.Particles2::ParticlePainter::particles
+    \qmlproperty list<string> QtQuick.Particles2::ParticlePainter::groups
     Which logical particle groups will be painted.
 
-    If empty, it will paint the default particle ("").
+    If empty, it will paint the default particle group ("").
 */
 QSGParticlePainter::QSGParticlePainter(QSGItem *parent) :
     QSGItem(parent),
@@ -144,7 +144,7 @@ void QSGParticlePainter::calcSystemOffset(bool resetPending)
     m_systemOffset = -1 * this->mapFromItem(m_system, QPointF(0.0, 0.0));
     if (lastOffset != m_systemOffset && !resetPending){
         //Reload all particles//TODO: Necessary?
-        foreach (const QString &g, m_particles){
+        foreach (const QString &g, m_groups){
             int gId = m_system->m_groupIds[g];
             foreach (QSGParticleData* d, m_system->m_groupData[gId]->data)
                 reload(d);
index 08ae3ae..d469947 100644 (file)
@@ -58,7 +58,7 @@ class QSGParticlePainter : public QSGItem
 {
     Q_OBJECT
     Q_PROPERTY(QSGParticleSystem* system READ system WRITE setSystem NOTIFY systemChanged)
-    Q_PROPERTY(QStringList particles READ particles WRITE setParticles NOTIFY particlesChanged)
+    Q_PROPERTY(QStringList groups READ groups WRITE setGroups NOTIFY groupsChanged)
 
 public:
     explicit QSGParticlePainter(QSGItem *parent = 0);
@@ -74,25 +74,25 @@ public:
     }
 
 
-    QStringList particles() const
+    QStringList groups() const
     {
-        return m_particles;
+        return m_groups;
     }
 
 signals:
     void countChanged();
     void systemChanged(QSGParticleSystem* arg);
 
-    void particlesChanged(QStringList arg);
+    void groupsChanged(QStringList arg);
 
 public slots:
 void setSystem(QSGParticleSystem* arg);
 
-void setParticles(QStringList arg)
+void setGroups(QStringList arg)
 {
-    if (m_particles != arg) {
-        m_particles = arg;
-        emit particlesChanged(arg);
+    if (m_groups != arg) {
+        m_groups = arg;
+        emit groupsChanged(arg);
     }
 }
 
@@ -121,7 +121,7 @@ protected:
     friend class QSGParticleSystem;
     int m_count;
     bool m_pleaseReset;
-    QStringList m_particles;
+    QStringList m_groups;
     QPointF m_systemOffset;
 
 private:
index 9fa0eba..f880842 100644 (file)
@@ -67,6 +67,7 @@
 #include "qsgcumulativedirection_p.h"
 #include "qsgcustomaffector_p.h"
 #include "qsgrectangleextruder_p.h"
+#include "qsgparticlegroup_p.h"
 
 QT_BEGIN_NAMESPACE
 
@@ -75,6 +76,7 @@ void QSGParticlesModule::defineModule()
     const char* uri = "QtQuick.Particles";
 
     qmlRegisterType<QSGParticleSystem>(uri, 2, 0, "ParticleSystem");
+    qmlRegisterType<QSGParticleGroup>(uri, 2, 0, "ParticleGroup");
 
     qmlRegisterType<QSGImageParticle>(uri, 2, 0, "ImageParticle");
     qmlRegisterType<QSGCustomParticle>(uri, 2, 0, "CustomParticle");
index 085e6af..bc27073 100644 (file)
@@ -47,6 +47,7 @@
 #include "qsgspriteengine_p.h"
 #include "qsgsprite_p.h"
 #include "qsgv8particledata_p.h"
+#include "qsgparticlegroup_p.h"
 
 #include "qsgtrailemitter_p.h"//###For auto-follow on states, perhaps should be in emitter?
 #include <private/qdeclarativeengine_p.h>
@@ -549,8 +550,8 @@ void QSGParticleData::debugDump()
 {
     qDebug() << "Particle" << systemIndex << group << "/" << index << stillAlive()
              << "Pos: " << x << "," << y
-             //<< "Vel: " << vx << "," << sy
-             //<< "Acc: " << ax << "," << ay
+             << "Vel: " << vx << "," << vy
+             << "Acc: " << ax << "," << ay
              << "Size: " << size << "," << endSize
              << "Time: " << t << "," <<lifeSpan << ";" << (system->m_timeInt / 1000.0) ;
 }
@@ -559,7 +560,6 @@ bool QSGParticleData::stillAlive()
 {
     if (!system)
         return false;
-    //fprintf(stderr, "%.9lf %.9lf\n",((qreal)system->m_timeInt/1000.0), (t+lifeSpan));
     return (t + lifeSpan - EPSILON) > ((qreal)system->m_timeInt/1000.0);
 }
 
@@ -601,7 +601,7 @@ void QSGParticleData::extendLife(float time)
 
 QSGParticleSystem::QSGParticleSystem(QSGItem *parent) :
     QSGItem(parent), m_particle_count(0), m_running(true), m_paused(false)
-  , m_nextIndex(0), m_componentComplete(false), m_spriteEngine(0)
+  , m_nextIndex(0), m_componentComplete(false), m_stateEngine(0)
 {
     connect(&m_painterMapper, SIGNAL(mapped(QObject*)),
             this, SLOT(loadPainter(QObject*)));
@@ -630,16 +630,11 @@ void QSGParticleSystem::initGroups()
     m_nextGroupId = 1;
 }
 
-    QDeclarativeListProperty<QSGSprite> QSGParticleSystem::particleStates()
-{
-    return QDeclarativeListProperty<QSGSprite>(this, &m_states, spriteAppend, spriteCount, spriteAt, spriteClear);
-}
-
 void QSGParticleSystem::registerParticlePainter(QSGParticlePainter* p)
 {
     //TODO: a way to Unregister emitters, painters and affectors
     m_painters << QPointer<QSGParticlePainter>(p);//###Set or uniqueness checking?
-    connect(p, SIGNAL(particlesChanged(QStringList)),
+    connect(p, SIGNAL(groupsChanged(QStringList)),
             &m_painterMapper, SLOT(map()));
     loadPainter(p);
 }
@@ -649,7 +644,7 @@ void QSGParticleSystem::registerParticleEmitter(QSGParticleEmitter* e)
     m_emitters << QPointer<QSGParticleEmitter>(e);//###How to get them out?
     connect(e, SIGNAL(particleCountChanged()),
             this, SLOT(emittersChanged()));
-    connect(e, SIGNAL(particleChanged(QString)),
+    connect(e, SIGNAL(groupChanged(QString)),
             this, SLOT(emittersChanged()));
     emittersChanged();
     e->reset();//Start, so that starttime factors appropriately
@@ -660,6 +655,12 @@ void QSGParticleSystem::registerParticleAffector(QSGParticleAffector* a)
     m_affectors << QPointer<QSGParticleAffector>(a);
 }
 
+void QSGParticleSystem::registerParticleGroup(QSGParticleGroup* g)
+{
+    m_groups << QPointer<QSGParticleGroup>(g);
+    createEngine();
+}
+
 void QSGParticleSystem::setRunning(bool arg)
 {
     if (m_running != arg) {
@@ -685,40 +686,45 @@ void QSGParticleSystem::setPaused(bool arg){
     }
 }
 
-void QSGParticleSystem::stateRedirect(QDeclarativeListProperty<QObject> *prop, QObject *value)
+void QSGParticleSystem::statePropertyRedirect(QDeclarativeListProperty<QObject> *prop, QObject *value)
 {
     //Hooks up automatic state-associated stuff
     QSGParticleSystem* sys = qobject_cast<QSGParticleSystem*>(prop->object->parent());
-    QSGSprite* sprite = qobject_cast<QSGSprite*>(prop->object);
-    if (!sprite || !sys)
+    QSGParticleGroup* group = qobject_cast<QSGParticleGroup*>(prop->object);
+    if (!group || !sys || !value)
         return;
+    stateRedirect(group, sys, value);
+}
+
+void QSGParticleSystem::stateRedirect(QSGParticleGroup* group, QSGParticleSystem* sys, QObject *value)
+{
     QStringList list;
-    list << sprite->name();
+    list << group->name();
     QSGParticleAffector* a = qobject_cast<QSGParticleAffector*>(value);
     if (a){
         a->setParentItem(sys);
-        a->setParticles(list);
+        a->setGroups(list);
         a->setSystem(sys);
         return;
     }
     QSGTrailEmitter* fe = qobject_cast<QSGTrailEmitter*>(value);
     if (fe){
         fe->setParentItem(sys);
-        fe->setFollow(sprite->name());
+        fe->setFollow(group->name());
         fe->setSystem(sys);
         return;
     }
     QSGParticleEmitter* e = qobject_cast<QSGParticleEmitter*>(value);
     if (e){
         e->setParentItem(sys);
-        e->setParticle(sprite->name());
+        e->setGroup(group->name());
         e->setSystem(sys);
         return;
     }
     QSGParticlePainter* p = qobject_cast<QSGParticlePainter*>(value);
     if (p){
         p->setParentItem(sys);
-        p->setParticles(list);
+        p->setGroups(list);
         p->setSystem(sys);
         return;
     }
@@ -785,14 +791,14 @@ void QSGParticleSystem::loadPainter(QObject *p)
     foreach (QSGParticleGroupData* sg, m_groupData)
         sg->painters.remove(painter);
     int particleCount = 0;
-    if (painter->particles().isEmpty()){//Uses default particle
+    if (painter->groups().isEmpty()){//Uses default particle
         QStringList def;
         def << "";
-        painter->setParticles(def);
+        painter->setGroups(def);
         particleCount += m_groupData[0]->size();
         m_groupData[0]->painters << painter;
     }else{
-        foreach (const QString &group, painter->particles()){
+        foreach (const QString &group, painter->groups()){
             if (group != QLatin1String("") && !m_groupIds[group]){//new group
                 int id = m_nextGroupId++;
                 QSGParticleGroupData* gd = new QSGParticleGroupData(id, this);
@@ -824,16 +830,16 @@ void QSGParticleSystem::emittersChanged()
     }
 
     foreach (QSGParticleEmitter* e, m_emitters){//Populate groups and set sizes.
-        if (!m_groupIds.contains(e->particle())
-                || (!e->particle().isEmpty() && !m_groupIds[e->particle()])){//or it was accidentally inserted by a failed lookup earlier
+        if (!m_groupIds.contains(e->group())
+                || (!e->group().isEmpty() && !m_groupIds[e->group()])){//or it was accidentally inserted by a failed lookup earlier
             int id = m_nextGroupId++;
             QSGParticleGroupData* gd = new QSGParticleGroupData(id, this);
-            m_groupIds.insert(e->particle(), id);
+            m_groupIds.insert(e->group(), id);
             m_groupData.insert(id, gd);
             previousSizes << 0;
             newSizes << 0;
         }
-        newSizes[m_groupIds[e->particle()]] += e->particleCount();
+        newSizes[m_groupIds[e->group()]] += e->particleCount();
         //###: Cull emptied groups?
     }
 
@@ -850,7 +856,7 @@ void QSGParticleSystem::emittersChanged()
     foreach (QSGParticlePainter *p, m_painters)
         loadPainter(p);
 
-    if (!m_states.isEmpty())
+    if (!m_groups.isEmpty())
         createEngine();
 
     if (m_debugMode)
@@ -861,58 +867,63 @@ void QSGParticleSystem::createEngine()
 {
     if (!m_componentComplete)
         return;
+    if (m_stateEngine && m_debugMode)
+        qDebug() << "Resetting Existing Sprite Engine...";
     //### Solve the losses if size/states go down
-    foreach (QSGSprite* sprite, m_states){
+    foreach (QSGParticleGroup* group, m_groups){
         bool exists = false;
         foreach (const QString &name, m_groupIds.keys())
-            if (sprite->name() == name)
+            if (group->name() == name)
                 exists = true;
         if (!exists){
             int id = m_nextGroupId++;
             QSGParticleGroupData* gd = new QSGParticleGroupData(id, this);
-            m_groupIds.insert(sprite->name(), id);
+            m_groupIds.insert(group->name(), id);
             m_groupData.insert(id, gd);
         }
     }
 
-    if (m_states.count()){
-        //Reorder Sprite List so as to have the same order as groups
-        QList<QSGSprite*> newList;
+    if (m_groups.count()){
+        //Reorder groups List so as to have the same order as groupData
+        QList<QSGParticleGroup*> newList;
         for (int i=0; i<m_nextGroupId; i++){
             bool exists = false;
             QString name = m_groupData[i]->name();
-            foreach (QSGSprite* existing, m_states){
+            foreach (QSGParticleGroup* existing, m_groups){
                 if (existing->name() == name){
                     newList << existing;
                     exists = true;
                 }
             }
             if (!exists){
-                newList << new QSGSprite(this);
+                newList << new QSGParticleGroup(this);
                 newList.back()->setName(name);
             }
         }
-        m_states = newList;
+        m_groups = newList;
+        QList<QSGStochasticState*> states;
+        foreach (QSGParticleGroup* g, m_groups)
+            states << (QSGStochasticState*)g;
 
-        if (!m_spriteEngine)
-            m_spriteEngine = new QSGSpriteEngine(this);
-        m_spriteEngine->setCount(m_particle_count);
-        m_spriteEngine->m_states = m_states;
+        if (!m_stateEngine)
+            m_stateEngine = new QSGStochasticEngine(this);
+        m_stateEngine->setCount(m_particle_count);
+        m_stateEngine->m_states = states;
 
-        connect(m_spriteEngine, SIGNAL(stateChanged(int)),
+        connect(m_stateEngine, SIGNAL(stateChanged(int)),
                 this, SLOT(particleStateChange(int)));
 
     }else{
-        if (m_spriteEngine)
-            delete m_spriteEngine;
-        m_spriteEngine = 0;
+        if (m_stateEngine)
+            delete m_stateEngine;
+        m_stateEngine = 0;
     }
 
 }
 
 void QSGParticleSystem::particleStateChange(int idx)
 {
-    moveGroups(m_bySysIdx[idx], m_spriteEngine->spriteState(idx));
+    moveGroups(m_bySysIdx[idx], m_stateEngine->curState(idx));
 }
 
 void QSGParticleSystem::moveGroups(QSGParticleData *d, int newGIdx)
@@ -934,8 +945,8 @@ int QSGParticleSystem::nextSystemIndex()
     }
     if (m_nextIndex >= m_bySysIdx.size()){
         m_bySysIdx.resize(m_bySysIdx.size() < 10 ? 10 : m_bySysIdx.size()*1.1);//###+1,10%,+10? Choose something non-arbitrarily
-        if (m_spriteEngine)
-            m_spriteEngine->setCount(m_bySysIdx.size());
+        if (m_stateEngine)
+            m_stateEngine->setCount(m_bySysIdx.size());
 
     }
     return m_nextIndex++;
@@ -954,8 +965,8 @@ QSGParticleData* QSGParticleSystem::newDatum(int groupId, bool respectLimits, in
             ret->systemIndex = nextSystemIndex();
     }else{
         if (ret->systemIndex != -1){
-            if (m_spriteEngine)
-                m_spriteEngine->stopSprite(ret->systemIndex);
+            if (m_stateEngine)
+                m_stateEngine->stop(ret->systemIndex);
             m_reusableIndexes << ret->systemIndex;
             m_bySysIdx[ret->systemIndex] = 0;
         }
@@ -963,8 +974,8 @@ QSGParticleData* QSGParticleSystem::newDatum(int groupId, bool respectLimits, in
     }
     m_bySysIdx[ret->systemIndex] = ret;
 
-    if (m_spriteEngine)
-        m_spriteEngine->startSprite(ret->systemIndex, ret->group);
+    if (m_stateEngine)
+        m_stateEngine->start(ret->systemIndex, ret->group);
 
     m_empty = false;
     return ret;
@@ -1011,8 +1022,8 @@ void QSGParticleSystem::updateCurrentTime( int currentTime )
     foreach (QSGParticleGroupData* gd, m_groupData)//Recycle all groups and see if they're out of live particles
         m_empty = gd->recycle() && m_empty;
 
-    if (m_spriteEngine)
-        m_spriteEngine->updateSprites(m_timeInt);
+    if (m_stateEngine)
+        m_stateEngine->updateSprites(m_timeInt);
 
     foreach (QSGParticleEmitter* emitter, m_emitters)
         if (emitter)
index 25a0c87..f531e7f 100644 (file)
@@ -65,9 +65,10 @@ class QSGParticleEmitter;
 class QSGParticlePainter;
 class QSGParticleData;
 class QSGParticleSystemAnimation;
-class QSGSpriteEngine;
+class QSGStochasticEngine;
 class QSGSprite;
 class QSGV8ParticleData;
+class QSGParticleGroup;
 
 struct QSGParticleDataHeapNode{
     int time;//in ms
@@ -223,12 +224,10 @@ class QSGParticleSystem : public QSGItem
     Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
     Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged)
     Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged)
-    Q_PROPERTY(QDeclarativeListProperty<QSGSprite> particleStates READ particleStates)
 
 public:
     explicit QSGParticleSystem(QSGItem *parent = 0);
     ~QSGParticleSystem();
-    QDeclarativeListProperty<QSGSprite> particleStates();
 
     //TODO: Hook up running and temporal manipulators to the animation
     bool isRunning() const
@@ -286,7 +285,7 @@ public://###but only really for related class usage. Perhaps we should all be fr
     QVector<QSGParticleData*> m_bySysIdx; //Another reference to the data (data owned by group), but by sysIdx
     QHash<QString, int> m_groupIds;
     QHash<int, QSGParticleGroupData*> m_groupData;
-    QSGSpriteEngine* m_spriteEngine;
+    QSGStochasticEngine* m_stateEngine;
 
     int m_timeInt;
     bool m_initialized;
@@ -294,9 +293,11 @@ public://###but only really for related class usage. Perhaps we should all be fr
     void registerParticlePainter(QSGParticlePainter* p);
     void registerParticleEmitter(QSGParticleEmitter* e);
     void registerParticleAffector(QSGParticleAffector* a);
+    void registerParticleGroup(QSGParticleGroup* g);
 
     int m_particle_count;
-    static void stateRedirect(QDeclarativeListProperty<QObject> *prop, QObject *value);//From QSGSprite
+    static void statePropertyRedirect(QDeclarativeListProperty<QObject> *prop, QObject *value);
+    static void stateRedirect(QSGParticleGroup* group, QSGParticleSystem* sys, QObject *value);
     bool isPaused() const
     {
         return m_paused;
@@ -315,11 +316,11 @@ private:
     QList<QPointer<QSGParticleAffector> > m_affectors;
     QList<QPointer<QSGParticlePainter> > m_painters;
     QList<QPointer<QSGParticlePainter> > m_syncList;
+    QList<QSGParticleGroup*> m_groups;
     int m_nextGroupId;
     int m_nextIndex;
     QSet<int> m_reusableIndexes;
     bool m_componentComplete;
-    QList<QSGSprite*> m_states;
 
     QSignalMapper m_painterMapper;
     QSignalMapper m_emitterMapper;
index 1837167..ec2be02 100644 (file)
@@ -64,16 +64,12 @@ QT_BEGIN_NAMESPACE
     \qmlproperty bool QtQuick.Particles2::SpriteGoal::systemStates
 */
 
-    Q_PROPERTY(QString goalState READ goalState WRITE setGoalState NOTIFY goalStateChanged)
-    Q_PROPERTY(bool jump READ jump WRITE setJump NOTIFY jumpChanged)
-    Q_PROPERTY(bool systemStates READ systemStates WRITE setSystemStates NOTIFY systemStatesChanged)
-
 QSGSpriteGoalAffector::QSGSpriteGoalAffector(QSGItem *parent) :
     QSGParticleAffector(parent), m_goalIdx(-1), m_jump(false), m_systemStates(false), m_lastEngine(0), m_notUsingEngine(false)
 {
 }
 
-void QSGSpriteGoalAffector::updateStateIndex(QSGSpriteEngine* e)
+void QSGSpriteGoalAffector::updateStateIndex(QSGStochasticEngine* e)
 {
     if (m_systemStates){
         m_goalIdx = m_system->m_groupIds[m_goalState];
@@ -104,14 +100,14 @@ void QSGSpriteGoalAffector::setGoalState(QString arg)
 bool QSGSpriteGoalAffector::affectParticle(QSGParticleData *d, qreal dt)
 {
     Q_UNUSED(dt);
-    QSGSpriteEngine *engine = 0;
+    QSGStochasticEngine *engine = 0;
     if (!m_systemStates){
         //TODO: Affect all engines
         foreach (QSGParticlePainter *p, m_system->m_groupData[d->group]->painters)
             if (qobject_cast<QSGImageParticle*>(p))
                 engine = qobject_cast<QSGImageParticle*>(p)->spriteEngine();
     }else{
-        engine = m_system->m_spriteEngine;
+        engine = m_system->m_stateEngine;
         if (!engine)
             m_notUsingEngine = true;
     }
@@ -126,7 +122,7 @@ bool QSGSpriteGoalAffector::affectParticle(QSGParticleData *d, qreal dt)
     if (m_notUsingEngine){//systemStates && no stochastic states defined. So cut out the engine
         //TODO: It's possible to move to a group that is intermediate and not used by painters or emitters - but right now that will redirect to the default group
         m_system->moveGroups(d, m_goalIdx);
-    }else if (engine->spriteState(index) != m_goalIdx){
+    }else if (engine->curState(index) != m_goalIdx){
         engine->setGoal(m_goalIdx, index, m_jump);
         emit affected(QPointF(d->curX(), d->curY()));//###Expensive if unconnected? Move to Affector?
         return true; //Doesn't affect particle data, but necessary for onceOff
index 7c799b1..043970b 100644 (file)
@@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE
 
 QT_MODULE(Declarative)
 
-class QSGSpriteEngine;
+class QSGStochasticEngine;
 
 class QSGSpriteGoalAffector : public QSGParticleAffector
 {
@@ -106,10 +106,10 @@ void setSystemStates(bool arg)
 }
 
 private:
-    void updateStateIndex(QSGSpriteEngine* e);
+    void updateStateIndex(QSGStochasticEngine* e);
     QString m_goalState;
     int m_goalIdx;
-    QSGSpriteEngine* m_lastEngine;
+    QSGStochasticEngine* m_lastEngine;
     bool m_jump;
     bool m_systemStates;
 
index 427b587..5a19ac5 100644 (file)
@@ -166,7 +166,7 @@ void QSGTrailEmitter::emitWindow(int timeStamp)
     qreal sizeAtEnd = m_particleEndSize >= 0 ? m_particleEndSize : m_particleSize;
 
     int gId = m_system->m_groupIds[m_follow];
-    int gId2 = m_system->m_groupIds[m_particle];
+    int gId2 = m_system->m_groupIds[m_group];
     foreach (QSGParticleData *d, m_system->m_groupData[gId]->data){
         if (!d || !d->stillAlive()){
             m_lastEmission[d->index] = time; //Should only start emitting when it returns to life
index 5ab6f24..009ccd5 100644 (file)
@@ -94,7 +94,7 @@ public:
     }
 
 signals:
-    void emitFollowParticle(QDeclarativeV8Handle particle, QDeclarativeV8Handle followed);
+    void emitFollowParticle(QDeclarativeV8Handle group, QDeclarativeV8Handle followed);
 
     void particlesPerParticlePerSecondChanged(int arg);