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 "component_property_widget.h"
#include "document.h" #include "document.h"
#include "float_number_widget.h" #include "float_number_widget.h"
#include "image_forever.h"
#include "image_preview_widget.h"
#include "theme.h" #include "theme.h"
#include <QColorDialog> #include <QColorDialog>
#include <QFileDialog>
#include <QGroupBox> #include <QGroupBox>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QPushButton> #include <QPushButton>
@ -188,29 +191,67 @@ ComponentPropertyWidget::ComponentPropertyWidget(Document* document,
cutFaceGroupBox->setLayout(cutFaceLayout); cutFaceGroupBox->setLayout(cutFaceLayout);
} }
QGroupBox* skinGroupBox = nullptr; QGroupBox* colorImageGroupBox = nullptr;
if (nullptr != m_part) { if (nullptr != m_part) {
QCheckBox* useImageBox = new QCheckBox(); ImagePreviewWidget* colorImagePreviewWidget = new ImagePreviewWidget;
Theme::initCheckbox(useImageBox); colorImagePreviewWidget->setFixedSize(Theme::partPreviewImageSize * 2, Theme::partPreviewImageSize * 2);
useImageBox->setText(tr("Use image")); colorImagePreviewWidget->updateImage(m_part->colorImageId.isNull() ? QImage() : *ImageForever::get(m_part->colorImageId));
useImageBox->setChecked(m_part->rounded); 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; QHBoxLayout* skinLayout = new QHBoxLayout;
skinLayout->addLayout(colorImageLayout);
skinLayout->addStretch(); skinLayout->addStretch();
skinLayout->addWidget(useImageBox);
skinGroupBox = new QGroupBox(tr("Skin")); colorImageGroupBox = new QGroupBox(tr("Color"));
skinGroupBox->setLayout(skinLayout); colorImageGroupBox->setLayout(skinLayout);
} }
QHBoxLayout* skinLayout = new QHBoxLayout;
if (nullptr != colorImageGroupBox)
skinLayout->addWidget(colorImageGroupBox);
QVBoxLayout* mainLayout = new QVBoxLayout; QVBoxLayout* mainLayout = new QVBoxLayout;
mainLayout->addLayout(colorLayout); mainLayout->addLayout(colorLayout);
if (nullptr != deformGroupBox) if (nullptr != deformGroupBox)
mainLayout->addWidget(deformGroupBox); mainLayout->addWidget(deformGroupBox);
if (nullptr != cutFaceGroupBox) if (nullptr != cutFaceGroupBox)
mainLayout->addWidget(cutFaceGroupBox); mainLayout->addWidget(cutFaceGroupBox);
if (nullptr != skinGroupBox) mainLayout->addLayout(skinLayout);
mainLayout->addWidget(skinGroupBox);
mainLayout->setSizeConstraint(QLayout::SetFixedSize); mainLayout->setSizeConstraint(QLayout::SetFixedSize);
connect(this, &ComponentPropertyWidget::setPartColorState, m_document, &Document::setPartColorState); 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::setPartSubdivState, m_document, &Document::setPartSubdivState);
connect(this, &ComponentPropertyWidget::setPartChamferState, m_document, &Document::setPartChamferState); connect(this, &ComponentPropertyWidget::setPartChamferState, m_document, &Document::setPartChamferState);
connect(this, &ComponentPropertyWidget::setPartRoundState, m_document, &Document::setPartRoundState); connect(this, &ComponentPropertyWidget::setPartRoundState, m_document, &Document::setPartRoundState);
connect(this, &ComponentPropertyWidget::setPartColorImage, m_document, &Document::setPartColorImage);
connect(this, &ComponentPropertyWidget::groupOperationAdded, m_document, &Document::saveSnapshot); connect(this, &ComponentPropertyWidget::groupOperationAdded, m_document, &Document::saveSnapshot);
setLayout(mainLayout); setLayout(mainLayout);
@ -230,6 +272,19 @@ ComponentPropertyWidget::ComponentPropertyWidget(Document* document,
setFixedSize(minimumSizeHint()); 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() void ComponentPropertyWidget::preparePartIds()
{ {
std::unordered_set<dust3d::Uuid> addedPartIdSet; std::unordered_set<dust3d::Uuid> addedPartIdSet;

View File

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

View File

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

View File

@ -32,6 +32,13 @@ void DocumentSaver::process()
void DocumentSaver::collectUsedResourceIds(const dust3d::Snapshot* snapshot, void DocumentSaver::collectUsedResourceIds(const dust3d::Snapshot* snapshot,
std::set<dust3d::Uuid>& imageIds) 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 (const auto& material : snapshot->materials) {
for (auto& layer : material.second) { for (auto& layer : material.second) {
for (auto& mapItem : layer.second) { for (auto& mapItem : layer.second) {