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 | |
12 | QT_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. |
18 | QVariant 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. |
120 | QString 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. |
137 | double 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. |
152 | int 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 | |
177 | void 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. |
188 | void 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 | |
265 | QT_END_NAMESPACE |
266 |