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