From ebbdea30ea659f1759fed57cbc7210d7ca026564 Mon Sep 17 00:00:00 2001 From: huxingyi Date: Thu, 15 Oct 2020 19:36:28 +0930 Subject: [PATCH] Fix part preview UI poor performance Change the part preview UI element from QOpenGLWidget to QLabel, the preview images will be generated in an offscreen render. This fixes the create multiple QOpenGLWidgets poor performace issue. --- .travis.yml | 3 + dust3d.pro | 3 + src/document.cpp | 2 +- src/documentwindow.cpp | 217 ++++++++++++++++++----------- src/documentwindow.h | 9 ++ src/meshgenerator.cpp | 1 + src/partpreviewimagesgenerator.cpp | 44 ++++++ src/partpreviewimagesgenerator.h | 47 +++++++ src/parttreewidget.cpp | 13 +- src/partwidget.cpp | 36 ++--- src/partwidget.h | 27 ++-- src/skeletondocument.h | 6 +- 12 files changed, 277 insertions(+), 131 deletions(-) create mode 100644 src/partpreviewimagesgenerator.cpp create mode 100644 src/partpreviewimagesgenerator.h diff --git a/.travis.yml b/.travis.yml index 9e5b8346..2cf6927c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,6 +21,9 @@ matrix: osx_image: xcode9.3 install: + - if [[ $TRAVIS_BRANCH != "ci" && $TRAVIS_TAG == "" ]]; then echo "Not branch ci and no tag, cancel build"; fi + - if [[ $TRAVIS_BRANCH != "ci" && $TRAVIS_TAG == "" ]]; then travis_terminate 0; fi + # (Linux) Prepare build environment - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo add-apt-repository --yes ppa:beineri/opt-qt591-xenial; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update; fi diff --git a/dust3d.pro b/dust3d.pro index 677fc062..9de1d790 100644 --- a/dust3d.pro +++ b/dust3d.pro @@ -533,6 +533,9 @@ HEADERS += src/ddsfile.h SOURCES += src/fileforever.cpp HEADERS += src/fileforever.h +SOURCES += src/partpreviewimagesgenerator.cpp +HEADERS += src/partpreviewimagesgenerator.h + SOURCES += src/main.cpp HEADERS += src/version.h diff --git a/src/document.cpp b/src/document.cpp index 010ee6b6..b1669ebd 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1937,7 +1937,7 @@ void Document::meshReady() if (part != partMap.end()) { Model *resultPartPreviewMesh = m_meshGenerator->takePartPreviewMesh(partId); part->second.updatePreviewMesh(resultPartPreviewMesh); - emit partPreviewChanged(partId); + //emit partPreviewChanged(partId); } } diff --git a/src/documentwindow.cpp b/src/documentwindow.cpp index c65a14fd..c0d5a456 100644 --- a/src/documentwindow.cpp +++ b/src/documentwindow.cpp @@ -267,6 +267,7 @@ DocumentWindow::DocumentWindow() : }); connect(m_document, &Document::resultMeshChanged, this, [=]() { updateRegenerateIconAndTips(regenerateButton, m_document->isMeshGenerationSucceed()); + generatePartPreviewImages(); }); connect(m_document, &Document::postProcessing, this, [=]() { regenerateButton->showSpinner(true); @@ -393,14 +394,14 @@ DocumentWindow::DocumentWindow() : QDockWidget *partTreeDocker = new QDockWidget(tr("Parts"), this); partTreeDocker->setAllowedAreas(Qt::RightDockWidgetArea); - PartTreeWidget *partTreeWidget = new PartTreeWidget(m_document, partTreeDocker); - partTreeDocker->setWidget(partTreeWidget); + m_partTreeWidget = new PartTreeWidget(m_document, partTreeDocker); + partTreeDocker->setWidget(m_partTreeWidget); addDockWidget(Qt::RightDockWidgetArea, partTreeDocker); - connect(partTreeDocker, &QDockWidget::topLevelChanged, [=](bool topLevel) { - Q_UNUSED(topLevel); - for (const auto &part: m_document->partMap) - partTreeWidget->partPreviewChanged(part.first); - }); + //connect(partTreeDocker, &QDockWidget::topLevelChanged, [=](bool topLevel) { + // Q_UNUSED(topLevel); + // for (const auto &part: m_document->partMap) + // m_partTreeWidget->partPreviewChanged(part.first); + //}); QDockWidget *materialDocker = new QDockWidget(tr("Materials"), this); materialDocker->setAllowedAreas(Qt::RightDockWidgetArea); @@ -1078,88 +1079,88 @@ DocumentWindow::DocumentWindow() : connect(m_document, &Document::checkNode, graphicsWidget, &SkeletonGraphicsWidget::addSelectNode); connect(m_document, &Document::checkEdge, graphicsWidget, &SkeletonGraphicsWidget::addSelectEdge); - connect(partTreeWidget, &PartTreeWidget::currentComponentChanged, m_document, &Document::setCurrentCanvasComponentId); - connect(partTreeWidget, &PartTreeWidget::moveComponentUp, m_document, &Document::moveComponentUp); - connect(partTreeWidget, &PartTreeWidget::moveComponentDown, m_document, &Document::moveComponentDown); - connect(partTreeWidget, &PartTreeWidget::moveComponentToTop, m_document, &Document::moveComponentToTop); - connect(partTreeWidget, &PartTreeWidget::moveComponentToBottom, m_document, &Document::moveComponentToBottom); - connect(partTreeWidget, &PartTreeWidget::checkPart, m_document, &Document::checkPart); - connect(partTreeWidget, &PartTreeWidget::createNewComponentAndMoveThisIn, m_document, &Document::createNewComponentAndMoveThisIn); - connect(partTreeWidget, &PartTreeWidget::createNewChildComponent, m_document, &Document::createNewChildComponent); - connect(partTreeWidget, &PartTreeWidget::renameComponent, m_document, &Document::renameComponent); - connect(partTreeWidget, &PartTreeWidget::setComponentExpandState, m_document, &Document::setComponentExpandState); - connect(partTreeWidget, &PartTreeWidget::setComponentSmoothAll, m_document, &Document::setComponentSmoothAll); - connect(partTreeWidget, &PartTreeWidget::setComponentSmoothSeam, m_document, &Document::setComponentSmoothSeam); - connect(partTreeWidget, &PartTreeWidget::setComponentPolyCount, m_document, &Document::setComponentPolyCount); - connect(partTreeWidget, &PartTreeWidget::setComponentLayer, m_document, &Document::setComponentLayer); - connect(partTreeWidget, &PartTreeWidget::moveComponent, m_document, &Document::moveComponent); - connect(partTreeWidget, &PartTreeWidget::removeComponent, m_document, &Document::removeComponent); - connect(partTreeWidget, &PartTreeWidget::hideOtherComponents, m_document, &Document::hideOtherComponents); - connect(partTreeWidget, &PartTreeWidget::lockOtherComponents, m_document, &Document::lockOtherComponents); - connect(partTreeWidget, &PartTreeWidget::hideAllComponents, m_document, &Document::hideAllComponents); - connect(partTreeWidget, &PartTreeWidget::showAllComponents, m_document, &Document::showAllComponents); - connect(partTreeWidget, &PartTreeWidget::collapseAllComponents, m_document, &Document::collapseAllComponents); - connect(partTreeWidget, &PartTreeWidget::expandAllComponents, m_document, &Document::expandAllComponents); - connect(partTreeWidget, &PartTreeWidget::lockAllComponents, m_document, &Document::lockAllComponents); - connect(partTreeWidget, &PartTreeWidget::unlockAllComponents, m_document, &Document::unlockAllComponents); - connect(partTreeWidget, &PartTreeWidget::setPartLockState, m_document, &Document::setPartLockState); - connect(partTreeWidget, &PartTreeWidget::setPartVisibleState, m_document, &Document::setPartVisibleState); - connect(partTreeWidget, &PartTreeWidget::setPartColorState, m_document, &Document::setPartColorState); - connect(partTreeWidget, &PartTreeWidget::setComponentCombineMode, m_document, &Document::setComponentCombineMode); - connect(partTreeWidget, &PartTreeWidget::setComponentClothStiffness, m_document, &Document::setComponentClothStiffness); - connect(partTreeWidget, &PartTreeWidget::setComponentClothIteration, m_document, &Document::setComponentClothIteration); - connect(partTreeWidget, &PartTreeWidget::setComponentClothForce, m_document, &Document::setComponentClothForce); - connect(partTreeWidget, &PartTreeWidget::setComponentClothOffset, m_document, &Document::setComponentClothOffset); - connect(partTreeWidget, &PartTreeWidget::setPartTarget, m_document, &Document::setPartTarget); - connect(partTreeWidget, &PartTreeWidget::setPartBase, m_document, &Document::setPartBase); - connect(partTreeWidget, &PartTreeWidget::hideDescendantComponents, m_document, &Document::hideDescendantComponents); - connect(partTreeWidget, &PartTreeWidget::showDescendantComponents, m_document, &Document::showDescendantComponents); - connect(partTreeWidget, &PartTreeWidget::lockDescendantComponents, m_document, &Document::lockDescendantComponents); - connect(partTreeWidget, &PartTreeWidget::unlockDescendantComponents, m_document, &Document::unlockDescendantComponents); - connect(partTreeWidget, &PartTreeWidget::groupOperationAdded, m_document, &Document::saveSnapshot); + connect(m_partTreeWidget, &PartTreeWidget::currentComponentChanged, m_document, &Document::setCurrentCanvasComponentId); + connect(m_partTreeWidget, &PartTreeWidget::moveComponentUp, m_document, &Document::moveComponentUp); + connect(m_partTreeWidget, &PartTreeWidget::moveComponentDown, m_document, &Document::moveComponentDown); + connect(m_partTreeWidget, &PartTreeWidget::moveComponentToTop, m_document, &Document::moveComponentToTop); + connect(m_partTreeWidget, &PartTreeWidget::moveComponentToBottom, m_document, &Document::moveComponentToBottom); + connect(m_partTreeWidget, &PartTreeWidget::checkPart, m_document, &Document::checkPart); + connect(m_partTreeWidget, &PartTreeWidget::createNewComponentAndMoveThisIn, m_document, &Document::createNewComponentAndMoveThisIn); + connect(m_partTreeWidget, &PartTreeWidget::createNewChildComponent, m_document, &Document::createNewChildComponent); + connect(m_partTreeWidget, &PartTreeWidget::renameComponent, m_document, &Document::renameComponent); + connect(m_partTreeWidget, &PartTreeWidget::setComponentExpandState, m_document, &Document::setComponentExpandState); + connect(m_partTreeWidget, &PartTreeWidget::setComponentSmoothAll, m_document, &Document::setComponentSmoothAll); + connect(m_partTreeWidget, &PartTreeWidget::setComponentSmoothSeam, m_document, &Document::setComponentSmoothSeam); + connect(m_partTreeWidget, &PartTreeWidget::setComponentPolyCount, m_document, &Document::setComponentPolyCount); + connect(m_partTreeWidget, &PartTreeWidget::setComponentLayer, m_document, &Document::setComponentLayer); + connect(m_partTreeWidget, &PartTreeWidget::moveComponent, m_document, &Document::moveComponent); + connect(m_partTreeWidget, &PartTreeWidget::removeComponent, m_document, &Document::removeComponent); + connect(m_partTreeWidget, &PartTreeWidget::hideOtherComponents, m_document, &Document::hideOtherComponents); + connect(m_partTreeWidget, &PartTreeWidget::lockOtherComponents, m_document, &Document::lockOtherComponents); + connect(m_partTreeWidget, &PartTreeWidget::hideAllComponents, m_document, &Document::hideAllComponents); + connect(m_partTreeWidget, &PartTreeWidget::showAllComponents, m_document, &Document::showAllComponents); + connect(m_partTreeWidget, &PartTreeWidget::collapseAllComponents, m_document, &Document::collapseAllComponents); + connect(m_partTreeWidget, &PartTreeWidget::expandAllComponents, m_document, &Document::expandAllComponents); + connect(m_partTreeWidget, &PartTreeWidget::lockAllComponents, m_document, &Document::lockAllComponents); + connect(m_partTreeWidget, &PartTreeWidget::unlockAllComponents, m_document, &Document::unlockAllComponents); + connect(m_partTreeWidget, &PartTreeWidget::setPartLockState, m_document, &Document::setPartLockState); + connect(m_partTreeWidget, &PartTreeWidget::setPartVisibleState, m_document, &Document::setPartVisibleState); + connect(m_partTreeWidget, &PartTreeWidget::setPartColorState, m_document, &Document::setPartColorState); + connect(m_partTreeWidget, &PartTreeWidget::setComponentCombineMode, m_document, &Document::setComponentCombineMode); + connect(m_partTreeWidget, &PartTreeWidget::setComponentClothStiffness, m_document, &Document::setComponentClothStiffness); + connect(m_partTreeWidget, &PartTreeWidget::setComponentClothIteration, m_document, &Document::setComponentClothIteration); + connect(m_partTreeWidget, &PartTreeWidget::setComponentClothForce, m_document, &Document::setComponentClothForce); + connect(m_partTreeWidget, &PartTreeWidget::setComponentClothOffset, m_document, &Document::setComponentClothOffset); + connect(m_partTreeWidget, &PartTreeWidget::setPartTarget, m_document, &Document::setPartTarget); + connect(m_partTreeWidget, &PartTreeWidget::setPartBase, m_document, &Document::setPartBase); + connect(m_partTreeWidget, &PartTreeWidget::hideDescendantComponents, m_document, &Document::hideDescendantComponents); + connect(m_partTreeWidget, &PartTreeWidget::showDescendantComponents, m_document, &Document::showDescendantComponents); + connect(m_partTreeWidget, &PartTreeWidget::lockDescendantComponents, m_document, &Document::lockDescendantComponents); + connect(m_partTreeWidget, &PartTreeWidget::unlockDescendantComponents, m_document, &Document::unlockDescendantComponents); + connect(m_partTreeWidget, &PartTreeWidget::groupOperationAdded, m_document, &Document::saveSnapshot); - connect(partTreeWidget, &PartTreeWidget::addPartToSelection, graphicsWidget, &SkeletonGraphicsWidget::addPartToSelection); + connect(m_partTreeWidget, &PartTreeWidget::addPartToSelection, graphicsWidget, &SkeletonGraphicsWidget::addPartToSelection); - connect(graphicsWidget, &SkeletonGraphicsWidget::partComponentChecked, partTreeWidget, &PartTreeWidget::partComponentChecked); + connect(graphicsWidget, &SkeletonGraphicsWidget::partComponentChecked, m_partTreeWidget, &PartTreeWidget::partComponentChecked); - connect(m_document, &Document::componentNameChanged, partTreeWidget, &PartTreeWidget::componentNameChanged); - connect(m_document, &Document::componentChildrenChanged, partTreeWidget, &PartTreeWidget::componentChildrenChanged); - connect(m_document, &Document::componentRemoved, partTreeWidget, &PartTreeWidget::componentRemoved); - connect(m_document, &Document::componentAdded, partTreeWidget, &PartTreeWidget::componentAdded); - connect(m_document, &Document::componentExpandStateChanged, partTreeWidget, &PartTreeWidget::componentExpandStateChanged); - connect(m_document, &Document::componentCombineModeChanged, partTreeWidget, &PartTreeWidget::componentCombineModeChanged); - connect(m_document, &Document::partPreviewChanged, partTreeWidget, &PartTreeWidget::partPreviewChanged); - connect(m_document, &Document::partLockStateChanged, partTreeWidget, &PartTreeWidget::partLockStateChanged); - connect(m_document, &Document::partVisibleStateChanged, partTreeWidget, &PartTreeWidget::partVisibleStateChanged); - connect(m_document, &Document::partSubdivStateChanged, partTreeWidget, &PartTreeWidget::partSubdivStateChanged); - connect(m_document, &Document::partDisableStateChanged, partTreeWidget, &PartTreeWidget::partDisableStateChanged); - connect(m_document, &Document::partXmirrorStateChanged, partTreeWidget, &PartTreeWidget::partXmirrorStateChanged); - connect(m_document, &Document::partDeformThicknessChanged, partTreeWidget, &PartTreeWidget::partDeformChanged); - connect(m_document, &Document::partDeformWidthChanged, partTreeWidget, &PartTreeWidget::partDeformChanged); - connect(m_document, &Document::partDeformMapImageIdChanged, partTreeWidget, &PartTreeWidget::partDeformChanged); - connect(m_document, &Document::partDeformMapScaleChanged, partTreeWidget, &PartTreeWidget::partDeformChanged); - connect(m_document, &Document::partRoundStateChanged, partTreeWidget, &PartTreeWidget::partRoundStateChanged); - connect(m_document, &Document::partChamferStateChanged, partTreeWidget, &PartTreeWidget::partChamferStateChanged); - connect(m_document, &Document::partColorStateChanged, partTreeWidget, &PartTreeWidget::partColorStateChanged); - connect(m_document, &Document::partCutRotationChanged, partTreeWidget, &PartTreeWidget::partCutRotationChanged); - connect(m_document, &Document::partCutFaceChanged, partTreeWidget, &PartTreeWidget::partCutFaceChanged); - connect(m_document, &Document::partHollowThicknessChanged, partTreeWidget, &PartTreeWidget::partHollowThicknessChanged); - connect(m_document, &Document::partMaterialIdChanged, partTreeWidget, &PartTreeWidget::partMaterialIdChanged); - connect(m_document, &Document::partColorSolubilityChanged, partTreeWidget, &PartTreeWidget::partColorSolubilityChanged); - connect(m_document, &Document::partCountershadeStateChanged, partTreeWidget, &PartTreeWidget::partCountershadeStateChanged); + connect(m_document, &Document::componentNameChanged, m_partTreeWidget, &PartTreeWidget::componentNameChanged); + connect(m_document, &Document::componentChildrenChanged, m_partTreeWidget, &PartTreeWidget::componentChildrenChanged); + connect(m_document, &Document::componentRemoved, m_partTreeWidget, &PartTreeWidget::componentRemoved); + connect(m_document, &Document::componentAdded, m_partTreeWidget, &PartTreeWidget::componentAdded); + connect(m_document, &Document::componentExpandStateChanged, m_partTreeWidget, &PartTreeWidget::componentExpandStateChanged); + connect(m_document, &Document::componentCombineModeChanged, m_partTreeWidget, &PartTreeWidget::componentCombineModeChanged); + //connect(m_document, &Document::partPreviewChanged, m_partTreeWidget, &PartTreeWidget::partPreviewChanged); + connect(m_document, &Document::partLockStateChanged, m_partTreeWidget, &PartTreeWidget::partLockStateChanged); + connect(m_document, &Document::partVisibleStateChanged, m_partTreeWidget, &PartTreeWidget::partVisibleStateChanged); + connect(m_document, &Document::partSubdivStateChanged, m_partTreeWidget, &PartTreeWidget::partSubdivStateChanged); + connect(m_document, &Document::partDisableStateChanged, m_partTreeWidget, &PartTreeWidget::partDisableStateChanged); + connect(m_document, &Document::partXmirrorStateChanged, m_partTreeWidget, &PartTreeWidget::partXmirrorStateChanged); + connect(m_document, &Document::partDeformThicknessChanged, m_partTreeWidget, &PartTreeWidget::partDeformChanged); + connect(m_document, &Document::partDeformWidthChanged, m_partTreeWidget, &PartTreeWidget::partDeformChanged); + connect(m_document, &Document::partDeformMapImageIdChanged, m_partTreeWidget, &PartTreeWidget::partDeformChanged); + connect(m_document, &Document::partDeformMapScaleChanged, m_partTreeWidget, &PartTreeWidget::partDeformChanged); + connect(m_document, &Document::partRoundStateChanged, m_partTreeWidget, &PartTreeWidget::partRoundStateChanged); + connect(m_document, &Document::partChamferStateChanged, m_partTreeWidget, &PartTreeWidget::partChamferStateChanged); + connect(m_document, &Document::partColorStateChanged, m_partTreeWidget, &PartTreeWidget::partColorStateChanged); + connect(m_document, &Document::partCutRotationChanged, m_partTreeWidget, &PartTreeWidget::partCutRotationChanged); + connect(m_document, &Document::partCutFaceChanged, m_partTreeWidget, &PartTreeWidget::partCutFaceChanged); + connect(m_document, &Document::partHollowThicknessChanged, m_partTreeWidget, &PartTreeWidget::partHollowThicknessChanged); + connect(m_document, &Document::partMaterialIdChanged, m_partTreeWidget, &PartTreeWidget::partMaterialIdChanged); + connect(m_document, &Document::partColorSolubilityChanged, m_partTreeWidget, &PartTreeWidget::partColorSolubilityChanged); + connect(m_document, &Document::partCountershadeStateChanged, m_partTreeWidget, &PartTreeWidget::partCountershadeStateChanged); - connect(m_document, &Document::partTargetChanged, partTreeWidget, &PartTreeWidget::partXmirrorStateChanged); - connect(m_document, &Document::partTargetChanged, partTreeWidget, &PartTreeWidget::partColorStateChanged); - connect(m_document, &Document::partTargetChanged, partTreeWidget, &PartTreeWidget::partSubdivStateChanged); - connect(m_document, &Document::partTargetChanged, partTreeWidget, &PartTreeWidget::partRoundStateChanged); - connect(m_document, &Document::partTargetChanged, partTreeWidget, &PartTreeWidget::partChamferStateChanged); - connect(m_document, &Document::partTargetChanged, partTreeWidget, &PartTreeWidget::partCutRotationChanged); - connect(m_document, &Document::partTargetChanged, partTreeWidget, &PartTreeWidget::partDeformChanged); + connect(m_document, &Document::partTargetChanged, m_partTreeWidget, &PartTreeWidget::partXmirrorStateChanged); + connect(m_document, &Document::partTargetChanged, m_partTreeWidget, &PartTreeWidget::partColorStateChanged); + connect(m_document, &Document::partTargetChanged, m_partTreeWidget, &PartTreeWidget::partSubdivStateChanged); + connect(m_document, &Document::partTargetChanged, m_partTreeWidget, &PartTreeWidget::partRoundStateChanged); + connect(m_document, &Document::partTargetChanged, m_partTreeWidget, &PartTreeWidget::partChamferStateChanged); + connect(m_document, &Document::partTargetChanged, m_partTreeWidget, &PartTreeWidget::partCutRotationChanged); + connect(m_document, &Document::partTargetChanged, m_partTreeWidget, &PartTreeWidget::partDeformChanged); - connect(m_document, &Document::partRemoved, partTreeWidget, &PartTreeWidget::partRemoved); - connect(m_document, &Document::cleanup, partTreeWidget, &PartTreeWidget::removeAllContent); - connect(m_document, &Document::partChecked, partTreeWidget, &PartTreeWidget::partChecked); - connect(m_document, &Document::partUnchecked, partTreeWidget, &PartTreeWidget::partUnchecked); + connect(m_document, &Document::partRemoved, m_partTreeWidget, &PartTreeWidget::partRemoved); + connect(m_document, &Document::cleanup, m_partTreeWidget, &PartTreeWidget::removeAllContent); + connect(m_document, &Document::partChecked, m_partTreeWidget, &PartTreeWidget::partChecked); + connect(m_document, &Document::partUnchecked, m_partTreeWidget, &PartTreeWidget::partUnchecked); connect(m_document, &Document::skeletonChanged, m_document, &Document::generateMesh); //connect(m_document, &SkeletonDocument::resultMeshChanged, [=]() { @@ -2227,3 +2228,51 @@ void DocumentWindow::import() return; importPath(fileName); } + +void DocumentWindow::generatePartPreviewImages() +{ + if (nullptr != m_partPreviewImagesGenerator) { + m_isPartPreviewImagesObsolete = true; + return; + } + + m_isPartPreviewImagesObsolete = false; + + QThread *thread = new QThread; + + m_partPreviewImagesGenerator = new PartPreviewImagesGenerator(new ModelOffscreenRender(m_modelRenderWidget->format())); + for (const auto &part: m_document->partMap) { + if (!part.second.isPreviewMeshObsolete) + continue; + m_partPreviewImagesGenerator->addPart(part.first, part.second.takePreviewMesh(), PartTarget::CutFace == part.second.target); + } + m_partPreviewImagesGenerator->moveToThread(thread); + connect(thread, &QThread::started, m_partPreviewImagesGenerator, &PartPreviewImagesGenerator::process); + connect(m_partPreviewImagesGenerator, &PartPreviewImagesGenerator::finished, this, &DocumentWindow::partPreviewImagesReady); + connect(m_partPreviewImagesGenerator, &PartPreviewImagesGenerator::finished, thread, &QThread::quit); + connect(thread, &QThread::finished, thread, &QThread::deleteLater); + thread->start(); +} + +void DocumentWindow::partPreviewImagesReady() +{ + std::map *partImages = m_partPreviewImagesGenerator->takePartImages(); + if (nullptr != partImages) { + for (const auto &it: *partImages) { + SkeletonPart *part = (SkeletonPart *)m_document->findPart(it.first); + if (nullptr != part) { + part->isPreviewMeshObsolete = false; + part->previewPixmap = QPixmap::fromImage(it.second); + } + } + for (const auto &it: *partImages) + m_partTreeWidget->partPreviewChanged(it.first); + } + delete partImages; + + delete m_partPreviewImagesGenerator; + m_partPreviewImagesGenerator = nullptr; + + if (m_isPartPreviewImagesObsolete) + generatePartPreviewImages(); +} diff --git a/src/documentwindow.h b/src/documentwindow.h index cb2cf8aa..5df0d24f 100644 --- a/src/documentwindow.h +++ b/src/documentwindow.h @@ -20,8 +20,10 @@ #include "graphicscontainerwidget.h" #include "normalanddepthmapsgenerator.h" #include "autosaver.h" +#include "partpreviewimagesgenerator.h" class SkeletonGraphicsWidget; +class PartTreeWidget; class DocumentWindow : public QMainWindow { @@ -96,6 +98,8 @@ public slots: void autoRecover(); void import(); void importPath(const QString &filename); + void generatePartPreviewImages(); + void partPreviewImagesReady(); private: void initLockButton(QPushButton *button); void setCurrentFilename(const QString &filename); @@ -222,6 +226,11 @@ private: bool m_isNormalAndDepthMapsObsolete = false; AutoSaver *m_autoSaver = nullptr; + + PartPreviewImagesGenerator *m_partPreviewImagesGenerator = nullptr; + bool m_isPartPreviewImagesObsolete = false; + + PartTreeWidget *m_partTreeWidget = nullptr; public: static int m_autoRecovered; }; diff --git a/src/meshgenerator.cpp b/src/meshgenerator.cpp index da214bc0..05ce440d 100644 --- a/src/meshgenerator.cpp +++ b/src/meshgenerator.cpp @@ -26,6 +26,7 @@ #include "fileforever.h" #include "snapshotxml.h" #include "fixholes.h" +#include "modeloffscreenrender.h" MeshGenerator::MeshGenerator(Snapshot *snapshot) : m_snapshot(snapshot) diff --git a/src/partpreviewimagesgenerator.cpp b/src/partpreviewimagesgenerator.cpp new file mode 100644 index 00000000..3ffa2db5 --- /dev/null +++ b/src/partpreviewimagesgenerator.cpp @@ -0,0 +1,44 @@ +#include +#include "partpreviewimagesgenerator.h" +#include "theme.h" + +void PartPreviewImagesGenerator::addPart(const QUuid &partId, Model *previewMesh, bool isCutFace) +{ + m_partPreviews.insert({partId, {previewMesh, isCutFace}}); +} + +void PartPreviewImagesGenerator::process() +{ + generate(); + + emit finished(); +} + +std::map *PartPreviewImagesGenerator::takePartImages() +{ + std::map *partImages = m_partImages; + m_partImages = nullptr; + return partImages; +} + +void PartPreviewImagesGenerator::generate() +{ + delete m_partImages; + m_partImages = new std::map; + + m_offscreenRender->setZRotation(0); + m_offscreenRender->setEyePosition(QVector3D(0, 0, -4.0)); + m_offscreenRender->setRenderPurpose(0); + for (auto &it: m_partPreviews) { + if (it.second.isCutFace) { + m_offscreenRender->setXRotation(0); + m_offscreenRender->setYRotation(0); + } else { + m_offscreenRender->setXRotation(30 * 16); + m_offscreenRender->setYRotation(-45 * 16); + } + m_offscreenRender->updateMesh(it.second.mesh); + it.second.mesh = nullptr; + (*m_partImages)[it.first] = m_offscreenRender->toImage(QSize(Theme::partPreviewImageSize, Theme::partPreviewImageSize)); + } +} diff --git a/src/partpreviewimagesgenerator.h b/src/partpreviewimagesgenerator.h new file mode 100644 index 00000000..e5a91572 --- /dev/null +++ b/src/partpreviewimagesgenerator.h @@ -0,0 +1,47 @@ +#ifndef DUST3D_PART_PREVIEW_IMAGES_GENERATOR_H +#define DUST3D_PART_PREVIEW_IMAGES_GENERATOR_H +#include +#include +#include +#include +#include "modeloffscreenrender.h" + +class PartPreviewImagesGenerator : public QObject +{ + Q_OBJECT +public: + PartPreviewImagesGenerator(ModelOffscreenRender *modelOffscreenRender) : + m_offscreenRender(modelOffscreenRender) + { + } + + struct PreviewInput + { + Model *mesh = nullptr; + bool isCutFace = false; + }; + + ~PartPreviewImagesGenerator() + { + for (const auto &it: m_partPreviews) + delete it.second.mesh; + + delete m_partImages; + + delete m_offscreenRender; + } + + void addPart(const QUuid &partId, Model *previewMesh, bool isCutFace); + void generate(); + std::map *takePartImages(); +signals: + void finished(); +public slots: + void process(); +private: + std::map m_partPreviews; + ModelOffscreenRender *m_offscreenRender = nullptr; + std::map *m_partImages = nullptr; +}; + +#endif diff --git a/src/parttreewidget.cpp b/src/parttreewidget.cpp index 9f356ee1..63c14a14 100644 --- a/src/parttreewidget.cpp +++ b/src/parttreewidget.cpp @@ -437,15 +437,10 @@ void PartTreeWidget::showContextMenu(const QPoint &pos, bool shorted) } } if (nullptr != part && nullptr != partWidget) { - ModelWidget *previewWidget = new ModelWidget; - previewWidget->enableMove(false); - previewWidget->enableZoom(false); - previewWidget->setFixedSize(Theme::partPreviewImageSize, Theme::partPreviewImageSize); - previewWidget->setXRotation(partWidget->previewWidget()->xRot()); - previewWidget->setYRotation(partWidget->previewWidget()->yRot()); - previewWidget->setZRotation(partWidget->previewWidget()->zRot()); - previewWidget->updateMesh(part->takePreviewMesh()); - layout->addWidget(previewWidget); + QLabel *previewLabel = new QLabel; + previewLabel->setFixedSize(Theme::partPreviewImageSize, Theme::partPreviewImageSize); + previewLabel->setPixmap(part->previewPixmap); + layout->addWidget(previewLabel); } else { QLabel *previewLabel = new QLabel; previewLabel->setFixedHeight(Theme::partPreviewImageSize); diff --git a/src/partwidget.cpp b/src/partwidget.cpp index 4f50e37e..67e65866 100644 --- a/src/partwidget.cpp +++ b/src/partwidget.cpp @@ -83,11 +83,14 @@ PartWidget::PartWidget(const Document *document, QUuid partId) : m_cutRotationButton->setSizePolicy(retainSizePolicy); initButton(m_cutRotationButton); - m_previewWidget = new ModelWidget; - m_previewWidget->setAttribute(Qt::WA_TransparentForMouseEvents); - m_previewWidget->enableMove(false); - m_previewWidget->enableZoom(false); - m_previewWidget->setFixedSize(Theme::partPreviewImageSize, Theme::partPreviewImageSize); + m_previewLabel = new QLabel; + m_previewLabel->setFixedSize(Theme::partPreviewImageSize, Theme::partPreviewImageSize); + + //m_previewWidget = new ModelWidget; + //m_previewWidget->setAttribute(Qt::WA_TransparentForMouseEvents); + //m_previewWidget->enableMove(false); + //m_previewWidget->enableZoom(false); + //m_previewWidget->setFixedSize(Theme::partPreviewImageSize, Theme::partPreviewImageSize); QWidget *hrLightWidget = new QWidget; hrLightWidget->setFixedHeight(1); @@ -126,7 +129,8 @@ PartWidget::PartWidget(const Document *document, QUuid partId) : previewAndToolsLayout->setSpacing(0); previewAndToolsLayout->setContentsMargins(0, 0, 0, 0); //previewAndToolsLayout->addWidget(m_visibleButton); - previewAndToolsLayout->addWidget(m_previewWidget); + //previewAndToolsLayout->addWidget(m_previewWidget); + previewAndToolsLayout->addWidget(m_previewLabel); previewAndToolsLayout->addLayout(toolsLayout); previewAndToolsLayout->setStretch(0, 0); previewAndToolsLayout->setStretch(1, 0); @@ -300,7 +304,8 @@ PartWidget::PartWidget(const Document *document, QUuid partId) : ModelWidget *PartWidget::previewWidget() { - return m_previewWidget; + //return m_previewWidget; + return nullptr; } QSize PartWidget::preferredSize() @@ -826,22 +831,7 @@ void PartWidget::updatePreview() qDebug() << "Part not found:" << m_partId; return; } - //m_previewLabel->setPixmap(QPixmap::fromImage(part->preview)); - Model *previewMesh = part->takePreviewMesh(); - m_previewWidget->updateMesh(previewMesh); - if (PartTarget::CutFace == part->target) { - if (0 != m_previewWidget->xRot()) { - m_previewWidget->setXRotation(0); - m_previewWidget->setYRotation(0); - m_previewWidget->setZRotation(0); - } - } else { - if (0 == m_previewWidget->xRot()) { - m_previewWidget->setXRotation(ModelWidget::m_defaultXRotation); - m_previewWidget->setYRotation(ModelWidget::m_defaultYRotation); - m_previewWidget->setZRotation(ModelWidget::m_defaultZRotation); - } - } + m_previewLabel->setPixmap(part->previewPixmap); } void PartWidget::updateLockButton() diff --git a/src/partwidget.h b/src/partwidget.h index ea2769eb..dda750f7 100644 --- a/src/partwidget.h +++ b/src/partwidget.h @@ -68,19 +68,20 @@ private: // need initialize QUuid m_partId; bool m_unnormal; private: - ModelWidget *m_previewWidget; - QPushButton *m_visibleButton; - QPushButton *m_lockButton; - QPushButton *m_subdivButton; - QPushButton *m_disableButton; - QPushButton *m_xMirrorButton; - QPushButton *m_zMirrorButton; - QPushButton *m_deformButton; - QPushButton *m_roundButton; - QPushButton *m_chamferButton; - QPushButton *m_colorButton; - QPushButton *m_cutRotationButton; - QWidget *m_backgroundWidget; + ModelWidget *m_previewWidget = nullptr; + QPushButton *m_visibleButton = nullptr; + QPushButton *m_lockButton = nullptr; + QPushButton *m_subdivButton = nullptr; + QPushButton *m_disableButton = nullptr; + QPushButton *m_xMirrorButton = nullptr; + QPushButton *m_zMirrorButton = nullptr; + QPushButton *m_deformButton = nullptr; + QPushButton *m_roundButton = nullptr; + QPushButton *m_chamferButton = nullptr; + QPushButton *m_colorButton = nullptr; + QPushButton *m_cutRotationButton = nullptr; + QWidget *m_backgroundWidget = nullptr; + QLabel *m_previewLabel = nullptr; private: void initToolButton(QPushButton *button); void initToolButtonWithoutFont(QPushButton *button); diff --git a/src/skeletondocument.h b/src/skeletondocument.h index 209b8316..b269a707 100644 --- a/src/skeletondocument.h +++ b/src/skeletondocument.h @@ -183,6 +183,8 @@ public: bool countershaded; bool gridded; QUuid fillMeshLinkedId; + bool isPreviewMeshObsolete; + QPixmap previewPixmap; SkeletonPart(const QUuid &withId=QUuid()) : visible(true), locked(false), @@ -205,7 +207,8 @@ public: deformMapScale(1.0), hollowThickness(0.0), countershaded(false), - gridded(false) + gridded(false), + isPreviewMeshObsolete(false) { id = withId.isNull() ? QUuid::createUuid() : withId; } @@ -384,6 +387,7 @@ public: { delete m_previewMesh; m_previewMesh = previewMesh; + isPreviewMeshObsolete = true; } Model *takePreviewMesh() const {