1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qquick3dparticleshapedatautils_p.h"
5#include <QtCore/QRect>
6#include <QtGui/QVector2D>
7#include <QtGui/QVector3D>
8#include <QtGui/QVector4D>
9#include <QtGui/QQuaternion>
10#include <QtGui/QColor>
11
12QT_BEGIN_NAMESPACE
13
14// This file contains useful methods to read & write shape
15// CBOR binary files and understand the format.
16
17// Read property 'type' value from CBOR and return it as QVariant.
18QVariant QQuick3DParticleShapeDataUtils::readValue(QCborStreamReader &reader, QMetaType::Type type)
19{
20 switch (type) {
21 case QMetaType::Bool: {
22 bool b = reader.toBool();
23 reader.next();
24 return QVariant(b);
25 }
26 case QMetaType::Int: {
27 int i = reader.toInteger();
28 reader.next();
29 return QVariant(i);
30 }
31 case QMetaType::Float: {
32 float f = reader.toFloat();
33 reader.next();
34 return QVariant(f);
35 }
36 case QMetaType::Double: {
37 double d = reader.toDouble();
38 reader.next();
39 return QVariant(d);
40 }
41 case QMetaType::QString: {
42 QString s = reader.readString().data;
43 return QVariant(s);
44 }
45 case QMetaType::QVector2D: {
46 QVector2D v;
47 v.setX(reader.toFloat());
48 reader.next();
49 v.setY(reader.toFloat());
50 reader.next();
51 return QVariant(v);
52 }
53 case QMetaType::QVector3D: {
54 QVector3D v;
55 v.setX(reader.toFloat());
56 reader.next();
57 v.setY(reader.toFloat());
58 reader.next();
59 v.setZ(reader.toFloat());
60 reader.next();
61 return QVariant(v);
62 }
63 case QMetaType::QVector4D: {
64 QVector4D v;
65 v.setX(reader.toFloat());
66 reader.next();
67 v.setY(reader.toFloat());
68 reader.next();
69 v.setZ(reader.toFloat());
70 reader.next();
71 v.setW(reader.toFloat());
72 reader.next();
73 return QVariant(v);
74 }
75 case QMetaType::QQuaternion: {
76 QQuaternion q;
77 q.setScalar(reader.toFloat());
78 reader.next();
79 q.setX(reader.toFloat());
80 reader.next();
81 q.setY(reader.toFloat());
82 reader.next();
83 q.setZ(reader.toFloat());
84 reader.next();
85 return QVariant(q);
86 }
87 case QMetaType::QColor: {
88 QColor c;
89 c.setRed(reader.toInteger());
90 reader.next();
91 c.setGreen(reader.toInteger());
92 reader.next();
93 c.setBlue(reader.toInteger());
94 reader.next();
95 c.setAlpha(reader.toInteger());
96 reader.next();
97 return QVariant(c);
98 }
99 case QMetaType::QRect: {
100 QRect r;
101 r.setX(reader.toInteger());
102 reader.next();
103 r.setY(reader.toInteger());
104 reader.next();
105 r.setWidth(reader.toInteger());
106 reader.next();
107 r.setHeight(reader.toInteger());
108 reader.next();
109 return QVariant(r);
110 }
111 default: {
112 qWarning() << "Property type not handled:" << type;
113 }
114 }
115
116 return QVariant();
117}
118
119// Read a string from CBOR.
120QString QQuick3DParticleShapeDataUtils::readString(QCborStreamReader &reader)
121{
122 QString result;
123 auto r = reader.readString();
124 while (r.status == QCborStreamReader::Ok) {
125 result += r.data;
126 r = reader.readString();
127 }
128
129 if (r.status == QCborStreamReader::Error) {
130 // handle error condition
131 result.clear();
132 }
133 return result;
134}
135
136// Read a real (double or float) from CBOR.
137double QQuick3DParticleShapeDataUtils::readReal(QCborStreamReader &reader)
138{
139 double result = 0.0;
140 if (reader.isDouble()) {
141 result = reader.toDouble();
142 reader.next();
143 } else if (reader.isFloat()) {
144 result = reader.toFloat();
145 reader.next();
146 }
147 return result;
148}
149
150// Read shape file header and return the version.
151// If header is not valid, -1 is returned.
152int QQuick3DParticleShapeDataUtils::readShapeHeader(QCborStreamReader &reader)
153{
154 int version = -1;
155 if (reader.lastError() == QCborError::NoError && reader.isArray()) {
156 // Start root array
157 reader.enterContainer();
158 if (reader.isString()) {
159 QString header = readString(reader);
160 if (header == QStringLiteral("QQ3D_SHAPE")) {
161 if (reader.isInteger()) {
162 version = reader.toInteger();
163 reader.next();
164 } else {
165 qWarning() << "Invalid shape version";
166 }
167 } else {
168 qWarning() << "Invalid shape header";
169 }
170 } else {
171 qWarning() << "Invalid shape container";
172 }
173 }
174 return version;
175}
176
177void QQuick3DParticleShapeDataUtils::writeShapeHeader(QCborStreamWriter &writer, int version)
178{
179 // Root array
180 writer.startArray();
181 // header name
182 writer.append(str: "QQ3D_SHAPE");
183 // file version
184 writer.append(i: version);
185}
186
187// Write QVariant value into CBOR in correct type.
188void QQuick3DParticleShapeDataUtils::writeValue(QCborStreamWriter &writer, const QVariant &value)
189{
190 const QMetaType type = value.metaType();
191 switch (type.id()) {
192 case QMetaType::Bool: {
193 bool b = value.toBool();
194 writer.append(b);
195 break;
196 }
197 case QMetaType::Int: {
198 int i = value.toInt();
199 writer.append(i);
200 break;
201 }
202 case QMetaType::Float: {
203 float f = value.toFloat();
204 writer.append(f);
205 break;
206 }
207 case QMetaType::Double: {
208 double d = value.toDouble();
209 writer.append(d);
210 break;
211 }
212 case QMetaType::QVector2D: {
213 QVector2D v = value.value<QVector2D>();
214 writer.append(f: v.x());
215 writer.append(f: v.y());
216 break;
217 }
218 case QMetaType::QVector3D: {
219 QVector3D v = value.value<QVector3D>();
220 writer.append(f: v.x());
221 writer.append(f: v.y());
222 writer.append(f: v.z());
223 break;
224 }
225 case QMetaType::QVector4D: {
226 QVector4D v = value.value<QVector4D>();
227 writer.append(f: v.x());
228 writer.append(f: v.y());
229 writer.append(f: v.z());
230 writer.append(f: v.w());
231 break;
232 }
233 case QMetaType::QQuaternion: {
234 QQuaternion q = value.value<QQuaternion>();
235 writer.append(f: q.scalar());
236 writer.append(f: q.x());
237 writer.append(f: q.y());
238 writer.append(f: q.z());
239 break;
240 }
241 case QMetaType::QColor: {
242 QColor c = value.value<QColor>();
243 writer.append(i: c.red());
244 writer.append(i: c.green());
245 writer.append(i: c.blue());
246 writer.append(i: c.alpha());
247 break;
248 }
249 case QMetaType::QRect: {
250 QRect r = value.value<QRect>();
251 writer.append(i: r.x());
252 writer.append(i: r.y());
253 writer.append(i: r.width());
254 writer.append(i: r.height());
255 break;
256 }
257 default: {
258 qDebug() << "Not able to add:" << value << "of type:" << type.name();
259 qDebug() << "Please add support for this type into generator.";
260 break;
261 }
262 }
263}
264
265QT_END_NAMESPACE
266

source code of qtquick3d/src/quick3dparticles/qquick3dparticleshapedatautils.cpp