diff --git a/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h b/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h index d248e5e6fd1..6ade6a92751 100644 --- a/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h +++ b/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h @@ -58,7 +58,9 @@ enum class View3DActionType { EditCameraStopAllMoves, SetLastSceneEnvData, Import3dUpdatePreviewImage, - Import3dRotatePreviewModel + Import3dRotatePreviewModel, + Import3dAddPreviewModel, + Import3dSetCurrentPreviewModel }; constexpr bool isNanotraceEnabled() diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp index 1cbced4dfac..f6b4b388c16 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp @@ -239,20 +239,18 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog( connect(ui->advancedSettingsButton, &QPushButton::clicked, this, &ItemLibraryAssetImportDialog::toggleAdvanced); + connect(ui->importList, &QListWidget::currentRowChanged, + this, &ItemLibraryAssetImportDialog::onCurrentRowChanged); QTimer::singleShot(0, this, &ItemLibraryAssetImportDialog::updateUi); - if (m_quick3DFiles.size() != 1) { - addInfo(tr("Select import options and press \"Import\" to import the following files:")); - } else { - addInfo(tr("Importing:")); - QTimer::singleShot(0, this, &ItemLibraryAssetImportDialog::onImport); - } + addInfo(tr("Importing:")); + QTimer::singleShot(0, this, &ItemLibraryAssetImportDialog::onImport); for (const auto &file : std::as_const(m_quick3DFiles)) addInfo(file); - updateImportButtonState(); + m_updatingControlStates = false; } ItemLibraryAssetImportDialog::~ItemLibraryAssetImportDialog() @@ -501,7 +499,7 @@ QGridLayout *ItemLibraryAssetImportDialog::createOptionsGrid( QJsonValue value(optCheck->isChecked()); optObj.insert("value", value); m_importOptions[optionsIndex].insert(optKey, optObj); - updateImportButtonState(); + updatePreviewOptions(); }); } else { // Simple options also exist in advanced, so don't connect simple controls directly @@ -512,13 +510,13 @@ QGridLayout *ItemLibraryAssetImportDialog::createOptionsGrid( QObject::connect(optCheck, &QCheckBox::toggled, this, [this, optCheck, advCheck]() { if (advCheck->isChecked() != optCheck->isChecked()) { advCheck->setChecked(optCheck->isChecked()); - updateImportButtonState(); + updatePreviewOptions(); } }); QObject::connect(advCheck, &QCheckBox::toggled, this, [this, optCheck, advCheck]() { if (advCheck->isChecked() != optCheck->isChecked()) { optCheck->setChecked(advCheck->isChecked()); - updateImportButtonState(); + updatePreviewOptions(); } }); } @@ -555,7 +553,7 @@ QGridLayout *ItemLibraryAssetImportDialog::createOptionsGrid( QJsonValue value(optSpin->value()); optObj.insert("value", value); m_importOptions[optionsIndex].insert(optKey, optObj); - updateImportButtonState(); + updatePreviewOptions(); }); } else { auto *advSpin = qobject_cast( @@ -566,14 +564,14 @@ QGridLayout *ItemLibraryAssetImportDialog::createOptionsGrid( this, [this, optSpin, advSpin] { if (advSpin->value() != optSpin->value()) { advSpin->setValue(optSpin->value()); - updateImportButtonState(); + updatePreviewOptions(); } }); QObject::connect(advSpin, &QDoubleSpinBox::valueChanged, this, [this, optSpin, advSpin] { if (advSpin->value() != optSpin->value()) { optSpin->setValue(advSpin->value()); - updateImportButtonState(); + updatePreviewOptions(); } }); } @@ -859,6 +857,15 @@ bool ItemLibraryAssetImportDialog::isHiddenOption(const QString &id) return hiddenOptions.contains(id); } +bool ItemLibraryAssetImportDialog::optionsChanged() +{ + for (const ItemLibraryAssetImporter::PreviewData &data : std::as_const(m_previewData)) { + if (data.renderedOptions != data.currentOptions) + return true; + } + return false; +} + void ItemLibraryAssetImportDialog::startPreview() { cleanupPreviewPuppet(); @@ -877,7 +884,7 @@ Rectangle { property alias sceneNode: sceneNode property alias view3d: view3d property string extents - property string sceneModelName: "%3" + property string sceneModelName gradient: Gradient { GradientStop { position: 1.0; color: "#222222" } @@ -925,7 +932,7 @@ Rectangle { )"; QSize size = canvas()->size(); - previewQml = previewQml.arg(size.width()).arg(size.height()).arg(m_previewCompName); + previewQml = previewQml.arg(size.width()).arg(size.height()); m_previewFile.writeFileContents(previewQml.toUtf8()); @@ -998,6 +1005,31 @@ Import3dCanvas *ItemLibraryAssetImportDialog::canvas() return ui->import3dcanvas; } +void ItemLibraryAssetImportDialog::resetOptionControls() +{ + const QString currentName = ui->importList->currentItem()->text(); + if (!m_previewData.contains(currentName)) + return; + + m_updatingControlStates = true; + + const ItemLibraryAssetImporter::PreviewData &data = m_previewData[currentName]; + const QJsonObject options = data.currentOptions; + const QStringList optKeys = options.keys(); + for (const QString &optKey : optKeys) { + QWidget *w = m_labelToControlWidgetMaps[data.optionsIndex].value(optKey); + const QJsonObject optObj = options.value(optKey).toObject(); + const QJsonValue optValue = optObj.value("value"); + if (auto *cb = qobject_cast(w)) + cb->setChecked(optValue.toBool()); + else if (auto *spin = qobject_cast(w)) + spin->setValue(optValue.toDouble()); + } + + m_updatingControlStates = false; + updatePreviewOptions(); +} + void ItemLibraryAssetImportDialog::resizeEvent(QResizeEvent *event) { m_dialogHeight = event->size().height(); @@ -1010,9 +1042,20 @@ void ItemLibraryAssetImportDialog::setCloseButtonState(bool importing) ui->closeButton->setText(importing ? tr("Cancel") : tr("Close")); } -void ItemLibraryAssetImportDialog::updateImportButtonState() +void ItemLibraryAssetImportDialog::updatePreviewOptions() { - ui->importButton->setText(m_previewOptions == m_importOptions ? tr("Accept") : tr("Import")); + if (m_updatingControlStates) + return; + + if (ui->importList->currentRow() >= 0) { + const QString assetName = ui->importList->currentItem()->text(); + if (m_previewData.contains(assetName)) { + ItemLibraryAssetImporter::PreviewData &data = m_previewData[assetName]; + data.currentOptions = m_importOptions[data.optionsIndex]; + } + } + + ui->importButton->setText(optionsChanged() ? tr("Import") : tr("Accept")); } void ItemLibraryAssetImportDialog::addError(const QString &error, const QString &srcPath) @@ -1035,8 +1078,12 @@ void ItemLibraryAssetImportDialog::addInfo(const QString &info, const QString &s void ItemLibraryAssetImportDialog::onImport() { ui->importButton->setEnabled(false); + ui->tabWidget->setEnabled(false); - if (!m_previewCompName.isEmpty() && m_previewOptions == m_importOptions) { + const ItemLibraryAssetImporter::PreviewData &data + = m_previewData.value(ui->importList->currentIndex().data().toString()); + + if (!data.name.isEmpty() && !optionsChanged()) { cleanupPreviewPuppet(); m_importer.finalizeQuick3DImport(); return; @@ -1046,8 +1093,13 @@ void ItemLibraryAssetImportDialog::onImport() ui->progressBar->setValue(0); if (!m_quick3DFiles.isEmpty()) { - if (!m_previewCompName.isEmpty()) { - m_importer.reImportQuick3D(m_previewCompName, m_importOptions); + if (!m_previewData.isEmpty()) { + QHash importOptions; + for (const ItemLibraryAssetImporter::PreviewData &data : std::as_const(m_previewData)) { + if (data.renderedOptions != data.currentOptions) + importOptions.insert(data.name, data.currentOptions); + } + m_importer.reImportQuick3D(importOptions); } else { m_importer.importQuick3D(m_quick3DFiles, m_quick3DImportPath, m_importOptions, m_extToImportOptionsMap, @@ -1066,19 +1118,50 @@ void ItemLibraryAssetImportDialog::setImportProgress(int value, const QString &t ui->progressBar->setValue(value); } -void ItemLibraryAssetImportDialog::onImportReadyForPreview(const QString &path, const QString &compName) +void ItemLibraryAssetImportDialog::onImportReadyForPreview( + const QString &path, const QList &previewData) { - addInfo(tr("Import is ready for preview.")); - if (m_previewCompName.isEmpty()) - addInfo(tr("Click \"Accept\" to finish the import or adjust options and click \"Import\" to import again.")); + QStringList assetNames; + for (const ItemLibraryAssetImporter::PreviewData &data : previewData) { + m_previewData[data.name] = data; + assetNames.append(data.name); - m_previewFile = Utils::FilePath::fromString(path).pathAppended(m_importer.previewFileName()); - m_previewCompName = compName; - m_previewOptions = m_importOptions; - QTimer::singleShot(0, this, &ItemLibraryAssetImportDialog::startPreview); + auto items = ui->importList->findItems(data.name, Qt::MatchExactly); + if (items.isEmpty()) + ui->importList->addItem(data.name); + + addInfo(tr("Import ready for preview: %1").arg(data.name)); + } + + if (m_firstImport) { + addInfo(tr("Click \"Accept\" to finish the import or adjust options and click \"Import\" to import again.")); + m_firstImport = false; + } + + if (m_previewFile.isEmpty()) { + m_previewFile = Utils::FilePath::fromString(path).pathAppended(m_importer.previewFileName()); + QTimer::singleShot(0, this, &ItemLibraryAssetImportDialog::startPreview); + } + + QTimer::singleShot(0, this, [this, assetNames]() { + if (!m_nodeInstanceView) + return; + for (const QString &assetName : std::as_const(assetNames)) { + const ItemLibraryAssetImporter::PreviewData &data = m_previewData.value(assetName); + if (!data.name.isEmpty()) { + QVariantHash msgData; + msgData.insert("name", data.name); + msgData.insert("folder", data.folderName); + m_nodeInstanceView->view3DAction(View3DActionType::Import3dAddPreviewModel, msgData); + } + } + }); ui->importButton->setEnabled(true); - updateImportButtonState(); + ui->tabWidget->setEnabled(true); + updatePreviewOptions(); + if (ui->importList->currentRow() < 0) + ui->importList->setCurrentRow(0); } void ItemLibraryAssetImportDialog::onRequestImageUpdate() @@ -1119,6 +1202,27 @@ void ItemLibraryAssetImportDialog::onImportFinished() } } +void ItemLibraryAssetImportDialog::onCurrentRowChanged(int) +{ + QTimer::singleShot(0, this, [this]() { + if (!m_nodeInstanceView) + return; + int row = ui->importList->currentRow(); + QString compName; + if (row >= 0) + compName = ui->importList->item(row)->text(); + m_nodeInstanceView->view3DAction(View3DActionType::Import3dSetCurrentPreviewModel, compName); + resetOptionControls(); + + if (m_previewData.contains(compName)) { + const ItemLibraryAssetImporter::PreviewData data = m_previewData[compName]; + for (int i = 0; i < ui->tabWidget->count(); ++i) + ui->tabWidget->widget(i)->setVisible(i == data.optionsIndex); + ui->tabWidget->setCurrentIndex(data.optionsIndex); + } + }); +} + void ItemLibraryAssetImportDialog::onClose() { ui->importButton->setEnabled(false); diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.h index e7c49330561..20cfa7b1485 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.h @@ -63,15 +63,17 @@ private slots: private: void setCloseButtonState(bool importing); - void updateImportButtonState(); + void updatePreviewOptions(); void onImport(); void setImportProgress(int value, const QString &text); - void onImportReadyForPreview(const QString &path, const QString &compName); + void onImportReadyForPreview(const QString &path, + const QList &previewData); void onRequestImageUpdate(); void onRequestRotation(const QPointF &delta); void onImportNearlyFinished(); void onImportFinished(); + void onCurrentRowChanged(int row); void onClose(); void doClose(); void toggleAdvanced(); @@ -84,10 +86,12 @@ private: bool isSimpleGroup(const QString &id); bool isSimpleOption(const QString &id); bool isHiddenOption(const QString &id); + bool optionsChanged(); void startPreview(); void cleanupPreviewPuppet(); Import3dCanvas *canvas(); + void resetOptionControls(); Ui::ItemLibraryAssetImportDialog *ui = nullptr; Utils::OutputFormatter *m_outputFormatter = nullptr; @@ -96,8 +100,9 @@ private: QPointer m_rewriterView; QPointer m_view; ModelPointer m_model; + + QMap m_previewData; Utils::FilePath m_previewFile; - QString m_previewCompName; struct OptionsData { @@ -110,7 +115,6 @@ private: QString m_quick3DImportPath; ItemLibraryAssetImporter m_importer; QVector m_importOptions; - QVector m_previewOptions; QHash m_extToImportOptionsMap; QSet m_preselectedFilesForOverwrite; bool m_closeOnFinish = true; @@ -120,5 +124,7 @@ private: bool m_advancedMode = false; int m_dialogHeight = 350; bool m_explicitClose = false; + bool m_updatingControlStates = true; + bool m_firstImport = true; }; } diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.ui b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.ui index e0b9d925fca..4a1a85c355d 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.ui +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.ui @@ -6,7 +6,7 @@ 0 0 - 1100 + 1280 350 @@ -14,6 +14,42 @@ Asset Import + + + + + + Imported objects + + + + + + + + 1 + 0 + + + + + 150 + 0 + + + + + 150 + 16777215 + + + + true + + + + + diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp index 010d00a970a..bdc703ca742 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp @@ -91,50 +91,60 @@ void ItemLibraryAssetImporter::importQuick3D(const QStringList &inputFiles, } } -void ItemLibraryAssetImporter::reImportQuick3D(const QString &assetName, - const QVector &options) +void ItemLibraryAssetImporter::reImportQuick3D(const QHash &importOptions) { - if (!assetName.isEmpty() && !m_parseData.contains(assetName)) { - addError(tr("Attempted to reimport non-existing asset: %1").arg(assetName)); - return; - } - - ParseData &pd = m_parseData[assetName]; - // Change outDir just in case reimport generates different files - QDir oldDir = pd.outDir; - QString assetFolder = generateAssetFolderName(pd.assetName); - pd.outDir.cdUp(); - pd.outDir.mkpath(assetFolder); - - if (!pd.outDir.cd(assetFolder)) { - addError(tr("Could not access temporary asset directory: \"%1\".") - .arg(pd.outDir.filePath(assetFolder))); - return; - } - - if (oldDir.absolutePath().contains(tempDirNameBase())) - oldDir.removeRecursively(); - m_isImporting = false; m_cancelled = false; + int importId = 1; + m_puppetProcess.reset(); - m_requiredImports.clear(); m_currentImportId = 0; m_puppetQueue.clear(); - - for (ParseData &pd : m_parseData) - pd.importId = -1; - - pd.options = options[pd.optionsIndex]; - pd.importId = 1; - - m_importFiles.remove(assetName); - m_importIdToAssetNameMap.clear(); - m_importIdToAssetNameMap[pd.importId] = assetName; - m_puppetQueue.append(pd.importId); + if (importOptions.isEmpty()) { + addError(tr("Attempted to reimport no assets.")); + cancelImport(); + return; + } + + const QStringList keys = importOptions.keys(); + for (const QString &key : keys) { + if (!key.isEmpty() && !m_parseData.contains(key)) { + addError(tr("Attempted to reimport non-existing asset: %1").arg(key)); + cancelImport(); + return; + } + + ParseData &pd = m_parseData[key]; + // Change outDir just in case reimport generates different files + QDir oldDir = pd.outDir; + QString assetFolder = generateAssetFolderName(pd.assetName); + pd.outDir.cdUp(); + pd.outDir.mkpath(assetFolder); + + if (!pd.outDir.cd(assetFolder)) { + addError(tr("Could not access temporary asset directory: \"%1\".") + .arg(pd.outDir.filePath(assetFolder))); + cancelImport(); + return; + } + + if (oldDir.absolutePath().contains(tempDirNameBase())) + oldDir.removeRecursively(); + + for (ParseData &pd : m_parseData) + pd.importId = -1; + + pd.options = importOptions[key]; + pd.importId = importId++; + + m_importFiles.remove(key); + m_importIdToAssetNameMap[pd.importId] = key; + + m_puppetQueue.append(pd.importId); + } startNextImportProcess(); } @@ -386,10 +396,11 @@ void ItemLibraryAssetImporter::postParseQuick3DAsset(ParseData &pd) qmlInfo.append("."); qmlInfo.append(pd.assetName); qmlInfo.append('\n'); - m_requiredImports.append( - QStringLiteral("%1.%2").arg(QmlDesignerPlugin::instance()->documentManager() - .generatedComponentUtils().import3dTypePrefix(), - pd.assetName)); + const QString reqImp = QStringLiteral("%1.%2").arg( + QmlDesignerPlugin::instance()->documentManager() + .generatedComponentUtils().import3dTypePrefix(), pd.assetName); + if (!m_requiredImports.contains(reqImp)) + m_requiredImports.append(reqImp); while (qmlIt.hasNext()) { qmlIt.next(); QFileInfo fi = QFileInfo(qmlIt.filePath()); @@ -633,14 +644,18 @@ void ItemLibraryAssetImporter::postImport() } if (!isCancelled()) { - // TODO: Currently we only support import preview for single imports - if (m_parseData.size() != 1) { - finalizeQuick3DImport(); - } else { - const ParseData &pd = m_parseData[m_parseData.keys().first()]; - const QString importedComponentName = pd.assetName; - emit importReadyForPreview(pd.outDir.absolutePath(), importedComponentName); + QList dataList; + for (const QString &assetName : std::as_const(m_importIdToAssetNameMap)) { + const ParseData &pd = m_parseData[assetName]; + PreviewData data; + data.name = pd.assetName; + data.folderName = pd.outDir.dirName(); + data.renderedOptions = pd.options; + data.currentOptions = pd.options; + data.optionsIndex = pd.optionsIndex; + dataList.append(data); } + emit importReadyForPreview(m_tempDir->path(), dataList); } } diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h index abe96909514..eaf2fd50b1f 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h @@ -33,7 +33,7 @@ public: const QHash &extToImportOptionsMap, const QSet &preselectedFilesForOverwrite); - void reImportQuick3D(const QString &assetName, const QVector &options); + void reImportQuick3D(const QHash &importOptions); bool isImporting() const; void cancelImport(); @@ -48,12 +48,21 @@ public: void finalizeQuick3DImport(); + struct PreviewData + { + int optionsIndex = 0; + QJsonObject renderedOptions; + QJsonObject currentOptions; + QString name; + QString folderName; + }; + signals: void errorReported(const QString &, const QString &); void warningReported(const QString &, const QString &); void infoReported(const QString &, const QString &); void progressChanged(int value, const QString &text); - void importReadyForPreview(const QString &path, const QString &compName); + void importReadyForPreview(const QString &path, const QList &previewData); void importNearlyFinished(); void importFinished(); diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5import3dnodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5import3dnodeinstanceserver.cpp index 5d45a881af5..5ed372b7ad8 100644 --- a/src/tools/qml2puppet/qml2puppet/instances/qt5import3dnodeinstanceserver.cpp +++ b/src/tools/qml2puppet/qml2puppet/instances/qt5import3dnodeinstanceserver.cpp @@ -17,9 +17,12 @@ #include +#include + +#ifdef QUICK3D_MODULE #include #include -#include +#endif namespace QmlDesigner { @@ -48,11 +51,24 @@ void Qt5Import3dNodeInstanceServer::createScene(const CreateSceneCommand &comman registerFonts(command.resourceUrl); setTranslationLanguage(command.language); setupScene(command); + +#ifdef QUICK3D_MODULE + QObject *obj = rootItem(); + QQmlProperty viewProp(obj, "view3d", context()); + QObject *viewObj = viewProp.read().value(); + m_view3D = qobject_cast(viewObj); + if (m_view3D) { + QQmlProperty sceneNodeProp(obj, "sceneNode", context()); + m_sceneNode = sceneNodeProp.read().value(); + } +#endif + startRenderTimer(); } void Qt5Import3dNodeInstanceServer::view3DAction([[maybe_unused]] const View3DActionCommand &command) { +#ifdef QUICK3D_MODULE switch (command.type()) { case View3DActionType::Import3dUpdatePreviewImage: { QObject *obj = rootItem(); @@ -63,7 +79,6 @@ void Qt5Import3dNodeInstanceServer::view3DAction([[maybe_unused]] const View3DAc wProp.write(size.width()); hProp.write(size.height()); resizeCanvasToRootItem(); - startRenderTimer(); } break; @@ -72,18 +87,72 @@ void Qt5Import3dNodeInstanceServer::view3DAction([[maybe_unused]] const View3DAc QObject *obj = rootItem(); QQmlProperty sceneNodeProp(obj, "sceneNode", context()); auto sceneNode = sceneNodeProp.read().value(); - if (sceneNode) { + if (sceneNode && m_previewData.contains(m_currentNode)) { + const PreviewData &data = m_previewData[m_currentNode]; QPointF delta = command.value().toPointF(); m_generalHelper->orbitCamera(m_view3D->camera(), m_view3D->camera()->eulerRotation(), - m_lookAt, {}, {float(delta.x()), float(delta.y()), 0.f}); + data.lookAt, {}, {float(delta.x()), float(delta.y()), 0.f}); m_keepRendering = true; startRenderTimer(); } break; } + case View3DActionType::Import3dAddPreviewModel: { + const QVariantHash cmd = command.value().toHash(); + const QString name = cmd["name"].toString(); + const QString folder = cmd["folder"].toString(); + + if (m_previewData.contains(name)) { + QQuick3DNode *node = m_previewData[name].node; + if (node) { + node->setParentItem({}); + node->setParent({}); + node->deleteLater(); + } + } + + PreviewData &data = m_previewData[name]; + data.name = name; + data.lookAt = {}; + + QFileInfo fi(fileUrl().toLocalFile()); + QString compPath = fi.absolutePath() + '/' + folder + '/' + name + ".qml"; + QQmlComponent comp(engine(), compPath, QQmlComponent::PreferSynchronous); + data.node = qobject_cast(comp.create(context())); + if (data.node) { + engine()->setObjectOwnership(data.node, QJSEngine::CppOwnership); + data.node->setParentItem(m_sceneNode); + data.node->setParent(m_sceneNode); + } + + if (m_currentNode == data.name) { + m_renderCount = 0; + startRenderTimer(); + } else if (data.node) { + data.node->setVisible(false); + } + break; + } + case View3DActionType::Import3dSetCurrentPreviewModel: { + QString newName = command.value().toString(); + if (m_previewData.contains(newName) && m_currentNode != newName) { + const PreviewData &newData = m_previewData[newName]; + const PreviewData oldData = m_previewData.value(m_currentNode); + if (oldData.node) + oldData.node->setVisible(false); + if (newData.node) + newData.node->setVisible(true); + m_renderCount = 0; + m_currentNode = newName; + startRenderTimer(); + } + break; + } + default: break; } +#endif } void Qt5Import3dNodeInstanceServer::startRenderTimer() @@ -97,16 +166,13 @@ void Qt5Import3dNodeInstanceServer::startRenderTimer() void Qt5Import3dNodeInstanceServer::cleanup() { #ifdef QUICK3D_MODULE - delete m_previewNode; + for (const PreviewData &data : std::as_const(m_previewData)) + delete data.node; + m_previewData.clear(); delete m_generalHelper; #endif } -void Qt5Import3dNodeInstanceServer::finish() -{ - cleanup(); -} - void Qt5Import3dNodeInstanceServer::collectItemChangesAndSendChangeCommands() { static bool inFunction = false; @@ -130,53 +196,32 @@ void Qt5Import3dNodeInstanceServer::render() #ifdef QUICK3D_MODULE ++m_renderCount; - if (m_renderCount == 1) { - QObject *obj = rootItem(); - QQmlProperty viewProp(obj, "view3d", context()); - QObject *viewObj = viewProp.read().value(); - m_view3D = qobject_cast(viewObj); - if (m_view3D) { - QQmlProperty sceneModelNameProp(obj, "sceneModelName", context()); - QQmlProperty sceneNodeProp(obj, "sceneNode", context()); - auto sceneNode = sceneNodeProp.read().value(); - if (sceneNode) { - QString sceneModelName = sceneModelNameProp.read().toString(); - QFileInfo fi(fileUrl().toLocalFile()); - QString compPath = fi.absolutePath() + '/' + sceneModelName + ".qml"; - QQmlComponent comp(engine(), compPath, QQmlComponent::PreferSynchronous); - m_previewNode = qobject_cast(comp.create(context())); - if (m_previewNode) { - engine()->setObjectOwnership(m_previewNode, QJSEngine::CppOwnership); - m_previewNode->setParentItem(sceneNode); - m_previewNode->setParent(sceneNode); - } - } - } - } + // Render scene at least once before calculating bounds to ensure geometries are intialized + if (m_renderCount == 2 && m_view3D && m_previewData.contains(m_currentNode)) { + PreviewData &data = m_previewData[m_currentNode]; + m_generalHelper->calculateBoundsAndFocusCamera(m_view3D->camera(), data.node, + m_view3D, 1050, false, data.lookAt, + data.extents); - // Render scene once to ensure geometries are intialized so bounds calculations work correctly - if (m_renderCount == 2 && m_view3D) { - QVector3D extents; - m_generalHelper->calculateBoundsAndFocusCamera(m_view3D->camera(), m_previewNode, - m_view3D, 1050, false, m_lookAt, extents); - auto getExtentStr = [&extents](int idx) -> QString { + auto getExtentStr = [&data](int idx) -> QString { int prec = 0; - float val = extents[idx]; + float val = data.extents[idx]; while (val < 100.f) { ++prec; val *= 10.f; } // Strip unnecessary zeroes after decimal separator if (prec > 0) { - QString checkStr = QString::number(extents[idx], 'f', prec); + QString checkStr = QString::number(data.extents[idx], 'f', prec); while (prec > 0 && (checkStr.last(1) == "0" || checkStr.last(1) == ".")) { --prec; checkStr.chop(1); } } - QString retval = QLocale().toString(extents[idx], 'f', prec); + QString retval = QLocale().toString(data.extents[idx], 'f', prec); return retval; }; + QQmlProperty extentsProp(rootItem(), "extents", context()); extentsProp.write(tr("Dimensions: %1 x %2 x %3").arg(getExtentStr(0)) .arg(getExtentStr(1)) diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5import3dnodeinstanceserver.h b/src/tools/qml2puppet/qml2puppet/instances/qt5import3dnodeinstanceserver.h index a68401ef9fd..3243d3a8ca3 100644 --- a/src/tools/qml2puppet/qml2puppet/instances/qt5import3dnodeinstanceserver.h +++ b/src/tools/qml2puppet/qml2puppet/instances/qt5import3dnodeinstanceserver.h @@ -3,12 +3,14 @@ #pragma once -#include "generalhelper.h" #include "qt5nodeinstanceserver.h" +#ifdef QUICK3D_MODULE +#include "generalhelper.h" QT_BEGIN_NAMESPACE class QQuick3DNode; QT_END_NAMESPACE +#endif namespace QmlDesigner { @@ -31,7 +33,6 @@ protected: void startRenderTimer() override; private: - void finish(); void cleanup(); int m_renderCount = 0; @@ -40,8 +41,17 @@ private: #ifdef QUICK3D_MODULE QQuick3DViewport *m_view3D = nullptr; Internal::GeneralHelper *m_generalHelper = nullptr; - QQuick3DNode *m_previewNode = nullptr; - QVector3D m_lookAt; + + struct PreviewData + { + QString name; + QVector3D lookAt; + QVector3D extents; + QQuick3DNode *node = {}; + }; + QHash m_previewData; + QString m_currentNode; + QQuick3DNode *m_sceneNode = {}; #endif };