Revision control
Copy as Markdown
// Copyright (C) 2019 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include "qssgassetimportmanager_p.h"
#include "qssgassetimporter_p.h"
#include "qssgassetimporterfactory_p.h"
#include <QtCore/QFile>
#include <QtCore/QDebug>
#include <QtCore/QHash>
#include <QtCore/QMap>
#include <QtCore/QList>
#include <QtCore/QString>
#include <QtQml/QQmlFile>
QT_BEGIN_NAMESPACE
QSSGAssetImportManager::QSSGAssetImportManager(QObject *parent) : QObject(parent)
{
// load assetimporters
const QStringList keys = QSSGAssetImporterFactory::keys();
for (const auto &key : keys) {
auto importer = QSSGAssetImporterFactory::create(key, QStringList());
if (importer) {
m_assetImporters.append(importer);
// Add to extension map; when several importers claim the same
// extension the one with the highest priority() wins, and equal
// priorities keep the first importer registered. Keys are
// normalized to lower case, because every lookup is.
const auto extensions = importer->inputExtensions();
for (const auto &extension : extensions) {
const QString extensionKey = extension.toLower();
const auto existing = m_extensionsMap.constFind(extensionKey);
if (existing == m_extensionsMap.cend() || (*existing)->priority() < importer->priority())
m_extensionsMap.insert(extensionKey, importer);
}
} else {
qWarning() << "Failed to load asset import plugin with key: " << key;
}
}
}
QSSGAssetImportManager::~QSSGAssetImportManager()
{
for (auto *importer : std::as_const(m_assetImporters))
delete importer;
}
// Compatibility with old API
QSSGAssetImportManager::ImportState QSSGAssetImportManager::importFile(const QString &filename,
const QDir &outputPath,
QString *error)
{
return importFile(filename, outputPath, QJsonObject(), error);
}
QSSGAssetImportManager::ImportState QSSGAssetImportManager::importFile(const QString &filename,
const QDir &outputPath,
const QJsonObject &options,
QString *error)
{
QFileInfo fileInfo(filename);
// Is this a real file?
if (!fileInfo.exists()) {
if (error)
*error = QStringLiteral("file does not exist");
return ImportState::IoError;
}
// Do we have a importer to load the file?
const auto extension = fileInfo.suffix().toLower();
auto importer = m_extensionsMap.value(extension, nullptr);
if (!importer) {
if (error)
*error = QStringLiteral("unsupported file extension %1").arg(extension);
return ImportState::Unsupported;
}
QStringList generatedFiles;
auto errorString = importer->import(fileInfo.absoluteFilePath(), outputPath, options, &generatedFiles);
if (!errorString.isEmpty()) {
if (error) {
*error = QStringLiteral("%1").arg(errorString);
}
return ImportState::IoError;
}
// debug output
for (const auto &file : std::as_const(generatedFiles))
qDebug() << "generated file: " << file;
return ImportState::Success;
}
QSSGAssetImportManager::ImportState QSSGAssetImportManager::importFile(const QUrl &url,
QSSGSceneDesc::Scene &scene,
QString *error)
{
return importFile(url, scene, {}, error);
}
QSSGAssetImportManager::ImportState QSSGAssetImportManager::importFile(const QUrl &url,
QSSGSceneDesc::Scene &scene,
const QJsonObject &options,
QString *error)
{
// Anything that is not a local file or a resource has to have its
// extension taken from the path rather than from the serialized URL, or a
// query string or fragment ends up being read as the suffix instead.
const QString filePath = QQmlFile::isLocalFile(url) ? QQmlFile::urlToLocalFileOrQrc(url) : url.path();
const auto extension = QFileInfo(filePath).suffix().toLower();
auto importer = m_extensionsMap.value(extension, nullptr);
if (!importer) {
if (error)
*error = QStringLiteral("unsupported file extension %1").arg(extension);
return ImportState::Unsupported;
}
const auto ret = importer->import(url, options, scene);
if (!ret.isEmpty()) {
if (error)
*error = ret;
return ImportState::IoError;
}
return ImportState::Success;
}
QJsonObject QSSGAssetImportManager::getOptionsForFile(const QString &filename)
{
QFileInfo fileInfo(filename);
QJsonObject options;
// Is this a real file?
if (fileInfo.exists()) {
// Do we have a importer to load the file?
const auto extension = fileInfo.suffix().toLower();
auto importer = m_extensionsMap.value(extension, nullptr);
if (importer)
options = importer->importOptions();
}
return options;
}
QSSGAssetImportManager::PluginOptionMaps QSSGAssetImportManager::getAllOptions() const
{
PluginOptionMaps options;
for (const auto importer : m_assetImporters)
options.insert(importer->inputExtensions().join(QChar::fromLatin1(':')), importer->importOptions());
return options;
}
QHash<QString, QStringList> QSSGAssetImportManager::getSupportedExtensions() const
{
QHash<QString, QStringList> extensionMap;
for (const auto importer : std::as_const(m_assetImporters))
extensionMap.insert(importer->typeDescription(), importer->inputExtensions());
return extensionMap;
}
QList<QSSGAssetImporterPluginInfo> QSSGAssetImportManager::getImporterPluginInfos() const
{
QList<QSSGAssetImporterPluginInfo> output;
for (const QSSGAssetImporter *importer : m_assetImporters) {
QSSGAssetImporterPluginInfo plugin;
plugin.name = importer->name();
plugin.inputExtensions = importer->inputExtensions();
plugin.outputExtension = importer->outputExtension();
plugin.type = importer->type();
plugin.importOptions = importer->importOptions();
plugin.typeDescription = importer->typeDescription();
output.push_back(plugin);
}
return output;
}
QT_END_NAMESPACE