diff --git a/dust3d.pro b/dust3d.pro index a269a1ef..18dd69fe 100644 --- a/dust3d.pro +++ b/dust3d.pro @@ -42,9 +42,6 @@ HEADERS += src/modelshaderprogram.h SOURCES += src/modelmeshbinder.cpp HEADERS += src/modelmeshbinder.h -SOURCES += src/modelofflinerender.cpp -HEADERS += src/modelofflinerender.h - SOURCES += src/modelwidget.cpp HEADERS += src/modelwidget.h diff --git a/src/meshgenerator.cpp b/src/meshgenerator.cpp index 6b91c171..d8aa70a0 100644 --- a/src/meshgenerator.cpp +++ b/src/meshgenerator.cpp @@ -5,7 +5,6 @@ #include "dust3dutil.h" #include "skeletondocument.h" #include "meshlite.h" -#include "modelofflinerender.h" #include "meshutil.h" #include "theme.h" #include "positionmap.h" @@ -32,7 +31,7 @@ void GeneratedCacheContext::updateComponentCombinableMesh(QString componentId, v MeshGenerator::MeshGenerator(SkeletonSnapshot *snapshot, QThread *thread) : m_snapshot(snapshot), m_mesh(nullptr), - m_preview(nullptr), + //m_preview(nullptr), m_thread(thread), m_meshResultContext(nullptr), m_sharedContextWidget(nullptr), @@ -45,12 +44,8 @@ MeshGenerator::~MeshGenerator() { delete m_snapshot; delete m_mesh; - delete m_preview; - for (const auto &partPreviewIt: m_partPreviewMap) { - delete partPreviewIt.second; - } - for (const auto &render: m_partPreviewRenderMap) { - delete render.second; + for (const auto &partPreviewMeshIt: m_partPreviewMeshMap) { + delete partPreviewMeshIt.second; } delete m_meshResultContext; } @@ -65,15 +60,10 @@ void MeshGenerator::setGeneratedCacheContext(GeneratedCacheContext *cacheContext m_cacheContext = cacheContext; } -void MeshGenerator::addPartPreviewRequirement(const QString &partId) +void MeshGenerator::addPartPreviewRequirement(const QUuid &partId) { //qDebug() << "addPartPreviewRequirement:" << partId; - m_requirePartPreviewMap.insert(partId); - if (m_partPreviewRenderMap.find(partId) == m_partPreviewRenderMap.end()) { - ModelOfflineRender *render = new ModelOfflineRender(m_sharedContextWidget); - render->setRenderThread(m_thread); - m_partPreviewRenderMap[partId] = render; - } + m_requirePreviewPartIds.insert(partId); } void MeshGenerator::setSharedContextWidget(QOpenGLWidget *widget) @@ -88,18 +78,21 @@ MeshLoader *MeshGenerator::takeResultMesh() return resultMesh; } -QImage *MeshGenerator::takePreview() +MeshLoader *MeshGenerator::takePartPreviewMesh(const QUuid &partId) { - QImage *resultPreview = m_preview; - m_preview = nullptr; - return resultPreview; + MeshLoader *resultMesh = m_partPreviewMeshMap[partId]; + m_partPreviewMeshMap[partId] = nullptr; + return resultMesh; } -QImage *MeshGenerator::takePartPreview(const QString &partId) +const std::set &MeshGenerator::requirePreviewPartIds() { - QImage *resultImage = m_partPreviewMap[partId]; - m_partPreviewMap[partId] = nullptr; - return resultImage; + return m_requirePreviewPartIds; +} + +const std::set &MeshGenerator::generatedPreviewPartIds() +{ + return m_generatedPreviewPartIds; } MeshResultContext *MeshGenerator::takeMeshResultContext() @@ -360,18 +353,10 @@ void *MeshGenerator::combinePartMesh(QString partId) } } - if (m_requirePartPreviewMap.find(partId) != m_requirePartPreviewMap.end()) { - ModelOfflineRender *render = m_partPreviewRenderMap[partId]; + if (m_requirePreviewPartIds.find(partIdNotAsString) != m_requirePreviewPartIds.end()) { int trimedMeshId = meshlite_trim(m_meshliteContext, meshId, 1); - render->updateMesh(new MeshLoader(m_meshliteContext, trimedMeshId, -1, partColor, nullptr, m_smoothNormal)); - QImage *image = new QImage(render->toImage(QSize(Theme::previewImageRenderSize, Theme::previewImageRenderSize))); - if (Theme::previewImageSize != Theme::previewImageRenderSize) { - int cropOffset = (Theme::previewImageRenderSize - Theme::previewImageSize) / 2; - QImage *crop = new QImage(image->copy(cropOffset, cropOffset, Theme::previewImageSize, Theme::previewImageSize)); - delete image; - image = crop; - } - m_partPreviewMap[partId] = image; + m_partPreviewMeshMap[partIdNotAsString] = new MeshLoader(m_meshliteContext, trimedMeshId, -1, partColor, nullptr, m_smoothNormal); + m_generatedPreviewPartIds.insert(partIdNotAsString); } if (isDisabled) { diff --git a/src/meshgenerator.h b/src/meshgenerator.h index 2ca963c1..77207129 100644 --- a/src/meshgenerator.h +++ b/src/meshgenerator.h @@ -9,7 +9,6 @@ #include #include "skeletonsnapshot.h" #include "meshloader.h" -#include "modelofflinerender.h" #include "meshresultcontext.h" #include "positionmap.h" @@ -34,12 +33,13 @@ public: MeshGenerator(SkeletonSnapshot *snapshot, QThread *thread); ~MeshGenerator(); void setSharedContextWidget(QOpenGLWidget *widget); - void addPartPreviewRequirement(const QString &partId); + void addPartPreviewRequirement(const QUuid &partId); void setGeneratedCacheContext(GeneratedCacheContext *cacheContext); void setSmoothNormal(bool smoothNormal); MeshLoader *takeResultMesh(); - QImage *takePreview(); - QImage *takePartPreview(const QString &partId); + MeshLoader *takePartPreviewMesh(const QUuid &partId); + const std::set &requirePreviewPartIds(); + const std::set &generatedPreviewPartIds(); MeshResultContext *takeMeshResultContext(); signals: void finished(); @@ -48,10 +48,9 @@ public slots: private: SkeletonSnapshot *m_snapshot; MeshLoader *m_mesh; - QImage *m_preview; - std::map m_partPreviewMap; - std::set m_requirePartPreviewMap; - std::map m_partPreviewRenderMap; + std::map m_partPreviewMeshMap; + std::set m_requirePreviewPartIds; + std::set m_generatedPreviewPartIds; QThread *m_thread; MeshResultContext *m_meshResultContext; QOpenGLWidget *m_sharedContextWidget; diff --git a/src/meshloader.cpp b/src/meshloader.cpp index 69fde464..886be732 100644 --- a/src/meshloader.cpp +++ b/src/meshloader.cpp @@ -244,6 +244,15 @@ MeshLoader::MeshLoader(MeshResultContext &resultContext) : } } +MeshLoader::MeshLoader() : + m_triangleVertices(nullptr), + m_triangleVertexCount(0), + m_edgeVertices(nullptr), + m_edgeVertexCount(0), + m_textureImage(nullptr) +{ +} + MeshLoader::~MeshLoader() { delete[] m_triangleVertices; diff --git a/src/meshloader.h b/src/meshloader.h index eafa52ff..71a166f5 100644 --- a/src/meshloader.h +++ b/src/meshloader.h @@ -42,6 +42,7 @@ public: MeshLoader(MeshResultContext &resultContext); MeshLoader(Vertex *triangleVertices, int vertexNum); MeshLoader(const MeshLoader &mesh); + MeshLoader(); ~MeshLoader(); Vertex *triangleVertices(); int triangleVertexCount(); @@ -54,15 +55,15 @@ public: void setTextureImage(QImage *textureImage); const QImage *textureImage(); private: - Vertex *m_triangleVertices; - int m_triangleVertexCount; - Vertex *m_edgeVertices; - int m_edgeVertexCount; + Vertex *m_triangleVertices = nullptr; + int m_triangleVertexCount = 0; + Vertex *m_edgeVertices = nullptr; + int m_edgeVertexCount = 0; std::vector m_vertices; std::vector> m_faces; std::vector m_triangulatedVertices; std::vector m_triangulatedFaces; - QImage *m_textureImage; + QImage *m_textureImage = nullptr; }; #endif diff --git a/src/modelofflinerender.cpp b/src/modelofflinerender.cpp deleted file mode 100644 index 52d2c20a..00000000 --- a/src/modelofflinerender.cpp +++ /dev/null @@ -1,151 +0,0 @@ -#include -#include -#include -#include "modelofflinerender.h" - -ModelOfflineRender::ModelOfflineRender(QOpenGLWidget *sharedContextWidget, QScreen *targetScreen) : - QOffscreenSurface(targetScreen), - m_context(nullptr), - m_mesh(nullptr), - m_xRot(0), - m_yRot(0), - m_zRot(0) -{ - create(); - - QOpenGLContext *current = nullptr; - - if (nullptr != sharedContextWidget) { - current = sharedContextWidget->context(); - current->doneCurrent(); - } - - m_context = new QOpenGLContext(); - - if (nullptr != current) { - m_context->setFormat(current->format()); - m_context->setShareContext(current); - } else { - QSurfaceFormat fmt = format(); - fmt.setAlphaBufferSize(8); - fmt.setSamples(4); - - setFormat(fmt); - - m_context->setFormat(fmt); - } - m_context->create(); - - if (nullptr != sharedContextWidget) { - sharedContextWidget->makeCurrent(); - } -} - -ModelOfflineRender::~ModelOfflineRender() -{ - delete m_context; - m_context = nullptr; - destroy(); - delete m_mesh; -} - -void ModelOfflineRender::updateMesh(MeshLoader *mesh) -{ - delete m_mesh; - m_mesh = mesh; -} - -void ModelOfflineRender::setRenderThread(QThread *thread) -{ - m_context->moveToThread(thread); -} - -QImage ModelOfflineRender::toImage(const QSize &size) -{ - QImage image; - - m_context->makeCurrent(this); - - QOpenGLFramebufferObjectFormat format; - format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); - format.setSamples(16); - QOpenGLFramebufferObject *renderFbo = new QOpenGLFramebufferObject(size, format); - renderFbo->bind(); - m_context->functions()->glViewport(0, 0, size.width(), size.height()); - - if (nullptr != m_mesh) { - int xRot = m_xRot; - int yRot = m_yRot; - int zRot = m_zRot; - QMatrix4x4 proj; - QMatrix4x4 camera; - QMatrix4x4 world; - - ModelShaderProgram *program = new ModelShaderProgram; - ModelMeshBinder meshBinder; - meshBinder.initialize(); - meshBinder.hideWireframes(); - - program->setUniformValue(program->lightPosLoc(), QVector3D(0, 0, 70)); - - m_context->functions()->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - m_context->functions()->glEnable(GL_DEPTH_TEST); - m_context->functions()->glEnable(GL_CULL_FACE); - m_context->functions()->glEnable(GL_LINE_SMOOTH); - - camera.setToIdentity(); - camera.translate(0, 0, -4.5); - - world.setToIdentity(); - world.rotate(xRot / 16.0f, 1, 0, 0); - world.rotate(yRot / 16.0f, 0, 1, 0); - world.rotate(zRot / 16.0f, 0, 0, 1); - - proj.setToIdentity(); - proj.perspective(45.0f, GLfloat(size.width()) / size.height(), 0.01f, 100.0f); - - program->bind(); - program->setUniformValue(program->projMatrixLoc(), proj); - program->setUniformValue(program->mvMatrixLoc(), camera * world); - QMatrix3x3 normalMatrix = world.normalMatrix(); - program->setUniformValue(program->normalMatrixLoc(), normalMatrix); - program->setUniformValue(program->textureEnabledLoc(), 0); - - meshBinder.updateMesh(m_mesh); - meshBinder.paint(program); - - meshBinder.cleanup(); - - program->release(); - delete program; - - m_mesh = nullptr; - } - - m_context->functions()->glFlush(); - - image = renderFbo->toImage(); - - renderFbo->bindDefault(); - delete renderFbo; - - m_context->doneCurrent(); - - return image; -} - -void ModelOfflineRender::setXRotation(int angle) -{ - m_xRot = angle; -} - -void ModelOfflineRender::setYRotation(int angle) -{ - m_yRot = angle; -} - -void ModelOfflineRender::setZRotation(int angle) -{ - m_zRot = angle; -} - diff --git a/src/modelofflinerender.h b/src/modelofflinerender.h deleted file mode 100644 index b1fc64bf..00000000 --- a/src/modelofflinerender.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef MODEL_OFFLINE_RENDER_H -#define MODEL_OFFLINE_RENDER_H -#include -#include -#include -#include -#include -#include -#include -#include "modelshaderprogram.h" -#include "modelmeshbinder.h" -#include "meshloader.h" - -class ModelOfflineRender : QOffscreenSurface -{ -public: - ModelOfflineRender(QOpenGLWidget *sharedContextWidget = nullptr, QScreen *targetScreen = Q_NULLPTR); - ~ModelOfflineRender(); - void setRenderThread(QThread *thread); - void updateMesh(MeshLoader *mesh); - QImage toImage(const QSize &size); - void setXRotation(int angle); - void setYRotation(int angle); - void setZRotation(int angle); -private: - QOpenGLContext *m_context; - MeshLoader *m_mesh; - int m_xRot; - int m_yRot; - int m_zRot; -}; - -#endif diff --git a/src/modelwidget.cpp b/src/modelwidget.cpp index 4484577e..a6e40621 100644 --- a/src/modelwidget.cpp +++ b/src/modelwidget.cpp @@ -19,7 +19,9 @@ ModelWidget::ModelWidget(QWidget *parent) : m_zRot(0), m_program(nullptr), m_moveStarted(false), - m_graphicsFunctions(NULL) + m_graphicsFunctions(NULL), + m_moveEnabled(true), + m_zoomEnabled(true) { // --transparent causes the clear color to be transparent. Therefore, on systems that // support it, the widget will become transparent apart from the logo. @@ -192,7 +194,7 @@ void ModelWidget::mousePressEvent(QMouseEvent *event) shouldStartMove = true; } } else if (event->button() == Qt::MidButton) { - shouldStartMove = true; + shouldStartMove = m_moveEnabled; } if (shouldStartMove) { m_lastPos = event->pos(); @@ -270,6 +272,8 @@ void ModelWidget::wheelEvent(QWheelEvent *event) return; if (m_moveStarted) return; + if (!m_zoomEnabled) + return; qreal delta = event->delta() / 10; if (QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier)) { if (delta > 0) @@ -299,3 +303,12 @@ void ModelWidget::exportMeshAsObjPlusMaterials(const QString &filename) m_meshBinder.exportMeshAsObjPlusMaterials(filename); } +void ModelWidget::enableMove(bool enabled) +{ + m_moveEnabled = enabled; +} + +void ModelWidget::enableZoom(bool enabled) +{ + m_zoomEnabled = enabled; +} diff --git a/src/modelwidget.h b/src/modelwidget.h index 6f849aa2..5daf126f 100644 --- a/src/modelwidget.h +++ b/src/modelwidget.h @@ -16,19 +16,24 @@ class SkeletonGraphicsFunctions; class ModelWidget : public QOpenGLWidget, protected QOpenGLFunctions { Q_OBJECT - public: ModelWidget(QWidget *parent = 0); ~ModelWidget(); - - static bool isTransparent() { return m_transparent; } - static void setTransparent(bool t) { m_transparent = t; } - + static bool isTransparent() + { + return m_transparent; + } + static void setTransparent(bool t) + { + m_transparent = t; + } void updateMesh(MeshLoader *mesh); void exportMeshAsObj(const QString &filename); void exportMeshAsObjPlusMaterials(const QString &filename); void setGraphicsFunctions(SkeletonGraphicsFunctions *graphicsFunctions); void toggleWireframe(); + void enableMove(bool enabled); + void enableZoom(bool enabled); public slots: void setXRotation(int angle); void setYRotation(int angle); @@ -39,7 +44,6 @@ signals: void xRotationChanged(int angle); void yRotationChanged(int angle); void zRotationChanged(int angle); - protected: void initializeGL() override; void paintGL() override; @@ -61,6 +65,8 @@ private: ModelShaderProgram *m_program; bool m_moveStarted; SkeletonGraphicsFunctions *m_graphicsFunctions; + bool m_moveEnabled; + bool m_zoomEnabled; private: QPoint m_lastPos; ModelMeshBinder m_meshBinder; diff --git a/src/skeletondocument.cpp b/src/skeletondocument.cpp index 9175d84f..9e4f67bb 100644 --- a/src/skeletondocument.cpp +++ b/src/skeletondocument.cpp @@ -137,7 +137,9 @@ void SkeletonDocument::removeEdge(QUuid edgeId) std::vector> groups; splitPartByEdge(&groups, edgeId); for (auto groupIt = groups.begin(); groupIt != groups.end(); groupIt++) { - SkeletonPart part; + const auto newUuid = QUuid::createUuid(); + SkeletonPart &part = partMap[newUuid]; + part.id = newUuid; part.copyAttributes(*oldPart); part.name = nextPartName; for (auto nodeIdIt = (*groupIt).begin(); nodeIdIt != (*groupIt).end(); nodeIdIt++) { @@ -157,7 +159,6 @@ void SkeletonDocument::removeEdge(QUuid edgeId) edgeIt->second.partId = part.id; } } - partMap[part.id] = part; addPartToComponent(part.id, findComponentParentId(part.componentId)); emit partAdded(part.id); } @@ -196,7 +197,9 @@ void SkeletonDocument::removeNode(QUuid nodeId) std::vector> groups; splitPartByNode(&groups, nodeId); for (auto groupIt = groups.begin(); groupIt != groups.end(); groupIt++) { - SkeletonPart part; + const auto newUuid = QUuid::createUuid(); + SkeletonPart &part = partMap[newUuid]; + part.id = newUuid; part.copyAttributes(*oldPart); part.name = nextPartName; for (auto nodeIdIt = (*groupIt).begin(); nodeIdIt != (*groupIt).end(); nodeIdIt++) { @@ -216,7 +219,6 @@ void SkeletonDocument::removeNode(QUuid nodeId) edgeIt->second.partId = part.id; } } - partMap[part.id] = part; addPartToComponent(part.id, findComponentParentId(part.componentId)); emit partAdded(part.id); } @@ -254,8 +256,9 @@ QUuid SkeletonDocument::createNode(float x, float y, float z, float radius, QUui const SkeletonNode *fromNode = nullptr; bool newPartAdded = false; if (fromNodeId.isNull()) { - SkeletonPart part; - partMap[part.id] = part; + const auto newUuid = QUuid::createUuid(); + SkeletonPart &part = partMap[newUuid]; + part.id = newUuid; partId = part.id; emit partAdded(partId); newPartAdded = true; @@ -828,7 +831,9 @@ void SkeletonDocument::addFromSnapshot(const SkeletonSnapshot &snapshot, bool fr std::map oldNewIdMap; for (const auto &partKv: snapshot.parts) { - SkeletonPart part; + const auto newUuid = QUuid::createUuid(); + SkeletonPart &part = partMap[newUuid]; + part.id = newUuid; oldNewIdMap[QUuid(partKv.first)] = part.id; part.name = valueOfKeyInMapOrEmpty(partKv.second, "name"); part.visible = isTrueValueString(valueOfKeyInMapOrEmpty(partKv.second, "visible")); @@ -852,7 +857,6 @@ void SkeletonDocument::addFromSnapshot(const SkeletonSnapshot &snapshot, bool fr const auto &deformWidthIt = partKv.second.find("deformWidth"); if (deformWidthIt != partKv.second.end()) part.setDeformWidth(deformWidthIt->second.toFloat()); - partMap[part.id] = part; newAddedPartIds.insert(part.id); } for (const auto &nodeKv: snapshot.nodes) { @@ -1037,18 +1041,12 @@ void SkeletonDocument::meshReady() MeshLoader *resultMesh = m_meshGenerator->takeResultMesh(); MeshResultContext *meshResultContext = m_meshGenerator->takeMeshResultContext(); - QImage *resultPreview = m_meshGenerator->takePreview(); - if (resultPreview) { - preview = *resultPreview; - delete resultPreview; - } - - for (auto &part: partMap) { - QImage *resultPartPreview = m_meshGenerator->takePartPreview(part.first.toString()); - if (resultPartPreview) { - part.second.preview = *resultPartPreview; - emit partPreviewChanged(part.first); - delete resultPartPreview; + for (auto &partId: m_meshGenerator->generatedPreviewPartIds()) { + auto part = partMap.find(partId); + if (part != partMap.end()) { + MeshLoader *resultPartPreviewMesh = m_meshGenerator->takePartPreviewMesh(partId); + part->second.updatePreviewMesh(resultPartPreviewMesh); + emit partPreviewChanged(partId); } } @@ -1134,7 +1132,7 @@ void SkeletonDocument::generateMesh() m_meshGenerator->setSharedContextWidget(m_sharedContextWidget); m_meshGenerator->moveToThread(thread); for (auto &part: partMap) { - m_meshGenerator->addPartPreviewRequirement(part.first.toString()); + m_meshGenerator->addPartPreviewRequirement(part.first); } connect(thread, &QThread::started, m_meshGenerator, &MeshGenerator::process); connect(m_meshGenerator, &MeshGenerator::finished, this, &SkeletonDocument::meshReady); diff --git a/src/skeletondocument.h b/src/skeletondocument.h index 3b75d26f..12d48d12 100644 --- a/src/skeletondocument.h +++ b/src/skeletondocument.h @@ -74,6 +74,10 @@ public: class SkeletonPart { public: + ~SkeletonPart() + { + delete m_previewMesh; + } QUuid id; QString name; bool visible; @@ -87,7 +91,6 @@ public: bool rounded; QColor color; bool hasColor; - QImage preview; QUuid componentId; std::vector nodeIds; bool dirty; @@ -157,6 +160,20 @@ public: wrapped = other.wrapped; componentId = other.componentId; } + void updatePreviewMesh(MeshLoader *previewMesh) + { + delete m_previewMesh; + m_previewMesh = previewMesh; + } + MeshLoader *takePreviewMesh() const + { + if (nullptr == m_previewMesh) + return nullptr; + return new MeshLoader(*m_previewMesh); + } +private: + Q_DISABLE_COPY(SkeletonPart); + MeshLoader *m_previewMesh = nullptr; }; enum class SkeletonProfile @@ -564,8 +581,8 @@ private: // need initialize MeshLoader *m_resultRigWeightMesh; std::vector *m_resultRigBones; std::map *m_resultRigWeights; - MeshResultContext *m_riggedResultContext; bool m_isRigObsolete; + MeshResultContext *m_riggedResultContext; private: static unsigned long m_maxSnapshot; std::deque m_undoItems; diff --git a/src/skeletondocumentwindow.cpp b/src/skeletondocumentwindow.cpp index 0ace9b5a..01a0291c 100644 --- a/src/skeletondocumentwindow.cpp +++ b/src/skeletondocumentwindow.cpp @@ -29,7 +29,6 @@ #include "graphicscontainerwidget.h" #include "skeletonparttreewidget.h" #include "rigwidget.h" -#include "modelofflinerender.h" #include "markiconcreator.h" #include "tetrapodposeeditwidget.h" @@ -1055,18 +1054,6 @@ void SkeletonDocumentWindow::exportObjPlusMaterialsResult() QApplication::restoreOverrideCursor(); } -void SkeletonDocumentWindow::exportRenderedResult() -{ - QString filename = QFileDialog::getSaveFileName(this, QString(), QString(), - tr("Image (*.png)")); - if (filename.isEmpty()) { - return; - } - QApplication::setOverrideCursor(Qt::WaitCursor); - exportRenderedAsImage(filename); - QApplication::restoreOverrideCursor(); -} - void SkeletonDocumentWindow::showExportPreview() { if (nullptr == m_exportPreviewWidget) { @@ -1146,14 +1133,3 @@ void SkeletonDocumentWindow::updateRadiusLockButtonState() else m_radiusLockButton->setStyleSheet("QPushButton {color: " + Theme::white.name() + "}"); } - -void SkeletonDocumentWindow::exportRenderedAsImage(const QString &filename) -{ - ModelOfflineRender offlineRender(m_modelRenderWidget); - offlineRender.setXRotation(m_modelRenderWidget->xRot()); - offlineRender.setYRotation(m_modelRenderWidget->yRot()); - offlineRender.setZRotation(m_modelRenderWidget->zRot()); - offlineRender.updateMesh(m_document->takeResultMesh()); - QImage renderedImage = offlineRender.toImage(QSize(1024, 1024)); - renderedImage.save(filename); -} diff --git a/src/skeletondocumentwindow.h b/src/skeletondocumentwindow.h index ebfa8936..d51f5ae5 100644 --- a/src/skeletondocumentwindow.h +++ b/src/skeletondocumentwindow.h @@ -39,7 +39,6 @@ public slots: void exportObjResult(); void exportObjPlusMaterialsResult(); void exportGltfResult(); - void exportRenderedResult(); void showExportPreview(); void newWindow(); void newDocument(); @@ -60,7 +59,6 @@ private: void initLockButton(QPushButton *button); void setCurrentFilename(const QString &filename); void updateTitle(); - void exportRenderedAsImage(const QString &filename); private: SkeletonDocument *m_document; bool m_firstShow; diff --git a/src/skeletonparttreewidget.cpp b/src/skeletonparttreewidget.cpp index 031365b0..e8d14dbb 100644 --- a/src/skeletonparttreewidget.cpp +++ b/src/skeletonparttreewidget.cpp @@ -62,6 +62,42 @@ SkeletonPartTreeWidget::SkeletonPartTreeWidget(const SkeletonDocument *document, connect(this, &QTreeWidget::itemCollapsed, this, &SkeletonPartTreeWidget::groupCollapsed); } +bool SkeletonPartTreeWidget::mouseMove(QMouseEvent *event) +{ + return false; +} + +bool SkeletonPartTreeWidget::wheel(QWheelEvent *event) +{ + return false; +} + +bool SkeletonPartTreeWidget::mouseRelease(QMouseEvent *event) +{ + return false; +} + +bool SkeletonPartTreeWidget::mousePress(QMouseEvent *event) +{ + if (event->button() == Qt::RightButton) { + showContextMenu(mapFromGlobal(event->globalPos())); + return true; + } + return false; +} + +bool SkeletonPartTreeWidget::mouseDoubleClick(QMouseEvent *event) +{ + return false; +} + +bool SkeletonPartTreeWidget::keyPress(QKeyEvent *event) +{ + if (m_graphicsFunctions) + return m_graphicsFunctions->keyPress(event); + return false; +} + void SkeletonPartTreeWidget::selectComponent(QUuid componentId, bool multiple) { if (multiple) { @@ -194,6 +230,7 @@ void SkeletonPartTreeWidget::showContextMenu(const QPoint &pos) { const SkeletonComponent *component = nullptr; const SkeletonPart *part = nullptr; + SkeletonPartWidget *partWidget = nullptr; std::set unorderedComponentIds = m_selectedComponentIds; if (!m_currentSelectedComponentId.isNull()) @@ -229,22 +266,38 @@ void SkeletonPartTreeWidget::showContextMenu(const QPoint &pos) } } - QWidgetAction forDisplayPartImage(this); - QLabel *previewLabel = new QLabel; - previewLabel->setFixedHeight(Theme::previewImageSize); - previewLabel->setStyleSheet("QLabel {color: " + Theme::red.name() + "}"); - if (nullptr != part) { - previewLabel->setPixmap(QPixmap::fromImage(part->preview)); - } else if (nullptr != component) { - previewLabel->setText(component->name); - } else if (!componentIds.empty()) { - previewLabel->setText(tr("(%1 items)").arg(QString::number(componentIds.size()))); - } QHBoxLayout *layout = new QHBoxLayout; + QWidgetAction forDisplayPartImage(this); layout->setAlignment(Qt::AlignCenter); - layout->addWidget(previewLabel); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); + if (nullptr != part) { + auto findItem = m_partItemMap.find(part->id); + if (findItem != m_partItemMap.end()) { + partWidget = (SkeletonPartWidget *)itemWidget(findItem->second, 0); + } + } + if (nullptr != part && nullptr != partWidget) { + ModelWidget *previewWidget = new ModelWidget; + previewWidget->enableMove(false); + previewWidget->enableZoom(false); + previewWidget->setFixedSize(Theme::previewImageSize, Theme::previewImageSize); + previewWidget->setXRotation(partWidget->previewWidget()->xRot()); + previewWidget->setYRotation(partWidget->previewWidget()->yRot()); + previewWidget->setZRotation(partWidget->previewWidget()->zRot()); + previewWidget->updateMesh(part->takePreviewMesh()); + layout->addWidget(previewWidget); + } else { + QLabel *previewLabel = new QLabel; + previewLabel->setFixedHeight(Theme::previewImageSize); + previewLabel->setStyleSheet("QLabel {color: " + Theme::red.name() + "}"); + if (nullptr != component) { + previewLabel->setText(component->name); + } else if (!componentIds.empty()) { + previewLabel->setText(tr("(%1 items)").arg(QString::number(componentIds.size()))); + } + layout->addWidget(previewLabel); + } QWidget *widget = new QWidget; widget->setLayout(layout); forDisplayPartImage.setDefaultWidget(widget); @@ -650,6 +703,7 @@ void SkeletonPartTreeWidget::addComponentChildrenToItem(QUuid componentId, QTree item->setFlags(item->flags() & ~(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable)); QUuid partId = component->linkToPartId; SkeletonPartWidget *widget = new SkeletonPartWidget(m_document, partId); + widget->previewWidget()->setGraphicsFunctions(this); item->setSizeHint(0, SkeletonPartWidget::preferredSize()); setItemWidget(item, 0, widget); widget->reload(); diff --git a/src/skeletonparttreewidget.h b/src/skeletonparttreewidget.h index 5a3a5928..1fb8c6e0 100644 --- a/src/skeletonparttreewidget.h +++ b/src/skeletonparttreewidget.h @@ -4,10 +4,9 @@ #include #include #include "skeletondocument.h" +#include "skeletongraphicswidget.h" -class SkeletonGraphicsFunctions; - -class SkeletonPartTreeWidget : public QTreeWidget +class SkeletonPartTreeWidget : public QTreeWidget, public SkeletonGraphicsFunctions { Q_OBJECT signals: @@ -74,6 +73,12 @@ protected: virtual QSize sizeHint() const; virtual void mousePressEvent(QMouseEvent *event); virtual void keyPressEvent(QKeyEvent *event); + bool mouseMove(QMouseEvent *event); + bool wheel(QWheelEvent *event); + bool mouseRelease(QMouseEvent *event); + bool mousePress(QMouseEvent *event); + bool mouseDoubleClick(QMouseEvent *event); + bool keyPress(QKeyEvent *event); private: void addComponentChildrenToItem(QUuid componentId, QTreeWidgetItem *parentItem); void deleteItemChildren(QTreeWidgetItem *item); diff --git a/src/skeletonpartwidget.cpp b/src/skeletonpartwidget.cpp index 44572d9d..24013026 100644 --- a/src/skeletonpartwidget.cpp +++ b/src/skeletonpartwidget.cpp @@ -52,8 +52,10 @@ SkeletonPartWidget::SkeletonPartWidget(const SkeletonDocument *document, QUuid p m_wrapButton->setSizePolicy(retainSizePolicy); initButton(m_wrapButton); - m_previewLabel = new QLabel; - m_previewLabel->setFixedSize(Theme::previewImageSize, Theme::previewImageSize); + m_previewWidget = new ModelWidget; + m_previewWidget->enableMove(false); + m_previewWidget->enableZoom(false); + m_previewWidget->setFixedSize(Theme::previewImageSize, Theme::previewImageSize); QWidget *hrLightWidget = new QWidget; hrLightWidget->setFixedHeight(1); @@ -89,7 +91,7 @@ SkeletonPartWidget::SkeletonPartWidget(const SkeletonDocument *document, QUuid p previewAndToolsLayout->setSpacing(0); previewAndToolsLayout->setContentsMargins(0, 0, 0, 0); previewAndToolsLayout->addWidget(m_visibleButton); - previewAndToolsLayout->addWidget(m_previewLabel); + previewAndToolsLayout->addWidget(m_previewWidget); previewAndToolsLayout->addLayout(toolsLayout); previewAndToolsLayout->setStretch(0, 0); previewAndToolsLayout->setStretch(1, 0); @@ -229,6 +231,11 @@ SkeletonPartWidget::SkeletonPartWidget(const SkeletonDocument *document, QUuid p updateAllButtons(); } +ModelWidget *SkeletonPartWidget::previewWidget() +{ + return m_previewWidget; +} + QSize SkeletonPartWidget::preferredSize() { return QSize(Theme::miniIconSize + Theme::previewImageSize + Theme::miniIconSize * 4 + 5 + 2, Theme::previewImageSize + 6); @@ -408,7 +415,9 @@ void SkeletonPartWidget::updatePreview() qDebug() << "Part not found:" << m_partId; return; } - m_previewLabel->setPixmap(QPixmap::fromImage(part->preview)); + //m_previewLabel->setPixmap(QPixmap::fromImage(part->preview)); + MeshLoader *previewMesh = part->takePreviewMesh(); + m_previewWidget->updateMesh(previewMesh); } void SkeletonPartWidget::updateLockButton() diff --git a/src/skeletonpartwidget.h b/src/skeletonpartwidget.h index af2b9387..d1bee77e 100644 --- a/src/skeletonpartwidget.h +++ b/src/skeletonpartwidget.h @@ -4,6 +4,7 @@ #include #include #include "skeletondocument.h" +#include "modelwidget.h" class SkeletonPartWidget : public QWidget { @@ -44,6 +45,7 @@ public: void updateWrapButton(); void updateCheckedState(bool checked); static QSize preferredSize(); + ModelWidget *previewWidget(); protected: void mouseDoubleClickEvent(QMouseEvent *event); public slots: @@ -53,7 +55,7 @@ private: // need initialize const SkeletonDocument *m_document; QUuid m_partId; private: - QLabel *m_previewLabel; + ModelWidget *m_previewWidget; QPushButton *m_visibleButton; QPushButton *m_lockButton; QPushButton *m_subdivButton; @@ -64,7 +66,6 @@ private: QPushButton *m_roundButton; QPushButton *m_colorButton; QPushButton *m_wrapButton; - QLabel *m_nameLabel; QWidget *m_backgroundWidget; private: void initToolButton(QPushButton *button);