From 29993ff8e91715bdfbaf964c91e07a112f6d2a24 Mon Sep 17 00:00:00 2001 From: Alan Alpert <alan.alpert@nokia.com> Date: Tue, 13 Sep 2011 09:39:11 +1000 Subject: [PATCH] Refactor SpriteEngine out of StochasticEngine 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> --- .../animation/basics/color-animation.qml | 4 +- examples/declarative/flickr/flickr.qml | 6 +- .../minehunt/MinehuntCore/Explosion.qml | 4 +- .../particles/allsmiles/smilefactory.qml | 10 +- .../particles/allsmiles/spriteparticles.qml | 8 +- .../particles/asteroid/asteroid.qml | 14 +- .../particles/asteroid/blackhole.qml | 16 +- .../particles/trails/combustion.qml | 116 +++++----- .../particles/trails/fireballs.qml | 16 +- .../particles/trails/fireworks.qml | 62 +++--- .../declarative/particles/trails/portal.qml | 6 +- .../particles/trails/turbulence.qml | 10 +- .../plasmapatrol/content/BlasterHardpoint.qml | 4 +- .../plasmapatrol/content/CannonHardpoint.qml | 4 +- .../plasmapatrol/content/Cruiser.qml | 6 +- .../plasmapatrol/content/Frigate.qml | 4 +- .../plasmapatrol/content/LaserHardpoint.qml | 4 +- .../content/PlasmaPatrolParticles.qml | 24 +-- .../plasmapatrol/content/Sloop.qml | 2 +- .../declarative/plasmapatrol/plasmapatrol.qml | 2 +- .../samegame/SamegameCore/BoomBlock.qml | 2 +- .../samegame/SamegameCore/GameArea.qml | 6 +- examples/declarative/snake/content/Cookie.qml | 4 +- examples/declarative/snake/content/Link.qml | 4 +- .../toys/dynamicscene/dynamicscene.qml | 4 +- src/declarative/items/qsgsprite.cpp | 27 +-- src/declarative/items/qsgsprite_p.h | 114 +--------- src/declarative/items/qsgspriteengine.cpp | 112 ++++++---- src/declarative/items/qsgspriteengine_p.h | 204 +++++++++++++++--- src/declarative/items/qsgspriteimage.cpp | 2 +- src/declarative/particles/particles.pri | 6 +- .../particles/qsgcustomparticle.cpp | 2 +- .../particles/qsgimageparticle.cpp | 6 +- .../particles/qsgimageparticle_p.h | 4 +- src/declarative/particles/qsgitemparticle.cpp | 2 +- .../particles/qsgparticleaffector.cpp | 18 +- .../particles/qsgparticleaffector_p.h | 20 +- .../particles/qsgparticleemitter.cpp | 6 +- .../particles/qsgparticleemitter_p.h | 18 +- .../particles/qsgparticlegroup.cpp | 142 ++++++++++++ .../particles/qsgparticlegroup_p.h | 107 +++++++++ .../particles/qsgparticlepainter.cpp | 6 +- .../particles/qsgparticlepainter_p.h | 18 +- .../particles/qsgparticlesmodule.cpp | 2 + .../particles/qsgparticlesystem.cpp | 117 +++++----- .../particles/qsgparticlesystem_p.h | 13 +- src/declarative/particles/qsgspritegoal.cpp | 12 +- src/declarative/particles/qsgspritegoal_p.h | 6 +- src/declarative/particles/qsgtrailemitter.cpp | 2 +- src/declarative/particles/qsgtrailemitter_p.h | 2 +- 50 files changed, 803 insertions(+), 507 deletions(-) create mode 100644 src/declarative/particles/qsgparticlegroup.cpp create mode 100644 src/declarative/particles/qsgparticlegroup_p.h diff --git a/examples/declarative/animation/basics/color-animation.qml b/examples/declarative/animation/basics/color-animation.qml index a83dbab569..9e0f29c4ec 100644 --- a/examples/declarative/animation/basics/color-animation.qml +++ b/examples/declarative/animation/basics/color-animation.qml @@ -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 diff --git a/examples/declarative/flickr/flickr.qml b/examples/declarative/flickr/flickr.qml index 14e4fcaedf..4397d0ad76 100644 --- a/examples/declarative/flickr/flickr.qml +++ b/examples/declarative/flickr/flickr.qml @@ -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 diff --git a/examples/declarative/minehunt/MinehuntCore/Explosion.qml b/examples/declarative/minehunt/MinehuntCore/Explosion.qml index 225c19d8a3..af98ad1309 100644 --- a/examples/declarative/minehunt/MinehuntCore/Explosion.qml +++ b/examples/declarative/minehunt/MinehuntCore/Explosion.qml @@ -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 diff --git a/examples/declarative/particles/allsmiles/smilefactory.qml b/examples/declarative/particles/allsmiles/smilefactory.qml index fe651491b9..4b01862f99 100644 --- a/examples/declarative/particles/allsmiles/smilefactory.qml +++ b/examples/declarative/particles/allsmiles/smilefactory.qml @@ -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 diff --git a/examples/declarative/particles/allsmiles/spriteparticles.qml b/examples/declarative/particles/allsmiles/spriteparticles.qml index 705016e050..0586dfd8db 100644 --- a/examples/declarative/particles/allsmiles/spriteparticles.qml +++ b/examples/declarative/particles/allsmiles/spriteparticles.qml @@ -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 diff --git a/examples/declarative/particles/asteroid/asteroid.qml b/examples/declarative/particles/asteroid/asteroid.qml index ea2fabd51d..6d556997c7 100644 --- a/examples/declarative/particles/asteroid/asteroid.qml +++ b/examples/declarative/particles/asteroid/asteroid.qml @@ -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 diff --git a/examples/declarative/particles/asteroid/blackhole.qml b/examples/declarative/particles/asteroid/blackhole.qml index 7e8a7a9edc..00fca7ef3c 100644 --- a/examples/declarative/particles/asteroid/blackhole.qml +++ b/examples/declarative/particles/asteroid/blackhole.qml @@ -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 diff --git a/examples/declarative/particles/trails/combustion.qml b/examples/declarative/particles/trails/combustion.qml index e4a21e9beb..238dbe8a79 100644 --- a/examples/declarative/particles/trails/combustion.qml +++ b/examples/declarative/particles/trails/combustion.qml @@ -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 diff --git a/examples/declarative/particles/trails/fireballs.qml b/examples/declarative/particles/trails/fireballs.qml index 97a0c0ac5f..c7c0420049 100644 --- a/examples/declarative/particles/trails/fireballs.qml +++ b/examples/declarative/particles/trails/fireballs.qml @@ -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 diff --git a/examples/declarative/particles/trails/fireworks.qml b/examples/declarative/particles/trails/fireworks.qml index 437d9ee3d6..6b370b3991 100644 --- a/examples/declarative/particles/trails/fireworks.qml +++ b/examples/declarative/particles/trails/fireworks.qml @@ -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 } diff --git a/examples/declarative/particles/trails/portal.qml b/examples/declarative/particles/trails/portal.qml index 85efd9a594..adf620fd9b 100644 --- a/examples/declarative/particles/trails/portal.qml +++ b/examples/declarative/particles/trails/portal.qml @@ -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 diff --git a/examples/declarative/particles/trails/turbulence.qml b/examples/declarative/particles/trails/turbulence.qml index 104bb10e80..13eae162f4 100644 --- a/examples/declarative/particles/trails/turbulence.qml +++ b/examples/declarative/particles/trails/turbulence.qml @@ -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 diff --git a/examples/declarative/plasmapatrol/content/BlasterHardpoint.qml b/examples/declarative/plasmapatrol/content/BlasterHardpoint.qml index 384275fc94..3e751f4e15 100644 --- a/examples/declarative/plasmapatrol/content/BlasterHardpoint.qml +++ b/examples/declarative/plasmapatrol/content/BlasterHardpoint.qml @@ -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 diff --git a/examples/declarative/plasmapatrol/content/CannonHardpoint.qml b/examples/declarative/plasmapatrol/content/CannonHardpoint.qml index b2c7aca1fd..dc15f0cae1 100644 --- a/examples/declarative/plasmapatrol/content/CannonHardpoint.qml +++ b/examples/declarative/plasmapatrol/content/CannonHardpoint.qml @@ -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 diff --git a/examples/declarative/plasmapatrol/content/Cruiser.qml b/examples/declarative/plasmapatrol/content/Cruiser.qml index b0d20023db..a4983fc2a0 100644 --- a/examples/declarative/plasmapatrol/content/Cruiser.qml +++ b/examples/declarative/plasmapatrol/content/Cruiser.qml @@ -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 diff --git a/examples/declarative/plasmapatrol/content/Frigate.qml b/examples/declarative/plasmapatrol/content/Frigate.qml index 8d493b81d5..f26e7e881c 100644 --- a/examples/declarative/plasmapatrol/content/Frigate.qml +++ b/examples/declarative/plasmapatrol/content/Frigate.qml @@ -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 diff --git a/examples/declarative/plasmapatrol/content/LaserHardpoint.qml b/examples/declarative/plasmapatrol/content/LaserHardpoint.qml index 45712bf68a..56fd91b5b3 100644 --- a/examples/declarative/plasmapatrol/content/LaserHardpoint.qml +++ b/examples/declarative/plasmapatrol/content/LaserHardpoint.qml @@ -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); diff --git a/examples/declarative/plasmapatrol/content/PlasmaPatrolParticles.qml b/examples/declarative/plasmapatrol/content/PlasmaPatrolParticles.qml index 792ba7ab72..7a8c3e61b3 100644 --- a/examples/declarative/plasmapatrol/content/PlasmaPatrolParticles.qml +++ b/examples/declarative/plasmapatrol/content/PlasmaPatrolParticles.qml @@ -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 diff --git a/examples/declarative/plasmapatrol/content/Sloop.qml b/examples/declarative/plasmapatrol/content/Sloop.qml index 82e57f5161..59678a75ea 100644 --- a/examples/declarative/plasmapatrol/content/Sloop.qml +++ b/examples/declarative/plasmapatrol/content/Sloop.qml @@ -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 diff --git a/examples/declarative/plasmapatrol/plasmapatrol.qml b/examples/declarative/plasmapatrol/plasmapatrol.qml index 4ea464b9f8..2fa9f44929 100644 --- a/examples/declarative/plasmapatrol/plasmapatrol.qml +++ b/examples/declarative/plasmapatrol/plasmapatrol.qml @@ -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"} diff --git a/examples/declarative/samegame/SamegameCore/BoomBlock.qml b/examples/declarative/samegame/SamegameCore/BoomBlock.qml index 1c84fa8614..df3e9bd8fa 100644 --- a/examples/declarative/samegame/SamegameCore/BoomBlock.qml +++ b/examples/declarative/samegame/SamegameCore/BoomBlock.qml @@ -75,7 +75,7 @@ Item { Emitter { id: particles system: particleSystem - particle: { + group: { if(type == 0){ "red"; } else if (type == 1) { diff --git a/examples/declarative/samegame/SamegameCore/GameArea.qml b/examples/declarative/samegame/SamegameCore/GameArea.qml index 967e299577..9a8f68ad89 100644 --- a/examples/declarative/samegame/SamegameCore/GameArea.qml +++ b/examples/declarative/samegame/SamegameCore/GameArea.qml @@ -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 diff --git a/examples/declarative/snake/content/Cookie.qml b/examples/declarative/snake/content/Cookie.qml index e3b3bbf3f5..d9fedd9436 100644 --- a/examples/declarative/snake/content/Cookie.qml +++ b/examples/declarative/snake/content/Cookie.qml @@ -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 diff --git a/examples/declarative/snake/content/Link.qml b/examples/declarative/snake/content/Link.qml index 82e0359a1a..31ad62248c 100644 --- a/examples/declarative/snake/content/Link.qml +++ b/examples/declarative/snake/content/Link.qml @@ -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 diff --git a/examples/declarative/toys/dynamicscene/dynamicscene.qml b/examples/declarative/toys/dynamicscene/dynamicscene.qml index 5670aacfa7..179d633c97 100644 --- a/examples/declarative/toys/dynamicscene/dynamicscene.qml +++ b/examples/declarative/toys/dynamicscene/dynamicscene.qml @@ -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" } } diff --git a/src/declarative/items/qsgsprite.cpp b/src/declarative/items/qsgsprite.cpp index 806f7a9ad8..63d1951b7c 100644 --- a/src/declarative/items/qsgsprite.cpp +++ b/src/declarative/items/qsgsprite.cpp @@ -40,42 +40,17 @@ ****************************************************************************/ #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 diff --git a/src/declarative/items/qsgsprite_p.h b/src/declarative/items/qsgsprite_p.h index c18e9b4505..ed7c6c4be4 100644 --- a/src/declarative/items/qsgsprite_p.h +++ b/src/declarative/items/qsgsprite_p.h @@ -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; }; diff --git a/src/declarative/items/qsgspriteengine.cpp b/src/declarative/items/qsgspriteengine.cpp index 1915db6000..0391ce1281 100644 --- a/src/declarative/items/qsgspriteengine.cpp +++ b/src/declarative/items/qsgspriteengine.cpp @@ -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){ diff --git a/src/declarative/items/qsgspriteengine_p.h b/src/declarative/items/qsgspriteengine_p.h index 10860a51f1..b2a06f2c87 100644 --- a/src/declarative/items/qsgspriteengine_p.h +++ b/src/declarative/items/qsgspriteengine_p.h @@ -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) { diff --git a/src/declarative/items/qsgspriteimage.cpp b/src/declarative/items/qsgspriteimage.cpp index afa80e4aa1..5557ea564a 100644 --- a/src/declarative/items/qsgspriteimage.cpp +++ b/src/declarative/items/qsgspriteimage.cpp @@ -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(); diff --git a/src/declarative/particles/particles.pri b/src/declarative/particles/particles.pri index 527bd9ae61..8676e52172 100644 --- a/src/declarative/particles/particles.pri +++ b/src/declarative/particles/particles.pri @@ -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 diff --git a/src/declarative/particles/qsgcustomparticle.cpp b/src/declarative/particles/qsgcustomparticle.cpp index ab4cfa0a3a..a1d65a5360 100644 --- a/src/declarative/particles/qsgcustomparticle.cpp +++ b/src/declarative/particles/qsgcustomparticle.cpp @@ -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 diff --git a/src/declarative/particles/qsgimageparticle.cpp b/src/declarative/particles/qsgimageparticle.cpp index 581024d578..b1aef784e8 100644 --- a/src/declarative/particles/qsgimageparticle.cpp +++ b/src/declarative/particles/qsgimageparticle.cpp @@ -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{ diff --git a/src/declarative/particles/qsgimageparticle_p.h b/src/declarative/particles/qsgimageparticle_p.h index 01eacbad99..1f87b16f63 100644 --- a/src/declarative/particles/qsgimageparticle_p.h +++ b/src/declarative/particles/qsgimageparticle_p.h @@ -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, diff --git a/src/declarative/particles/qsgitemparticle.cpp b/src/declarative/particles/qsgitemparticle.cpp index c330880980..2572d67783 100644 --- a/src/declarative/particles/qsgitemparticle.cpp +++ b/src/declarative/particles/qsgitemparticle.cpp @@ -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(); diff --git a/src/declarative/particles/qsgparticleaffector.cpp b/src/declarative/particles/qsgparticleaffector.cpp index cff3c29444..7cb4869f3e 100644 --- a/src/declarative/particles/qsgparticleaffector.cpp +++ b/src/declarative/particles/qsgparticleaffector.cpp @@ -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)); } diff --git a/src/declarative/particles/qsgparticleaffector_p.h b/src/declarative/particles/qsgparticleaffector_p.h index 5700969aad..0dadeff6a7 100644 --- a/src/declarative/particles/qsgparticleaffector_p.h +++ b/src/declarative/particles/qsgparticleaffector_p.h @@ -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; diff --git a/src/declarative/particles/qsgparticleemitter.cpp b/src/declarative/particles/qsgparticleemitter.cpp index 13ab3e6185..fdba3def41 100644 --- a/src/declarative/particles/qsgparticleemitter.cpp +++ b/src/declarative/particles/qsgparticleemitter.cpp @@ -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; diff --git a/src/declarative/particles/qsgparticleemitter_p.h b/src/declarative/particles/qsgparticleemitter_p.h index 8ed7ee7053..8bd205b207 100644 --- a/src/declarative/particles/qsgparticleemitter_p.h +++ b/src/declarative/particles/qsgparticleemitter_p.h @@ -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 index 0000000000..28eb4d2c85 --- /dev/null +++ b/src/declarative/particles/qsgparticlegroup.cpp @@ -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 index 0000000000..346b4ab77e --- /dev/null +++ b/src/declarative/particles/qsgparticlegroup_p.h @@ -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 diff --git a/src/declarative/particles/qsgparticlepainter.cpp b/src/declarative/particles/qsgparticlepainter.cpp index f4639c20a2..670c1f2118 100644 --- a/src/declarative/particles/qsgparticlepainter.cpp +++ b/src/declarative/particles/qsgparticlepainter.cpp @@ -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); diff --git a/src/declarative/particles/qsgparticlepainter_p.h b/src/declarative/particles/qsgparticlepainter_p.h index 08ae3aede8..d469947453 100644 --- a/src/declarative/particles/qsgparticlepainter_p.h +++ b/src/declarative/particles/qsgparticlepainter_p.h @@ -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: diff --git a/src/declarative/particles/qsgparticlesmodule.cpp b/src/declarative/particles/qsgparticlesmodule.cpp index 9fa0ebad97..f880842acb 100644 --- a/src/declarative/particles/qsgparticlesmodule.cpp +++ b/src/declarative/particles/qsgparticlesmodule.cpp @@ -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"); diff --git a/src/declarative/particles/qsgparticlesystem.cpp b/src/declarative/particles/qsgparticlesystem.cpp index 085e6afe64..bc27073142 100644 --- a/src/declarative/particles/qsgparticlesystem.cpp +++ b/src/declarative/particles/qsgparticlesystem.cpp @@ -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) diff --git a/src/declarative/particles/qsgparticlesystem_p.h b/src/declarative/particles/qsgparticlesystem_p.h index 25a0c87f53..f531e7fcf9 100644 --- a/src/declarative/particles/qsgparticlesystem_p.h +++ b/src/declarative/particles/qsgparticlesystem_p.h @@ -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; diff --git a/src/declarative/particles/qsgspritegoal.cpp b/src/declarative/particles/qsgspritegoal.cpp index 1837167813..ec2be02326 100644 --- a/src/declarative/particles/qsgspritegoal.cpp +++ b/src/declarative/particles/qsgspritegoal.cpp @@ -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 diff --git a/src/declarative/particles/qsgspritegoal_p.h b/src/declarative/particles/qsgspritegoal_p.h index 7c799b13b1..043970b90b 100644 --- a/src/declarative/particles/qsgspritegoal_p.h +++ b/src/declarative/particles/qsgspritegoal_p.h @@ -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; diff --git a/src/declarative/particles/qsgtrailemitter.cpp b/src/declarative/particles/qsgtrailemitter.cpp index 427b587caf..5a19ac508b 100644 --- a/src/declarative/particles/qsgtrailemitter.cpp +++ b/src/declarative/particles/qsgtrailemitter.cpp @@ -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 diff --git a/src/declarative/particles/qsgtrailemitter_p.h b/src/declarative/particles/qsgtrailemitter_p.h index 5ab6f24270..009ccd508c 100644 --- a/src/declarative/particles/qsgtrailemitter_p.h +++ b/src/declarative/particles/qsgtrailemitter_p.h @@ -94,7 +94,7 @@ public: } signals: - void emitFollowParticle(QDeclarativeV8Handle particle, QDeclarativeV8Handle followed); + void emitFollowParticle(QDeclarativeV8Handle group, QDeclarativeV8Handle followed); void particlesPerParticlePerSecondChanged(int arg); -- GitLab