// Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "qquick3dparticleshapedatautils_p.h" #include #include #include #include #include #include QT_BEGIN_NAMESPACE // This file contains useful methods to read & write shape // CBOR binary files and understand the format. // Read property 'type' value from CBOR and return it as QVariant. QVariant QQuick3DParticleShapeDataUtils::readValue(QCborStreamReader &reader, QMetaType::Type type) { switch (type) { case QMetaType::Bool: { bool b = reader.toBool(); reader.next(); return QVariant(b); } case QMetaType::Int: { int i = reader.toInteger(); reader.next(); return QVariant(i); } case QMetaType::Float: { float f = reader.toFloat(); reader.next(); return QVariant(f); } case QMetaType::Double: { double d = reader.toDouble(); reader.next(); return QVariant(d); } case QMetaType::QString: { QString s = reader.readString().data; return QVariant(s); } case QMetaType::QVector2D: { QVector2D v; v.setX(reader.toFloat()); reader.next(); v.setY(reader.toFloat()); reader.next(); return QVariant(v); } case QMetaType::QVector3D: { QVector3D v; v.setX(reader.toFloat()); reader.next(); v.setY(reader.toFloat()); reader.next(); v.setZ(reader.toFloat()); reader.next(); return QVariant(v); } case QMetaType::QVector4D: { QVector4D v; v.setX(reader.toFloat()); reader.next(); v.setY(reader.toFloat()); reader.next(); v.setZ(reader.toFloat()); reader.next(); v.setW(reader.toFloat()); reader.next(); return QVariant(v); } case QMetaType::QQuaternion: { QQuaternion q; q.setScalar(reader.toFloat()); reader.next(); q.setX(reader.toFloat()); reader.next(); q.setY(reader.toFloat()); reader.next(); q.setZ(reader.toFloat()); reader.next(); return QVariant(q); } case QMetaType::QColor: { QColor c; c.setRed(reader.toInteger()); reader.next(); c.setGreen(reader.toInteger()); reader.next(); c.setBlue(reader.toInteger()); reader.next(); c.setAlpha(reader.toInteger()); reader.next(); return QVariant(c); } case QMetaType::QRect: { QRect r; r.setX(reader.toInteger()); reader.next(); r.setY(reader.toInteger()); reader.next(); r.setWidth(reader.toInteger()); reader.next(); r.setHeight(reader.toInteger()); reader.next(); return QVariant(r); } default: { qWarning() << "Property type not handled:" << type; } } return QVariant(); } // Read a string from CBOR. QString QQuick3DParticleShapeDataUtils::readString(QCborStreamReader &reader) { QString result; auto r = reader.readString(); while (r.status == QCborStreamReader::Ok) { result += r.data; r = reader.readString(); } if (r.status == QCborStreamReader::Error) { // handle error condition result.clear(); } return result; } // Read a real (double or float) from CBOR. double QQuick3DParticleShapeDataUtils::readReal(QCborStreamReader &reader) { double result = 0.0; if (reader.isDouble()) { result = reader.toDouble(); reader.next(); } else if (reader.isFloat()) { result = reader.toFloat(); reader.next(); } return result; } // Read shape file header and return the version. // If header is not valid, -1 is returned. int QQuick3DParticleShapeDataUtils::readShapeHeader(QCborStreamReader &reader) { int version = -1; if (reader.lastError() == QCborError::NoError && reader.isArray()) { // Start root array reader.enterContainer(); if (reader.isString()) { QString header = readString(reader); if (header == QStringLiteral("QQ3D_SHAPE")) { if (reader.isInteger()) { version = reader.toInteger(); reader.next(); } else { qWarning() << "Invalid shape version"; } } else { qWarning() << "Invalid shape header"; } } else { qWarning() << "Invalid shape container"; } } return version; } #if QT_CONFIG(cborstreamwriter) void QQuick3DParticleShapeDataUtils::writeShapeHeader(QCborStreamWriter &writer, int version) { // Root array writer.startArray(); // header name writer.append("QQ3D_SHAPE"); // file version writer.append(version); } // Write QVariant value into CBOR in correct type. void QQuick3DParticleShapeDataUtils::writeValue(QCborStreamWriter &writer, const QVariant &value) { const QMetaType type = value.metaType(); switch (type.id()) { case QMetaType::Bool: { bool b = value.toBool(); writer.append(b); break; } case QMetaType::Int: { int i = value.toInt(); writer.append(i); break; } case QMetaType::Float: { float f = value.toFloat(); writer.append(f); break; } case QMetaType::Double: { double d = value.toDouble(); writer.append(d); break; } case QMetaType::QVector2D: { QVector2D v = value.value(); writer.append(v.x()); writer.append(v.y()); break; } case QMetaType::QVector3D: { QVector3D v = value.value(); writer.append(v.x()); writer.append(v.y()); writer.append(v.z()); break; } case QMetaType::QVector4D: { QVector4D v = value.value(); writer.append(v.x()); writer.append(v.y()); writer.append(v.z()); writer.append(v.w()); break; } case QMetaType::QQuaternion: { QQuaternion q = value.value(); writer.append(q.scalar()); writer.append(q.x()); writer.append(q.y()); writer.append(q.z()); break; } case QMetaType::QColor: { QColor c = value.value(); writer.append(c.red()); writer.append(c.green()); writer.append(c.blue()); writer.append(c.alpha()); break; } case QMetaType::QRect: { QRect r = value.value(); writer.append(r.x()); writer.append(r.y()); writer.append(r.width()); writer.append(r.height()); break; } default: { qDebug() << "Not able to add:" << value << "of type:" << type.name(); qDebug() << "Please add support for this type into generator."; break; } } } #endif QT_END_NAMESPACE