Add new part attribute: colorImageId

master
Jeremy HU 2022-10-22 16:27:58 +11:00
parent 4fb109a583
commit b0000e7a34
4 changed files with 81 additions and 10 deletions

View File

@ -1,8 +1,11 @@
#include "component_property_widget.h"
#include "document.h"
#include "float_number_widget.h"
#include "image_forever.h"
#include "image_preview_widget.h"
#include "theme.h"
#include <QColorDialog>
#include <QFileDialog>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QPushButton>
@ -188,29 +191,67 @@ ComponentPropertyWidget::ComponentPropertyWidget(Document* document,
cutFaceGroupBox->setLayout(cutFaceLayout);
}
QGroupBox* skinGroupBox = nullptr;
QGroupBox* colorImageGroupBox = nullptr;
if (nullptr != m_part) {
QCheckBox* useImageBox = new QCheckBox();
Theme::initCheckbox(useImageBox);
useImageBox->setText(tr("Use image"));
useImageBox->setChecked(m_part->rounded);
ImagePreviewWidget* colorImagePreviewWidget = new ImagePreviewWidget;
colorImagePreviewWidget->setFixedSize(Theme::partPreviewImageSize * 2, Theme::partPreviewImageSize * 2);
colorImagePreviewWidget->updateImage(m_part->colorImageId.isNull() ? QImage() : *ImageForever::get(m_part->colorImageId));
connect(m_document, &Document::partColorImageChanged, this, [=]() {
auto part = m_document->findPart(m_partId);
if (nullptr == part)
return;
colorImagePreviewWidget->updateImage(part->colorImageId.isNull() ? QImage() : *ImageForever::get(part->colorImageId));
});
QPushButton* colorImageEraser = new QPushButton(QChar(fa::eraser));
Theme::initIconButton(colorImageEraser);
connect(colorImageEraser, &QPushButton::clicked, [=]() {
emit setPartColorImage(m_partId, dust3d::Uuid());
emit groupOperationAdded();
});
QPushButton* colorImagePicker = new QPushButton(QChar(fa::image));
Theme::initIconButton(colorImagePicker);
connect(colorImagePicker, &QPushButton::clicked, [=]() {
QImage* image = pickImage();
if (nullptr == image)
return;
auto imageId = ImageForever::add(image);
delete image;
emit setPartColorImage(m_partId, imageId);
emit groupOperationAdded();
});
QHBoxLayout* colorImageToolsLayout = new QHBoxLayout;
colorImageToolsLayout->addWidget(colorImageEraser);
colorImageToolsLayout->addWidget(colorImagePicker);
colorImageToolsLayout->addStretch();
QVBoxLayout* colorImageLayout = new QVBoxLayout;
colorImageLayout->addWidget(colorImagePreviewWidget);
colorImageLayout->addLayout(colorImageToolsLayout);
QHBoxLayout* skinLayout = new QHBoxLayout;
skinLayout->addLayout(colorImageLayout);
skinLayout->addStretch();
skinLayout->addWidget(useImageBox);
skinGroupBox = new QGroupBox(tr("Skin"));
skinGroupBox->setLayout(skinLayout);
colorImageGroupBox = new QGroupBox(tr("Color"));
colorImageGroupBox->setLayout(skinLayout);
}
QHBoxLayout* skinLayout = new QHBoxLayout;
if (nullptr != colorImageGroupBox)
skinLayout->addWidget(colorImageGroupBox);
QVBoxLayout* mainLayout = new QVBoxLayout;
mainLayout->addLayout(colorLayout);
if (nullptr != deformGroupBox)
mainLayout->addWidget(deformGroupBox);
if (nullptr != cutFaceGroupBox)
mainLayout->addWidget(cutFaceGroupBox);
if (nullptr != skinGroupBox)
mainLayout->addWidget(skinGroupBox);
mainLayout->addLayout(skinLayout);
mainLayout->setSizeConstraint(QLayout::SetFixedSize);
connect(this, &ComponentPropertyWidget::setPartColorState, m_document, &Document::setPartColorState);
@ -223,6 +264,7 @@ ComponentPropertyWidget::ComponentPropertyWidget(Document* document,
connect(this, &ComponentPropertyWidget::setPartSubdivState, m_document, &Document::setPartSubdivState);
connect(this, &ComponentPropertyWidget::setPartChamferState, m_document, &Document::setPartChamferState);
connect(this, &ComponentPropertyWidget::setPartRoundState, m_document, &Document::setPartRoundState);
connect(this, &ComponentPropertyWidget::setPartColorImage, m_document, &Document::setPartColorImage);
connect(this, &ComponentPropertyWidget::groupOperationAdded, m_document, &Document::saveSnapshot);
setLayout(mainLayout);
@ -230,6 +272,19 @@ ComponentPropertyWidget::ComponentPropertyWidget(Document* document,
setFixedSize(minimumSizeHint());
}
QImage* ComponentPropertyWidget::pickImage()
{
QString fileName = QFileDialog::getOpenFileName(this, QString(), QString(),
tr("Image Files (*.png *.jpg *.bmp)"))
.trimmed();
if (fileName.isEmpty())
return nullptr;
QImage* image = new QImage();
if (!image->load(fileName))
return nullptr;
return image;
}
void ComponentPropertyWidget::preparePartIds()
{
std::unordered_set<dust3d::Uuid> addedPartIdSet;

View File

@ -20,6 +20,7 @@ signals:
void setPartChamferState(const dust3d::Uuid& partId, bool chamfered);
void setPartRoundState(const dust3d::Uuid& partId, bool rounded);
void setPartCutRotation(const dust3d::Uuid& partId, float cutRotation);
void setPartColorImage(const dust3d::Uuid& partId, const dust3d::Uuid& imageId);
void groupOperationAdded();
public:
@ -38,6 +39,7 @@ private:
QColor m_color;
QColor lastColor();
void preparePartIds();
QImage* pickImage();
};
#endif

View File

@ -1615,6 +1615,9 @@ void Document::toSnapshot(dust3d::Snapshot* snapshot, const std::set<dust3d::Uui
part["cutFace"] = CutFaceToString(partIt.second.cutFace);
}
}
if (!partIt.second.colorImageId.isNull()) {
part["colorImageId"] = partIt.second.colorImageId.toString();
}
part["__dirty"] = partIt.second.dirty ? "true" : "false";
if (partIt.second.hasColor)
part["color"] = partIt.second.color.name(QColor::HexArgb).toUtf8().constData();
@ -1857,6 +1860,10 @@ void Document::addFromSnapshot(const dust3d::Snapshot& snapshot, enum SnapshotSo
cutFaceLinkedIdModifyMap.insert({ part.id, cutFaceLinkedId });
}
}
const auto& colorImageIt = partKv.second.find("colorImageId");
if (colorImageIt != partKv.second.end()) {
part.colorImageId = dust3d::Uuid(colorImageIt->second);
}
if (dust3d::String::isTrue(dust3d::String::valueOrEmpty(partKv.second, "inverse")))
inversePartIds.insert(part.id);
const auto& colorIt = partKv.second.find("color");

View File

@ -32,6 +32,13 @@ void DocumentSaver::process()
void DocumentSaver::collectUsedResourceIds(const dust3d::Snapshot* snapshot,
std::set<dust3d::Uuid>& imageIds)
{
for (const auto& part : snapshot->parts) {
auto findImageIdString = part.second.find("colorImageId");
if (findImageIdString == part.second.end())
continue;
dust3d::Uuid imageId = dust3d::Uuid(findImageIdString->second);
imageIds.insert(imageId);
}
for (const auto& material : snapshot->materials) {
for (auto& layer : material.second) {
for (auto& mapItem : layer.second) {