Add new part attribute: colorImageId
parent
4fb109a583
commit
b0000e7a34
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue