forked from qt-creator/qt-creator
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:
@@ -18,6 +18,7 @@ public:
|
||||
ActiveSceneChanged,
|
||||
ActiveSplitChanged,
|
||||
RenderModelNodePreviewImage,
|
||||
Import3DPreviewIcon,
|
||||
Import3DPreviewImage,
|
||||
Import3DSupport,
|
||||
NodeAtPos,
|
||||
|
@@ -16,6 +16,11 @@ Import3dConnectionManager::Import3dConnectionManager()
|
||||
connections().emplace_back("Import 3D", "import3dmode");
|
||||
}
|
||||
|
||||
void Import3dConnectionManager::setPreviewIconCallback(IconCallback callback)
|
||||
{
|
||||
m_previewIconCallback = std::move(callback);
|
||||
}
|
||||
|
||||
void Import3dConnectionManager::setPreviewImageCallback(ImageCallback callback)
|
||||
{
|
||||
m_previewImageCallback = std::move(callback);
|
||||
@@ -29,6 +34,15 @@ void Import3dConnectionManager::dispatchCommand(const QVariant &command,
|
||||
if (command.typeId() == commandType) {
|
||||
auto cmd = command.value<PuppetToCreatorCommand>();
|
||||
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: {
|
||||
ImageContainer container = qvariant_cast<ImageContainer>(cmd.data());
|
||||
QImage image = container.image();
|
||||
|
@@ -12,16 +12,19 @@ namespace QmlDesigner {
|
||||
class Import3dConnectionManager : public InteractiveConnectionManager
|
||||
{
|
||||
public:
|
||||
using IconCallback = std::function<void(const QString &, const QImage &)>;
|
||||
using ImageCallback = std::function<void(const QImage &)>;
|
||||
|
||||
Import3dConnectionManager();
|
||||
|
||||
void setPreviewIconCallback(IconCallback callback);
|
||||
void setPreviewImageCallback(ImageCallback callback);
|
||||
|
||||
protected:
|
||||
void dispatchCommand(const QVariant &command, Connection &connection) override;
|
||||
|
||||
private:
|
||||
IconCallback m_previewIconCallback;
|
||||
ImageCallback m_previewImageCallback;
|
||||
};
|
||||
|
||||
|
@@ -7,6 +7,8 @@
|
||||
#include "import3dcanvas.h"
|
||||
#include "import3dconnectionmanager.h"
|
||||
|
||||
#include <designeractionmanager.h>
|
||||
#include <designericons.h>
|
||||
#include <model.h>
|
||||
#include <model/modelutils.h>
|
||||
#include <nodeinstanceview.h>
|
||||
@@ -18,6 +20,7 @@
|
||||
|
||||
#include <theme.h>
|
||||
#include <utils/outputformatter.h>
|
||||
#include <utils/stylehelper.h>
|
||||
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/projectmanager.h>
|
||||
@@ -25,7 +28,9 @@
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QFontMetrics>
|
||||
#include <QDir>
|
||||
#include <QLocale>
|
||||
#include <QLoggingCategory>
|
||||
#include <QTimer>
|
||||
#include <QJsonArray>
|
||||
@@ -63,6 +68,17 @@ void addFormattedMessage(Utils::OutputFormatter *formatter,
|
||||
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 checkBoxColWidth = 18;
|
||||
const int labelMinWidth = 130;
|
||||
@@ -88,6 +104,11 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(
|
||||
setModal(true);
|
||||
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->setPlainTextEdit(ui->plainTextEdit);
|
||||
|
||||
@@ -239,8 +260,8 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(
|
||||
|
||||
connect(ui->advancedSettingsButton, &QPushButton::clicked,
|
||||
this, &ItemLibraryAssetImportDialog::toggleAdvanced);
|
||||
connect(ui->importList, &QListWidget::currentRowChanged,
|
||||
this, &ItemLibraryAssetImportDialog::onCurrentRowChanged);
|
||||
connect(ui->importList, &QListWidget::currentItemChanged,
|
||||
this, &ItemLibraryAssetImportDialog::onCurrentItemChanged);
|
||||
|
||||
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,
|
||||
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)
|
||||
{
|
||||
static QStringList simpleGroups {
|
||||
@@ -859,8 +898,8 @@ bool ItemLibraryAssetImportDialog::isHiddenOption(const QString &id)
|
||||
|
||||
bool ItemLibraryAssetImportDialog::optionsChanged()
|
||||
{
|
||||
for (const ItemLibraryAssetImporter::PreviewData &data : std::as_const(m_previewData)) {
|
||||
if (data.renderedOptions != data.currentOptions)
|
||||
for (const ImportData &data : std::as_const(m_importData)) {
|
||||
if (data.previewData.renderedOptions != data.previewData.currentOptions)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -883,6 +922,7 @@ Rectangle {
|
||||
|
||||
property alias sceneNode: sceneNode
|
||||
property alias view3d: view3d
|
||||
property alias iconView3d: iconView3d
|
||||
property string extents
|
||||
property string sceneModelName
|
||||
|
||||
@@ -897,30 +937,40 @@ Rectangle {
|
||||
camera: viewCamera
|
||||
|
||||
environment: SceneEnvironment {
|
||||
id: sceneEnvironment
|
||||
antialiasingMode: SceneEnvironment.MSAA
|
||||
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 {
|
||||
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 {
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
@@ -966,6 +1016,15 @@ Rectangle {
|
||||
|
||||
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) {
|
||||
canvas()->updateRenderImage(image);
|
||||
};
|
||||
@@ -975,6 +1034,7 @@ Rectangle {
|
||||
cleanupPreviewPuppet();
|
||||
};
|
||||
|
||||
m_connectionManager->setPreviewIconCallback(std::move(previewIconCallback));
|
||||
m_connectionManager->setPreviewImageCallback(std::move(previewImageCallback));
|
||||
m_nodeInstanceView->setCrashCallback(std::move(crashCallback));
|
||||
|
||||
@@ -992,8 +1052,10 @@ void ItemLibraryAssetImportDialog::cleanupPreviewPuppet()
|
||||
if (m_nodeInstanceView)
|
||||
m_nodeInstanceView->setCrashCallback({});
|
||||
|
||||
if (m_connectionManager)
|
||||
if (m_connectionManager) {
|
||||
m_connectionManager->setPreviewIconCallback({});
|
||||
m_connectionManager->setPreviewImageCallback({});
|
||||
}
|
||||
|
||||
delete m_rewriterView;
|
||||
delete m_nodeInstanceView;
|
||||
@@ -1007,17 +1069,17 @@ Import3dCanvas *ItemLibraryAssetImportDialog::canvas()
|
||||
|
||||
void ItemLibraryAssetImportDialog::resetOptionControls()
|
||||
{
|
||||
const QString currentName = ui->importList->currentItem()->text();
|
||||
if (!m_previewData.contains(currentName))
|
||||
const QString currentName = assetNameForListItem(ui->importList->currentItem());
|
||||
if (!m_importData.contains(currentName))
|
||||
return;
|
||||
|
||||
m_updatingControlStates = true;
|
||||
|
||||
const ItemLibraryAssetImporter::PreviewData &data = m_previewData[currentName];
|
||||
const QJsonObject options = data.currentOptions;
|
||||
const ImportData &data = m_importData[currentName];
|
||||
const QJsonObject options = data.previewData.currentOptions;
|
||||
const QStringList optKeys = options.keys();
|
||||
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 QJsonValue optValue = optObj.value("value");
|
||||
if (auto *cb = qobject_cast<QCheckBox *>(w))
|
||||
@@ -1048,10 +1110,10 @@ void ItemLibraryAssetImportDialog::updatePreviewOptions()
|
||||
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];
|
||||
const QString assetName = assetNameForListItem(ui->importList->currentItem());
|
||||
if (m_importData.contains(assetName)) {
|
||||
ImportData &data = m_importData[assetName];
|
||||
data.previewData.currentOptions = m_importOptions[data.previewData.optionsIndex];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1079,25 +1141,26 @@ void ItemLibraryAssetImportDialog::onImport()
|
||||
{
|
||||
ui->importButton->setEnabled(false);
|
||||
ui->tabWidget->setEnabled(false);
|
||||
ui->importList->setEnabled(false);
|
||||
|
||||
const ItemLibraryAssetImporter::PreviewData &data
|
||||
= m_previewData.value(ui->importList->currentIndex().data().toString());
|
||||
|
||||
if (!data.name.isEmpty() && !optionsChanged()) {
|
||||
if (!m_importData.isEmpty() && !optionsChanged()) {
|
||||
cleanupPreviewPuppet();
|
||||
m_importer.finalizeQuick3DImport();
|
||||
return;
|
||||
}
|
||||
|
||||
const QString assetName = assetNameForListItem(ui->importList->currentItem());
|
||||
const ImportData &data = m_importData.value(assetName);
|
||||
|
||||
setCloseButtonState(true);
|
||||
ui->progressBar->setValue(0);
|
||||
|
||||
if (!m_quick3DFiles.isEmpty()) {
|
||||
if (!m_previewData.isEmpty()) {
|
||||
if (!m_importData.isEmpty()) {
|
||||
QHash<QString , QJsonObject> importOptions;
|
||||
for (const ItemLibraryAssetImporter::PreviewData &data : std::as_const(m_previewData)) {
|
||||
if (data.renderedOptions != data.currentOptions)
|
||||
importOptions.insert(data.name, data.currentOptions);
|
||||
for (const ImportData &data : std::as_const(m_importData)) {
|
||||
if (data.previewData.renderedOptions != data.previewData.currentOptions)
|
||||
importOptions.insert(data.previewData.name, data.previewData.currentOptions);
|
||||
}
|
||||
m_importer.reImportQuick3D(importOptions);
|
||||
} else {
|
||||
@@ -1121,16 +1184,79 @@ void ItemLibraryAssetImportDialog::setImportProgress(int value, const QString &t
|
||||
void ItemLibraryAssetImportDialog::onImportReadyForPreview(
|
||||
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;
|
||||
for (const ItemLibraryAssetImporter::PreviewData &data : previewData) {
|
||||
m_previewData[data.name] = data;
|
||||
assetNames.append(data.name);
|
||||
const QString assetName = 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 (items.isEmpty())
|
||||
ui->importList->addItem(data.name);
|
||||
if (!m_importData.contains(assetName))
|
||||
return;
|
||||
|
||||
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) {
|
||||
@@ -1147,11 +1273,11 @@ void ItemLibraryAssetImportDialog::onImportReadyForPreview(
|
||||
if (!m_nodeInstanceView)
|
||||
return;
|
||||
for (const QString &assetName : std::as_const(assetNames)) {
|
||||
const ItemLibraryAssetImporter::PreviewData &data = m_previewData.value(assetName);
|
||||
if (!data.name.isEmpty()) {
|
||||
const ImportData &data = m_importData.value(assetName);
|
||||
if (!data.previewData.name.isEmpty()) {
|
||||
QVariantHash msgData;
|
||||
msgData.insert("name", data.name);
|
||||
msgData.insert("folder", data.folderName);
|
||||
msgData.insert("name", data.previewData.name);
|
||||
msgData.insert("folder", data.previewData.folderName);
|
||||
m_nodeInstanceView->view3DAction(View3DActionType::Import3dAddPreviewModel, msgData);
|
||||
}
|
||||
}
|
||||
@@ -1159,6 +1285,7 @@ void ItemLibraryAssetImportDialog::onImportReadyForPreview(
|
||||
|
||||
ui->importButton->setEnabled(true);
|
||||
ui->tabWidget->setEnabled(true);
|
||||
ui->importList->setEnabled(true);
|
||||
updatePreviewOptions();
|
||||
if (ui->importList->currentRow() < 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)
|
||||
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);
|
||||
if (m_importData.contains(assetName)) {
|
||||
m_nodeInstanceView->view3DAction(View3DActionType::Import3dSetCurrentPreviewModel,
|
||||
assetName);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1268,4 +1405,20 @@ void ItemLibraryAssetImportDialog::toggleAdvanced()
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -9,12 +9,15 @@
|
||||
#include <utils/filepath.h>
|
||||
|
||||
#include <QDialog>
|
||||
#include <QIcon>
|
||||
#include <QJsonObject>
|
||||
#include <QPointer>
|
||||
#include <QSet>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QGridLayout;
|
||||
class QLabel;
|
||||
class QListWidgetItem;
|
||||
class QPushButton;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -23,7 +26,6 @@ class OutputFormatter;
|
||||
}
|
||||
|
||||
namespace QmlDesigner {
|
||||
class ItemLibraryAssetImporter;
|
||||
class Import3dCanvas;
|
||||
class Import3dConnectionManager;
|
||||
class NodeInstanceView;
|
||||
@@ -53,6 +55,8 @@ public:
|
||||
const QVariantMap &supportedExts,
|
||||
const QVariantMap &supportedOpts);
|
||||
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
@@ -62,6 +66,22 @@ private slots:
|
||||
void addInfo(const QString &info, const QString &srcPath = {});
|
||||
|
||||
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 updatePreviewOptions();
|
||||
|
||||
@@ -73,15 +93,17 @@ private:
|
||||
void onRequestRotation(const QPointF &delta);
|
||||
void onImportNearlyFinished();
|
||||
void onImportFinished();
|
||||
void onCurrentRowChanged(int row);
|
||||
void onCurrentItemChanged(QListWidgetItem *current, QListWidgetItem *previous);
|
||||
void onClose();
|
||||
void doClose();
|
||||
void toggleAdvanced();
|
||||
void onRemoveAsset(const QString &assetName);
|
||||
|
||||
void createTab(const QString &tabLabel, int optionsIndex, const QJsonObject &groups);
|
||||
QGridLayout *createOptionsGrid(QWidget *contentWidget, bool advanced, int optionsIndex,
|
||||
const QJsonObject &groups);
|
||||
void updateUi();
|
||||
QString assetNameForListItem(QListWidgetItem *item);
|
||||
|
||||
bool isSimpleGroup(const QString &id);
|
||||
bool isSimpleOption(const QString &id);
|
||||
@@ -101,16 +123,9 @@ private:
|
||||
QPointer<AbstractView> m_view;
|
||||
ModelPointer m_model;
|
||||
|
||||
QMap<QString, ItemLibraryAssetImporter::PreviewData> m_previewData;
|
||||
QMap<QString, ImportData> m_importData;
|
||||
Utils::FilePath m_previewFile;
|
||||
|
||||
struct OptionsData
|
||||
{
|
||||
int optionsRows = 0;
|
||||
int optionsHeight = 0;
|
||||
QList<QWidget *> contentWidgets; // Tab content widgets
|
||||
};
|
||||
|
||||
QStringList m_quick3DFiles;
|
||||
QString m_quick3DImportPath;
|
||||
ItemLibraryAssetImporter m_importer;
|
||||
@@ -126,5 +141,7 @@ private:
|
||||
bool m_explicitClose = false;
|
||||
bool m_updatingControlStates = true;
|
||||
bool m_firstImport = true;
|
||||
QIcon m_selectedRemoveIcon;
|
||||
QIcon m_unselectedRemoveIcon;
|
||||
};
|
||||
}
|
||||
|
@@ -33,7 +33,7 @@
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<width>250</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
|
@@ -238,7 +238,6 @@ void ItemLibraryAssetImporter::reset()
|
||||
delete m_tempDir;
|
||||
m_tempDir = new QTemporaryDir(QDir::tempPath() + tempDirNameBase());
|
||||
m_importFiles.clear();
|
||||
m_overwrittenImports.clear();
|
||||
m_puppetProcess.reset();
|
||||
m_parseData.clear();
|
||||
m_requiredImports.clear();
|
||||
@@ -337,14 +336,14 @@ bool ItemLibraryAssetImporter::preParseQuick3DAsset(const QString &file, ParseDa
|
||||
overwriteFiles = dlg.selectedFiles();
|
||||
if (!overwriteFiles.isEmpty()) {
|
||||
overwriteFiles.append(::Utils::toList(alwaysOverwrite));
|
||||
m_overwrittenImports.insert(pd.targetDirPath, overwriteFiles);
|
||||
pd.overwrittenImports.insert(pd.targetDirPath, overwriteFiles);
|
||||
} else {
|
||||
addWarning(tr("No files selected for overwrite, skipping import: \"%1\".").arg(pd.assetName));
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
m_overwrittenImports.insert(pd.targetDirPath, {});
|
||||
pd.overwrittenImports.insert(pd.targetDirPath, {});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,9 +395,7 @@ void ItemLibraryAssetImporter::postParseQuick3DAsset(ParseData &pd)
|
||||
qmlInfo.append(".");
|
||||
qmlInfo.append(pd.assetName);
|
||||
qmlInfo.append('\n');
|
||||
const QString reqImp = QStringLiteral("%1.%2").arg(
|
||||
QmlDesignerPlugin::instance()->documentManager()
|
||||
.generatedComponentUtils().import3dTypePrefix(), pd.assetName);
|
||||
const QString reqImp = generateRequiredImportForAsset(pd.assetName);
|
||||
if (!m_requiredImports.contains(reqImp))
|
||||
m_requiredImports.append(reqImp);
|
||||
while (qmlIt.hasNext()) {
|
||||
@@ -480,9 +477,13 @@ void ItemLibraryAssetImporter::postParseQuick3DAsset(ParseData &pd)
|
||||
|
||||
// Gather all generated files
|
||||
QDirIterator dirIt(outDir.path(), QDir::Files, QDirIterator::Subdirectories);
|
||||
pd.assetSize = 0;
|
||||
while (dirIt.hasNext()) {
|
||||
dirIt.next();
|
||||
insertAsset(dirIt.filePath());
|
||||
QFileInfo fi = dirIt.fileInfo();
|
||||
if (fi.isFile())
|
||||
pd.assetSize += fi.size();
|
||||
}
|
||||
|
||||
// Copy the original asset into a subdirectory
|
||||
@@ -492,14 +493,17 @@ void ItemLibraryAssetImporter::postParseQuick3DAsset(ParseData &pd)
|
||||
|
||||
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.");
|
||||
addInfo(progressTitle);
|
||||
notifyProgress(0, progressTitle);
|
||||
|
||||
int counter = 0;
|
||||
auto it = m_overwrittenImports.constBegin();
|
||||
while (it != m_overwrittenImports.constEnd()) {
|
||||
auto it = allOverwrites.constBegin();
|
||||
while (it != allOverwrites.constEnd()) {
|
||||
Utils::FilePath dir = Utils::FilePath::fromUserInput(it.key());
|
||||
if (dir.exists()) {
|
||||
const auto &overwrittenFiles = it.value();
|
||||
@@ -512,7 +516,7 @@ void ItemLibraryAssetImporter::copyImportedFiles()
|
||||
QFile::remove(fileName);
|
||||
}
|
||||
}
|
||||
notifyProgress((100 * ++counter) / m_overwrittenImports.size(), progressTitle);
|
||||
notifyProgress((100 * ++counter) / allOverwrites.size(), progressTitle);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
@@ -568,6 +572,13 @@ QString ItemLibraryAssetImporter::generateAssetFolderName(const QString &assetNa
|
||||
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)
|
||||
{
|
||||
const QString title = tr("Overwrite Existing Asset?");
|
||||
@@ -653,8 +664,11 @@ void ItemLibraryAssetImporter::postImport()
|
||||
data.renderedOptions = pd.options;
|
||||
data.currentOptions = pd.options;
|
||||
data.optionsIndex = pd.optionsIndex;
|
||||
data.type = pd.sourceInfo.suffix().toLower();
|
||||
data.size = pd.assetSize;
|
||||
dataList.append(data);
|
||||
}
|
||||
|
||||
emit importReadyForPreview(m_tempDir->path(), dataList);
|
||||
}
|
||||
}
|
||||
@@ -716,8 +730,12 @@ void ItemLibraryAssetImporter::finalizeQuick3DImport()
|
||||
addError(tr("Failed to update imports: %1").arg(e.description()));
|
||||
}
|
||||
} else if (counter >= 50) {
|
||||
if (!m_overwrittenImports.isEmpty())
|
||||
model->rewriterView()->emitCustomNotification("asset_import_update");
|
||||
for (const ParseData &pd : std::as_const(m_parseData)) {
|
||||
if (!pd.overwrittenImports.isEmpty()) {
|
||||
model->rewriterView()->emitCustomNotification("asset_import_update");
|
||||
break;
|
||||
}
|
||||
}
|
||||
timer->stop();
|
||||
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)
|
||||
{
|
||||
return pd.targetDirPath + QStringLiteral("/source scene/") + pd.sourceInfo.fileName();
|
||||
|
@@ -47,6 +47,7 @@ public:
|
||||
QString tempDirNameBase() const { return "/qds3dimport"; }
|
||||
|
||||
void finalizeQuick3DImport();
|
||||
void removeAssetFromImport(const QString &assetName);
|
||||
|
||||
struct PreviewData
|
||||
{
|
||||
@@ -55,6 +56,8 @@ public:
|
||||
QJsonObject currentOptions;
|
||||
QString name;
|
||||
QString folderName;
|
||||
QString type;
|
||||
qint64 size;
|
||||
};
|
||||
|
||||
signals:
|
||||
@@ -78,8 +81,10 @@ private:
|
||||
QFileInfo sourceInfo;
|
||||
QString assetName;
|
||||
QString originalAssetName;
|
||||
qint64 assetSize;
|
||||
int importId = -1;
|
||||
int optionsIndex = -1;
|
||||
QHash<QString, QStringList> overwrittenImports;
|
||||
};
|
||||
|
||||
void notifyFinished();
|
||||
@@ -96,6 +101,7 @@ private:
|
||||
void notifyProgress(int value);
|
||||
void keepUiAlive() const;
|
||||
QString generateAssetFolderName(const QString &assetName) const;
|
||||
QString generateRequiredImportForAsset(const QString &assetName) const;
|
||||
|
||||
enum class OverwriteResult {
|
||||
Skip,
|
||||
@@ -109,7 +115,6 @@ private:
|
||||
QString sourceSceneTargetFilePath(const ParseData &pd);
|
||||
|
||||
QHash<QString, QHash<QString, QString>> m_importFiles; // Key: asset name
|
||||
QHash<QString, QStringList> m_overwrittenImports;
|
||||
bool m_isImporting = false;
|
||||
bool m_cancelled = false;
|
||||
QString m_importPath;
|
||||
|
@@ -35,7 +35,7 @@ Qt5Import3dNodeInstanceServer::Qt5Import3dNodeInstanceServer(NodeInstanceClientI
|
||||
#ifdef QUICK3D_MODULE
|
||||
m_generalHelper = new Internal::GeneralHelper();
|
||||
QObject::connect(m_generalHelper, &Internal::GeneralHelper::requestRender, this, [this]() {
|
||||
startRenderTimer();
|
||||
addCurrentNodeToRenderQueue();
|
||||
});
|
||||
#endif
|
||||
}
|
||||
@@ -54,16 +54,22 @@ void Qt5Import3dNodeInstanceServer::createScene(const CreateSceneCommand &comman
|
||||
|
||||
#ifdef QUICK3D_MODULE
|
||||
QObject *obj = rootItem();
|
||||
QQmlProperty viewProp(obj, "view3d", context());
|
||||
QObject *viewObj = viewProp.read().value<QObject *>();
|
||||
m_view3D = qobject_cast<QQuick3DViewport *>(viewObj);
|
||||
auto initView = [&obj, this](const QString &viewId, QQuick3DViewport *&view3D) {
|
||||
QQmlProperty viewProp(obj, viewId, context());
|
||||
QObject *viewObj = viewProp.read().value<QObject *>();
|
||||
view3D = qobject_cast<QQuick3DViewport *>(viewObj);
|
||||
};
|
||||
initView("view3d", m_view3D);
|
||||
initView("iconView3d", m_iconView3D);
|
||||
|
||||
if (m_view3D) {
|
||||
QQmlProperty sceneNodeProp(obj, "sceneNode", context());
|
||||
m_sceneNode = sceneNodeProp.read().value<QQuick3DNode *>();
|
||||
m_defaultCameraRotation = m_view3D->camera()->rotation();
|
||||
m_defaultCameraPosition = m_view3D->camera()->position();
|
||||
addInitToRenderQueue();
|
||||
}
|
||||
#endif
|
||||
|
||||
startRenderTimer();
|
||||
}
|
||||
|
||||
void Qt5Import3dNodeInstanceServer::view3DAction([[maybe_unused]] const View3DActionCommand &command)
|
||||
@@ -79,7 +85,7 @@ void Qt5Import3dNodeInstanceServer::view3DAction([[maybe_unused]] const View3DAc
|
||||
wProp.write(size.width());
|
||||
hProp.write(size.height());
|
||||
resizeCanvasToRootItem();
|
||||
startRenderTimer();
|
||||
addCurrentNodeToRenderQueue();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -92,8 +98,8 @@ void Qt5Import3dNodeInstanceServer::view3DAction([[maybe_unused]] const View3DAc
|
||||
QPointF delta = command.value().toPointF();
|
||||
m_generalHelper->orbitCamera(m_view3D->camera(), m_view3D->camera()->eulerRotation(),
|
||||
data.lookAt, {}, {float(delta.x()), float(delta.y()), 0.f});
|
||||
m_keepRendering = true;
|
||||
startRenderTimer();
|
||||
// Add 2 renders to keep render timer alive for smooth rotation
|
||||
addCurrentNodeToRenderQueue(2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -123,28 +129,23 @@ void Qt5Import3dNodeInstanceServer::view3DAction([[maybe_unused]] const View3DAc
|
||||
engine()->setObjectOwnership(data.node, QJSEngine::CppOwnership);
|
||||
data.node->setParentItem(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;
|
||||
}
|
||||
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();
|
||||
addInitToRenderQueue();
|
||||
addCurrentNodeToRenderQueue();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -157,8 +158,10 @@ void Qt5Import3dNodeInstanceServer::view3DAction([[maybe_unused]] const View3DAc
|
||||
|
||||
void Qt5Import3dNodeInstanceServer::startRenderTimer()
|
||||
{
|
||||
if (m_keepRendering && timerMode() == TimerMode::NormalTimer)
|
||||
#ifdef QUICK3D_MODULE
|
||||
if (!m_renderQueue.isEmpty() && timerMode() == TimerMode::NormalTimer)
|
||||
return;
|
||||
#endif
|
||||
|
||||
NodeInstanceServer::startRenderTimer();
|
||||
}
|
||||
@@ -173,6 +176,45 @@ void Qt5Import3dNodeInstanceServer::cleanup()
|
||||
#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()
|
||||
{
|
||||
static bool inFunction = false;
|
||||
@@ -194,54 +236,112 @@ void Qt5Import3dNodeInstanceServer::collectItemChangesAndSendChangeCommands()
|
||||
void Qt5Import3dNodeInstanceServer::render()
|
||||
{
|
||||
#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
|
||||
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);
|
||||
RenderType currentType = m_renderQueue.takeFirst();
|
||||
PreviewData data;
|
||||
QQuick3DViewport *currentView = m_view3D;
|
||||
QVector3D cameraPosition = m_view3D->camera()->position();
|
||||
QQuaternion cameraRotation = m_view3D->camera()->rotation();
|
||||
|
||||
auto getExtentStr = [&data](int idx) -> QString {
|
||||
int prec = 0;
|
||||
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(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;
|
||||
if (currentType == RenderType::Init) {
|
||||
m_view3D->setVisible(true);
|
||||
m_iconView3D->setVisible(true);
|
||||
} else {
|
||||
auto showNode = [this](const QString &name) {
|
||||
for (const PreviewData &data : std::as_const(m_previewData))
|
||||
data.node->setVisible(data.name == name);
|
||||
};
|
||||
|
||||
QQmlProperty extentsProp(rootItem(), "extents", context());
|
||||
extentsProp.write(tr("Dimensions: %1 x %2 x %3").arg(getExtentStr(0))
|
||||
.arg(getExtentStr(1))
|
||||
.arg(getExtentStr(2)));
|
||||
if (currentType == RenderType::CurrentNode) {
|
||||
if (m_previewData.contains(m_currentNode)) {
|
||||
showNode(m_currentNode);
|
||||
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();
|
||||
|
||||
if (m_renderCount >= 2) {
|
||||
ImageContainer imgContainer(0, renderImage, m_renderCount);
|
||||
nodeInstanceClient()->handlePuppetToCreatorCommand(
|
||||
{PuppetToCreatorCommand::Import3DPreviewImage,
|
||||
QVariant::fromValue(imgContainer)});
|
||||
|
||||
if (!m_keepRendering)
|
||||
slowDownRenderTimer();
|
||||
|
||||
m_keepRendering = false;
|
||||
if (currentType == RenderType::Init) {
|
||||
m_refocus = true;
|
||||
} else if (currentType == RenderType::CurrentNode) {
|
||||
if (m_previewData.contains(m_currentNode)) {
|
||||
ImageContainer imgContainer(0, renderImage, 1000000);
|
||||
nodeInstanceClient()->handlePuppetToCreatorCommand(
|
||||
{PuppetToCreatorCommand::Import3DPreviewImage, QVariant::fromValue(imgContainer)});
|
||||
}
|
||||
} else if (currentType == RenderType::NextIcon) {
|
||||
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
|
||||
slowDownRenderTimer();
|
||||
#endif
|
||||
|
@@ -35,11 +35,13 @@ protected:
|
||||
private:
|
||||
void cleanup();
|
||||
|
||||
int m_renderCount = 0;
|
||||
bool m_keepRendering = false;
|
||||
|
||||
#ifdef QUICK3D_MODULE
|
||||
void addInitToRenderQueue();
|
||||
void addCurrentNodeToRenderQueue(int count = 1);
|
||||
void addIconToRenderQueue(const QString &assetName);
|
||||
|
||||
QQuick3DViewport *m_view3D = nullptr;
|
||||
QQuick3DViewport *m_iconView3D = nullptr;
|
||||
Internal::GeneralHelper *m_generalHelper = nullptr;
|
||||
|
||||
struct PreviewData
|
||||
@@ -50,8 +52,21 @@ private:
|
||||
QQuick3DNode *node = {};
|
||||
};
|
||||
QHash<QString, PreviewData> m_previewData;
|
||||
|
||||
enum class RenderType
|
||||
{
|
||||
Init,
|
||||
CurrentNode,
|
||||
NextIcon
|
||||
};
|
||||
QList<RenderType> m_renderQueue;
|
||||
|
||||
bool m_refocus = false;
|
||||
QString m_currentNode;
|
||||
QQuick3DNode *m_sceneNode = {};
|
||||
QStringList m_generateIconQueue;
|
||||
QQuaternion m_defaultCameraRotation;
|
||||
QVector3D m_defaultCameraPosition;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user