Rename speed -> velocity in the particle system
[profile/ivi/qtdeclarative.git] / src / particles / qquickparticlesystem_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQuick module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef PARTICLESYSTEM_H
43 #define PARTICLESYSTEM_H
44
45 #include <QtQuick/QQuickItem>
46 #include <QElapsedTimer>
47 #include <QVector>
48 #include <QHash>
49 #include <QPointer>
50 #include <QSignalMapper>
51 #include <private/qquicksprite_p.h>
52 #include <QAbstractAnimation>
53 #include <QtQml/qqml.h>
54 #include <private/qv8engine_p.h> //For QQmlV8Handle
55
56 QT_BEGIN_HEADER
57
58 QT_BEGIN_NAMESPACE
59
60 class QQuickParticleSystem;
61 class QQuickParticleAffector;
62 class QQuickParticleEmitter;
63 class QQuickParticlePainter;
64 class QQuickParticleData;
65 class QQuickParticleSystemAnimation;
66 class QQuickStochasticEngine;
67 class QQuickSprite;
68 class QQuickV8ParticleData;
69 class QQuickParticleGroup;
70 class QQuickImageParticle;
71
72 struct QQuickParticleDataHeapNode{
73     int time;//in ms
74     QSet<QQuickParticleData*> data;//Set ptrs instead?
75 };
76
77 class QQuickParticleDataHeap {
78     //Idea is to do a binary heap, but which also stores a set of int,Node* so that if the int already exists, you can
79     //add it to the data* list. Pops return the whole list at once.
80 public:
81     QQuickParticleDataHeap();
82     void insert(QQuickParticleData* data);
83     void insertTimed(QQuickParticleData* data, int time);
84
85     int top();
86
87     QSet<QQuickParticleData*> pop();
88
89     void clear();
90
91     bool contains(QQuickParticleData*);//O(n), for debugging purposes only
92 private:
93     void grow();
94     void swap(int, int);
95     void bubbleUp(int);
96     void bubbleDown(int);
97     int m_size;
98     int m_end;
99     QQuickParticleDataHeapNode m_tmp;
100     QVector<QQuickParticleDataHeapNode> m_data;
101     QHash<int,int> m_lookups;
102 };
103
104 class Q_AUTOTEST_EXPORT QQuickParticleGroupData {
105 public:
106     QQuickParticleGroupData(int id, QQuickParticleSystem* sys);
107     ~QQuickParticleGroupData();
108
109     int size();
110     QString name();
111
112     void setSize(int newSize);
113
114     int index;
115     QSet<QQuickParticlePainter*> painters;//TODO: What if they are dynamically removed?
116
117     //TODO: Refactor particle data list out into a separate class
118     QVector<QQuickParticleData*> data;
119     QQuickParticleDataHeap dataHeap;
120     QSet<int> reusableIndexes;
121     bool recycle(); //Force recycling round, returns true if all indexes are now reusable
122
123     void initList();
124     void kill(QQuickParticleData* d);
125
126     //After calling this, initialize, then call prepareRecycler(d)
127     QQuickParticleData* newDatum(bool respectsLimits);
128
129     //TODO: Find and clean up those that don't get added to the recycler (currently they get lost)
130     void prepareRecycler(QQuickParticleData* d);
131
132 private:
133     int m_size;
134     QQuickParticleSystem* m_system;
135 };
136
137 struct Color4ub {
138     uchar r;
139     uchar g;
140     uchar b;
141     uchar a;
142 };
143
144 class Q_AUTOTEST_EXPORT QQuickParticleData {
145 public:
146     //TODO: QObject like memory management (without the cost, just attached to system)
147     QQuickParticleData(QQuickParticleSystem* sys);
148     ~QQuickParticleData();
149
150     //Convenience functions for working backwards, because parameters are from the start of particle life
151     //If setting multiple parameters at once, doing the conversion yourself will be faster.
152
153     //sets the x accleration without affecting the instantaneous x velocity or position
154     void setInstantaneousAX(qreal ax);
155     //sets the x velocity without affecting the instantaneous x postion
156     void setInstantaneousVX(qreal vx);
157     //sets the instantaneous x postion
158     void setInstantaneousX(qreal x);
159     //sets the y accleration without affecting the instantaneous y velocity or position
160     void setInstantaneousAY(qreal ay);
161     //sets the y velocity without affecting the instantaneous y postion
162     void setInstantaneousVY(qreal vy);
163     //sets the instantaneous Y postion
164     void setInstantaneousY(qreal y);
165
166     //TODO: Slight caching?
167     qreal curX() const;
168     qreal curVX() const;
169     qreal curAX() const { return ax; }
170     qreal curY() const;
171     qreal curVY() const;
172     qreal curAY() const { return ay; }
173
174     int group;
175     QQuickParticleEmitter* e;//### Needed?
176     QQuickParticleSystem* system;
177     int index;
178     int systemIndex;
179
180     //General Position Stuff
181     float x;
182     float y;
183     float t;
184     float lifeSpan;
185     float size;
186     float endSize;
187     float vx;
188     float vy;
189     float ax;
190     float ay;
191
192     //Painter-specific stuff, now universally shared
193     //Used by ImageParticle color mode
194     Color4ub color;
195     //Used by ImageParticle deform mode
196     float xx;
197     float xy;
198     float yx;
199     float yy;
200     float rotation;
201     float rotationVelocity;
202     float autoRotate;//Assume that GPUs prefer floats to bools
203     //Used by ImageParticle Sprite mode
204     float animIdx;
205     float frameDuration;
206     float frameAt;//Used for duration -1
207     float frameCount;
208     float animT;
209     float animX;
210     float animY;
211     float animWidth;
212     float animHeight;
213     //Used by ImageParticle data shadowing
214     QQuickImageParticle* colorOwner;
215     QQuickImageParticle* rotationOwner;
216     QQuickImageParticle* deformationOwner;
217     QQuickImageParticle* animationOwner;
218     //Used by CustomParticle
219     float r;
220     //Used by ItemParticle
221     QQuickItem* delegate;
222     int modelIndex;
223     //Used by custom affectors
224     float update;
225
226
227     void debugDump();
228     bool stillAlive();//Only checks end, because usually that's all you need and it's a little faster.
229     bool alive();
230     float lifeLeft();
231     float curSize();
232     void clone(const QQuickParticleData& other);//Not =, leaves meta-data like index
233     QQmlV8Handle v8Value();
234     void extendLife(float time);
235 private:
236     QQuickV8ParticleData* v8Datum;
237 };
238
239 class Q_AUTOTEST_EXPORT QQuickParticleSystem : public QQuickItem
240 {
241     Q_OBJECT
242     Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
243     Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged)
244     Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged)
245
246 public:
247     explicit QQuickParticleSystem(QQuickItem *parent = 0);
248     ~QQuickParticleSystem();
249
250     bool isRunning() const
251     {
252         return m_running;
253     }
254
255     int count(){ return particleCount; }
256
257     static const int maxLife = 600000;
258
259 signals:
260
261     void systemInitialized();
262     void runningChanged(bool arg);
263     void pausedChanged(bool arg);
264     void emptyChanged(bool arg);
265
266 public slots:
267     void start(){setRunning(true);}
268     void stop(){setRunning(false);}
269     void restart(){setRunning(false);setRunning(true);}
270     void pause(){setPaused(true);}
271     void resume(){setPaused(false);}
272
273     void reset();
274     void setRunning(bool arg);
275     void setPaused(bool arg);
276
277     virtual int duration() const { return -1; }
278
279
280 protected:
281     //This one only once per frame (effectively)
282     void componentComplete();
283
284 private slots:
285     void emittersChanged();
286     void loadPainter(QObject* p);
287     void createEngine(); //Not invoked by sprite engine, unlike Sprite uses
288     void particleStateChange(int idx);
289
290 public:
291     //These can be called multiple times per frame, performance critical
292     void emitParticle(QQuickParticleData* p);
293     QQuickParticleData* newDatum(int groupId, bool respectLimits = true, int sysIdx = -1);
294     void finishNewDatum(QQuickParticleData*);
295     void moveGroups(QQuickParticleData *d, int newGIdx);
296     int nextSystemIndex();
297
298     //This one only once per painter per frame
299     int systemSync(QQuickParticlePainter* p);
300
301     //Data members here for ease of related class and auto-test usage. Not "public" API. TODO: d_ptrize
302     QSet<QQuickParticleData*> needsReset;
303     QVector<QQuickParticleData*> bySysIdx; //Another reference to the data (data owned by group), but by sysIdx
304     QHash<QString, int> groupIds;
305     QHash<int, QQuickParticleGroupData*> groupData;
306     QQuickStochasticEngine* stateEngine;
307
308     //Also only here for auto-test usage
309     void updateCurrentTime( int currentTime );
310     QQuickParticleSystemAnimation* m_animation;
311     bool m_running;
312     bool m_debugMode;
313
314     int timeInt;
315     bool initialized;
316     int particleCount;
317
318     void registerParticlePainter(QQuickParticlePainter* p);
319     void registerParticleEmitter(QQuickParticleEmitter* e);
320     void registerParticleAffector(QQuickParticleAffector* a);
321     void registerParticleGroup(QQuickParticleGroup* g);
322
323     static void statePropertyRedirect(QQmlListProperty<QObject> *prop, QObject *value);
324     static void stateRedirect(QQuickParticleGroup* group, QQuickParticleSystem* sys, QObject *value);
325     bool isPaused() const
326     {
327         return m_paused;
328     }
329
330     bool isEmpty() const
331     {
332         return m_empty;
333     }
334
335 private:
336     void initializeSystem();
337     void initGroups();
338     QList<QPointer<QQuickParticleEmitter> > m_emitters;
339     QList<QPointer<QQuickParticleAffector> > m_affectors;
340     QList<QPointer<QQuickParticlePainter> > m_painters;
341     QList<QPointer<QQuickParticlePainter> > m_syncList;
342     QList<QQuickParticleGroup*> m_groups;
343     int m_nextGroupId;
344     int m_nextIndex;
345     QSet<int> m_reusableIndexes;
346     bool m_componentComplete;
347
348     QSignalMapper m_painterMapper;
349     QSignalMapper m_emitterMapper;
350     bool m_paused;
351     bool m_allDead;
352     bool m_empty;
353 };
354
355 // Internally, this animation drives all the timing. Painters sync up in their updatePaintNode
356 class QQuickParticleSystemAnimation : public QAbstractAnimation
357 {
358     Q_OBJECT
359 public:
360     QQuickParticleSystemAnimation(QQuickParticleSystem* system)
361         : QAbstractAnimation(static_cast<QObject*>(system)), m_system(system)
362     { }
363 protected:
364     virtual void updateCurrentTime( int t )
365     {
366         m_system->updateCurrentTime(t);
367     }
368
369     virtual int duration() const
370     {
371         return -1;
372     }
373
374 private:
375     QQuickParticleSystem* m_system;
376 };
377
378
379 QT_END_NAMESPACE
380
381 QT_END_HEADER
382
383 #endif // PARTICLESYSTEM_H
384
385