Implement component preview image decorator
parent
bc82539cf2
commit
24e675911e
|
@ -104,6 +104,8 @@ HEADERS += sources/component_list_model.h
|
|||
SOURCES += sources/component_list_model.cc
|
||||
HEADERS += sources/component_preview_grid_widget.h
|
||||
SOURCES += sources/component_preview_grid_widget.cc
|
||||
HEADERS += sources/component_preview_images_decorator.h
|
||||
SOURCES += sources/component_preview_images_decorator.cc
|
||||
HEADERS += sources/cut_face_preview.h
|
||||
SOURCES += sources/cut_face_preview.cc
|
||||
HEADERS += sources/dds_file.h
|
||||
|
|
|
@ -7,7 +7,7 @@ ComponentListModel::ComponentListModel(const Document *document, QObject *parent
|
|||
QAbstractListModel(parent),
|
||||
m_document(document)
|
||||
{
|
||||
connect(m_document, &Document::componentPreviewImageChanged, [this](const dust3d::Uuid &componentId) {
|
||||
connect(m_document, &Document::componentPreviewPixmapChanged, [this](const dust3d::Uuid &componentId) {
|
||||
// FIXME: dont refresh the whole layout
|
||||
emit this->layoutChanged();
|
||||
});
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
#include <dust3d/base/debug.h>
|
||||
#include <QPainter>
|
||||
#include "theme.h"
|
||||
#include "component_preview_images_decorator.h"
|
||||
|
||||
ComponentPreviewImagesDecorator::ComponentPreviewImagesDecorator(std::unique_ptr<std::vector<PreviewInput>> previewInputs)
|
||||
{
|
||||
m_previewInputs = std::move(previewInputs);
|
||||
}
|
||||
|
||||
std::unique_ptr<std::unordered_map<dust3d::Uuid, std::unique_ptr<QImage>>> ComponentPreviewImagesDecorator::takeResultImages()
|
||||
{
|
||||
return std::move(m_resultImages);
|
||||
}
|
||||
|
||||
void ComponentPreviewImagesDecorator::decorate()
|
||||
{
|
||||
if (nullptr == m_previewInputs)
|
||||
return;
|
||||
|
||||
m_resultImages = std::make_unique<std::unordered_map<dust3d::Uuid, std::unique_ptr<QImage>>>();
|
||||
|
||||
for (auto &it: *m_previewInputs) {
|
||||
if (it.isDirectory) {
|
||||
QPainter painter(it.image.get());
|
||||
painter.setRenderHints(QPainter::Antialiasing);
|
||||
QPolygonF polygon;
|
||||
polygon << QPointF(it.image->width() / 4, 0.0) << QPointF(it.image->width() / 2.5, 0.0);
|
||||
polygon << QPointF(0.0, it.image->height() / 2.5) << QPointF(0.0, it.image->height() / 4);
|
||||
QPainterPath painterPath;
|
||||
painterPath.addPolygon(polygon);
|
||||
painter.setBrush(Theme::white);
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.drawPath(painterPath);
|
||||
}
|
||||
m_resultImages->emplace(it.id, std::move(it.image));
|
||||
}
|
||||
}
|
||||
|
||||
void ComponentPreviewImagesDecorator::process()
|
||||
{
|
||||
decorate();
|
||||
emit finished();
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef DUST3D_APPLICATION_COMPONENT_PREVIEW_IMAGES_DECORATOR_H_
|
||||
#define DUST3D_APPLICATION_COMPONENT_PREVIEW_IMAGES_DECORATOR_H_
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <dust3d/base/uuid.h>
|
||||
#include <QImage>
|
||||
|
||||
class ComponentPreviewImagesDecorator: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
struct PreviewInput
|
||||
{
|
||||
dust3d::Uuid id;
|
||||
std::unique_ptr<QImage> image;
|
||||
bool isDirectory = false;
|
||||
};
|
||||
|
||||
ComponentPreviewImagesDecorator(std::unique_ptr<std::vector<PreviewInput>> previewInputs);
|
||||
std::unique_ptr<std::unordered_map<dust3d::Uuid, std::unique_ptr<QImage>>> takeResultImages();
|
||||
signals:
|
||||
void finished();
|
||||
public slots:
|
||||
void process();
|
||||
private:
|
||||
std::unique_ptr<std::vector<PreviewInput>> m_previewInputs;
|
||||
std::unique_ptr<std::unordered_map<dust3d::Uuid, std::unique_ptr<QImage>>> m_resultImages;
|
||||
void decorate();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -22,6 +22,7 @@
|
|||
#include <QFormLayout>
|
||||
#include <QTextBrowser>
|
||||
#include <QMimeData>
|
||||
#include <QPixmap>
|
||||
#include <dust3d/base/ds3_file.h>
|
||||
#include <dust3d/base/snapshot.h>
|
||||
#include <dust3d/base/snapshot_xml.h>
|
||||
|
@ -1197,9 +1198,10 @@ void DocumentWindow::generateComponentPreviewImages()
|
|||
QThread *thread = new QThread;
|
||||
|
||||
m_componentPreviewImagesGenerator = new MeshPreviewImagesGenerator(new ModelOffscreenRender(m_modelRenderWidget->format()));
|
||||
for (const auto &component: m_document->componentMap) {
|
||||
for (auto &component: m_document->componentMap) {
|
||||
if (!component.second.isPreviewMeshObsolete)
|
||||
continue;
|
||||
component.second.isPreviewMeshObsolete = false;
|
||||
m_componentPreviewImagesGenerator->addInput(component.first, std::unique_ptr<ModelMesh>(component.second.takePreviewMesh()));
|
||||
}
|
||||
m_componentPreviewImagesGenerator->moveToThread(thread);
|
||||
|
@ -1216,10 +1218,12 @@ void DocumentWindow::componentPreviewImagesReady()
|
|||
componentImages.reset(m_componentPreviewImagesGenerator->takeImages());
|
||||
if (nullptr != componentImages) {
|
||||
for (const auto &it: *componentImages) {
|
||||
m_document->setComponentPreviewImage(it.first, it.second);
|
||||
m_document->setComponentPreviewImage(it.first, std::make_unique<QImage>(std::move(it.second)));
|
||||
}
|
||||
}
|
||||
|
||||
decorateComponentPreviewImages();
|
||||
|
||||
delete m_componentPreviewImagesGenerator;
|
||||
m_componentPreviewImagesGenerator = nullptr;
|
||||
|
||||
|
@ -1227,6 +1231,56 @@ void DocumentWindow::componentPreviewImagesReady()
|
|||
generateComponentPreviewImages();
|
||||
}
|
||||
|
||||
void DocumentWindow::decorateComponentPreviewImages()
|
||||
{
|
||||
if (nullptr != m_componentPreviewImagesDecorator) {
|
||||
m_isComponentPreviewImageDecorationsObsolete = true;
|
||||
return;
|
||||
}
|
||||
|
||||
m_isComponentPreviewImageDecorationsObsolete = false;
|
||||
|
||||
QThread *thread = new QThread;
|
||||
|
||||
auto previewInputs = std::make_unique<std::vector<ComponentPreviewImagesDecorator::PreviewInput>>();
|
||||
for (auto &component: m_document->componentMap) {
|
||||
if (!component.second.isPreviewImageDecorationObsolete)
|
||||
continue;
|
||||
component.second.isPreviewImageDecorationObsolete = false;
|
||||
if (nullptr == component.second.previewImage)
|
||||
continue;
|
||||
previewInputs->emplace_back(ComponentPreviewImagesDecorator::PreviewInput {
|
||||
component.first,
|
||||
std::make_unique<QImage>(*component.second.previewImage),
|
||||
!component.second.childrenIds.empty()
|
||||
});
|
||||
}
|
||||
m_componentPreviewImagesDecorator = std::make_unique<ComponentPreviewImagesDecorator>(std::move(previewInputs));
|
||||
m_componentPreviewImagesDecorator->moveToThread(thread);
|
||||
connect(thread, &QThread::started, m_componentPreviewImagesDecorator.get(), &ComponentPreviewImagesDecorator::process);
|
||||
connect(m_componentPreviewImagesDecorator.get(), &ComponentPreviewImagesDecorator::finished, this, &DocumentWindow::componentPreviewImageDecorationsReady);
|
||||
connect(m_componentPreviewImagesDecorator.get(), &ComponentPreviewImagesDecorator::finished, thread, &QThread::quit);
|
||||
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
|
||||
thread->start();
|
||||
}
|
||||
|
||||
void DocumentWindow::componentPreviewImageDecorationsReady()
|
||||
{
|
||||
auto resultImages = m_componentPreviewImagesDecorator->takeResultImages();
|
||||
if (nullptr != resultImages) {
|
||||
for (auto &it: *resultImages) {
|
||||
if (nullptr == it.second)
|
||||
continue;
|
||||
m_document->setComponentPreviewPixmap(it.first, QPixmap::fromImage(*it.second));
|
||||
}
|
||||
}
|
||||
|
||||
m_componentPreviewImagesDecorator.reset();
|
||||
|
||||
if (m_isComponentPreviewImageDecorationsObsolete)
|
||||
decorateComponentPreviewImages();
|
||||
}
|
||||
|
||||
ModelWidget *DocumentWindow::modelWidget()
|
||||
{
|
||||
return m_modelRenderWidget;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef DUST3D_APPLICATION_DOCUMENT_WINDOW_H_
|
||||
#define DUST3D_APPLICATION_DOCUMENT_WINDOW_H_
|
||||
|
||||
#include <memory>
|
||||
#include <QMainWindow>
|
||||
#include <QShowEvent>
|
||||
#include <QPushButton>
|
||||
|
@ -14,6 +15,7 @@
|
|||
#include "model_widget.h"
|
||||
#include "graphics_container_widget.h"
|
||||
#include "mesh_preview_images_generator.h"
|
||||
#include "component_preview_images_decorator.h"
|
||||
|
||||
class Document;
|
||||
class SkeletonGraphicsWidget;
|
||||
|
@ -82,6 +84,8 @@ public slots:
|
|||
void toggleRotation();
|
||||
void generateComponentPreviewImages();
|
||||
void componentPreviewImagesReady();
|
||||
void decorateComponentPreviewImages();
|
||||
void componentPreviewImageDecorationsReady();
|
||||
void updateInprogressIndicator();
|
||||
void openRecentFile();
|
||||
void updateRecentFileActions();
|
||||
|
@ -158,6 +162,9 @@ private:
|
|||
MeshPreviewImagesGenerator *m_componentPreviewImagesGenerator = nullptr;
|
||||
bool m_isComponentPreviewImagesObsolete = false;
|
||||
|
||||
std::unique_ptr<ComponentPreviewImagesDecorator> m_componentPreviewImagesDecorator;
|
||||
bool m_isComponentPreviewImageDecorationsObsolete = false;
|
||||
|
||||
PartManageWidget *m_partManageWidget = nullptr;
|
||||
|
||||
SpinnableToolbarIcon *m_inprogressIndicator = nullptr;
|
||||
|
|
|
@ -1272,14 +1272,22 @@ void SkeletonDocument::setRadiusLockState(bool locked)
|
|||
emit radiusLockStateChanged();
|
||||
}
|
||||
|
||||
void SkeletonDocument::setComponentPreviewImage(const dust3d::Uuid &componentId, const QImage &image)
|
||||
void SkeletonDocument::setComponentPreviewImage(const dust3d::Uuid &componentId, std::unique_ptr<QImage> image)
|
||||
{
|
||||
SkeletonComponent *component = (SkeletonComponent *)findComponent(componentId);
|
||||
if (nullptr == component)
|
||||
return;
|
||||
component->isPreviewMeshObsolete = false;
|
||||
component->previewPixmap = QPixmap::fromImage(image);
|
||||
emit componentPreviewImageChanged(componentId);
|
||||
component->isPreviewImageDecorationObsolete = true;
|
||||
component->previewImage = std::move(image);
|
||||
}
|
||||
|
||||
void SkeletonDocument::setComponentPreviewPixmap(const dust3d::Uuid &componentId, const QPixmap &pixmap)
|
||||
{
|
||||
SkeletonComponent *component = (SkeletonComponent *)findComponent(componentId);
|
||||
if (nullptr == component)
|
||||
return;
|
||||
component->previewPixmap = pixmap;
|
||||
emit componentPreviewPixmapChanged(componentId);
|
||||
}
|
||||
|
||||
void SkeletonDocument::setComponentPreviewMesh(const dust3d::Uuid &componentId, std::unique_ptr<ModelMesh> mesh)
|
||||
|
|
|
@ -427,6 +427,8 @@ public:
|
|||
bool dirty = true;
|
||||
std::vector<dust3d::Uuid> childrenIds;
|
||||
bool isPreviewMeshObsolete = false;
|
||||
std::unique_ptr<QImage> previewImage;
|
||||
bool isPreviewImageDecorationObsolete = false;
|
||||
QPixmap previewPixmap;
|
||||
QString linkData() const
|
||||
{
|
||||
|
@ -547,7 +549,7 @@ signals:
|
|||
void componentAdded(dust3d::Uuid componentId);
|
||||
void componentExpandStateChanged(dust3d::Uuid componentId);
|
||||
void componentPreviewMeshChanged(const dust3d::Uuid &componentId);
|
||||
void componentPreviewImageChanged(const dust3d::Uuid &componentId);
|
||||
void componentPreviewPixmapChanged(const dust3d::Uuid &componentId);
|
||||
void nodeRemoved(dust3d::Uuid nodeId);
|
||||
void edgeRemoved(dust3d::Uuid edgeId);
|
||||
void nodeRadiusChanged(dust3d::Uuid nodeId);
|
||||
|
@ -586,6 +588,7 @@ public:
|
|||
void collectComponentDescendantParts(dust3d::Uuid componentId, std::vector<dust3d::Uuid> &partIds) const;
|
||||
void collectComponentDescendantComponents(dust3d::Uuid componentId, std::vector<dust3d::Uuid> &componentIds) const;
|
||||
void setComponentPreviewMesh(const dust3d::Uuid &componentId, std::unique_ptr<ModelMesh> mesh);
|
||||
void setComponentPreviewImage(const dust3d::Uuid &componentId, std::unique_ptr<QImage> image);
|
||||
void resetDirtyFlags();
|
||||
void markAllDirty();
|
||||
|
||||
|
@ -691,7 +694,7 @@ public slots:
|
|||
void showDescendantComponents(dust3d::Uuid componentId);
|
||||
void lockDescendantComponents(dust3d::Uuid componentId);
|
||||
void unlockDescendantComponents(dust3d::Uuid componentId);
|
||||
void setComponentPreviewImage(const dust3d::Uuid &componentId, const QImage &image);
|
||||
void setComponentPreviewPixmap(const dust3d::Uuid &componentId, const QPixmap &pixmap);
|
||||
void setPartLockState(dust3d::Uuid partId, bool locked);
|
||||
void setPartVisibleState(dust3d::Uuid partId, bool visible);
|
||||
void setPartDisableState(dust3d::Uuid partId, bool disabled);
|
||||
|
|
Loading…
Reference in New Issue