diff --git a/src/document.cpp b/src/document.cpp index a467297d..7d458d88 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -16,6 +16,7 @@ #include "skeletonside.h" #include "scriptrunner.h" #include "mousepicker.h" +#include "imageforever.h" unsigned long Document::m_maxSnapshot = 1000; @@ -70,7 +71,7 @@ Document::Document() : m_isMouseTargetResultObsolete(false), m_paintMode(PaintMode::None), m_mousePickRadius(0.2), - m_saveNextSnapshot(false) + m_saveNextPaintSnapshot(false) { connect(&Preferences::instance(), &Preferences::partColorChanged, this, &Document::applyPreferencePartColorChange); connect(&Preferences::instance(), &Preferences::flatShadingChanged, this, &Document::applyPreferenceFlatShadingChange); @@ -1998,15 +1999,16 @@ void Document::mouseTargetReady() if (changedPartIds.find(partId) == changedPartIds.end()) continue; const auto &imageId = it.second; + m_intermediatePaintImageIds.insert(imageId); setPartDeformMapImageId(partId, imageId); } delete m_mousePicker; m_mousePicker = nullptr; - if (!m_isMouseTargetResultObsolete && m_saveNextSnapshot) { - m_saveNextSnapshot = false; - saveSnapshot(); + if (!m_isMouseTargetResultObsolete && m_saveNextPaintSnapshot) { + m_saveNextPaintSnapshot = false; + stopPaint(); } emit mouseTargetChanged(); @@ -2613,8 +2615,8 @@ void Document::setPartDeformMapImageId(QUuid partId, QUuid imageId) qDebug() << "Part not found:" << partId; return; } - //if (part->second.deformMapImageId == imageId) - // return; + if (part->second.deformMapImageId == imageId) + return; part->second.deformMapImageId = imageId; part->second.dirty = true; emit partDeformMapImageIdChanged(partId); @@ -3669,13 +3671,25 @@ const QString &Document::scriptConsoleLog() const return m_scriptConsoleLog; } -void Document::saveNextSnapshot(void) +void Document::startPaint(void) +{ +} + +void Document::stopPaint(void) { if (m_mousePicker || m_isMouseTargetResultObsolete) { - m_saveNextSnapshot = true; + m_saveNextPaintSnapshot = true; return; } saveSnapshot(); + for (const auto &it: partMap) { + m_intermediatePaintImageIds.erase(it.second.deformMapImageId); + } + for (const auto &it: m_intermediatePaintImageIds) { + //qDebug() << "Remove intermediate image:" << it; + ImageForever::remove(it); + } + m_intermediatePaintImageIds.clear(); } void Document::setMousePickMaskNodeIds(const std::set &nodeIds) diff --git a/src/document.h b/src/document.h index 3149cb89..0b1eabc8 100644 --- a/src/document.h +++ b/src/document.h @@ -678,7 +678,8 @@ public slots: void scriptResultReady(); void updateVariable(const QString &name, const std::map &value); void updateVariableValue(const QString &name, const QString &value); - void saveNextSnapshot(void); + void startPaint(void); + void stopPaint(void); void setMousePickMaskNodeIds(const std::set &nodeIds); private: void splitPartByNode(std::vector> *groups, QUuid nodeId); @@ -738,7 +739,7 @@ private: // need initialize bool m_isMouseTargetResultObsolete; PaintMode m_paintMode; float m_mousePickRadius; - bool m_saveNextSnapshot; + bool m_saveNextPaintSnapshot; private: static unsigned long m_maxSnapshot; std::deque m_undoItems; @@ -752,6 +753,7 @@ private: QString m_scriptConsoleLog; QString m_script; std::set m_mousePickMaskNodeIds; + std::set m_intermediatePaintImageIds; }; #endif diff --git a/src/documentwindow.cpp b/src/documentwindow.cpp index 982b52b9..957234d0 100644 --- a/src/documentwindow.cpp +++ b/src/documentwindow.cpp @@ -293,6 +293,7 @@ DocumentWindow::DocumentWindow() : m_document->pickMouseTarget(nearPosition, farPosition); }); connect(m_modelRenderWidget, &ModelWidget::mousePressed, m_document, [=]() { + m_document->startPaint(); if (QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier)) m_document->setPaintMode(PaintMode::Push); else @@ -300,7 +301,7 @@ DocumentWindow::DocumentWindow() : }); connect(m_modelRenderWidget, &ModelWidget::mouseReleased, m_document, [=]() { m_document->setPaintMode(PaintMode::None); - m_document->saveNextSnapshot(); + m_document->stopPaint(); }); connect(m_modelRenderWidget, &ModelWidget::addMouseRadius, m_document, [=](float radius) { m_document->setMousePickRadius(m_document->mousePickRadius() + radius); diff --git a/src/imageforever.cpp b/src/imageforever.cpp index e397104e..57e67c52 100644 --- a/src/imageforever.cpp +++ b/src/imageforever.cpp @@ -11,7 +11,6 @@ struct ImageForeverItem QByteArray *imageByteArray; }; static std::map g_foreverMap; -static std::map g_foreverCacheKeyToIdMap; static QMutex g_mapMutex; const QImage *ImageForever::get(const QUuid &id) @@ -23,6 +22,15 @@ const QImage *ImageForever::get(const QUuid &id) return findResult->second.image; } +void ImageForever::copy(const QUuid &id, QImage &image) +{ + QMutexLocker locker(&g_mapMutex); + auto findResult = g_foreverMap.find(id); + if (findResult == g_foreverMap.end()) + return; + image = *findResult->second.image; +} + const QByteArray *ImageForever::getPngByteArray(const QUuid &id) { QMutexLocker locker(&g_mapMutex); @@ -37,11 +45,6 @@ QUuid ImageForever::add(const QImage *image, QUuid toId) QMutexLocker locker(&g_mapMutex); if (nullptr == image) return QUuid(); - auto key = image->cacheKey(); - auto findResult = g_foreverCacheKeyToIdMap.find(key); - if (findResult != g_foreverCacheKeyToIdMap.end()) { - return findResult->second; - } QUuid newId = toId.isNull() ? QUuid::createUuid() : toId; if (g_foreverMap.find(newId) != g_foreverMap.end()) return newId; @@ -51,6 +54,16 @@ QUuid ImageForever::add(const QImage *image, QUuid toId) pngBuffer.open(QIODevice::WriteOnly); newImage->save(&pngBuffer, "PNG"); g_foreverMap[newId] = {newImage, newId, imageByteArray}; - g_foreverCacheKeyToIdMap[newImage->cacheKey()] = newId; return newId; } + +void ImageForever::remove(const QUuid &id) +{ + QMutexLocker locker(&g_mapMutex); + auto findImage = g_foreverMap.find(id); + if (findImage == g_foreverMap.end()) + return; + delete findImage->second.image; + delete findImage->second.imageByteArray; + g_foreverMap.erase(id); +} diff --git a/src/imageforever.h b/src/imageforever.h index e843f650..709e55b7 100644 --- a/src/imageforever.h +++ b/src/imageforever.h @@ -8,8 +8,10 @@ class ImageForever { public: static const QImage *get(const QUuid &id); + static void copy(const QUuid &id, QImage &image); static const QByteArray *getPngByteArray(const QUuid &id); static QUuid add(const QImage *image, QUuid toId=QUuid()); + static void remove(const QUuid &id); }; #endif diff --git a/src/meshgenerator.cpp b/src/meshgenerator.cpp index d4d199ea..81638fa2 100644 --- a/src/meshgenerator.cpp +++ b/src/meshgenerator.cpp @@ -362,10 +362,13 @@ nodemesh::Combiner::Mesh *MeshGenerator::combinePartMesh(const QString &partIdSt deformWidth = widthString.toFloat(); } + QImage deformImageStruct; const QImage *deformImage = nullptr; QString deformMapImageIdString = valueOfKeyInMapOrEmpty(part, "deformMapImageId"); if (!deformMapImageIdString.isEmpty()) { - deformImage = ImageForever::get(QUuid(deformMapImageIdString)); + ImageForever::copy(QUuid(deformMapImageIdString), deformImageStruct); + if (!deformImageStruct.isNull()) + deformImage = &deformImageStruct; if (nullptr == deformImage) { qDebug() << "Deform image id not found:" << deformMapImageIdString; } diff --git a/thirdparty/nodemesh/nodemesh/builder.cpp b/thirdparty/nodemesh/nodemesh/builder.cpp index a0abc936..c54a8958 100644 --- a/thirdparty/nodemesh/nodemesh/builder.cpp +++ b/thirdparty/nodemesh/nodemesh/builder.cpp @@ -1038,6 +1038,8 @@ void Builder::applyDeform() float degrees = degreeBetweenIn360(node.baseNormal, ray.normalized(), node.traverseDirection); int x = node.reversedTraverseOrder * m_deformMapImage->width() / m_nodes.size(); int y = degrees * m_deformMapImage->height() / 360.0; + if (y >= m_deformMapImage->height()) + y = m_deformMapImage->height() - 1; float gray = (float)(qGray(m_deformMapImage->pixelColor(x, y).rgb()) - 127) / 127; position += m_deformMapScale * gray * ray; ray = position - node.position;