1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QQUICKIMAGEPARTICLE_P_H
5#define QQUICKIMAGEPARTICLE_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include "qquickparticlepainter_p.h"
19#include "qquickdirection_p.h"
20#include <private/qquickpixmapcache_p.h>
21#include <QQmlListProperty>
22#include <QtGui/qcolor.h>
23#include <QtQuick/qsgmaterial.h>
24
25QT_BEGIN_NAMESPACE
26
27class ImageMaterialData;
28class QSGGeometryNode;
29class QSGMaterial;
30
31class QQuickSprite;
32class QQuickStochasticEngine;
33
34class QRhi;
35
36struct SimplePointVertex {
37 float x;
38 float y;
39 float t;
40 float lifeSpan;
41 float size;
42 float endSize;
43 float vx;
44 float vy;
45 float ax;
46 float ay;
47};
48
49struct ColoredPointVertex {
50 float x;
51 float y;
52 float t;
53 float lifeSpan;
54 float size;
55 float endSize;
56 float vx;
57 float vy;
58 float ax;
59 float ay;
60 Color4ub color;
61};
62
63// Like Colored, but using DrawTriangles instead of DrawPoints
64struct ColoredVertex {
65 float x;
66 float y;
67 float t;
68 float lifeSpan;
69 float size;
70 float endSize;
71 float vx;
72 float vy;
73 float ax;
74 float ay;
75 Color4ub color;
76 uchar tx;
77 uchar ty;
78 uchar _padding[2]; // feel free to use
79};
80
81struct DeformableVertex {
82 float x;
83 float y;
84 float rotation;
85 float rotationVelocity;
86 float t;
87 float lifeSpan;
88 float size;
89 float endSize;
90 float vx;
91 float vy;
92 float ax;
93 float ay;
94 Color4ub color;
95 float xx;
96 float xy;
97 float yx;
98 float yy;
99 uchar tx;
100 uchar ty;
101 uchar autoRotate;
102 uchar _padding; // feel free to use
103};
104
105struct SpriteVertex {
106 float x;
107 float y;
108 float rotation;
109 float rotationVelocity;
110 float t;
111 float lifeSpan;
112 float size;
113 float endSize;
114 float vx;
115 float vy;
116 float ax;
117 float ay;
118 Color4ub color;
119 float xx;
120 float xy;
121 float yx;
122 float yy;
123 uchar tx;
124 uchar ty;
125 uchar autoRotate;
126 uchar _padding; // feel free to use
127 float animW;
128 float animH;
129 float animProgress;
130 float animX1;
131 float animY1;
132 float animX2;
133};
134
135template <typename Vertex>
136struct Vertices {
137 Vertex v1;
138 Vertex v2;
139 Vertex v3;
140 Vertex v4;
141};
142
143class ImageMaterial : public QSGMaterial
144{
145public:
146 virtual ImageMaterialData *state() = 0;
147};
148
149class Q_QUICKPARTICLES_PRIVATE_EXPORT QQuickImageParticle : public QQuickParticlePainter
150{
151 Q_OBJECT
152 Q_PROPERTY(QUrl source READ image WRITE setImage NOTIFY imageChanged FINAL)
153 Q_PROPERTY(QQmlListProperty<QQuickSprite> sprites READ sprites FINAL)
154 Q_PROPERTY(Status status READ status NOTIFY statusChanged FINAL)
155 //### Is it worth having progress like Image has?
156 //Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
157
158 Q_PROPERTY(QUrl colorTable READ colortable WRITE setColortable NOTIFY colortableChanged FINAL)
159 Q_PROPERTY(QUrl sizeTable READ sizetable WRITE setSizetable NOTIFY sizetableChanged FINAL)
160 Q_PROPERTY(QUrl opacityTable READ opacitytable WRITE setOpacitytable NOTIFY opacitytableChanged FINAL)
161
162 //###Now just colorize - add a flag for 'solid' color particles(where the img is just a mask?)?
163 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged RESET resetColor FINAL)
164 //Stacks (added) with individual colorVariations
165 Q_PROPERTY(qreal colorVariation READ colorVariation WRITE setColorVariation NOTIFY colorVariationChanged RESET resetColor FINAL)
166 Q_PROPERTY(qreal redVariation READ redVariation WRITE setRedVariation NOTIFY redVariationChanged RESET resetColor FINAL)
167 Q_PROPERTY(qreal greenVariation READ greenVariation WRITE setGreenVariation NOTIFY greenVariationChanged RESET resetColor FINAL)
168 Q_PROPERTY(qreal blueVariation READ blueVariation WRITE setBlueVariation NOTIFY blueVariationChanged RESET resetColor FINAL)
169 //Stacks (multiplies) with the Alpha in the color, mostly here so you can use svg color names (which have full alpha)
170 Q_PROPERTY(qreal alpha READ alpha WRITE setAlpha NOTIFY alphaChanged RESET resetColor FINAL)
171 Q_PROPERTY(qreal alphaVariation READ alphaVariation WRITE setAlphaVariation NOTIFY alphaVariationChanged RESET resetColor FINAL)
172
173 Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged RESET resetRotation)
174 Q_PROPERTY(qreal rotationVariation READ rotationVariation WRITE setRotationVariation NOTIFY rotationVariationChanged RESET resetRotation FINAL)
175 Q_PROPERTY(qreal rotationVelocity READ rotationVelocity WRITE setRotationVelocity NOTIFY rotationVelocityChanged RESET resetRotation FINAL)
176 Q_PROPERTY(qreal rotationVelocityVariation READ rotationVelocityVariation WRITE setRotationVelocityVariation NOTIFY rotationVelocityVariationChanged RESET resetRotation FINAL)
177 //If true, then will face the direction of motion. Stacks with rotation, e.g. setting rotation
178 //to 180 will lead to facing away from the direction of motion
179 Q_PROPERTY(bool autoRotation READ autoRotation WRITE setAutoRotation NOTIFY autoRotationChanged RESET resetRotation FINAL)
180
181 //xVector is the vector from the top-left point to the top-right point, and is multiplied by current size
182 Q_PROPERTY(QQuickDirection* xVector READ xVector WRITE setXVector NOTIFY xVectorChanged RESET resetDeformation FINAL)
183 //yVector is the same, but top-left to bottom-left. The particle is always a parallelogram.
184 Q_PROPERTY(QQuickDirection* yVector READ yVector WRITE setYVector NOTIFY yVectorChanged RESET resetDeformation FINAL)
185 Q_PROPERTY(bool spritesInterpolate READ spritesInterpolate WRITE setSpritesInterpolate NOTIFY spritesInterpolateChanged FINAL)
186
187 Q_PROPERTY(EntryEffect entryEffect READ entryEffect WRITE setEntryEffect NOTIFY entryEffectChanged FINAL)
188 QML_NAMED_ELEMENT(ImageParticle)
189 QML_ADDED_IN_VERSION(2, 0)
190public:
191 explicit QQuickImageParticle(QQuickItem *parent = nullptr);
192 virtual ~QQuickImageParticle();
193
194 enum Status { Null, Ready, Loading, Error };
195 Q_ENUM(Status)
196
197 QQmlListProperty<QQuickSprite> sprites();
198 QQuickStochasticEngine* spriteEngine() {return m_spriteEngine;}
199
200 enum EntryEffect {
201 None = 0,
202 Fade = 1,
203 Scale = 2
204 };
205 Q_ENUM(EntryEffect)
206
207 enum PerformanceLevel{//TODO: Expose?
208 Unknown = 0,
209 SimplePoint,
210 ColoredPoint,
211 Colored,
212 Deformable,
213 Tabled,
214 Sprites
215 };
216
217 QUrl image() const { return m_image ? m_image->source : QUrl(); }
218 void setImage(const QUrl &image);
219
220 QUrl colortable() const { return m_colorTable ? m_colorTable->source : QUrl(); }
221 void setColortable(const QUrl &table);
222
223 QUrl sizetable() const { return m_sizeTable ? m_sizeTable->source : QUrl(); }
224 void setSizetable (const QUrl &table);
225
226 QUrl opacitytable() const { return m_opacityTable ? m_opacityTable->source : QUrl(); }
227 void setOpacitytable(const QUrl &table);
228
229 QColor color() const { return m_color; }
230 void setColor(const QColor &color);
231
232 qreal colorVariation() const { return m_color_variation; }
233 void setColorVariation(qreal var);
234
235 qreal alphaVariation() const { return m_alphaVariation; }
236
237 qreal alpha() const { return m_alpha; }
238
239 qreal redVariation() const { return m_redVariation; }
240
241 qreal greenVariation() const { return m_greenVariation; }
242
243 qreal blueVariation() const { return m_blueVariation; }
244
245 qreal rotation() const { return m_rotation; }
246
247 qreal rotationVariation() const { return m_rotationVariation; }
248
249 qreal rotationVelocity() const { return m_rotationVelocity; }
250
251 qreal rotationVelocityVariation() const { return m_rotationVelocityVariation; }
252
253 bool autoRotation() const { return m_autoRotation; }
254
255 QQuickDirection* xVector() const { return m_xVector; }
256
257 QQuickDirection* yVector() const { return m_yVector; }
258
259 bool spritesInterpolate() const { return m_spritesInterpolate; }
260
261 bool bypassOptimizations() const { return m_bypassOptimizations; }
262
263 EntryEffect entryEffect() const { return m_entryEffect; }
264
265 Status status() const { return m_status; }
266
267 void resetColor();
268 void resetRotation();
269 void resetDeformation();
270
271Q_SIGNALS:
272
273 void imageChanged();
274 void colortableChanged();
275 void sizetableChanged();
276 void opacitytableChanged();
277
278 void colorChanged();
279 void colorVariationChanged();
280
281 void alphaVariationChanged(qreal arg);
282
283 void alphaChanged(qreal arg);
284
285 void redVariationChanged(qreal arg);
286
287 void greenVariationChanged(qreal arg);
288
289 void blueVariationChanged(qreal arg);
290
291 void rotationChanged(qreal arg);
292
293 void rotationVariationChanged(qreal arg);
294
295 void rotationVelocityChanged(qreal arg);
296
297 void rotationVelocityVariationChanged(qreal arg);
298
299 void autoRotationChanged(bool arg);
300
301 void xVectorChanged(QQuickDirection* arg);
302
303 void yVectorChanged(QQuickDirection* arg);
304
305 void spritesInterpolateChanged(bool arg);
306
307 void bypassOptimizationsChanged(bool arg);
308
309 void entryEffectChanged(EntryEffect arg);
310
311 void statusChanged(Status arg);
312
313public Q_SLOTS:
314 void setAlphaVariation(qreal arg);
315
316 void setAlpha(qreal arg);
317
318 void setRedVariation(qreal arg);
319
320 void setGreenVariation(qreal arg);
321
322 void setBlueVariation(qreal arg);
323
324 void setRotation(qreal arg);
325
326 void setRotationVariation(qreal arg);
327
328 void setRotationVelocity(qreal arg);
329
330 void setRotationVelocityVariation(qreal arg);
331
332 void setAutoRotation(bool arg);
333
334 void setXVector(QQuickDirection* arg);
335
336 void setYVector(QQuickDirection* arg);
337
338 void setSpritesInterpolate(bool arg);
339
340 void setBypassOptimizations(bool arg);
341
342 void setEntryEffect(EntryEffect arg);
343
344protected:
345 void reset() override;
346 void initialize(int gIdx, int pIdx) override;
347 void commit(int gIdx, int pIdx) override;
348
349 QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) override;
350 bool prepareNextFrame(QSGNode**);
351 void buildParticleNodes(QSGNode**);
352
353 void sceneGraphInvalidated() override;
354
355private Q_SLOTS:
356 void createEngine(); //### method invoked by sprite list changing (in engine.h) - pretty nasty
357
358 void spriteAdvance(int spriteIndex);
359 void spritesUpdate(qreal time = 0 );
360 void mainThreadFetchImageData();
361 void finishBuildParticleNodes(QSGNode **n);
362 void invalidateSceneGraph();
363
364private:
365 struct ImageData {
366 QUrl source;
367 QQuickPixmap pix;
368 };
369 QScopedPointer<ImageData> m_image;
370 QScopedPointer<ImageData> m_colorTable;
371 QScopedPointer<ImageData> m_sizeTable;
372 QScopedPointer<ImageData> m_opacityTable;
373 bool loadingSomething();
374
375
376 QColor m_color;
377 qreal m_color_variation;
378
379 QSGNode *m_outgoingNode;
380 QHash<int, QSGGeometryNode *> m_nodes;
381 QHash<int, int> m_idxStarts;//TODO: Proper resizing will lead to needing a spriteEngine per particle - do this after sprite engine gains transparent sharing?
382 QList<QPair<int, int> > m_startsIdx;//Same data, optimized for alternate retrieval
383
384 int m_lastIdxStart;
385 QSGMaterial *m_material;
386
387 // derived values...
388
389 qreal m_alphaVariation;
390 qreal m_alpha;
391 qreal m_redVariation;
392 qreal m_greenVariation;
393 qreal m_blueVariation;
394 qreal m_rotation;
395 qreal m_rotationVariation;
396 qreal m_rotationVelocity;
397 qreal m_rotationVelocityVariation;
398 bool m_autoRotation;
399 QQuickDirection* m_xVector;
400 QQuickDirection* m_yVector;
401
402 QList<QQuickSprite*> m_sprites;
403 QQuickSpriteEngine* m_spriteEngine;
404 bool m_spritesInterpolate;
405
406 bool m_explicitColor;
407 bool m_explicitRotation;
408 bool m_explicitDeformation;
409 bool m_explicitAnimation;
410 QHash<int, QVector<QQuickParticleData*> > m_shadowData;
411 void clearShadows();
412 QQuickParticleData* getShadowDatum(QQuickParticleData* datum);
413
414 bool m_bypassOptimizations;
415 PerformanceLevel perfLevel;
416 PerformanceLevel m_targetPerfLevel;
417 void checkPerfLevel(PerformanceLevel level);
418
419 bool m_debugMode;
420
421 template<class Vertex>
422 void initTexCoords(Vertex* v, int count){
423 Vertex* end = v + count;
424 // Vertex coords between (0.0, 0.0) and (1.0, 1.0)
425 while (v < end){
426 v[0].tx = 0;
427 v[0].ty = 0;
428
429 v[1].tx = 255;
430 v[1].ty = 0;
431
432 v[2].tx = 0;
433 v[2].ty = 255;
434
435 v[3].tx = 255;
436 v[3].ty = 255;
437
438 v += 4;
439 }
440 }
441
442 ImageMaterialData *getState(QSGMaterial *m) {
443 return static_cast<ImageMaterial *>(m)->state();
444 }
445
446 EntryEffect m_entryEffect;
447 Status m_status;
448 int m_startedImageLoading;
449 QRhi *m_rhi;
450 bool m_apiChecked;
451 qreal m_dpr;
452 bool m_previousActive;
453};
454
455QT_END_NAMESPACE
456
457#endif // QQUICKIMAGEPARTICLE_P_H
458

source code of qtdeclarative/src/particles/qquickimageparticle_p.h