Add some more properties to JS particle type
[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 <QSGItem>
46 #include <QElapsedTimer>
47 #include <QVector>
48 #include <QHash>
49 #include <QPointer>
50 #include <QSignalMapper>
51 #include <QtDeclarative/private/qsgsprite_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 QSGSpriteEngine;
69 class QSGSprite;
70 class QSGV8ParticleData;
71
72 struct QSGParticleDataHeapNode{
73     int time;//in ms
74     QSet<QSGParticleData*> data;//Set ptrs instead?
75 };
76
77 class QSGParticleDataHeap {
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     QSGParticleDataHeap();
82     void insert(QSGParticleData* data);
83
84     int top();
85
86     QSet<QSGParticleData*> pop();
87
88     void clear();
89
90     bool contains(QSGParticleData*);//O(n), for debugging purposes only
91 private:
92     void grow();
93     void swap(int, int);
94     void bubbleUp(int);
95     void bubbleDown(int);
96     int m_size;
97     int m_end;
98     QSGParticleDataHeapNode m_tmp;
99     QVector<QSGParticleDataHeapNode> m_data;
100     QHash<int,int> m_lookups;
101 };
102
103 class QSGParticleGroupData{
104 public:
105     QSGParticleGroupData(int id, QSGParticleSystem* sys);
106     ~QSGParticleGroupData();
107
108     int size();
109     QString name();
110
111     void setSize(int newSize);
112
113     int index;
114     QSet<QSGParticlePainter*> painters;
115
116     //TODO: Refactor particle data list out into a separate class
117     QVector<QSGParticleData*> data;
118     QSGParticleDataHeap dataHeap;
119     QSet<int> reusableIndexes;
120
121     void initList();
122     void kill(QSGParticleData* d);
123
124     //After calling this, initialize, then call prepareRecycler(d)
125     QSGParticleData* newDatum(bool respectsLimits);
126
127     //TODO: Find and clean up those that don't get added to the recycler (currently they get lost)
128     void prepareRecycler(QSGParticleData* d);
129
130 private:
131     int m_size;
132     QSGParticleSystem* m_system;
133 };
134
135 struct Color4ub {
136     uchar r;
137     uchar g;
138     uchar b;
139     uchar a;
140 };
141
142 class QSGParticleData{
143 public:
144     //TODO: QObject like memory management (without the cost, just attached to system)
145     QSGParticleData(QSGParticleSystem* sys);
146
147     //Convenience functions for working backwards, because parameters are from the start of particle life
148     //If setting multiple parameters at once, doing the conversion yourself will be faster.
149
150     //sets the x accleration without affecting the instantaneous x velocity or position
151     void setInstantaneousAX(qreal ax);
152     //sets the x velocity without affecting the instantaneous x postion
153     void setInstantaneousVX(qreal vx);
154     //sets the instantaneous x postion
155     void setInstantaneousX(qreal x);
156     //sets the y accleration without affecting the instantaneous y velocity or position
157     void setInstantaneousAY(qreal ay);
158     //sets the y velocity without affecting the instantaneous y postion
159     void setInstantaneousVY(qreal vy);
160     //sets the instantaneous Y postion
161     void setInstantaneousY(qreal y);
162
163     //TODO: Slight caching?
164     qreal curX() const;
165     qreal curVX() const;
166     qreal curAX() const { return ax; }
167     qreal curY() const;
168     qreal curVY() const;
169     qreal curAY() const { return ay; }
170
171     int group;
172     QSGParticleEmitter* e;//### Needed?
173     QSGParticleSystem* system;
174     int index;
175     int systemIndex;
176
177     //General Position Stuff
178     float x;
179     float y;
180     float t;
181     float lifeSpan;
182     float size;
183     float endSize;
184     float vx;
185     float vy;
186     float ax;
187     float ay;
188
189     //Other stuff, now universally shared
190     Color4ub color;
191     float xx;
192     float xy;
193     float yx;
194     float yy;
195     float rotation;
196     float rotationSpeed;
197     float autoRotate;//Assume that GPUs prefer floats to bools
198     float animIdx;
199     float frameDuration;
200     float frameCount;
201     float animT;
202     float r;
203     QSGItem* delegate;
204     int modelIndex;
205
206     void debugDump();
207     bool stillAlive();
208     float lifeLeft();
209     float curSize();
210     void clone(const QSGParticleData& other);//Not =, leaves meta-data like index
211     QDeclarativeV8Handle v8Value();
212 private:
213     QSGV8ParticleData* v8Datum;
214 };
215
216 class QSGParticleSystem : public QSGItem
217 {
218     Q_OBJECT
219     Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
220     Q_PROPERTY(int startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged)
221     Q_PROPERTY(QDeclarativeListProperty<QSGSprite> particleStates READ particleStates)
222
223 public:
224     explicit QSGParticleSystem(QSGItem *parent = 0);
225     ~QSGParticleSystem();
226     QDeclarativeListProperty<QSGSprite> particleStates();
227
228     //TODO: Hook up running and temporal manipulators to the animation
229     bool isRunning() const
230     {
231         return m_running;
232     }
233
234     int startTime() const
235     {
236         return m_startTime;
237     }
238
239     int count(){ return m_particle_count; }
240
241 signals:
242
243     void systemInitialized();
244     void runningChanged(bool arg);
245
246     void startTimeChanged(int arg);
247
248
249 public slots:
250     void reset();
251     void setRunning(bool arg);
252
253
254     void setStartTime(int arg)
255     {
256         m_startTime = arg;
257     }
258
259     void fastForward(int ms)
260     {
261         m_startTime += ms;
262     }
263
264     virtual int duration() const { return -1; }
265
266 protected:
267     //This one only once per frame (effectively)
268     void componentComplete();
269
270 private slots:
271     void emittersChanged();
272     void loadPainter(QObject* p);
273     void createEngine(); //### method invoked by sprite list changing (in engine.h) - pretty nasty
274     void particleStateChange(int idx);
275
276 public://###but only really for related class usage. Perhaps we should all be friends?
277     //These can be called multiple times per frame, performance critical
278     void emitParticle(QSGParticleData* p);
279     QSGParticleData* newDatum(int groupId, bool respectLimits = true, int sysIdx = -1);//TODO: implement respectLimits in emitters (which means interacting with maxCount?)
280     void finishNewDatum(QSGParticleData*);
281     void moveGroups(QSGParticleData *d, int newGIdx);
282     int nextSystemIndex();
283
284     //This one only once per painter per frame
285     int systemSync(QSGParticlePainter* p);
286
287     QSet<QSGParticleData*> m_needsReset;
288     QVector<QSGParticleData*> m_bySysIdx; //Another reference to the data (data owned by group), but by sysIdx
289     QHash<QString, int> m_groupIds;
290     QHash<int, QSGParticleGroupData*> m_groupData;
291     QSGSpriteEngine* m_spriteEngine;
292
293     int m_timeInt;
294     bool m_initialized;
295
296     void registerParticlePainter(QSGParticlePainter* p);
297     void registerParticleEmitter(QSGParticleEmitter* e);
298     void registerParticleAffector(QSGParticleAffector* a);
299
300     int m_particle_count;
301     static void stateRedirect(QDeclarativeListProperty<QObject> *prop, QObject *value);//From QSGSprite
302 private:
303     void initializeSystem();
304     bool m_running;
305     QList<QPointer<QSGParticleEmitter> > m_emitters;
306     QList<QPointer<QSGParticleAffector> > m_affectors;
307     QList<QPointer<QSGParticlePainter> > m_particlePainters;
308     QList<QPointer<QSGParticlePainter> > m_syncList;
309     qint64 m_startTime;
310     int m_nextGroupId;
311     int m_nextIndex;
312     QSet<int> m_reusableIndexes;
313     bool m_componentComplete;
314     QList<QSGSprite*> m_states;
315
316     QSignalMapper m_painterMapper;
317     QSignalMapper m_emitterMapper;
318     friend class QSGParticleSystemAnimation;
319     void updateCurrentTime( int currentTime );
320     QSGParticleSystemAnimation* m_animation;
321 };
322
323 // Internally, this animation drives all the timing. Painters sync up in their updatePaintNode
324 class QSGParticleSystemAnimation : public QAbstractAnimation
325 {
326     Q_OBJECT
327 public:
328     QSGParticleSystemAnimation(QSGParticleSystem* system)
329         : QAbstractAnimation(static_cast<QObject*>(system)), m_system(system)
330     { }
331 protected:
332     virtual void updateCurrentTime( int t )
333     {
334         m_system->updateCurrentTime(t);
335     }
336
337     virtual int duration() const
338     {
339         return -1;
340     }
341
342 private:
343     QSGParticleSystem* m_system;
344 };
345
346
347 QT_END_NAMESPACE
348
349 QT_END_HEADER
350
351 #endif // PARTICLESYSTEM_H
352
353