diff --git a/share/qtcreator/qml/qmlpuppet/commands/puppettocreatorcommand.h b/share/qtcreator/qml/qmlpuppet/commands/puppettocreatorcommand.h index dc125d4ead1..cfe4529ba1b 100644 --- a/share/qtcreator/qml/qmlpuppet/commands/puppettocreatorcommand.h +++ b/share/qtcreator/qml/qmlpuppet/commands/puppettocreatorcommand.h @@ -34,7 +34,13 @@ namespace QmlDesigner { class PuppetToCreatorCommand { public: - enum Type { Edit3DToolState, Render3DView, ActiveSceneChanged, RenderModelNodePreviewImage, None }; + enum Type { + Edit3DToolState, + Render3DView, + ActiveSceneChanged, + RenderModelNodePreviewImage, + Import3DSupport, + None }; PuppetToCreatorCommand(Type type, const QVariant &data); PuppetToCreatorCommand() = default; diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/import3d/import3d.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/import3d/import3d.cpp new file mode 100644 index 00000000000..c7eb52158b7 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/import3d/import3d.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "import3d.h" + +#ifdef IMPORT_QUICK3D_ASSETS +#include +#endif + +#include +#include +#include +#include +#include + +namespace Import3D +{ + +void import3D(const QString &sourceAsset, const QString &outDir, int exitId, const QString &options) +{ +#ifdef IMPORT_QUICK3D_ASSETS + QScopedPointer importer {new QSSGAssetImportManager}; + + QJsonParseError error; + QJsonDocument optDoc = QJsonDocument::fromJson(options.toUtf8(), &error); + + if (!optDoc.isNull() && optDoc.isObject()) { + QString errorStr; + QJsonObject optObj = optDoc.object(); + if (importer->importFile(sourceAsset, outDir, optObj.toVariantMap(), &errorStr) + != QSSGAssetImportManager::ImportState::Success) { + qWarning() << __FUNCTION__ << "Failed to import 3D asset" + << sourceAsset << "with error:" << errorStr; + } else { + // Allow little time for file operations to finish + QTimer::singleShot(2000, nullptr, [exitId]() { + qApp->exit(exitId); + }); + return; + } + } else { + qWarning() << __FUNCTION__ << "Failed to parse import options:" << error.errorString(); + } +#else + Q_UNUSED(sourceAsset) + Q_UNUSED(outDir) + Q_UNUSED(exitId) + Q_UNUSED(options) + qWarning() << __FUNCTION__ << "Failed to parse import options, Quick3DAssetImport not available"; +#endif + QTimer::singleShot(0, nullptr, [exitId]() { + // Negative exitId means import failure + qApp->exit(-exitId); + }); +} + +} diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/import3d/import3d.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/import3d/import3d.h new file mode 100644 index 00000000000..eb2e4731724 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/import3d/import3d.h @@ -0,0 +1,33 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include + +namespace Import3D +{ + void import3D(const QString &sourceAsset, const QString &outDir, int id, const QString &options); +}; diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/import3d/import3d.pri b/share/qtcreator/qml/qmlpuppet/qml2puppet/import3d/import3d.pri new file mode 100644 index 00000000000..8e4d6b6a318 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/import3d/import3d.pri @@ -0,0 +1,3 @@ +HEADERS += $$PWD/import3d.h + +SOURCES += $$PWD/import3d.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/instances.pri b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/instances.pri index 448a67c913a..d0096f86609 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/instances.pri +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/instances.pri @@ -1,8 +1,14 @@ INCLUDEPATH += $$PWD/ -versionAtLeast(QT_VERSION, 5.15.0):qtHaveModule(quick3d) { - QT *= quick3d-private - DEFINES *= QUICK3D_MODULE +versionAtLeast(QT_VERSION, 5.15.0) { + qtHaveModule(quick3d) { + QT *= quick3d-private + DEFINES *= QUICK3D_MODULE + } + qtHaveModule(quick3dassetimport) { + QT *= quick3dassetimport-private + DEFINES *= IMPORT_QUICK3D_ASSETS + } } HEADERS += $$PWD/qt5nodeinstanceserver.h \ diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp index 466bf97db8a..064d1fed1b1 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp @@ -102,6 +102,10 @@ #endif #endif +#ifdef IMPORT_QUICK3D_ASSETS +#include +#endif + // Uncomment to display FPS counter on the lower left corner of edit 3D view //#define FPS_COUNTER #ifdef FPS_COUNTER @@ -253,6 +257,37 @@ void Qt5InformationNodeInstanceServer::handleInputEvents() } } +void Qt5InformationNodeInstanceServer::resolveImportSupport() +{ +#ifdef IMPORT_QUICK3D_ASSETS + QSSGAssetImportManager importManager; + const QHash supportedExtensions = importManager.getSupportedExtensions(); + const QHash supportedOptions = importManager.getAllOptions(); + + QVariantMap supportMap; + + QVariantMap extMap; + auto itExt = supportedExtensions.constBegin(); + while (itExt != supportedExtensions.constEnd()) { + extMap.insert(itExt.key(), itExt.value()); + ++itExt; + } + + QVariantMap optMap; + auto itOpt = supportedOptions.constBegin(); + while (itOpt != supportedOptions.constEnd()) { + optMap.insert(itOpt.key(), itOpt.value()); + ++itOpt; + } + + supportMap.insert("options", optMap); + supportMap.insert("extensions", extMap); + nodeInstanceClient()->handlePuppetToCreatorCommand( + {PuppetToCreatorCommand::Import3DSupport, QVariant(supportMap)}); + +#endif +} + void Qt5InformationNodeInstanceServer::createEditView3D() { #ifdef QUICK3D_MODULE @@ -1462,6 +1497,9 @@ void Qt5InformationNodeInstanceServer::createScene(const CreateSceneCommand &com QObject::connect(&m_renderModelNodeImageViewTimer, &QTimer::timeout, this, &Qt5InformationNodeInstanceServer::doRenderModelNodeImageView); +#ifdef IMPORT_QUICK3D_ASSETS + QTimer::singleShot(0, this, &Qt5InformationNodeInstanceServer::resolveImportSupport); +#endif } void Qt5InformationNodeInstanceServer::sendChildrenChangedCommand(const QList &childList) diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h index 353f57b3fc4..55a07379b4e 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h @@ -131,6 +131,7 @@ private: void doRenderModelNode2DImageView(); void updateLockedAndHiddenStates(const QSet &instances); void handleInputEvents(); + void resolveImportSupport(); void createAuxiliaryQuickView(const QUrl &url, RenderViewData &viewData); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri index 940047c6b2c..189324f478e 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri @@ -24,6 +24,7 @@ include (../interfaces/interfaces.pri) include (../types/types.pri) include (../qmlprivategate/qmlprivategate.pri) include (iconrenderer/iconrenderer.pri) +include (import3d/import3d.pri) SOURCES += $$PWD/qml2puppetmain.cpp RESOURCES += $$PWD/../qmlpuppet.qrc diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp index e690adf75ae..30aec5b0c99 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp @@ -35,6 +35,7 @@ #include #include "iconrenderer/iconrenderer.h" +#include "import3d/import3d.h" #include #include @@ -152,12 +153,14 @@ int internalMain(QGuiApplication *application) if (application->arguments().count() < 2 || (application->arguments().at(1) == "--readcapturedstream" && application->arguments().count() < 3) - || (application->arguments().at(1) == "--rendericon" && application->arguments().count() < 5)) { + || (application->arguments().at(1) == "--rendericon" && application->arguments().count() < 5) + || (application->arguments().at(1) == "--import3dAsset" && application->arguments().count() < 6)) { qDebug() << "Usage:\n"; qDebug() << "--test"; qDebug() << "--version"; qDebug() << "--readcapturedstream [control stream file]"; qDebug() << "--rendericon "; + qDebug() << "--import3dAsset "; return -1; } @@ -220,6 +223,17 @@ int internalMain(QGuiApplication *application) return application->exec(); } + if (application->arguments().at(1) == "--import3dAsset") { + QString sourceAsset = application->arguments().at(2); + QString outDir = application->arguments().at(3); + int exitId = application->arguments().at(4).toInt(); + QString options = application->arguments().at(5); + + Import3D::import3D(sourceAsset, outDir, exitId, options); + + return application->exec(); + } + #ifdef ENABLE_QT_BREAKPAD const QString libexecPath = QCoreApplication::applicationDirPath() + '/' + RELATIVE_LIBEXEC_PATH; QtSystemExceptionHandler systemExceptionHandler(libexecPath); diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt index 1f35535bd04..72fb68836cc 100644 --- a/src/plugins/qmldesigner/CMakeLists.txt +++ b/src/plugins/qmldesigner/CMakeLists.txt @@ -326,14 +326,6 @@ extend_qtc_plugin(QmlDesigner itemlibraryiconimageprovider.cpp itemlibraryiconimageprovider.h ) -find_package(Qt5 COMPONENTS Quick3DAssetImport QUIET) -extend_qtc_plugin(QmlDesigner - CONDITION TARGET Qt5::Quick3DAssetImport - FEATURE_INFO "Qt Quick 3D asset import" - DEPENDS Qt5::Quick3DAssetImportPrivate - DEFINES IMPORT_QUICK3D_ASSETS -) - extend_qtc_plugin(QmlDesigner SOURCES_PREFIX components/navigator SOURCES diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp index d51b3844723..d8c21fecffe 100644 --- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp +++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp @@ -199,6 +199,15 @@ void DesignerActionManager::registerAddResourceHandler(const AddResourceHandler m_addResourceHandler.append(handler); } +void DesignerActionManager::unregisterAddResourceHandlers(const QString &category) +{ + for (int i = m_addResourceHandler.size() - 1; i >= 0 ; --i) { + const AddResourceHandler &handler = m_addResourceHandler[i]; + if (handler.category == category) + m_addResourceHandler.removeAt(i); + } +} + void DesignerActionManager::registerModelNodePreviewHandler(const ModelNodePreviewImageHandler &handler) { m_modelNodePreviewImageHandlers.append(handler); diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.h b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.h index 66109d16402..bf7ab60017f 100644 --- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.h +++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.h @@ -129,6 +129,7 @@ public: QList addResourceHandler() const; void registerAddResourceHandler(const AddResourceHandler &handler); + void unregisterAddResourceHandlers(const QString &category); void registerModelNodePreviewHandler(const ModelNodePreviewImageHandler &handler); bool hasModelNodePreviewHandler(const ModelNode &node) const; diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.pri b/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.pri index 8eaa9ce983f..bb4ebaa5bb3 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.pri +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrary.pri @@ -1,10 +1,5 @@ VPATH += $$PWD -qtHaveModule(quick3dassetimport) { - QT *= quick3dassetimport-private - DEFINES *= IMPORT_QUICK3D_ASSETS -} - # Input HEADERS += itemlibraryview.h \ $$PWD/itemlibraryiconimageprovider.h \ diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp index af2a34de7c4..e49ffbb9bf0 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp @@ -71,10 +71,13 @@ static const int rowHeight = 26; } ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(const QStringList &importFiles, - const QString &defaulTargetDirectory, QWidget *parent) : - QDialog(parent), - ui(new Ui::ItemLibraryAssetImportDialog), - m_importer(this) + const QString &defaulTargetDirectory, + const QVariantMap &supportedExts, + const QVariantMap &supportedOpts, + QWidget *parent) : + QDialog(parent) + , ui(new Ui::ItemLibraryAssetImportDialog) + , m_importer(this) { setModal(true); ui->setupUi(this); @@ -83,15 +86,24 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(const QStringList &im m_outputFormatter->setPlainTextEdit(ui->plainTextEdit); // Skip unsupported assets - bool skipSome = false; + QHash supportMap; for (const auto &file : importFiles) { - if (m_importer.isQuick3DAsset(file)) + QString suffix = QFileInfo(file).suffix(); + if (!supportMap.contains(suffix)) { + bool supported = false; + for (const auto &exts : supportedExts) { + if (exts.toStringList().contains(suffix)) { + supported = true; + break; + } + } + supportMap.insert(suffix, supported); + } + if (supportMap[suffix]) m_quick3DFiles << file; - else - skipSome = true; } - if (skipSome) + if (m_quick3DFiles.size() != importFiles.size()) addWarning("Cannot import 3D and other assets simultaneously. Skipping non-3D assets."); ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Import")); @@ -153,14 +165,12 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(const QStringList &im m_quick3DImportPath = candidatePath; if (!m_quick3DFiles.isEmpty()) { - const QHash allOptions = m_importer.allOptions(); - const QHash supportedExtensions = m_importer.supportedExtensions(); QVector groups; - auto optIt = allOptions.constBegin(); + auto optIt = supportedOpts.constBegin(); int optIndex = 0; - while (optIt != allOptions.constEnd()) { - QJsonObject options = QJsonObject::fromVariantMap(optIt.value()); + while (optIt != supportedOpts.constEnd()) { + QJsonObject options = QJsonObject::fromVariantMap(qvariant_cast(optIt.value())); m_importOptions << options.value("options").toObject(); groups << options.value("groups").toObject(); const auto &exts = optIt.key().split(':'); @@ -173,10 +183,10 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(const QStringList &im // Create tab for each supported extension group that also has files included in the import QMap tabMap; // QMap used for alphabetical order for (const auto &file : qAsConst(m_quick3DFiles)) { - auto extIt = supportedExtensions.constBegin(); + auto extIt = supportedExts.constBegin(); QString ext = QFileInfo(file).suffix().toLower(); - while (extIt != supportedExtensions.constEnd()) { - if (!tabMap.contains(extIt.key()) && extIt.value().contains(ext)) { + while (extIt != supportedExts.constEnd()) { + if (!tabMap.contains(extIt.key()) && extIt.value().toStringList().contains(ext)) { tabMap.insert(extIt.key(), m_extToImportOptionsMap.value(ext)); break; } diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.h index 713e3fd20b4..3d4069986ec 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.h @@ -46,7 +46,10 @@ class ItemLibraryAssetImportDialog : public QDialog public: explicit ItemLibraryAssetImportDialog(const QStringList &importFiles, - const QString &defaulTargetDirectory, QWidget *parent = nullptr); + const QString &defaulTargetDirectory, + const QVariantMap &supportedExts, + const QVariantMap &supportedOpts, + QWidget *parent = nullptr); ~ItemLibraryAssetImportDialog(); protected: diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp index 23ab98d1ab0..bb510674acd 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp @@ -30,18 +30,15 @@ #include "model.h" #include "puppetcreator.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef IMPORT_QUICK3D_ASSETS -#include -#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace { @@ -53,9 +50,6 @@ namespace QmlDesigner { ItemLibraryAssetImporter::ItemLibraryAssetImporter(QObject *parent) : QObject (parent) { -#ifdef IMPORT_QUICK3D_ASSETS - m_quick3DAssetImporter.reset(new QSSGAssetImportManager); -#endif } ItemLibraryAssetImporter::~ItemLibraryAssetImporter() { @@ -73,7 +67,6 @@ void ItemLibraryAssetImporter::importQuick3D(const QStringList &inputFiles, reset(); m_isImporting = true; -#ifdef IMPORT_QUICK3D_ASSETS if (!m_tempDir->isValid()) { addError(tr("Could not create a temporary directory for import.")); notifyFinished(); @@ -85,24 +78,27 @@ void ItemLibraryAssetImporter::importQuick3D(const QStringList &inputFiles, parseFiles(inputFiles, options, extToImportOptionsMap); if (!isCancelled()) { - // Wait for icon generation processes to finish + const auto parseData = m_parseData; + for (const auto &pd : parseData) { + if (!startImportProcess(pd)) { + addError(tr("Failed to start import 3D asset process"), + pd.sourceInfo.absoluteFilePath()); + m_parseData.remove(pd.importId); + } + } + } + + if (!isCancelled()) { + // Wait for puppet processes to finish if (m_qmlPuppetProcesses.empty()) { - finalizeQuick3DImport(); + postImport(); } else { m_qmlPuppetCount = static_cast(m_qmlPuppetProcesses.size()); - const QString progressTitle = tr("Generating icons."); + const QString progressTitle = tr("Importing 3D assets."); addInfo(progressTitle); notifyProgress(0, progressTitle); } } -#else - Q_UNUSED(inputFiles) - Q_UNUSED(importPath) - Q_UNUSED(options) - Q_UNUSED(extToImportOptionsMap) - addError(tr("Importing 3D assets requires building against Qt Quick 3D module.")); - notifyFinished(); -#endif } bool ItemLibraryAssetImporter::isImporting() const @@ -135,67 +131,47 @@ void ItemLibraryAssetImporter::addInfo(const QString &infoMsg, const QString &sr emit infoReported(infoMsg, srcPath); } -bool ItemLibraryAssetImporter::isQuick3DAsset(const QString &fileName) const +void ItemLibraryAssetImporter::importProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) { -#ifdef IMPORT_QUICK3D_ASSETS - static QStringList quick3DExt; - if (quick3DExt.isEmpty()) { - const auto exts = m_quick3DAssetImporter->getSupportedExtensions(); - for (const auto &ext : exts) - quick3DExt << ext; + Q_UNUSED(exitStatus) + + ++m_qmlImportFinishedCount; + + m_qmlPuppetProcesses.erase( + std::remove_if(m_qmlPuppetProcesses.begin(), m_qmlPuppetProcesses.end(), + [&](const auto &entry) { + return !entry || entry->state() == QProcess::NotRunning; + })); + + if (m_parseData.contains(-exitCode)) { + const ParseData pd = m_parseData.take(-exitCode); + addError(tr("Asset import process failed for: \"%1\"").arg(pd.sourceInfo.absoluteFilePath())); + } + + if (m_qmlImportFinishedCount == m_qmlPuppetCount) { + notifyProgress(100); + QTimer::singleShot(0, this, &ItemLibraryAssetImporter::postImport); + } else { + notifyProgress(int(100. * (double(m_qmlImportFinishedCount) / double(m_qmlPuppetCount)))); } - return quick3DExt.contains(QFileInfo(fileName).suffix().toLower()); -#else - Q_UNUSED(fileName) - return false; -#endif } -QVariantMap ItemLibraryAssetImporter::supportedOptions(const QString &modelFile) const -{ -#ifdef IMPORT_QUICK3D_ASSETS - return m_quick3DAssetImporter->getOptionsForFile(modelFile); -#else - Q_UNUSED(modelFile) - return {}; -#endif -} - -QHash ItemLibraryAssetImporter::allOptions() const -{ -#ifdef IMPORT_QUICK3D_ASSETS - return m_quick3DAssetImporter->getAllOptions(); -#else - return {}; -#endif -} - -QHash ItemLibraryAssetImporter::supportedExtensions() const -{ -#ifdef IMPORT_QUICK3D_ASSETS - return m_quick3DAssetImporter->getSupportedExtensions(); -#else - return {}; -#endif -} - -void ItemLibraryAssetImporter::processFinished(int exitCode, QProcess::ExitStatus exitStatus) +void ItemLibraryAssetImporter::iconProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) { Q_UNUSED(exitCode) Q_UNUSED(exitStatus) m_qmlPuppetProcesses.erase( - std::remove_if(m_qmlPuppetProcesses.begin(), m_qmlPuppetProcesses.end(), [&](const auto &entry) { + std::remove_if(m_qmlPuppetProcesses.begin(), m_qmlPuppetProcesses.end(), + [&](const auto &entry) { return !entry || entry->state() == QProcess::NotRunning; })); - const QString progressTitle = tr("Generating icons."); if (m_qmlPuppetProcesses.empty()) { - notifyProgress(100, progressTitle); - finalizeQuick3DImport(); + notifyProgress(100); + QTimer::singleShot(0, this, &ItemLibraryAssetImporter::finalizeQuick3DImport); } else { - notifyProgress(int(100. * (1. - double(m_qmlPuppetCount) / double(m_qmlPuppetProcesses.size()))), - progressTitle); + notifyProgress(int(100. * (1. - (double(m_qmlPuppetProcesses.size()) / double(m_qmlPuppetCount))))); } } @@ -210,14 +186,14 @@ void ItemLibraryAssetImporter::reset() m_isImporting = false; m_cancelled = false; -#ifdef IMPORT_QUICK3D_ASSETS delete m_tempDir; m_tempDir = new QTemporaryDir; m_importFiles.clear(); m_overwrittenImports.clear(); m_qmlPuppetProcesses.clear(); m_qmlPuppetCount = 0; -#endif + m_qmlImportFinishedCount = 0; + m_parseData.clear(); } void ItemLibraryAssetImporter::parseFiles(const QStringList &filePaths, @@ -235,99 +211,86 @@ void ItemLibraryAssetImporter::parseFiles(const QStringList &filePaths, notifyProgress(qRound(quota * (count + value)), progressTitle); }; for (const QString &file : filePaths) { - if (isCancelled()) - return; - if (isQuick3DAsset(file)) { - int index = extToImportOptionsMap.value(QFileInfo(file).suffix()); - parseQuick3DAsset(file, options[index].toVariantMap()); + int index = extToImportOptionsMap.value(QFileInfo(file).suffix()); + ParseData pd; + pd.options = options[index]; + if (preParseQuick3DAsset(file, pd)) { + pd.importId = ++m_importIdCounter; + m_parseData.insert(pd.importId, pd); } notifyProgress(qRound(++count * quota), progressTitle); } - notifyProgress(100, progressTitle); } -void ItemLibraryAssetImporter::parseQuick3DAsset(const QString &file, const QVariantMap &options) +bool ItemLibraryAssetImporter::preParseQuick3DAsset(const QString &file, ParseData &pd) { -#ifdef IMPORT_QUICK3D_ASSETS - addInfo(tr("Parsing 3D Model"), file); + pd.targetDir = QDir(m_importPath); + pd.outDir = QDir(m_tempDir->path()); + pd.sourceInfo = QFileInfo(file); + pd.assetName = pd.sourceInfo.completeBaseName(); - QString errorString; - - QDir targetDir(m_importPath); - QDir outDir(m_tempDir->path()); - QFileInfo sourceInfo(file); - QString assetName = sourceInfo.completeBaseName(); - - if (!assetName.isEmpty()) { + if (!pd.assetName.isEmpty()) { // Fix name so it plays nice with imports - for (QChar ¤tChar : assetName) { + for (QChar ¤tChar : pd.assetName) { if (!currentChar.isLetter() && !currentChar.isDigit()) currentChar = QLatin1Char('_'); } - const QChar firstChar = assetName[0]; + const QChar firstChar = pd.assetName[0]; if (firstChar.isDigit()) - assetName[0] = QLatin1Char('_'); + pd.assetName[0] = QLatin1Char('_'); if (firstChar.isLower()) - assetName[0] = firstChar.toUpper(); + pd.assetName[0] = firstChar.toUpper(); } - QString targetDirPath = targetDir.filePath(assetName); + pd.targetDirPath = pd.targetDir.filePath(pd.assetName); - if (outDir.exists(assetName)) { - addWarning(tr("Skipped import of duplicate asset: \"%1\"").arg(assetName)); - return; + if (pd.outDir.exists(pd.assetName)) { + addWarning(tr("Skipped import of duplicate asset: \"%1\"").arg(pd.assetName)); + return false; } - QString originalAssetName = assetName; - if (targetDir.exists(assetName)) { + pd.originalAssetName = pd.assetName; + if (pd.targetDir.exists(pd.assetName)) { // If we have a file system with case insensitive filenames, assetName may be // different from the existing name. Modify assetName to ensure exact match to // the overwritten old asset capitalization - const QStringList assetDirs = targetDir.entryList({assetName}, QDir::Dirs); + const QStringList assetDirs = pd.targetDir.entryList({pd.assetName}, QDir::Dirs); if (assetDirs.size() == 1) { - assetName = assetDirs[0]; - targetDirPath = targetDir.filePath(assetName); + pd.assetName = assetDirs[0]; + pd.targetDirPath = pd.targetDir.filePath(pd.assetName); } - if (!confirmAssetOverwrite(assetName)) { - addWarning(tr("Skipped import of existing asset: \"%1\"").arg(assetName)); - return; + if (!confirmAssetOverwrite(pd.assetName)) { + addWarning(tr("Skipped import of existing asset: \"%1\"").arg(pd.assetName)); + return false; } - m_overwrittenImports << targetDirPath; + m_overwrittenImports << pd.targetDirPath; } - outDir.mkpath(assetName); + pd.outDir.mkpath(pd.assetName); - if (!outDir.cd(assetName)) { + if (!pd.outDir.cd(pd.assetName)) { addError(tr("Could not access temporary asset directory: \"%1\"") - .arg(outDir.filePath(assetName))); - return; + .arg(pd.outDir.filePath(pd.assetName))); + return false; } + return true; +} - addInfo(tr("Generating 3D assets for: \"%1\"").arg(targetDir.absoluteFilePath(assetName))); - - if (m_quick3DAssetImporter->importFile( - sourceInfo.absoluteFilePath(), outDir, options, &errorString) - != QSSGAssetImportManager::ImportState::Success) { - addError(tr("Failed to import 3D asset with error: %1").arg(errorString), - sourceInfo.absoluteFilePath()); - return; - } - - // The importer is reset after every import to avoid issues with it caching various things - m_quick3DAssetImporter.reset(new QSSGAssetImportManager); - - if (originalAssetName != assetName) { +void ItemLibraryAssetImporter::postParseQuick3DAsset(const ParseData &pd) +{ + QDir outDir = pd.outDir; + if (pd.originalAssetName != pd.assetName) { // Fix the generated qml file name - const QString assetQml = originalAssetName + ".qml"; + const QString assetQml = pd.originalAssetName + ".qml"; if (outDir.exists(assetQml)) - outDir.rename(assetQml, assetName + ".qml"); + outDir.rename(assetQml, pd.assetName + ".qml"); } QHash assetFiles; const int outDirPathSize = outDir.path().size(); auto insertAsset = [&](const QString &filePath) { QString targetPath = filePath.mid(outDirPathSize); - targetPath.prepend(targetDirPath); + targetPath.prepend(pd.targetDirPath); assetFiles.insert(filePath, targetPath); }; @@ -348,7 +311,7 @@ void ItemLibraryAssetImporter::parseQuick3DAsset(const QString &file, const QVar qmlInfo.append("module "); qmlInfo.append(m_importPath.split('/').last()); qmlInfo.append("."); - qmlInfo.append(assetName); + qmlInfo.append(pd.assetName); qmlInfo.append('\n'); while (qmlIt.hasNext()) { qmlIt.next(); @@ -382,7 +345,7 @@ void ItemLibraryAssetImporter::parseQuick3DAsset(const QString &file, const QVar out << "canBeDroppedInView3D: true" << Qt::endl; file.close(); } - if (generateComponentIcon(24, iconFileName, qmlIt.filePath())) { + if (startIconProcess(24, iconFileName, qmlIt.filePath())) { // Since icon is generated by external process, the file won't be // ready for asset gathering below, so assume its generation succeeds // and add it now. @@ -395,7 +358,7 @@ void ItemLibraryAssetImporter::parseQuick3DAsset(const QString &file, const QVar qmldirFile.write(qmlInfo.toUtf8()); qmldirFile.commit(); } else { - addError(tr("Failed to create qmldir file for asset: \"%1\"").arg(assetName)); + addError(tr("Failed to create qmldir file for asset: \"%1\"").arg(pd.assetName)); } } } @@ -408,19 +371,13 @@ void ItemLibraryAssetImporter::parseQuick3DAsset(const QString &file, const QVar } // Copy the original asset into a subdirectory - assetFiles.insert(sourceInfo.absoluteFilePath(), - targetDirPath + QStringLiteral("/source scene/") + sourceInfo.fileName()); + assetFiles.insert(pd.sourceInfo.absoluteFilePath(), + pd.targetDirPath + QStringLiteral("/source scene/") + pd.sourceInfo.fileName()); m_importFiles.insert(assetFiles); - -#else - Q_UNUSED(file) - Q_UNUSED(options) -#endif } void ItemLibraryAssetImporter::copyImportedFiles() { -#ifdef IMPORT_QUICK3D_ASSETS if (!m_overwrittenImports.isEmpty()) { const QString progressTitle = tr("Removing old overwritten assets."); addInfo(progressTitle); @@ -461,15 +418,20 @@ void ItemLibraryAssetImporter::copyImportedFiles() } notifyProgress(100, progressTitle); } -#endif } -void ItemLibraryAssetImporter::notifyProgress(int value, const QString &text) const +void ItemLibraryAssetImporter::notifyProgress(int value, const QString &text) { - emit progressChanged(value, text); + m_progressTitle = text; + emit progressChanged(value, m_progressTitle); keepUiAlive(); } +void ItemLibraryAssetImporter::notifyProgress(int value) +{ + notifyProgress(value, m_progressTitle); +} + void ItemLibraryAssetImporter::keepUiAlive() const { QApplication::processEvents(); @@ -484,8 +446,42 @@ bool ItemLibraryAssetImporter::confirmAssetOverwrite(const QString &assetName) QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes; } -bool ItemLibraryAssetImporter::generateComponentIcon(int size, const QString &iconFile, - const QString &iconSource) +bool ItemLibraryAssetImporter::startImportProcess(const ParseData &pd) +{ + auto doc = QmlDesignerPlugin::instance()->currentDesignDocument(); + Model *model = doc ? doc->currentModel() : nullptr; + + if (model) { + PuppetCreator puppetCreator(doc->currentTarget(), model); + puppetCreator.createQml2PuppetExecutableIfMissing(); + QStringList puppetArgs; + QJsonDocument optDoc(pd.options); + + puppetArgs << "--import3dAsset" << pd.sourceInfo.absoluteFilePath() + << pd.outDir.absolutePath() << QString::number(pd.importId) + << QString::fromUtf8(optDoc.toJson()); + + QProcessUniquePointer process = puppetCreator.createPuppetProcess( + "custom", + {}, + std::function(), + [&](int exitCode, QProcess::ExitStatus exitStatus) { + importProcessFinished(exitCode, exitStatus); + }, + puppetArgs); + + if (process->waitForStarted(5000)) { + m_qmlPuppetProcesses.push_back(std::move(process)); + return true; + } else { + process.reset(); + } + } + return false; +} + +bool ItemLibraryAssetImporter::startIconProcess(int size, const QString &iconFile, + const QString &iconSource) { auto doc = QmlDesignerPlugin::instance()->currentDesignDocument(); Model *model = doc ? doc->currentModel() : nullptr; @@ -500,7 +496,7 @@ bool ItemLibraryAssetImporter::generateComponentIcon(int size, const QString &ic {}, std::function(), [&](int exitCode, QProcess::ExitStatus exitStatus) { - processFinished(exitCode, exitStatus); + iconProcessFinished(exitCode, exitStatus); }, puppetArgs); @@ -514,9 +510,30 @@ bool ItemLibraryAssetImporter::generateComponentIcon(int size, const QString &ic return false; } +void ItemLibraryAssetImporter::postImport() +{ + Q_ASSERT(m_qmlPuppetProcesses.empty()); + + if (!isCancelled()) { + for (const auto &pd : qAsConst(m_parseData)) + postParseQuick3DAsset(pd); + } + + if (!isCancelled()) { + // Wait for icon generation processes to finish + if (m_qmlPuppetProcesses.empty()) { + finalizeQuick3DImport(); + } else { + m_qmlPuppetCount = static_cast(m_qmlPuppetProcesses.size()); + const QString progressTitle = tr("Generating icons."); + addInfo(progressTitle); + notifyProgress(0, progressTitle); + } + } +} + void ItemLibraryAssetImporter::finalizeQuick3DImport() { -#ifdef IMPORT_QUICK3D_ASSETS if (!isCancelled()) { // Don't allow cancel anymore as existing asset overwrites are not trivially recoverable. // Also, on Windows at least you can't delete a subdirectory of a watched directory, @@ -562,7 +579,6 @@ void ItemLibraryAssetImporter::finalizeQuick3DImport() notifyFinished(); } } -#endif } bool ItemLibraryAssetImporter::isCancelled() const diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h index 59211441519..a0a759a2307 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h @@ -29,11 +29,13 @@ #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include QT_BEGIN_NAMESPACE class QSSGAssetImportManager; @@ -62,11 +64,6 @@ public: void addWarning(const QString &warningMsg, const QString &srcPath = {}) const; void addInfo(const QString &infoMsg, const QString &srcPath = {}) const; - bool isQuick3DAsset(const QString &fileName) const; - QVariantMap supportedOptions(const QString &modelFile) const; - QHash allOptions() const; - QHash supportedExtensions() const; - signals: void errorReported(const QString &, const QString &) const; void warningReported(const QString &, const QString &) const; @@ -76,32 +73,49 @@ signals: void importFinished(); private slots: - void processFinished(int exitCode, QProcess::ExitStatus exitStatus); + void importProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); + void iconProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); private: + struct ParseData { + QJsonObject options; + QDir targetDir; + QDir outDir; + QString targetDirPath; + QFileInfo sourceInfo; + QString assetName; + QString originalAssetName; + int importId; + }; + void notifyFinished(); void reset(); void parseFiles(const QStringList &filePaths, const QVector &options, const QHash &extToImportOptionsMap); - void parseQuick3DAsset(const QString &file, const QVariantMap &options); + bool preParseQuick3DAsset(const QString &file, ParseData &pd); + void postParseQuick3DAsset(const ParseData &pd); void copyImportedFiles(); - void notifyProgress(int value, const QString &text) const; + void notifyProgress(int value, const QString &text); + void notifyProgress(int value); void keepUiAlive() const; bool confirmAssetOverwrite(const QString &assetName); - bool generateComponentIcon(int size, const QString &iconFile, const QString &iconSource); + bool startImportProcess(const ParseData &pd); + bool startIconProcess(int size, const QString &iconFile, const QString &iconSource); + void postImport(); void finalizeQuick3DImport(); -#ifdef IMPORT_QUICK3D_ASSETS - QScopedPointer m_quick3DAssetImporter; QSet> m_importFiles; QSet m_overwrittenImports; -#endif bool m_isImporting = false; bool m_cancelled = false; QString m_importPath; QTemporaryDir *m_tempDir = nullptr; std::vector m_qmlPuppetProcesses; int m_qmlPuppetCount = 0; + int m_qmlImportFinishedCount = 0; + int m_importIdCounter = 1000000; // Use ids in range unlikely to clash with any normal process exit codes + QHash m_parseData; + QString m_progressTitle; }; } // QmlDesigner diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp index 823baa5d149..c1a3c704d8c 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp @@ -25,6 +25,7 @@ #include "itemlibraryview.h" #include "itemlibrarywidget.h" +#include "itemlibraryassetimportdialog.h" #include "metainfo.h" #include #include @@ -216,4 +217,46 @@ void ItemLibraryView::updateImports() m_widget->delayedUpdateModel(); } +void ItemLibraryView::updateImport3DSupport(const QVariantMap &supportMap) +{ + QVariantMap extMap = qvariant_cast(supportMap.value("extensions")); + if (m_importableExtensions3DMap != extMap) { + DesignerActionManager *actionManager = + &QmlDesignerPlugin::instance()->viewManager().designerActionManager(); + + // All things importable by QSSGAssetImportManager are considered to be in the same category + // so we don't get multiple separate import dialogs when different file types are imported. + const QString category = tr("3D Assets"); + + if (!m_importableExtensions3DMap.isEmpty()) + actionManager->unregisterAddResourceHandlers(category); + + m_importableExtensions3DMap = extMap; + + auto handle3DModel = [this](const QStringList &fileNames, const QString &defaultDir) -> bool { + auto importDlg = new ItemLibraryAssetImportDialog(fileNames, defaultDir, + m_importableExtensions3DMap, + m_importOptions3DMap, + Core::ICore::mainWindow()); + importDlg->show(); + return true; + }; + + auto add3DHandler = [&](const QString &category, const QString &ext) { + const QString filter = QStringLiteral("*.%1").arg(ext); + actionManager->registerAddResourceHandler( + AddResourceHandler(category, filter, handle3DModel, 10)); + }; + + const auto groups = extMap.keys(); + for (const auto &group : groups) { + const QStringList exts = extMap[group].toStringList(); + for (const auto &ext : exts) + add3DHandler(category, ext); + } + } + + m_importOptions3DMap = qvariant_cast(supportMap.value("options")); +} + } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.h index 21d23098cf3..25d411f7b16 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.h @@ -53,6 +53,7 @@ public: void modelAboutToBeDetached(Model *model) override; void importsChanged(const QList &addedImports, const QList &removedImports) override; void documentMessagesChanged(const QList &errors, const QList &warnings) override; + void updateImport3DSupport(const QVariantMap &supportMap) override; void setResourcePath(const QString &resourcePath); @@ -66,6 +67,8 @@ private: QPointer m_widget; ImportManagerView *m_importManagerView; bool m_hasErrors = false; + QVariantMap m_importableExtensions3DMap; + QVariantMap m_importOptions3DMap; }; } diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp index bbd43986d9e..ccc9c595c17 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp @@ -26,7 +26,6 @@ #include "itemlibrarywidget.h" #include "customfilesystemmodel.h" -#include "itemlibraryassetimportdialog.h" #include "itemlibraryiconimageprovider.h" #include @@ -53,10 +52,6 @@ #include #include -#ifdef IMPORT_QUICK3D_ASSETS -#include -#endif - #include #include #include @@ -205,49 +200,6 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache, addResources({}); }); -#ifdef IMPORT_QUICK3D_ASSETS - DesignerActionManager *actionManager = - &QmlDesignerPlugin::instance()->viewManager().designerActionManager(); - - auto handle3DModel = [](const QStringList &fileNames, const QString &defaultDir) -> bool { - auto importDlg = new ItemLibraryAssetImportDialog(fileNames, defaultDir, Core::ICore::mainWindow()); - importDlg->show(); - return true; - }; - - auto add3DHandler = [&](const QString &category, const QString &ext) { - const QString filter = QStringLiteral("*.%1").arg(ext); - actionManager->registerAddResourceHandler( - AddResourceHandler(category, filter, handle3DModel, 10)); - }; - - QSSGAssetImportManager importManager; - QHash supportedExtensions = importManager.getSupportedExtensions(); - - // All things importable by QSSGAssetImportManager are considered to be in the same category - // so we don't get multiple separate import dialogs when different file types are imported. - const QString category = tr("3D Assets"); - - // Skip if 3D asset handlers have already been added - const QList handlers = actionManager->addResourceHandler(); - bool categoryAlreadyAdded = false; - for (const auto &handler : handlers) { - if (handler.category == category) { - categoryAlreadyAdded = true; - break; - } - } - - if (!categoryAlreadyAdded) { - const auto groups = supportedExtensions.keys(); - for (const auto &group : groups) { - const auto extensions = supportedExtensions[group]; - for (const auto &ext : extensions) - add3DHandler(category, ext); - } - } -#endif - const auto dropSupport = new Utils::DropSupport( m_resourcesView.data(), [this](QDropEvent *event, Utils::DropSupport *) { // Accept supported file types diff --git a/src/plugins/qmldesigner/designercore/include/abstractview.h b/src/plugins/qmldesigner/designercore/include/abstractview.h index 88c15ccf76c..8645da77935 100644 --- a/src/plugins/qmldesigner/designercore/include/abstractview.h +++ b/src/plugins/qmldesigner/designercore/include/abstractview.h @@ -189,6 +189,7 @@ public: void emitRenderImage3DChanged(const QImage &image); void emitUpdateActiveScene3D(const QVariantMap &sceneState); void emitModelNodelPreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap); + void emitImport3DSupportChanged(const QVariantMap &supportMap); void sendTokenToInstances(const QString &token, int number, const QVector &nodeVector); @@ -248,6 +249,7 @@ public: virtual void renderImage3DChanged(const QImage &image); virtual void updateActiveScene3D(const QVariantMap &sceneState); + virtual void updateImport3DSupport(const QVariantMap &supportMap); virtual void modelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap); void changeRootNodeType(const TypeName &type, int majorVersion, int minorVersion); diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp index 508970c4d83..d4741928a53 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp @@ -1578,6 +1578,9 @@ void NodeInstanceView::handlePuppetToCreatorCommand(const PuppetToCreatorCommand updatePreviewImageForNode(node, image); } } + } else if (command.type() == PuppetToCreatorCommand::Import3DSupport) { + const QVariantMap supportMap = qvariant_cast(command.data()); + emitImport3DSupportChanged(supportMap); } } diff --git a/src/plugins/qmldesigner/designercore/model/abstractview.cpp b/src/plugins/qmldesigner/designercore/model/abstractview.cpp index 963b001f238..b6818d2ee67 100644 --- a/src/plugins/qmldesigner/designercore/model/abstractview.cpp +++ b/src/plugins/qmldesigner/designercore/model/abstractview.cpp @@ -386,6 +386,10 @@ void AbstractView::updateActiveScene3D(const QVariantMap & /*sceneState*/) { } +void AbstractView::updateImport3DSupport(const QVariantMap & /*supportMap*/) +{ +} + void AbstractView::modelNodePreviewPixmapChanged(const ModelNode & /*node*/, const QPixmap & /*pixmap*/) { } @@ -804,6 +808,12 @@ void AbstractView::emitModelNodelPreviewPixmapChanged(const ModelNode &node, con model()->d->notifyModelNodePreviewPixmapChanged(node, pixmap); } +void AbstractView::emitImport3DSupportChanged(const QVariantMap &supportMap) +{ + if (model()) + model()->d->notifyImport3DSupportChanged(supportMap); +} + void AbstractView::emitRewriterEndTransaction() { if (model()) diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp index 008f5dd6a79..53a1e563d42 100644 --- a/src/plugins/qmldesigner/designercore/model/model.cpp +++ b/src/plugins/qmldesigner/designercore/model/model.cpp @@ -575,6 +575,11 @@ void ModelPrivate::notifyModelNodePreviewPixmapChanged(const ModelNode &node, co [&](AbstractView *view) { view->modelNodePreviewPixmapChanged(node, pixmap); }); } +void ModelPrivate::notifyImport3DSupportChanged(const QVariantMap &supportMap) +{ + notifyInstanceChanges([&](AbstractView *view) { view->updateImport3DSupport(supportMap); }); +} + void ModelPrivate::notifyRewriterBeginTransaction() { notifyNodeInstanceViewLast([&](AbstractView *view) { view->rewriterBeginTransaction(); }); diff --git a/src/plugins/qmldesigner/designercore/model/model_p.h b/src/plugins/qmldesigner/designercore/model/model_p.h index 072b6a887fc..7a15b73468b 100644 --- a/src/plugins/qmldesigner/designercore/model/model_p.h +++ b/src/plugins/qmldesigner/designercore/model/model_p.h @@ -176,6 +176,7 @@ public: void notifyRenderImage3DChanged(const QImage &image); void notifyUpdateActiveScene3D(const QVariantMap &sceneState); void notifyModelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap); + void notifyImport3DSupportChanged(const QVariantMap &supportMap); void setDocumentMessages(const QList &errors, const QList &warnings); diff --git a/src/tools/qml2puppet/CMakeLists.txt b/src/tools/qml2puppet/CMakeLists.txt index 0881e549437..56cbec3f012 100644 --- a/src/tools/qml2puppet/CMakeLists.txt +++ b/src/tools/qml2puppet/CMakeLists.txt @@ -137,6 +137,14 @@ extend_qtc_executable(qml2puppet icongizmoimageprovider.cpp icongizmoimageprovider.h ) +find_package(Qt5 5.15.0 COMPONENTS Quick3DAssetImport QUIET) +extend_qtc_executable(qml2puppet + CONDITION TARGET Qt5::Quick3DAssetImport + FEATURE_INFO "Qt Quick 3D asset import" + DEPENDS Qt5::Quick3DAssetImportPrivate + DEFINES IMPORT_QUICK3D_ASSETS +) + extend_qtc_executable(qml2puppet CONDITION Qt5_VERSION VERSION_GREATER_EQUAL 6.0.0 @@ -151,6 +159,12 @@ extend_qtc_executable(qml2puppet iconrenderer.cpp iconrenderer.h ) +extend_qtc_executable(qml2puppet + SOURCES_PREFIX "${SRCDIR}/qml2puppet/import3d" + SOURCES + import3d.cpp import3d.h +) + extend_qtc_executable(qml2puppet SOURCES_PREFIX "${SRCDIR}/qml2puppet/instances" SOURCES diff --git a/src/tools/qml2puppet/qml2puppet.qbs b/src/tools/qml2puppet/qml2puppet.qbs index f55104559c9..08d947d14d6 100644 --- a/src/tools/qml2puppet/qml2puppet.qbs +++ b/src/tools/qml2puppet/qml2puppet.qbs @@ -243,6 +243,8 @@ QtcTool { "editor3d/icongizmoimageprovider.h", "iconrenderer/iconrenderer.cpp", "iconrenderer/iconrenderer.h", + "import3d/import3d.cpp", + "import3d/import3d.h", "qml2puppetmain.cpp", ]