QmlDesigner: Show more information on import 3D dialog list

Preview image and some additional info are now shown on 3D import
dialog's list of imported objects. Individual items can be removed
from the list by clicking "x" button on the list or pressing delete
key.

Fixes: QDS-12900
Change-Id: Iad366ea308203a25bc3379b47c1d9c4f75f13fa7
Reviewed-by: Ali Kianian <ali.kianian@qt.io>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
Miikka Heikkinen
2024-05-31 16:33:38 +03:00
parent 4e4c8cc8c4
commit 01501e00dc
10 changed files with 484 additions and 151 deletions

View File

@@ -18,6 +18,7 @@ public:
ActiveSceneChanged, ActiveSceneChanged,
ActiveSplitChanged, ActiveSplitChanged,
RenderModelNodePreviewImage, RenderModelNodePreviewImage,
Import3DPreviewIcon,
Import3DPreviewImage, Import3DPreviewImage,
Import3DSupport, Import3DSupport,
NodeAtPos, NodeAtPos,

View File

@@ -16,6 +16,11 @@ Import3dConnectionManager::Import3dConnectionManager()
connections().emplace_back("Import 3D", "import3dmode"); connections().emplace_back("Import 3D", "import3dmode");
} }
void Import3dConnectionManager::setPreviewIconCallback(IconCallback callback)
{
m_previewIconCallback = std::move(callback);
}
void Import3dConnectionManager::setPreviewImageCallback(ImageCallback callback) void Import3dConnectionManager::setPreviewImageCallback(ImageCallback callback)
{ {
m_previewImageCallback = std::move(callback); m_previewImageCallback = std::move(callback);
@@ -29,6 +34,15 @@ void Import3dConnectionManager::dispatchCommand(const QVariant &command,
if (command.typeId() == commandType) { if (command.typeId() == commandType) {
auto cmd = command.value<PuppetToCreatorCommand>(); auto cmd = command.value<PuppetToCreatorCommand>();
switch (cmd.type()) { switch (cmd.type()) {
case PuppetToCreatorCommand::Import3DPreviewIcon: {
const QVariantList data = cmd.data().toList();
const QString assetName = data[0].toString();
ImageContainer container = qvariant_cast<ImageContainer>(data[1]);
QImage image = container.image();
if (!image.isNull())
m_previewIconCallback(assetName, image);
break;
}
case PuppetToCreatorCommand::Import3DPreviewImage: { case PuppetToCreatorCommand::Import3DPreviewImage: {
ImageContainer container = qvariant_cast<ImageContainer>(cmd.data()); ImageContainer container = qvariant_cast<ImageContainer>(cmd.data());
QImage image = container.image(); QImage image = container.image();

View File

@@ -12,16 +12,19 @@ namespace QmlDesigner {
class Import3dConnectionManager : public InteractiveConnectionManager class Import3dConnectionManager : public InteractiveConnectionManager
{ {
public: public:
using IconCallback = std::function<void(const QString &, const QImage &)>;
using ImageCallback = std::function<void(const QImage &)>; using ImageCallback = std::function<void(const QImage &)>;
Import3dConnectionManager(); Import3dConnectionManager();
void setPreviewIconCallback(IconCallback callback);
void setPreviewImageCallback(ImageCallback callback); void setPreviewImageCallback(ImageCallback callback);
protected: protected:
void dispatchCommand(const QVariant &command, Connection &connection) override; void dispatchCommand(const QVariant &command, Connection &connection) override;
private: private:
IconCallback m_previewIconCallback;
ImageCallback m_previewImageCallback; ImageCallback m_previewImageCallback;
}; };

View File

@@ -7,6 +7,8 @@
#include "import3dcanvas.h" #include "import3dcanvas.h"
#include "import3dconnectionmanager.h" #include "import3dconnectionmanager.h"
#include <designeractionmanager.h>
#include <designericons.h>
#include <model.h> #include <model.h>
#include <model/modelutils.h> #include <model/modelutils.h>
#include <nodeinstanceview.h> #include <nodeinstanceview.h>
@@ -18,6 +20,7 @@
#include <theme.h> #include <theme.h>
#include <utils/outputformatter.h> #include <utils/outputformatter.h>
#include <utils/stylehelper.h>
#include <projectexplorer/project.h> #include <projectexplorer/project.h>
#include <projectexplorer/projectmanager.h> #include <projectexplorer/projectmanager.h>
@@ -25,7 +28,9 @@
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <QFileInfo> #include <QFileInfo>
#include <QFontMetrics>
#include <QDir> #include <QDir>
#include <QLocale>
#include <QLoggingCategory> #include <QLoggingCategory>
#include <QTimer> #include <QTimer>
#include <QJsonArray> #include <QJsonArray>
@@ -63,6 +68,17 @@ void addFormattedMessage(Utils::OutputFormatter *formatter,
formatter->plainTextEdit()->verticalScrollBar()->maximum()); formatter->plainTextEdit()->verticalScrollBar()->maximum());
} }
QIcon iconFromIconFont(Theme::Icon iconType, const QColor &color)
{
const QString unicode = Theme::getIconUnicode(iconType);
const QString fontName = "qtds_propertyIconFont.ttf";
const auto helper = Utils::StyleHelper::IconFontHelper(
unicode, color, QSize(28, 28), QIcon::Normal);
return Utils::StyleHelper::getIconFromIconFont(fontName, {helper});
}
const int rowHeight = 32; const int rowHeight = 32;
const int checkBoxColWidth = 18; const int checkBoxColWidth = 18;
const int labelMinWidth = 130; const int labelMinWidth = 130;
@@ -88,6 +104,11 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(
setModal(true); setModal(true);
ui->setupUi(this); ui->setupUi(this);
m_selectedRemoveIcon = iconFromIconFont(Theme::Icon::delete_small,
Theme::getColor(Theme::IconsBaseColor));
m_unselectedRemoveIcon = iconFromIconFont(Theme::Icon::delete_small,
Theme::getColor(Theme::IconsDisabledColor));
m_outputFormatter = new Utils::OutputFormatter; m_outputFormatter = new Utils::OutputFormatter;
m_outputFormatter->setPlainTextEdit(ui->plainTextEdit); m_outputFormatter->setPlainTextEdit(ui->plainTextEdit);
@@ -239,8 +260,8 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(
connect(ui->advancedSettingsButton, &QPushButton::clicked, connect(ui->advancedSettingsButton, &QPushButton::clicked,
this, &ItemLibraryAssetImportDialog::toggleAdvanced); this, &ItemLibraryAssetImportDialog::toggleAdvanced);
connect(ui->importList, &QListWidget::currentRowChanged, connect(ui->importList, &QListWidget::currentItemChanged,
this, &ItemLibraryAssetImportDialog::onCurrentRowChanged); this, &ItemLibraryAssetImportDialog::onCurrentItemChanged);
QTimer::singleShot(0, this, &ItemLibraryAssetImportDialog::updateUi); QTimer::singleShot(0, this, &ItemLibraryAssetImportDialog::updateUi);
@@ -383,6 +404,15 @@ void ItemLibraryAssetImportDialog::updateImport(AbstractView *view,
} }
} }
void ItemLibraryAssetImportDialog::keyPressEvent(QKeyEvent *event)
{
if ((event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete)
&& ui->importList->currentItem()) {
onRemoveAsset(assetNameForListItem(ui->importList->currentItem()));
}
return QDialog::keyPressEvent(event);
}
void ItemLibraryAssetImportDialog::createTab(const QString &tabLabel, int optionsIndex, void ItemLibraryAssetImportDialog::createTab(const QString &tabLabel, int optionsIndex,
const QJsonObject &groups) const QJsonObject &groups)
{ {
@@ -828,6 +858,15 @@ void ItemLibraryAssetImportDialog::updateUi()
} }
} }
QString ItemLibraryAssetImportDialog::assetNameForListItem(QListWidgetItem *item)
{
for (const ImportData &data : std::as_const(m_importData)) {
if (data.listItem == item)
return data.previewData.name;
}
return {};
}
bool ItemLibraryAssetImportDialog::isSimpleGroup(const QString &id) bool ItemLibraryAssetImportDialog::isSimpleGroup(const QString &id)
{ {
static QStringList simpleGroups { static QStringList simpleGroups {
@@ -859,8 +898,8 @@ bool ItemLibraryAssetImportDialog::isHiddenOption(const QString &id)
bool ItemLibraryAssetImportDialog::optionsChanged() bool ItemLibraryAssetImportDialog::optionsChanged()
{ {
for (const ItemLibraryAssetImporter::PreviewData &data : std::as_const(m_previewData)) { for (const ImportData &data : std::as_const(m_importData)) {
if (data.renderedOptions != data.currentOptions) if (data.previewData.renderedOptions != data.previewData.currentOptions)
return true; return true;
} }
return false; return false;
@@ -883,6 +922,7 @@ Rectangle {
property alias sceneNode: sceneNode property alias sceneNode: sceneNode
property alias view3d: view3d property alias view3d: view3d
property alias iconView3d: iconView3d
property string extents property string extents
property string sceneModelName property string sceneModelName
@@ -897,30 +937,40 @@ Rectangle {
camera: viewCamera camera: viewCamera
environment: SceneEnvironment { environment: SceneEnvironment {
id: sceneEnvironment
antialiasingMode: SceneEnvironment.MSAA antialiasingMode: SceneEnvironment.MSAA
antialiasingQuality: SceneEnvironment.VeryHigh antialiasingQuality: SceneEnvironment.VeryHigh
} }
PerspectiveCamera {
id: viewCamera
x: 600
y: 600
z: 600
eulerRotation.x: -45
eulerRotation.y: -45
clipFar: 100000
clipNear: 10
}
DirectionalLight {
rotation: viewCamera.rotation
}
Node { Node {
id: sceneNode id: sceneNode
PerspectiveCamera {
id: viewCamera
x: 600
y: 600
z: 600
eulerRotation.x: -45
eulerRotation.y: -45
clipFar: 100000
clipNear: 10
}
DirectionalLight {
rotation: viewCamera.rotation
}
} }
} }
View3D {
id: iconView3d
importScene: sceneNode
camera: viewCamera
environment: sceneEnvironment
visible: false
width: 48
height: 48
}
Text { Text {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: parent.left anchors.left: parent.left
@@ -966,6 +1016,15 @@ Rectangle {
m_nodeInstanceView->setTarget(m_view->nodeInstanceView()->target()); m_nodeInstanceView->setTarget(m_view->nodeInstanceView()->target());
auto previewIconCallback = [this](const QString &assetName, const QImage &image) {
if (!m_importData.contains(assetName)) {
addWarning(tr("Preview icon generated for non-existent asset: %1").arg(assetName));
return;
}
if (m_importData[assetName].iconLabel)
m_importData[assetName].iconLabel->setPixmap(QPixmap::fromImage(image));
};
auto previewImageCallback = [this](const QImage &image) { auto previewImageCallback = [this](const QImage &image) {
canvas()->updateRenderImage(image); canvas()->updateRenderImage(image);
}; };
@@ -975,6 +1034,7 @@ Rectangle {
cleanupPreviewPuppet(); cleanupPreviewPuppet();
}; };
m_connectionManager->setPreviewIconCallback(std::move(previewIconCallback));
m_connectionManager->setPreviewImageCallback(std::move(previewImageCallback)); m_connectionManager->setPreviewImageCallback(std::move(previewImageCallback));
m_nodeInstanceView->setCrashCallback(std::move(crashCallback)); m_nodeInstanceView->setCrashCallback(std::move(crashCallback));
@@ -992,8 +1052,10 @@ void ItemLibraryAssetImportDialog::cleanupPreviewPuppet()
if (m_nodeInstanceView) if (m_nodeInstanceView)
m_nodeInstanceView->setCrashCallback({}); m_nodeInstanceView->setCrashCallback({});
if (m_connectionManager) if (m_connectionManager) {
m_connectionManager->setPreviewIconCallback({});
m_connectionManager->setPreviewImageCallback({}); m_connectionManager->setPreviewImageCallback({});
}
delete m_rewriterView; delete m_rewriterView;
delete m_nodeInstanceView; delete m_nodeInstanceView;
@@ -1007,17 +1069,17 @@ Import3dCanvas *ItemLibraryAssetImportDialog::canvas()
void ItemLibraryAssetImportDialog::resetOptionControls() void ItemLibraryAssetImportDialog::resetOptionControls()
{ {
const QString currentName = ui->importList->currentItem()->text(); const QString currentName = assetNameForListItem(ui->importList->currentItem());
if (!m_previewData.contains(currentName)) if (!m_importData.contains(currentName))
return; return;
m_updatingControlStates = true; m_updatingControlStates = true;
const ItemLibraryAssetImporter::PreviewData &data = m_previewData[currentName]; const ImportData &data = m_importData[currentName];
const QJsonObject options = data.currentOptions; const QJsonObject options = data.previewData.currentOptions;
const QStringList optKeys = options.keys(); const QStringList optKeys = options.keys();
for (const QString &optKey : optKeys) { for (const QString &optKey : optKeys) {
QWidget *w = m_labelToControlWidgetMaps[data.optionsIndex].value(optKey); QWidget *w = m_labelToControlWidgetMaps[data.previewData.optionsIndex].value(optKey);
const QJsonObject optObj = options.value(optKey).toObject(); const QJsonObject optObj = options.value(optKey).toObject();
const QJsonValue optValue = optObj.value("value"); const QJsonValue optValue = optObj.value("value");
if (auto *cb = qobject_cast<QCheckBox *>(w)) if (auto *cb = qobject_cast<QCheckBox *>(w))
@@ -1048,10 +1110,10 @@ void ItemLibraryAssetImportDialog::updatePreviewOptions()
return; return;
if (ui->importList->currentRow() >= 0) { if (ui->importList->currentRow() >= 0) {
const QString assetName = ui->importList->currentItem()->text(); const QString assetName = assetNameForListItem(ui->importList->currentItem());
if (m_previewData.contains(assetName)) { if (m_importData.contains(assetName)) {
ItemLibraryAssetImporter::PreviewData &data = m_previewData[assetName]; ImportData &data = m_importData[assetName];
data.currentOptions = m_importOptions[data.optionsIndex]; data.previewData.currentOptions = m_importOptions[data.previewData.optionsIndex];
} }
} }
@@ -1079,25 +1141,26 @@ void ItemLibraryAssetImportDialog::onImport()
{ {
ui->importButton->setEnabled(false); ui->importButton->setEnabled(false);
ui->tabWidget->setEnabled(false); ui->tabWidget->setEnabled(false);
ui->importList->setEnabled(false);
const ItemLibraryAssetImporter::PreviewData &data if (!m_importData.isEmpty() && !optionsChanged()) {
= m_previewData.value(ui->importList->currentIndex().data().toString());
if (!data.name.isEmpty() && !optionsChanged()) {
cleanupPreviewPuppet(); cleanupPreviewPuppet();
m_importer.finalizeQuick3DImport(); m_importer.finalizeQuick3DImport();
return; return;
} }
const QString assetName = assetNameForListItem(ui->importList->currentItem());
const ImportData &data = m_importData.value(assetName);
setCloseButtonState(true); setCloseButtonState(true);
ui->progressBar->setValue(0); ui->progressBar->setValue(0);
if (!m_quick3DFiles.isEmpty()) { if (!m_quick3DFiles.isEmpty()) {
if (!m_previewData.isEmpty()) { if (!m_importData.isEmpty()) {
QHash<QString , QJsonObject> importOptions; QHash<QString , QJsonObject> importOptions;
for (const ItemLibraryAssetImporter::PreviewData &data : std::as_const(m_previewData)) { for (const ImportData &data : std::as_const(m_importData)) {
if (data.renderedOptions != data.currentOptions) if (data.previewData.renderedOptions != data.previewData.currentOptions)
importOptions.insert(data.name, data.currentOptions); importOptions.insert(data.previewData.name, data.previewData.currentOptions);
} }
m_importer.reImportQuick3D(importOptions); m_importer.reImportQuick3D(importOptions);
} else { } else {
@@ -1121,16 +1184,79 @@ void ItemLibraryAssetImportDialog::setImportProgress(int value, const QString &t
void ItemLibraryAssetImportDialog::onImportReadyForPreview( void ItemLibraryAssetImportDialog::onImportReadyForPreview(
const QString &path, const QList<ItemLibraryAssetImporter::PreviewData> &previewData) const QString &path, const QList<ItemLibraryAssetImporter::PreviewData> &previewData)
{ {
if (previewData.isEmpty()) {
m_importer.cancelImport();
return;
}
QPixmap placeHolder = QPixmap(":/navigator/icon/tooltip_placeholder.png").scaled(48, 48);
int maxNameLen = 150;
QStringList assetNames; QStringList assetNames;
for (const ItemLibraryAssetImporter::PreviewData &data : previewData) { for (const ItemLibraryAssetImporter::PreviewData &data : previewData) {
m_previewData[data.name] = data; const QString assetName = data.name;
assetNames.append(data.name); assetNames.append(assetName);
if (!m_importData.contains(assetName)) {
ImportData impData;
impData.previewData = data;
auto lwi = new QListWidgetItem();
impData.listItem = lwi;
auto w = new QWidget(ui->importList);
w->setToolTip(assetName);
auto layout = new QHBoxLayout(w);
auto iconLabel = new QLabel(w);
iconLabel->setPixmap(placeHolder);
impData.iconLabel = iconLabel;
layout->addWidget(iconLabel);
auto infoLabel = new QLabel(w);
infoLabel->setFixedWidth(maxNameLen);
impData.infoLabel = infoLabel;
layout->addWidget(infoLabel);
layout->addStretch(1);
auto removeButton = new QPushButton(m_unselectedRemoveIcon, {}, w);
removeButton->setFlat(true);
impData.removeButton = removeButton;
layout->addWidget(removeButton, 0, Qt::AlignRight);
layout->setSizeConstraint(QLayout::SetNoConstraint);
w->setLayout(layout);
w->resize(w->height(), ui->importList->width());
lwi->setSizeHint(w->sizeHint());
ui->importList->addItem(lwi);
ui->importList->setItemWidget(lwi, w);
m_importData[assetName] = impData;
QObject::connect(removeButton, &QPushButton::clicked, this, [this, assetName]() {
onRemoveAsset(assetName);
});
} else {
m_importData[assetName].previewData = data;
}
auto items = ui->importList->findItems(data.name, Qt::MatchExactly); if (!m_importData.contains(assetName))
if (items.isEmpty()) return;
ui->importList->addItem(data.name);
addInfo(tr("Import ready for preview: %1").arg(data.name)); const ImportData &impData = m_importData[assetName];
if (QLabel *l = impData.infoLabel) {
QFontMetrics fm = l->fontMetrics();
QString truncNameBase = assetName;
QString truncName = assetName;
int truncNameLen = fm.boundingRect(truncName).width();
while (!truncNameBase.isEmpty() && truncNameLen > maxNameLen) {
truncNameBase.chop(1);
truncName = truncNameBase + "...";
truncNameLen = fm.boundingRect(truncName).width();
}
QString s;
s += truncName + '\n';
s += tr("Object Type: %1\n").arg(data.type);
s += tr("Imported Size: %1").arg(QLocale::system().formattedDataSize(
data.size, 2, QLocale::DataSizeTraditionalFormat));
l->setText(s);
}
addInfo(tr("Import ready for preview: %1").arg(assetName));
} }
if (m_firstImport) { if (m_firstImport) {
@@ -1147,11 +1273,11 @@ void ItemLibraryAssetImportDialog::onImportReadyForPreview(
if (!m_nodeInstanceView) if (!m_nodeInstanceView)
return; return;
for (const QString &assetName : std::as_const(assetNames)) { for (const QString &assetName : std::as_const(assetNames)) {
const ItemLibraryAssetImporter::PreviewData &data = m_previewData.value(assetName); const ImportData &data = m_importData.value(assetName);
if (!data.name.isEmpty()) { if (!data.previewData.name.isEmpty()) {
QVariantHash msgData; QVariantHash msgData;
msgData.insert("name", data.name); msgData.insert("name", data.previewData.name);
msgData.insert("folder", data.folderName); msgData.insert("folder", data.previewData.folderName);
m_nodeInstanceView->view3DAction(View3DActionType::Import3dAddPreviewModel, msgData); m_nodeInstanceView->view3DAction(View3DActionType::Import3dAddPreviewModel, msgData);
} }
} }
@@ -1159,6 +1285,7 @@ void ItemLibraryAssetImportDialog::onImportReadyForPreview(
ui->importButton->setEnabled(true); ui->importButton->setEnabled(true);
ui->tabWidget->setEnabled(true); ui->tabWidget->setEnabled(true);
ui->importList->setEnabled(true);
updatePreviewOptions(); updatePreviewOptions();
if (ui->importList->currentRow() < 0) if (ui->importList->currentRow() < 0)
ui->importList->setCurrentRow(0); ui->importList->setCurrentRow(0);
@@ -1202,23 +1329,33 @@ void ItemLibraryAssetImportDialog::onImportFinished()
} }
} }
void ItemLibraryAssetImportDialog::onCurrentRowChanged(int) void ItemLibraryAssetImportDialog::onCurrentItemChanged(QListWidgetItem *current, QListWidgetItem *)
{ {
QTimer::singleShot(0, this, [this]() { if (!current)
return;
for (const ImportData &data : std::as_const(m_importData)) {
if (data.removeButton) {
if (current == data.listItem)
data.removeButton->setIcon(m_selectedRemoveIcon);
else
data.removeButton->setIcon(m_unselectedRemoveIcon);
}
}
const QString assetName = assetNameForListItem(ui->importList->currentItem());
resetOptionControls();
const ImportData data = m_importData.value(assetName);
for (int i = 0; i < ui->tabWidget->count(); ++i)
ui->tabWidget->widget(i)->setVisible(i == data.previewData.optionsIndex);
ui->tabWidget->setCurrentIndex(data.previewData.optionsIndex);
QTimer::singleShot(0, this, [this, assetName]() {
if (!m_nodeInstanceView) if (!m_nodeInstanceView)
return; return;
int row = ui->importList->currentRow(); if (m_importData.contains(assetName)) {
QString compName; m_nodeInstanceView->view3DAction(View3DActionType::Import3dSetCurrentPreviewModel,
if (row >= 0) assetName);
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);
} }
}); });
} }
@@ -1268,4 +1405,20 @@ void ItemLibraryAssetImportDialog::toggleAdvanced()
updateUi(); updateUi();
} }
void ItemLibraryAssetImportDialog::onRemoveAsset(const QString &assetName)
{
m_importer.removeAssetFromImport(assetName);
if (m_importData.contains(assetName)) {
ImportData data = m_importData.take(assetName);
addInfo(tr("Removed %1 from the import.").arg(assetName));
if (data.listItem) {
ui->importList->removeItemWidget(data.listItem);
delete data.listItem;
}
}
if (m_importData.isEmpty())
onClose();
}
} }

View File

@@ -9,12 +9,15 @@
#include <utils/filepath.h> #include <utils/filepath.h>
#include <QDialog> #include <QDialog>
#include <QIcon>
#include <QJsonObject> #include <QJsonObject>
#include <QPointer> #include <QPointer>
#include <QSet> #include <QSet>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QGridLayout; class QGridLayout;
class QLabel;
class QListWidgetItem;
class QPushButton; class QPushButton;
QT_END_NAMESPACE QT_END_NAMESPACE
@@ -23,7 +26,6 @@ class OutputFormatter;
} }
namespace QmlDesigner { namespace QmlDesigner {
class ItemLibraryAssetImporter;
class Import3dCanvas; class Import3dCanvas;
class Import3dConnectionManager; class Import3dConnectionManager;
class NodeInstanceView; class NodeInstanceView;
@@ -53,6 +55,8 @@ public:
const QVariantMap &supportedExts, const QVariantMap &supportedExts,
const QVariantMap &supportedOpts); const QVariantMap &supportedOpts);
void keyPressEvent(QKeyEvent *event) override;
protected: protected:
void resizeEvent(QResizeEvent *event) override; void resizeEvent(QResizeEvent *event) override;
@@ -62,6 +66,22 @@ private slots:
void addInfo(const QString &info, const QString &srcPath = {}); void addInfo(const QString &info, const QString &srcPath = {});
private: private:
struct ImportData
{
QListWidgetItem *listItem = {};
QLabel *iconLabel = {};
QLabel *infoLabel = {};
QPushButton *removeButton = {};
ItemLibraryAssetImporter::PreviewData previewData;
};
struct OptionsData
{
int optionsRows = 0;
int optionsHeight = 0;
QList<QWidget *> contentWidgets;
};
void setCloseButtonState(bool importing); void setCloseButtonState(bool importing);
void updatePreviewOptions(); void updatePreviewOptions();
@@ -73,15 +93,17 @@ private:
void onRequestRotation(const QPointF &delta); void onRequestRotation(const QPointF &delta);
void onImportNearlyFinished(); void onImportNearlyFinished();
void onImportFinished(); void onImportFinished();
void onCurrentRowChanged(int row); void onCurrentItemChanged(QListWidgetItem *current, QListWidgetItem *previous);
void onClose(); void onClose();
void doClose(); void doClose();
void toggleAdvanced(); void toggleAdvanced();
void onRemoveAsset(const QString &assetName);
void createTab(const QString &tabLabel, int optionsIndex, const QJsonObject &groups); void createTab(const QString &tabLabel, int optionsIndex, const QJsonObject &groups);
QGridLayout *createOptionsGrid(QWidget *contentWidget, bool advanced, int optionsIndex, QGridLayout *createOptionsGrid(QWidget *contentWidget, bool advanced, int optionsIndex,
const QJsonObject &groups); const QJsonObject &groups);
void updateUi(); void updateUi();
QString assetNameForListItem(QListWidgetItem *item);
bool isSimpleGroup(const QString &id); bool isSimpleGroup(const QString &id);
bool isSimpleOption(const QString &id); bool isSimpleOption(const QString &id);
@@ -101,16 +123,9 @@ private:
QPointer<AbstractView> m_view; QPointer<AbstractView> m_view;
ModelPointer m_model; ModelPointer m_model;
QMap<QString, ItemLibraryAssetImporter::PreviewData> m_previewData; QMap<QString, ImportData> m_importData;
Utils::FilePath m_previewFile; Utils::FilePath m_previewFile;
struct OptionsData
{
int optionsRows = 0;
int optionsHeight = 0;
QList<QWidget *> contentWidgets; // Tab content widgets
};
QStringList m_quick3DFiles; QStringList m_quick3DFiles;
QString m_quick3DImportPath; QString m_quick3DImportPath;
ItemLibraryAssetImporter m_importer; ItemLibraryAssetImporter m_importer;
@@ -126,5 +141,7 @@ private:
bool m_explicitClose = false; bool m_explicitClose = false;
bool m_updatingControlStates = true; bool m_updatingControlStates = true;
bool m_firstImport = true; bool m_firstImport = true;
QIcon m_selectedRemoveIcon;
QIcon m_unselectedRemoveIcon;
}; };
} }

View File

@@ -33,7 +33,7 @@
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>150</width> <width>250</width>
<height>0</height> <height>0</height>
</size> </size>
</property> </property>

View File

@@ -238,7 +238,6 @@ void ItemLibraryAssetImporter::reset()
delete m_tempDir; delete m_tempDir;
m_tempDir = new QTemporaryDir(QDir::tempPath() + tempDirNameBase()); m_tempDir = new QTemporaryDir(QDir::tempPath() + tempDirNameBase());
m_importFiles.clear(); m_importFiles.clear();
m_overwrittenImports.clear();
m_puppetProcess.reset(); m_puppetProcess.reset();
m_parseData.clear(); m_parseData.clear();
m_requiredImports.clear(); m_requiredImports.clear();
@@ -337,14 +336,14 @@ bool ItemLibraryAssetImporter::preParseQuick3DAsset(const QString &file, ParseDa
overwriteFiles = dlg.selectedFiles(); overwriteFiles = dlg.selectedFiles();
if (!overwriteFiles.isEmpty()) { if (!overwriteFiles.isEmpty()) {
overwriteFiles.append(::Utils::toList(alwaysOverwrite)); overwriteFiles.append(::Utils::toList(alwaysOverwrite));
m_overwrittenImports.insert(pd.targetDirPath, overwriteFiles); pd.overwrittenImports.insert(pd.targetDirPath, overwriteFiles);
} else { } else {
addWarning(tr("No files selected for overwrite, skipping import: \"%1\".").arg(pd.assetName)); addWarning(tr("No files selected for overwrite, skipping import: \"%1\".").arg(pd.assetName));
return false; return false;
} }
} else { } else {
m_overwrittenImports.insert(pd.targetDirPath, {}); pd.overwrittenImports.insert(pd.targetDirPath, {});
} }
} }
@@ -396,9 +395,7 @@ void ItemLibraryAssetImporter::postParseQuick3DAsset(ParseData &pd)
qmlInfo.append("."); qmlInfo.append(".");
qmlInfo.append(pd.assetName); qmlInfo.append(pd.assetName);
qmlInfo.append('\n'); qmlInfo.append('\n');
const QString reqImp = QStringLiteral("%1.%2").arg( const QString reqImp = generateRequiredImportForAsset(pd.assetName);
QmlDesignerPlugin::instance()->documentManager()
.generatedComponentUtils().import3dTypePrefix(), pd.assetName);
if (!m_requiredImports.contains(reqImp)) if (!m_requiredImports.contains(reqImp))
m_requiredImports.append(reqImp); m_requiredImports.append(reqImp);
while (qmlIt.hasNext()) { while (qmlIt.hasNext()) {
@@ -480,9 +477,13 @@ void ItemLibraryAssetImporter::postParseQuick3DAsset(ParseData &pd)
// Gather all generated files // Gather all generated files
QDirIterator dirIt(outDir.path(), QDir::Files, QDirIterator::Subdirectories); QDirIterator dirIt(outDir.path(), QDir::Files, QDirIterator::Subdirectories);
pd.assetSize = 0;
while (dirIt.hasNext()) { while (dirIt.hasNext()) {
dirIt.next(); dirIt.next();
insertAsset(dirIt.filePath()); insertAsset(dirIt.filePath());
QFileInfo fi = dirIt.fileInfo();
if (fi.isFile())
pd.assetSize += fi.size();
} }
// Copy the original asset into a subdirectory // Copy the original asset into a subdirectory
@@ -492,14 +493,17 @@ void ItemLibraryAssetImporter::postParseQuick3DAsset(ParseData &pd)
void ItemLibraryAssetImporter::copyImportedFiles() void ItemLibraryAssetImporter::copyImportedFiles()
{ {
if (!m_overwrittenImports.isEmpty()) { QHash<QString, QStringList> allOverwrites;
for (const ParseData &pd: std::as_const(m_parseData))
allOverwrites.insert(pd.overwrittenImports);
if (!allOverwrites.isEmpty()) {
const QString progressTitle = tr("Removing old overwritten assets."); const QString progressTitle = tr("Removing old overwritten assets.");
addInfo(progressTitle); addInfo(progressTitle);
notifyProgress(0, progressTitle); notifyProgress(0, progressTitle);
int counter = 0; int counter = 0;
auto it = m_overwrittenImports.constBegin(); auto it = allOverwrites.constBegin();
while (it != m_overwrittenImports.constEnd()) { while (it != allOverwrites.constEnd()) {
Utils::FilePath dir = Utils::FilePath::fromUserInput(it.key()); Utils::FilePath dir = Utils::FilePath::fromUserInput(it.key());
if (dir.exists()) { if (dir.exists()) {
const auto &overwrittenFiles = it.value(); const auto &overwrittenFiles = it.value();
@@ -512,7 +516,7 @@ void ItemLibraryAssetImporter::copyImportedFiles()
QFile::remove(fileName); QFile::remove(fileName);
} }
} }
notifyProgress((100 * ++counter) / m_overwrittenImports.size(), progressTitle); notifyProgress((100 * ++counter) / allOverwrites.size(), progressTitle);
++it; ++it;
} }
} }
@@ -568,6 +572,13 @@ QString ItemLibraryAssetImporter::generateAssetFolderName(const QString &assetNa
return assetName + "_QDS_" + QString::number(counter++); return assetName + "_QDS_" + QString::number(counter++);
} }
QString ItemLibraryAssetImporter::generateRequiredImportForAsset(const QString &assetName) const
{
return QStringLiteral("%1.%2").arg(
QmlDesignerPlugin::instance()->documentManager()
.generatedComponentUtils().import3dTypePrefix(), assetName);
}
ItemLibraryAssetImporter::OverwriteResult ItemLibraryAssetImporter::confirmAssetOverwrite(const QString &assetName) ItemLibraryAssetImporter::OverwriteResult ItemLibraryAssetImporter::confirmAssetOverwrite(const QString &assetName)
{ {
const QString title = tr("Overwrite Existing Asset?"); const QString title = tr("Overwrite Existing Asset?");
@@ -653,8 +664,11 @@ void ItemLibraryAssetImporter::postImport()
data.renderedOptions = pd.options; data.renderedOptions = pd.options;
data.currentOptions = pd.options; data.currentOptions = pd.options;
data.optionsIndex = pd.optionsIndex; data.optionsIndex = pd.optionsIndex;
data.type = pd.sourceInfo.suffix().toLower();
data.size = pd.assetSize;
dataList.append(data); dataList.append(data);
} }
emit importReadyForPreview(m_tempDir->path(), dataList); emit importReadyForPreview(m_tempDir->path(), dataList);
} }
} }
@@ -716,8 +730,12 @@ void ItemLibraryAssetImporter::finalizeQuick3DImport()
addError(tr("Failed to update imports: %1").arg(e.description())); addError(tr("Failed to update imports: %1").arg(e.description()));
} }
} else if (counter >= 50) { } else if (counter >= 50) {
if (!m_overwrittenImports.isEmpty()) for (const ParseData &pd : std::as_const(m_parseData)) {
model->rewriterView()->emitCustomNotification("asset_import_update"); if (!pd.overwrittenImports.isEmpty()) {
model->rewriterView()->emitCustomNotification("asset_import_update");
break;
}
}
timer->stop(); timer->stop();
notifyFinished(); notifyFinished();
} }
@@ -732,6 +750,13 @@ void ItemLibraryAssetImporter::finalizeQuick3DImport()
} }
} }
void ItemLibraryAssetImporter::removeAssetFromImport(const QString &assetName)
{
m_parseData.remove(assetName);
m_importFiles.remove(assetName);
m_requiredImports.removeOne(generateRequiredImportForAsset(assetName));
}
QString ItemLibraryAssetImporter::sourceSceneTargetFilePath(const ParseData &pd) QString ItemLibraryAssetImporter::sourceSceneTargetFilePath(const ParseData &pd)
{ {
return pd.targetDirPath + QStringLiteral("/source scene/") + pd.sourceInfo.fileName(); return pd.targetDirPath + QStringLiteral("/source scene/") + pd.sourceInfo.fileName();

View File

@@ -47,6 +47,7 @@ public:
QString tempDirNameBase() const { return "/qds3dimport"; } QString tempDirNameBase() const { return "/qds3dimport"; }
void finalizeQuick3DImport(); void finalizeQuick3DImport();
void removeAssetFromImport(const QString &assetName);
struct PreviewData struct PreviewData
{ {
@@ -55,6 +56,8 @@ public:
QJsonObject currentOptions; QJsonObject currentOptions;
QString name; QString name;
QString folderName; QString folderName;
QString type;
qint64 size;
}; };
signals: signals:
@@ -78,8 +81,10 @@ private:
QFileInfo sourceInfo; QFileInfo sourceInfo;
QString assetName; QString assetName;
QString originalAssetName; QString originalAssetName;
qint64 assetSize;
int importId = -1; int importId = -1;
int optionsIndex = -1; int optionsIndex = -1;
QHash<QString, QStringList> overwrittenImports;
}; };
void notifyFinished(); void notifyFinished();
@@ -96,6 +101,7 @@ private:
void notifyProgress(int value); void notifyProgress(int value);
void keepUiAlive() const; void keepUiAlive() const;
QString generateAssetFolderName(const QString &assetName) const; QString generateAssetFolderName(const QString &assetName) const;
QString generateRequiredImportForAsset(const QString &assetName) const;
enum class OverwriteResult { enum class OverwriteResult {
Skip, Skip,
@@ -109,7 +115,6 @@ private:
QString sourceSceneTargetFilePath(const ParseData &pd); QString sourceSceneTargetFilePath(const ParseData &pd);
QHash<QString, QHash<QString, QString>> m_importFiles; // Key: asset name QHash<QString, QHash<QString, QString>> m_importFiles; // Key: asset name
QHash<QString, QStringList> m_overwrittenImports;
bool m_isImporting = false; bool m_isImporting = false;
bool m_cancelled = false; bool m_cancelled = false;
QString m_importPath; QString m_importPath;

View File

@@ -35,7 +35,7 @@ Qt5Import3dNodeInstanceServer::Qt5Import3dNodeInstanceServer(NodeInstanceClientI
#ifdef QUICK3D_MODULE #ifdef QUICK3D_MODULE
m_generalHelper = new Internal::GeneralHelper(); m_generalHelper = new Internal::GeneralHelper();
QObject::connect(m_generalHelper, &Internal::GeneralHelper::requestRender, this, [this]() { QObject::connect(m_generalHelper, &Internal::GeneralHelper::requestRender, this, [this]() {
startRenderTimer(); addCurrentNodeToRenderQueue();
}); });
#endif #endif
} }
@@ -54,16 +54,22 @@ void Qt5Import3dNodeInstanceServer::createScene(const CreateSceneCommand &comman
#ifdef QUICK3D_MODULE #ifdef QUICK3D_MODULE
QObject *obj = rootItem(); QObject *obj = rootItem();
QQmlProperty viewProp(obj, "view3d", context()); auto initView = [&obj, this](const QString &viewId, QQuick3DViewport *&view3D) {
QObject *viewObj = viewProp.read().value<QObject *>(); QQmlProperty viewProp(obj, viewId, context());
m_view3D = qobject_cast<QQuick3DViewport *>(viewObj); QObject *viewObj = viewProp.read().value<QObject *>();
view3D = qobject_cast<QQuick3DViewport *>(viewObj);
};
initView("view3d", m_view3D);
initView("iconView3d", m_iconView3D);
if (m_view3D) { if (m_view3D) {
QQmlProperty sceneNodeProp(obj, "sceneNode", context()); QQmlProperty sceneNodeProp(obj, "sceneNode", context());
m_sceneNode = sceneNodeProp.read().value<QQuick3DNode *>(); m_sceneNode = sceneNodeProp.read().value<QQuick3DNode *>();
m_defaultCameraRotation = m_view3D->camera()->rotation();
m_defaultCameraPosition = m_view3D->camera()->position();
addInitToRenderQueue();
} }
#endif #endif
startRenderTimer();
} }
void Qt5Import3dNodeInstanceServer::view3DAction([[maybe_unused]] const View3DActionCommand &command) void Qt5Import3dNodeInstanceServer::view3DAction([[maybe_unused]] const View3DActionCommand &command)
@@ -79,7 +85,7 @@ void Qt5Import3dNodeInstanceServer::view3DAction([[maybe_unused]] const View3DAc
wProp.write(size.width()); wProp.write(size.width());
hProp.write(size.height()); hProp.write(size.height());
resizeCanvasToRootItem(); resizeCanvasToRootItem();
startRenderTimer(); addCurrentNodeToRenderQueue();
} }
break; break;
} }
@@ -92,8 +98,8 @@ void Qt5Import3dNodeInstanceServer::view3DAction([[maybe_unused]] const View3DAc
QPointF delta = command.value().toPointF(); QPointF delta = command.value().toPointF();
m_generalHelper->orbitCamera(m_view3D->camera(), m_view3D->camera()->eulerRotation(), m_generalHelper->orbitCamera(m_view3D->camera(), m_view3D->camera()->eulerRotation(),
data.lookAt, {}, {float(delta.x()), float(delta.y()), 0.f}); data.lookAt, {}, {float(delta.x()), float(delta.y()), 0.f});
m_keepRendering = true; // Add 2 renders to keep render timer alive for smooth rotation
startRenderTimer(); addCurrentNodeToRenderQueue(2);
} }
break; break;
} }
@@ -123,28 +129,23 @@ void Qt5Import3dNodeInstanceServer::view3DAction([[maybe_unused]] const View3DAc
engine()->setObjectOwnership(data.node, QJSEngine::CppOwnership); engine()->setObjectOwnership(data.node, QJSEngine::CppOwnership);
data.node->setParentItem(m_sceneNode); data.node->setParentItem(m_sceneNode);
data.node->setParent(m_sceneNode); data.node->setParent(m_sceneNode);
addInitToRenderQueue();
if (m_currentNode == name)
addCurrentNodeToRenderQueue();
addIconToRenderQueue(name);
} }
if (m_currentNode == data.name) {
m_renderCount = 0;
startRenderTimer();
} else if (data.node) {
data.node->setVisible(false);
}
break; break;
} }
case View3DActionType::Import3dSetCurrentPreviewModel: { case View3DActionType::Import3dSetCurrentPreviewModel: {
QString newName = command.value().toString(); QString newName = command.value().toString();
if (m_previewData.contains(newName) && m_currentNode != newName) { 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; m_currentNode = newName;
startRenderTimer(); addInitToRenderQueue();
addCurrentNodeToRenderQueue();
} }
break; break;
} }
@@ -157,8 +158,10 @@ void Qt5Import3dNodeInstanceServer::view3DAction([[maybe_unused]] const View3DAc
void Qt5Import3dNodeInstanceServer::startRenderTimer() void Qt5Import3dNodeInstanceServer::startRenderTimer()
{ {
if (m_keepRendering && timerMode() == TimerMode::NormalTimer) #ifdef QUICK3D_MODULE
if (!m_renderQueue.isEmpty() && timerMode() == TimerMode::NormalTimer)
return; return;
#endif
NodeInstanceServer::startRenderTimer(); NodeInstanceServer::startRenderTimer();
} }
@@ -173,6 +176,45 @@ void Qt5Import3dNodeInstanceServer::cleanup()
#endif #endif
} }
#ifdef QUICK3D_MODULE
void Qt5Import3dNodeInstanceServer::addInitToRenderQueue()
{
startRenderTimer();
// "Init" render is simply a rendering of the entire scene without producing any images.
// This is done to make sure everything is initialized properly for subsequent renders.
if (m_renderQueue.isEmpty() || m_renderQueue[0] != RenderType::Init)
m_renderQueue.prepend(RenderType::Init);
}
void Qt5Import3dNodeInstanceServer::addCurrentNodeToRenderQueue(int count)
{
startRenderTimer();
int remaining = count;
for (const RenderType &type : std::as_const(m_renderQueue)) {
if (type == RenderType::CurrentNode && --remaining <= 0)
return;
}
int index = !m_renderQueue.isEmpty() && m_renderQueue[0] == RenderType::Init ? 1 : 0;
while (remaining > 0) {
m_renderQueue.insert(index, RenderType::CurrentNode);
--remaining;
}
}
void Qt5Import3dNodeInstanceServer::addIconToRenderQueue(const QString &assetName)
{
startRenderTimer();
m_generateIconQueue.append(assetName);
m_renderQueue.append(RenderType::NextIcon);
}
#endif
void Qt5Import3dNodeInstanceServer::collectItemChangesAndSendChangeCommands() void Qt5Import3dNodeInstanceServer::collectItemChangesAndSendChangeCommands()
{ {
static bool inFunction = false; static bool inFunction = false;
@@ -194,54 +236,112 @@ void Qt5Import3dNodeInstanceServer::collectItemChangesAndSendChangeCommands()
void Qt5Import3dNodeInstanceServer::render() void Qt5Import3dNodeInstanceServer::render()
{ {
#ifdef QUICK3D_MODULE #ifdef QUICK3D_MODULE
++m_renderCount; if (m_renderQueue.isEmpty() || !m_view3D || !m_iconView3D)
return;
// Render scene at least once before calculating bounds to ensure geometries are intialized RenderType currentType = m_renderQueue.takeFirst();
if (m_renderCount == 2 && m_view3D && m_previewData.contains(m_currentNode)) { PreviewData data;
PreviewData &data = m_previewData[m_currentNode]; QQuick3DViewport *currentView = m_view3D;
m_generalHelper->calculateBoundsAndFocusCamera(m_view3D->camera(), data.node, QVector3D cameraPosition = m_view3D->camera()->position();
m_view3D, 1050, false, data.lookAt, QQuaternion cameraRotation = m_view3D->camera()->rotation();
data.extents);
auto getExtentStr = [&data](int idx) -> QString { if (currentType == RenderType::Init) {
int prec = 0; m_view3D->setVisible(true);
float val = data.extents[idx]; m_iconView3D->setVisible(true);
while (val < 100.f) { } else {
++prec; auto showNode = [this](const QString &name) {
val *= 10.f; for (const PreviewData &data : std::as_const(m_previewData))
} data.node->setVisible(data.name == name);
// Strip unnecessary zeroes after decimal separator
if (prec > 0) {
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(data.extents[idx], 'f', prec);
return retval;
}; };
QQmlProperty extentsProp(rootItem(), "extents", context()); if (currentType == RenderType::CurrentNode) {
extentsProp.write(tr("Dimensions: %1 x %2 x %3").arg(getExtentStr(0)) if (m_previewData.contains(m_currentNode)) {
.arg(getExtentStr(1)) showNode(m_currentNode);
.arg(getExtentStr(2))); data = m_previewData[m_currentNode];
m_view3D->setVisible(true);
m_iconView3D->setVisible(false);
}
} else if (currentType == RenderType::NextIcon) {
if (!m_generateIconQueue.isEmpty()) {
const QString assetName = m_generateIconQueue.takeFirst();
if (m_previewData.contains(assetName)) {
m_view3D->setVisible(false);
m_iconView3D->setVisible(true);
showNode(assetName);
data = m_previewData[assetName];
m_refocus = true;
currentView = m_iconView3D;
currentView->camera()->setRotation(m_defaultCameraRotation);
currentView->camera()->setPosition(m_defaultCameraPosition);
}
}
}
if (m_refocus && data.node) {
m_generalHelper->calculateBoundsAndFocusCamera(currentView->camera(), data.node,
currentView, 1050, false, data.lookAt,
data.extents);
if (currentType == RenderType::CurrentNode) {
auto getExtentStr = [&data](int idx) -> QString {
int prec = 0;
float val = data.extents[idx];
if (val == 0.f) {
prec = 1;
} else {
while (val < 100.f) {
++prec;
val *= 10.f;
}
}
// Strip unnecessary zeroes after decimal separator
if (prec > 0) {
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(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))
.arg(getExtentStr(2)));
}
}
} }
rootNodeInstance().updateDirtyNodeRecursive(); currentView->update();
QImage renderImage = grabWindow(); QImage renderImage = grabWindow();
if (m_renderCount >= 2) { if (currentType == RenderType::Init) {
ImageContainer imgContainer(0, renderImage, m_renderCount); m_refocus = true;
nodeInstanceClient()->handlePuppetToCreatorCommand( } else if (currentType == RenderType::CurrentNode) {
{PuppetToCreatorCommand::Import3DPreviewImage, if (m_previewData.contains(m_currentNode)) {
QVariant::fromValue(imgContainer)}); ImageContainer imgContainer(0, renderImage, 1000000);
nodeInstanceClient()->handlePuppetToCreatorCommand(
if (!m_keepRendering) {PuppetToCreatorCommand::Import3DPreviewImage, QVariant::fromValue(imgContainer)});
slowDownRenderTimer(); }
} else if (currentType == RenderType::NextIcon) {
m_keepRendering = false; if (!data.name.isEmpty()) {
QSizeF iconSize = m_iconView3D->size();
QImage iconImage = renderImage.copy(0, 0, iconSize.width(), iconSize.height());
ImageContainer imgContainer(0, iconImage, 1000001);
QVariantList cmdData;
cmdData.append(data.name);
cmdData.append(QVariant::fromValue(imgContainer));
nodeInstanceClient()->handlePuppetToCreatorCommand(
{PuppetToCreatorCommand::Import3DPreviewIcon, cmdData});
}
m_refocus = true;
currentView->camera()->setRotation(cameraRotation);
currentView->camera()->setPosition(cameraPosition);
} }
if (m_renderQueue.isEmpty())
slowDownRenderTimer();
#else #else
slowDownRenderTimer(); slowDownRenderTimer();
#endif #endif

View File

@@ -35,11 +35,13 @@ protected:
private: private:
void cleanup(); void cleanup();
int m_renderCount = 0;
bool m_keepRendering = false;
#ifdef QUICK3D_MODULE #ifdef QUICK3D_MODULE
void addInitToRenderQueue();
void addCurrentNodeToRenderQueue(int count = 1);
void addIconToRenderQueue(const QString &assetName);
QQuick3DViewport *m_view3D = nullptr; QQuick3DViewport *m_view3D = nullptr;
QQuick3DViewport *m_iconView3D = nullptr;
Internal::GeneralHelper *m_generalHelper = nullptr; Internal::GeneralHelper *m_generalHelper = nullptr;
struct PreviewData struct PreviewData
@@ -50,8 +52,21 @@ private:
QQuick3DNode *node = {}; QQuick3DNode *node = {};
}; };
QHash<QString, PreviewData> m_previewData; QHash<QString, PreviewData> m_previewData;
enum class RenderType
{
Init,
CurrentNode,
NextIcon
};
QList<RenderType> m_renderQueue;
bool m_refocus = false;
QString m_currentNode; QString m_currentNode;
QQuick3DNode *m_sceneNode = {}; QQuick3DNode *m_sceneNode = {};
QStringList m_generateIconQueue;
QQuaternion m_defaultCameraRotation;
QVector3D m_defaultCameraPosition;
#endif #endif
}; };