diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj
index a7798fa..c3eee0b 100644
--- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj
+++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj
@@ -110,6 +110,7 @@
+
@@ -222,6 +223,7 @@
+
diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters
index dcbccc4..cf15c33 100644
--- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters
+++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters
@@ -288,6 +288,9 @@
Source Files
+
+ Source Files
+
@@ -359,6 +362,9 @@
Header Files
+
+ Header Files
+
diff --git a/ArchitectureColoredPainting/src/Editor/EditorWidget.cpp b/ArchitectureColoredPainting/src/Editor/EditorWidget.cpp
index d612699..00c3691 100644
--- a/ArchitectureColoredPainting/src/Editor/EditorWidget.cpp
+++ b/ArchitectureColoredPainting/src/Editor/EditorWidget.cpp
@@ -1,6 +1,7 @@
#include "EditorWidget.h"
#include "EditorWidgetItem.h"
#include "Properties/ProjectPropertyDialog.h"
+#include "Properties/MaterialReplaceDialog.h"
#include
#include
#include
@@ -22,11 +23,11 @@ EditorWidget::EditorWidget(QWidget* parent) : QWidget(parent)
initProjectMenu();
connect(this->tabWidget, &QTabWidget::tabCloseRequested, [this](int index) {
- const int prevCount = this->tabWidget->count();
- this->tabWidget->removeTab(index);
- const int nowCount = this->tabWidget->count();
+ const int prevCount = this->tabWidget->count();
+ this->tabWidget->removeTab(index);
+ const int nowCount = this->tabWidget->count();
- emit tabCountChanged(prevCount, nowCount);
+ emit tabCountChanged(prevCount, nowCount);
});
}
@@ -149,8 +150,10 @@ void EditorWidget::initProjectMenu()
projectMenuButton->setDisabled(true);
}
- auto* actionProjectSettings = new QAction(QStringLiteral("项目设置"), projectMenuButton);
+ auto actionProjectSettings = new QAction(QStringLiteral("项目设置"), projectMenuButton);
+ auto actionMaterialReplace = new QAction(QStringLiteral("材质替换"), projectMenuButton);
projectMenuButton->addMenuAction(actionProjectSettings);
+ projectMenuButton->addMenuAction(actionMaterialReplace);
connect(actionProjectSettings, &QAction::triggered, [this]
{
@@ -160,9 +163,9 @@ void EditorWidget::initProjectMenu()
connect(dialog, &ProjectPropertyDialog::projectNameChanged,
currentEditorWidgetItem, &EditorWidgetItem::handleProjectNameChange);
- connect(dialog, &ProjectPropertyDialog::backgroundColorChanged,
+ connect(dialog, &ProjectPropertyDialog::backgroundColorChanged,
currentEditorWidgetItem, &EditorWidgetItem::handleBackgroundColorChange);
- connect(dialog, &ProjectPropertyDialog::canvasSizeChanged,
+ connect(dialog, &ProjectPropertyDialog::canvasSizeChanged,
currentEditorWidgetItem, &EditorWidgetItem::handleCanvasSizeChange);
connect(dialog, &ProjectPropertyDialog::canvasRoughnessChanged,
currentEditorWidgetItem, &EditorWidgetItem::handleCanvasRoughnessChange);
@@ -170,4 +173,10 @@ void EditorWidget::initProjectMenu()
currentEditorWidgetItem, &EditorWidgetItem::handleCanvasMetallicChange);
dialog->exec();
});
+ connect(actionMaterialReplace, &QAction::triggered, [this]
+ {
+ auto* currentEditorWidgetItem = static_cast(this->tabWidget->currentWidget());
+ const auto dialog = new MaterialReplaceDialog(currentEditorWidgetItem, this);
+ dialog->exec();
+ });
}
diff --git a/ArchitectureColoredPainting/src/Editor/EditorWidgetItem.cpp b/ArchitectureColoredPainting/src/Editor/EditorWidgetItem.cpp
index a50f89e..4e7220f 100644
--- a/ArchitectureColoredPainting/src/Editor/EditorWidgetItem.cpp
+++ b/ArchitectureColoredPainting/src/Editor/EditorWidgetItem.cpp
@@ -274,6 +274,11 @@ void EditorWidgetItem::handleCanvasMetallicChange(const float& metallic)
previewWindow->canvasMetallic = metallic;
}
+void EditorWidgetItem::handleMaterialReplace(const Renderer::Material& origin, const Renderer::Material& target)
+{
+
+}
+
QSize EditorWidgetItem::getCanvasReferSize() const
{
return previewWindow->referSize;
diff --git a/ArchitectureColoredPainting/src/Editor/EditorWidgetItem.h b/ArchitectureColoredPainting/src/Editor/EditorWidgetItem.h
index b95c0df..7a7c858 100644
--- a/ArchitectureColoredPainting/src/Editor/EditorWidgetItem.h
+++ b/ArchitectureColoredPainting/src/Editor/EditorWidgetItem.h
@@ -50,6 +50,7 @@ class EditorWidgetItem : public QWidget
void handleCanvasSizeChange(const QSize& size);
void handleCanvasRoughnessChange(const float& roughness);
void handleCanvasMetallicChange(const float& metallic);
+ void handleMaterialReplace(const Renderer::Material& origin, const Renderer::Material& target);
QSize getCanvasReferSize() const;
float getCanvasRoughness() const;
float getCanvasMetallic() const;
diff --git a/ArchitectureColoredPainting/src/Editor/LayerStyle.cpp b/ArchitectureColoredPainting/src/Editor/LayerStyle.cpp
index 6492544..8db6d14 100644
--- a/ArchitectureColoredPainting/src/Editor/LayerStyle.cpp
+++ b/ArchitectureColoredPainting/src/Editor/LayerStyle.cpp
@@ -16,421 +16,441 @@
std::vector StrokeElementLayerStyle::toBaseStyles() const
{
- std::vector baseStyles;
- if (enableEachSideIndependent)
- {
- if (!radialStroke(strokePair.first)->materialMap.empty())
- {
- baseStyles.push_back({ std::make_shared(), strokePair.first });
- }
- if (!radialStroke(strokePair.second)->materialMap.empty())
- {
- baseStyles.push_back({ std::make_shared(), strokePair.second });
- }
- }
- else if (!radialStroke(strokePair.first)->materialMap.empty())
- {
- const auto material = std::shared_ptr(std::move(strokePair.first->clone()));
- std::static_pointer_cast(material)->strokeType = Renderer::StrokeType::kBothSides;
+ std::vector baseStyles;
+ if (enableEachSideIndependent)
+ {
+ if (!radialStroke(strokePair.first)->materialMap.empty())
+ {
+ baseStyles.push_back({ std::make_shared(), strokePair.first });
+ }
+ if (!radialStroke(strokePair.second)->materialMap.empty())
+ {
+ baseStyles.push_back({ std::make_shared(), strokePair.second });
+ }
+ }
+ else if (!radialStroke(strokePair.first)->materialMap.empty())
+ {
+ const auto material = std::shared_ptr(std::move(strokePair.first->clone()));
+ std::static_pointer_cast(material)->strokeType = Renderer::StrokeType::kBothSides;
- baseStyles.push_back({ std::make_shared(), material });
- }
- return baseStyles;
+ baseStyles.push_back({ std::make_shared(), material });
+ }
+ return baseStyles;
}
QWidget* StrokeElementLayerStyle::getInputWidget()
{
- auto* w = new QWidget;
+ auto* w = new QWidget;
- auto* layout = new QVBoxLayout(w);
- layout->setMargin(0);
+ auto* layout = new QVBoxLayout(w);
+ layout->setMargin(0);
- auto* leftStrokeView = new StrokeStyleWidget(this->strokePair.first, w);
- layout->addWidget(leftStrokeView);
-
- auto* checkEachSideIndependent = new QtMaterialCheckBox(w);
- checkEachSideIndependent->setText(QStringLiteral("右侧独立描边"));
- checkEachSideIndependent->setChecked(enableEachSideIndependent);
- layout->addWidget(checkEachSideIndependent);
+ auto* leftStrokeView = new StrokeStyleWidget(this->strokePair.first, w);
+ layout->addWidget(leftStrokeView);
- auto* rightStrokeView = new StrokeStyleWidget(this->strokePair.second, w);
- layout->addWidget(rightStrokeView);
- rightStrokeView->setDisabled(!this->enableEachSideIndependent);
+ auto* checkEachSideIndependent = new QtMaterialCheckBox(w);
+ checkEachSideIndependent->setText(QStringLiteral("右侧独立描边"));
+ checkEachSideIndependent->setChecked(enableEachSideIndependent);
+ layout->addWidget(checkEachSideIndependent);
- QObject::connect(checkEachSideIndependent, &QtMaterialCheckBox::toggled, [this, rightStrokeView](bool toggled) {
- this->enableEachSideIndependent = toggled;
- rightStrokeView->setDisabled(!toggled);
- });
- return w;
+ auto* rightStrokeView = new StrokeStyleWidget(this->strokePair.second, w);
+ layout->addWidget(rightStrokeView);
+ rightStrokeView->setDisabled(!this->enableEachSideIndependent);
+
+ QObject::connect(checkEachSideIndependent, &QtMaterialCheckBox::toggled, [this, rightStrokeView](bool toggled) {
+ this->enableEachSideIndependent = toggled;
+ rightStrokeView->setDisabled(!toggled);
+ });
+ return w;
}
QWidget* StrokeElementLayerStyle::getListDisplayWidget() const
{
- auto* w = new QWidget;
- auto* name = new QLabel(w);
- name->setText(QStringLiteral("描边"));
- auto* layout = new QHBoxLayout(w);
- layout->setMargin(0);
- layout->addWidget(name);
- return w;
+ auto* w = new QWidget;
+ auto* name = new QLabel(w);
+ name->setText(QStringLiteral("描边"));
+ auto* layout = new QHBoxLayout(w);
+ layout->setMargin(0);
+ layout->addWidget(name);
+ return w;
}
void LayerStyleContainer::computeNewHash()
{
- hash = 0;
- for (auto& f : styles
- | std::views::values
- | std::views::transform(&LayerStyle::toBaseStyles)
- | std::views::join
- | std::views::transform(&Renderer::BaseStyle::material)
- | std::views::transform(&MaterialStyle::encoded)
- | std::views::join)
- {
- const unsigned int u = *reinterpret_cast(&f);
- hash ^= u + 0x9e3779b9 + (hash << 6) + (hash >> 2);
- }
+ hash = 0;
+ for (auto& f : styles
+ | std::views::values
+ | std::views::transform(&LayerStyle::toBaseStyles)
+ | std::views::join
+ | std::views::transform(&Renderer::BaseStyle::material)
+ | std::views::transform(&MaterialStyle::encoded)
+ | std::views::join)
+ {
+ const unsigned int u = *reinterpret_cast(&f);
+ hash ^= u + 0x9e3779b9 + (hash << 6) + (hash >> 2);
+ }
}
LayerStyleContainer LayerStyleContainer::fromJson(ElementType::ElementType elementType, const QJsonArray& jsonArray)
{
- LayerStyleContainer container(elementType);
- for (const auto& style : jsonArray)
- {
- container.useStyle(LayerStyle::fromJson(style.toObject()));
- }
- return container;
+ LayerStyleContainer container(elementType);
+ for (const auto& style : jsonArray)
+ {
+ container.useStyle(LayerStyle::fromJson(style.toObject()));
+ }
+ return container;
}
LayerStyleContainer::LayerStyleContainer(ElementType::ElementType elementType) : elementType(elementType), hash(0)
{
- for (const auto& style : commonStyles)
- {
- unusedStyles.insert(style);
- }
- if (elementType & ElementType::TYPE_UNCLOSED)
- {
- for (const auto& style : unclosedOnlyStyles)
- {
- unusedStyles.insert(style);
- }
- }
- if (elementType & ElementType::TYPE_CLOSED)
- {
- for (const auto& style : closedOnlyStyles)
- {
- unusedStyles.insert(style);
- }
- }
+ for (const auto& style : commonStyles)
+ {
+ unusedStyles.insert(style);
+ }
+ if (elementType & ElementType::TYPE_UNCLOSED)
+ {
+ for (const auto& style : unclosedOnlyStyles)
+ {
+ unusedStyles.insert(style);
+ }
+ }
+ if (elementType & ElementType::TYPE_CLOSED)
+ {
+ for (const auto& style : closedOnlyStyles)
+ {
+ unusedStyles.insert(style);
+ }
+ }
}
std::vector LayerStyleContainer::toBaseStyles() const
{
- std::vector result;
- for (const auto& style : styles | std::views::values)
- {
- auto baseStyles = style->toBaseStyles();
- result.insert(result.end(),
- std::make_move_iterator(baseStyles.begin()),
- std::make_move_iterator(baseStyles.end()));
- }
- return result;
+ std::vector result;
+ for (const auto& style : styles | std::views::values)
+ {
+ auto baseStyles = style->toBaseStyles();
+ result.insert(result.end(),
+ std::make_move_iterator(baseStyles.begin()),
+ std::make_move_iterator(baseStyles.end()));
+ }
+ return result;
}
QJsonArray LayerStyleContainer::toJson() const
{
- QJsonArray json;
- for (const auto& style : styles | std::views::values)
- {
- json.append(style->toJson());
- }
- return json;
+ QJsonArray json;
+ for (const auto& style : styles | std::views::values)
+ {
+ json.append(style->toJson());
+ }
+ return json;
+}
+
+void LayerStyleContainer::replaceMaterial(const Renderer::Material& origin, const Renderer::Material& target)
+{
+ for (auto& style : styles | std::views::values)
+ style->replaceMaterial(origin, target);
+ computeNewHash();
}
QStringList LayerStyleContainer::unusedStyleNames() const
{
- QStringList result;
- for(const auto& name : unusedStyles | std::views::keys)
- {
- result << name;
- }
- return result;
+ QStringList result;
+ for(const auto& name : unusedStyles | std::views::keys)
+ {
+ result << name;
+ }
+ return result;
}
std::unique_ptr LayerStyleContainer::makeUnusedStyle(const QString& styleName) const
{
- return unusedStyles.at(styleName)();
+ return unusedStyles.at(styleName)();
}
bool LayerStyleContainer::empty() const
{
- return styles.empty();
+ return styles.empty();
}
bool LayerStyleContainer::full() const
{
- return unusedStyles.empty();
+ return unusedStyles.empty();
}
std::map>::iterator LayerStyleContainer::begin()
{
- return styles.begin();
+ return styles.begin();
}
std::map>::iterator LayerStyleContainer::end()
{
- return styles.end();
+ return styles.end();
}
std::map>::const_iterator LayerStyleContainer::cbegin() const
{
- return styles.cbegin();
+ return styles.cbegin();
}
std::map>::const_iterator LayerStyleContainer::cend() const
{
- return styles.cend();
+ return styles.cend();
}
bool LayerStyleContainer::useStyle(const std::shared_ptr& style, bool forceOverride)
{
- const auto styleDisplayName = style->getDisplayName();
- auto styleNode = unusedStyles.extract(styleDisplayName);
- if (styleNode.empty() && !forceOverride)
- {
- return false;
- }
- auto uFittedStyle = style->fitForElementType(this->elementType);
- auto fittedStyle = std::shared_ptr(std::move(uFittedStyle));
- if (!fittedStyle)
- {
- return false;
- }
- if (!styleNode.empty())
- {
- usedStyles.insert(std::move(styleNode));
- }
- styles[styleDisplayName] = fittedStyle;
- return true;
+ const auto styleDisplayName = style->getDisplayName();
+ auto styleNode = unusedStyles.extract(styleDisplayName);
+ if (styleNode.empty() && !forceOverride)
+ {
+ return false;
+ }
+ auto uFittedStyle = style->fitForElementType(this->elementType);
+ auto fittedStyle = std::shared_ptr(std::move(uFittedStyle));
+ if (!fittedStyle)
+ {
+ return false;
+ }
+ if (!styleNode.empty())
+ {
+ usedStyles.insert(std::move(styleNode));
+ }
+ styles[styleDisplayName] = fittedStyle;
+ return true;
}
bool LayerStyleContainer::overrideStyle(const std::shared_ptr& style)
{
- auto fittedStyle = std::shared_ptr(std::move(style->fitForElementType(this->elementType)));
- if (!fittedStyle)
- {
- return false;
- }
- styles[style->getDisplayName()] = fittedStyle;
- return true;
+ auto fittedStyle = std::shared_ptr(std::move(style->fitForElementType(this->elementType)));
+ if (!fittedStyle)
+ {
+ return false;
+ }
+ styles[style->getDisplayName()] = fittedStyle;
+ return true;
}
bool LayerStyleContainer::dropStyle(const QString& styleName)
{
- auto styleNode = usedStyles.extract(styleName);
+ auto styleNode = usedStyles.extract(styleName);
if (styleNode.empty())
- {
- return false;
- }
- styles.erase(styleName);
- unusedStyles.insert(std::move(styleNode));
+ {
+ return false;
+ }
+ styles.erase(styleName);
+ unusedStyles.insert(std::move(styleNode));
return true;
}
std::shared_ptr LayerStyleContainer::getStyle(const QString& styleName) const
{
- return styles.at(styleName);
+ return styles.at(styleName);
}
float LayerStyleContainer::boundingBoxAffectValue() const {
- float maxLineWidth = 0;
- const auto strokeStyle = styles.find(StrokeElementLayerStyle::displayName());
- if (strokeStyle != styles.end())
- {
- if (const auto strokeElementLayerStyle =
- std::dynamic_pointer_cast(strokeStyle->second);
- strokeElementLayerStyle != nullptr)
- {
- const auto& leftStyleStroke = strokeElementLayerStyle->strokePair.first;
- const auto& rightStyleStroke = strokeElementLayerStyle->strokePair.second;
- if (leftStyleStroke != nullptr)
- {
- maxLineWidth = std::max(maxLineWidth, leftStyleStroke->halfWidth);
- }
- if (rightStyleStroke != nullptr)
- {
- maxLineWidth = std::max(maxLineWidth, rightStyleStroke->halfWidth);
- }
- }
- }
- return maxLineWidth;
+ float maxLineWidth = 0;
+ const auto strokeStyle = styles.find(StrokeElementLayerStyle::displayName());
+ if (strokeStyle != styles.end())
+ {
+ if (const auto strokeElementLayerStyle =
+ std::dynamic_pointer_cast(strokeStyle->second);
+ strokeElementLayerStyle != nullptr)
+ {
+ const auto& leftStyleStroke = strokeElementLayerStyle->strokePair.first;
+ const auto& rightStyleStroke = strokeElementLayerStyle->strokePair.second;
+ if (leftStyleStroke != nullptr)
+ {
+ maxLineWidth = std::max(maxLineWidth, leftStyleStroke->halfWidth);
+ }
+ if (rightStyleStroke != nullptr)
+ {
+ maxLineWidth = std::max(maxLineWidth, rightStyleStroke->halfWidth);
+ }
+ }
+ }
+ return maxLineWidth;
}
size_t LayerStyleContainer::getHash() const
{
- return hash;
+ return hash;
}
bool LayerStyleContainer::operator==(const LayerStyleContainer& other) const
{
- if (getHash() != other.getHash() || unusedStyleNames() != other.unusedStyleNames())
- {
- return false;
- }
- return std::ranges::equal(styles | std::views::values, other.styles | std::views::values);
+ if (getHash() != other.getHash() || unusedStyleNames() != other.unusedStyleNames())
+ {
+ return false;
+ }
+ return std::ranges::equal(styles | std::views::values, other.styles | std::views::values);
}
LayerStyleContainer LayerStyleContainer::operator|(const LayerStyleContainer& other) const
{
- LayerStyleContainer result = other;
- for (const auto& style : std::ranges::subrange(this->cbegin(), this->cend())
- | std::views::values)
- {
- result.useStyle(style);
- }
- result.computeNewHash();
- return result;
+ LayerStyleContainer result = other;
+ for (const auto& style : std::ranges::subrange(this->cbegin(), this->cend())
+ | std::views::values)
+ {
+ result.useStyle(style);
+ }
+ result.computeNewHash();
+ return result;
}
LayerStyleContainer& LayerStyleContainer::operator<<(const LayerStyleContainer& other)
{
- for (auto& style : std::ranges::subrange(other.cbegin(), other.cend())
- | std::views::values)
- {
- this->useStyle(style, true);
- }
- computeNewHash();
- return *this;
+ for (auto& style : std::ranges::subrange(other.cbegin(), other.cend())
+ | std::views::values)
+ {
+ this->useStyle(style, true);
+ }
+ computeNewHash();
+ return *this;
}
std::unique_ptr StrokeElementLayerStyle::fromJson(const QJsonObject& json)
{
- auto ptr = std::make_unique(
- std::static_pointer_cast(
- std::shared_ptr(std::move(MaterialStyle::decoded(EncodeUtil::fromBase64(json["left"].toString()))))
- ),
- std::static_pointer_cast(
- std::shared_ptr(std::move(MaterialStyle::decoded(EncodeUtil::fromBase64(json["right"].toString()))))
- )
- );
- ptr->enableEachSideIndependent = json["enableEachSideIndependent"].toBool();
- return ptr;
+ auto ptr = std::make_unique(
+ std::static_pointer_cast(
+ std::shared_ptr(std::move(MaterialStyle::decoded(EncodeUtil::fromBase64(json["left"].toString()))))
+ ),
+ std::static_pointer_cast(
+ std::shared_ptr(std::move(MaterialStyle::decoded(EncodeUtil::fromBase64(json["right"].toString()))))
+ )
+ );
+ ptr->enableEachSideIndependent = json["enableEachSideIndependent"].toBool();
+ return ptr;
}
StrokeElementLayerStyle::StrokeElementLayerStyle(bool isClosed)
{
- const auto materialMap = std::map();
- this->strokePair.first = std::make_shared(
- 7,
- Renderer::StrokeType::kLeftSide, isClosed ? Renderer::StrokeEndType::kClosed : Renderer::StrokeEndType::kFlat,
- std::make_shared(materialMap, false)
- );
+ const auto materialMap = std::map();
+ this->strokePair.first = std::make_shared(
+ 7,
+ Renderer::StrokeType::kLeftSide, isClosed ? Renderer::StrokeEndType::kClosed : Renderer::StrokeEndType::kFlat,
+ std::make_shared(materialMap, false)
+ );
+
+ this->strokePair.second = std::make_shared(
+ 7,
+ Renderer::StrokeType::kRightSide, isClosed ? Renderer::StrokeEndType::kClosed : Renderer::StrokeEndType::kFlat,
+ std::make_shared(materialMap, false)
+ );
- this->strokePair.second = std::make_shared(
- 7,
- Renderer::StrokeType::kRightSide, isClosed ? Renderer::StrokeEndType::kClosed : Renderer::StrokeEndType::kFlat,
- std::make_shared(materialMap, false)
- );
-
}
StrokeElementLayerStyle::StrokeElementLayerStyle(const PMaterialStyleStroke& left, const PMaterialStyleStroke& right)
{
- this->strokePair.first = left;
- this->strokePair.second = right ? right : std::static_pointer_cast(
- std::shared_ptr(std::move(left->clone()))
- );
+ this->strokePair.first = left;
+ this->strokePair.second = right ? right : std::static_pointer_cast(
+ std::shared_ptr(std::move(left->clone()))
+ );
}
StrokeElementLayerStyle::StrokeElementLayerStyle(const StrokeElementLayerStyle& other)
{
- strokePair.first = std::static_pointer_cast(
- std::shared_ptr(std::move(other.strokePair.first->clone()))
- );
- strokePair.second = std::static_pointer_cast(
- std::shared_ptr(std::move(other.strokePair.second->clone()))
- );
- enableEachSideIndependent = other.enableEachSideIndependent;
+ strokePair.first = std::static_pointer_cast(
+ std::shared_ptr(std::move(other.strokePair.first->clone()))
+ );
+ strokePair.second = std::static_pointer_cast(
+ std::shared_ptr(std::move(other.strokePair.second->clone()))
+ );
+ enableEachSideIndependent = other.enableEachSideIndependent;
}
QJsonObject StrokeElementLayerStyle::toJson() const
{
- auto json = LayerStyle::toJson();
- json["enableEachSideIndependent"] = enableEachSideIndependent;
- json["left"] = EncodeUtil::toBase64(strokePair.first->encoded());
- json["right"] = EncodeUtil::toBase64(strokePair.second->encoded());
- return json;
+ auto json = LayerStyle::toJson();
+ json["enableEachSideIndependent"] = enableEachSideIndependent;
+ json["left"] = EncodeUtil::toBase64(strokePair.first->encoded());
+ json["right"] = EncodeUtil::toBase64(strokePair.second->encoded());
+ return json;
+}
+
+void StrokeElementLayerStyle::replaceMaterial(const Renderer::Material& origin, const Renderer::Material& target)
+{
+ auto styles = { strokePair.first, strokePair.second };
+ for (auto& style : styles)
+ {
+ if (!style) continue;
+
+ for (auto& material : std::dynamic_pointer_cast(style->materialStroke)->materialMap | std::views::values)
+ if (material == origin)
+ material = target;
+ }
}
std::unique_ptr StrokeElementLayerStyle::clone() const
{
- return std::make_unique(StrokeElementLayerStyle(*this));
+ return std::make_unique(StrokeElementLayerStyle(*this));
}
std::unique_ptr StrokeElementLayerStyle::fitForElementType(ElementType::ElementType type) const
{
- auto result = std::unique_ptr(reinterpret_cast(this->clone().release()));
- const bool isThisClosed = strokePair.first->endType == Renderer::StrokeEndType::kClosed;
- const bool isRequiredTypeClosed = (type & ElementType::TYPE_CLOSED) == ElementType::TYPE_CLOSED;
- if (isThisClosed == isRequiredTypeClosed)
- {
- return result;
- }
- if (type == ElementType::TYPE_CLOSED)
- {
- result->strokePair.first->endType = Renderer::StrokeEndType::kClosed;
- result->strokePair.second->endType = Renderer::StrokeEndType::kClosed;
- }
- else if (isThisClosed)
- {
- result->strokePair.first->endType = Renderer::StrokeEndType::kFlat;
- result->strokePair.second->endType = Renderer::StrokeEndType::kFlat;
- }
- return result;
+ auto result = std::unique_ptr(reinterpret_cast(this->clone().release()));
+ const bool isThisClosed = strokePair.first->endType == Renderer::StrokeEndType::kClosed;
+ const bool isRequiredTypeClosed = (type & ElementType::TYPE_CLOSED) == ElementType::TYPE_CLOSED;
+ if (isThisClosed == isRequiredTypeClosed)
+ {
+ return result;
+ }
+ if (type == ElementType::TYPE_CLOSED)
+ {
+ result->strokePair.first->endType = Renderer::StrokeEndType::kClosed;
+ result->strokePair.second->endType = Renderer::StrokeEndType::kClosed;
+ }
+ else if (isThisClosed)
+ {
+ result->strokePair.first->endType = Renderer::StrokeEndType::kFlat;
+ result->strokePair.second->endType = Renderer::StrokeEndType::kFlat;
+ }
+ return result;
}
bool StrokeElementLayerStyle::operator==(const LayerStyle& other) const
{
if (!LayerStyle::operator==(other))
{
- return false;
+ return false;
}
- const auto otherStyle = dynamic_cast(&other);
+ const auto otherStyle = dynamic_cast(&other);
if (!otherStyle)
{
- return false;
+ return false;
}
- return this->strokePair.first == otherStyle->strokePair.first && this->strokePair.second == otherStyle->strokePair.second;
+ return this->strokePair.first == otherStyle->strokePair.first && this->strokePair.second == otherStyle->strokePair.second;
}
std::unique_ptr FillElementLayerStyle::fromJson(const QJsonObject& json)
{
- auto ptr = std::make_unique(
- std::static_pointer_cast(
- std::shared_ptr(std::move(MaterialStyle::decoded(EncodeUtil::fromBase64(json["material"].toString()))))
- )
- );
- return ptr;
+ auto ptr = std::make_unique(
+ std::static_pointer_cast(
+ std::shared_ptr(std::move(MaterialStyle::decoded(EncodeUtil::fromBase64(json["material"].toString()))))
+ )
+ );
+ return ptr;
}
std::vector FillElementLayerStyle::toBaseStyles() const
{
- return { {std::make_shared(), fillMaterialStyle} };
+ return { {std::make_shared(), fillMaterialStyle} };
}
QWidget* FillElementLayerStyle::getInputWidget()
{
- return new FillStyleWidget(fillMaterialStyle);
+ return new FillStyleWidget(fillMaterialStyle);
}
QWidget* FillElementLayerStyle::getListDisplayWidget() const
{
- auto* w = new QWidget;
- auto* name = new QLabel(w);
- name->setText(QStringLiteral("填充"));
- auto* layout = new QHBoxLayout(w);
- layout->setMargin(0);
- layout->addWidget(name);
- return w;
+ auto* w = new QWidget;
+ auto* name = new QLabel(w);
+ name->setText(QStringLiteral("填充"));
+ auto* layout = new QHBoxLayout(w);
+ layout->setMargin(0);
+ layout->addWidget(name);
+ return w;
}
FillElementLayerStyle::FillElementLayerStyle(const PMaterialStyleFill& fillMaterialStyle)
@@ -438,76 +458,83 @@ FillElementLayerStyle::FillElementLayerStyle(const PMaterialStyleFill& fillMater
{
if (!fillMaterialStyle)
{
- this->fillMaterialStyle = std::make_shared(
- std::make_shared(ColorHelper::instance().getPrimary1())
- );
+ this->fillMaterialStyle = std::make_shared(
+ std::make_shared(ColorHelper::instance().getPrimary1())
+ );
}
}
FillElementLayerStyle::FillElementLayerStyle(const FillElementLayerStyle& other)
{
- this->fillMaterialStyle = std::static_pointer_cast(
- std::shared_ptr(std::move(other.fillMaterialStyle->clone()))
- );
+ this->fillMaterialStyle = std::static_pointer_cast(
+ std::shared_ptr(std::move(other.fillMaterialStyle->clone()))
+ );
}
QJsonObject FillElementLayerStyle::toJson() const
{
- auto json = LayerStyle::toJson();
- json["material"] = EncodeUtil::toBase64(fillMaterialStyle->encoded());
- return json;
+ auto json = LayerStyle::toJson();
+ json["material"] = EncodeUtil::toBase64(fillMaterialStyle->encoded());
+ return json;
+}
+
+void FillElementLayerStyle::replaceMaterial(const Renderer::Material& origin, const Renderer::Material& target)
+{
+ auto materialFill = std::dynamic_pointer_cast(fillMaterialStyle->materialFill);
+ if (materialFill->material == origin)
+ materialFill->material = target;
}
std::unique_ptr FillElementLayerStyle::clone() const
{
- return std::make_unique(FillElementLayerStyle(*this));
+ return std::make_unique(FillElementLayerStyle(*this));
}
std::unique_ptr FillElementLayerStyle::fitForElementType(ElementType::ElementType type) const
{
- if (type & ElementType::TYPE_CLOSED)
- {
- return this->clone();
- }
- return nullptr;
+ if (type & ElementType::TYPE_CLOSED)
+ {
+ return this->clone();
+ }
+ return nullptr;
}
bool FillElementLayerStyle::operator==(const LayerStyle& other) const
{
- if (!LayerStyle::operator==(other))
- {
- return false;
- }
- const auto otherStyle = dynamic_cast(&other);
- if (!otherStyle)
- {
- return false;
- }
- return this->fillMaterialStyle == otherStyle->fillMaterialStyle;
+ if (!LayerStyle::operator==(other))
+ {
+ return false;
+ }
+ const auto otherStyle = dynamic_cast(&other);
+ if (!otherStyle)
+ {
+ return false;
+ }
+ return this->fillMaterialStyle == otherStyle->fillMaterialStyle;
}
std::unique_ptr LayerStyle::fromJson(const QJsonObject& json)
{
- QString type = json["type"].toString();
- if (type == StrokeElementLayerStyle::typeName())
- {
- return StrokeElementLayerStyle::fromJson(json);
- }
- if (type == FillElementLayerStyle::typeName())
- {
- return FillElementLayerStyle::fromJson(json);
- }
+ QString type = json["type"].toString();
+ if (type == StrokeElementLayerStyle::typeName())
+ {
+ return StrokeElementLayerStyle::fromJson(json);
+ }
+ if (type == FillElementLayerStyle::typeName())
+ {
+ return FillElementLayerStyle::fromJson(json);
+ }
return nullptr;
}
QJsonObject LayerStyle::toJson() const
{
- QJsonObject json;
- json["type"] = this->getTypeName();
- return json;
+ QJsonObject json;
+ json["type"] = this->getTypeName();
+ return json;
}
bool LayerStyle::operator==(const LayerStyle& other) const
{
- return this->getTypeName() == other.getTypeName();
+ return this->getTypeName() == other.getTypeName();
}
diff --git a/ArchitectureColoredPainting/src/Editor/LayerStyle.h b/ArchitectureColoredPainting/src/Editor/LayerStyle.h
index 3e29ae5..04d2b42 100644
--- a/ArchitectureColoredPainting/src/Editor/LayerStyle.h
+++ b/ArchitectureColoredPainting/src/Editor/LayerStyle.h
@@ -23,79 +23,82 @@ using Renderer::MaterialStyleFill;
namespace ElementType
{
- using ElementType = unsigned short;
- constexpr ElementType TYPE_ALL = 0xffff;
- constexpr ElementType TYPE_CLOSED = 0b01;
- constexpr ElementType TYPE_UNCLOSED = 0b10;
+ using ElementType = unsigned short;
+ constexpr ElementType TYPE_ALL = 0xffff;
+ constexpr ElementType TYPE_CLOSED = 0b01;
+ constexpr ElementType TYPE_UNCLOSED = 0b10;
};
class LayerStyle : public Renderer::ElementStyle
{
public:
- static std::unique_ptr fromJson(const QJsonObject& json);
- virtual ~LayerStyle() = default;
+ static std::unique_ptr fromJson(const QJsonObject& json);
+ virtual ~LayerStyle() = default;
- virtual QString getDisplayName() const = 0;
- virtual QString getTypeName() const = 0;
+ virtual QString getDisplayName() const = 0;
+ virtual QString getTypeName() const = 0;
- virtual QWidget* getInputWidget() = 0;
- virtual QWidget* getListDisplayWidget() const = 0;
+ virtual QWidget* getInputWidget() = 0;
+ virtual QWidget* getListDisplayWidget() const = 0;
- virtual QJsonObject toJson() const;
- virtual std::unique_ptr clone() const = 0;
- virtual std::unique_ptr fitForElementType(ElementType::ElementType type) const = 0;
+ virtual QJsonObject toJson() const;
+ virtual void replaceMaterial(const Renderer::Material& origin, const Renderer::Material& target) = 0;
+ virtual std::unique_ptr clone() const = 0;
+ virtual std::unique_ptr fitForElementType(ElementType::ElementType type) const = 0;
- virtual bool operator==(const LayerStyle& other) const;
+ virtual bool operator==(const LayerStyle& other) const;
};
class StrokeElementLayerStyle : public LayerStyle
{
- using PMaterialStyleStroke = std::shared_ptr;
+ using PMaterialStyleStroke = std::shared_ptr;
public:
- STYLE_NAME("描边", "stroke")
- static std::unique_ptr fromJson(const QJsonObject& json);
+ STYLE_NAME("描边", "stroke")
+ static std::unique_ptr fromJson(const QJsonObject& json);
- StrokeElementLayerStyle(bool isClosed);
- StrokeElementLayerStyle(const PMaterialStyleStroke& left, const PMaterialStyleStroke& right = nullptr);
- StrokeElementLayerStyle(const StrokeElementLayerStyle& other);
- ~StrokeElementLayerStyle() override = default;
+ StrokeElementLayerStyle(bool isClosed);
+ StrokeElementLayerStyle(const PMaterialStyleStroke& left, const PMaterialStyleStroke& right = nullptr);
+ StrokeElementLayerStyle(const StrokeElementLayerStyle& other);
+ ~StrokeElementLayerStyle() override = default;
- std::vector toBaseStyles() const override;
- QWidget* getInputWidget() override;
- QWidget* getListDisplayWidget() const override;
- QJsonObject toJson() const override;
- std::unique_ptr clone() const override;
- std::unique_ptr fitForElementType(ElementType::ElementType type) const override;
+ std::vector toBaseStyles() const override;
+ QWidget* getInputWidget() override;
+ QWidget* getListDisplayWidget() const override;
+ QJsonObject toJson() const override;
+ void replaceMaterial(const Renderer::Material& origin, const Renderer::Material& target) override;
+ std::unique_ptr clone() const override;
+ std::unique_ptr fitForElementType(ElementType::ElementType type) const override;
- bool operator==(const LayerStyle& other) const override;
+ bool operator==(const LayerStyle& other) const override;
- std::pair strokePair;
- bool enableEachSideIndependent = false;
+ std::pair strokePair;
+ bool enableEachSideIndependent = false;
};
class FillElementLayerStyle : public LayerStyle
{
- using PMaterialStyleFill = std::shared_ptr;
+ using PMaterialStyleFill = std::shared_ptr;
public:
- STYLE_NAME("填充", "fill")
- static std::unique_ptr fromJson(const QJsonObject& json);
+ STYLE_NAME("填充", "fill")
+ static std::unique_ptr fromJson(const QJsonObject& json);
- FillElementLayerStyle(const PMaterialStyleFill& fillMaterialStyle = nullptr);
- FillElementLayerStyle(const FillElementLayerStyle& other);
- ~FillElementLayerStyle() override = default;
+ FillElementLayerStyle(const PMaterialStyleFill& fillMaterialStyle = nullptr);
+ FillElementLayerStyle(const FillElementLayerStyle& other);
+ ~FillElementLayerStyle() override = default;
- std::vector toBaseStyles() const override;
- QWidget* getInputWidget() override;
- QWidget* getListDisplayWidget() const override;
- QJsonObject toJson() const override;
- std::unique_ptr clone() const override;
- std::unique_ptr fitForElementType(ElementType::ElementType type) const override;
+ std::vector toBaseStyles() const override;
+ QWidget* getInputWidget() override;
+ QWidget* getListDisplayWidget() const override;
+ QJsonObject toJson() const override;
+ void replaceMaterial(const Renderer::Material& origin, const Renderer::Material& target) override;
+ std::unique_ptr clone() const override;
+ std::unique_ptr fitForElementType(ElementType::ElementType type) const override;
- bool operator==(const LayerStyle& other) const override;
+ bool operator==(const LayerStyle& other) const override;
- PMaterialStyleFill fillMaterialStyle;
+ PMaterialStyleFill fillMaterialStyle;
};
/**
@@ -103,62 +106,63 @@ public:
*/
class LayerStyleContainer : public Renderer::ElementStyle
{
- using DisplayNameWithSupplier = std::map()>>;
+ using DisplayNameWithSupplier = std::map()>>;
private:
- inline const static DisplayNameWithSupplier commonStyles = { };
- inline const static DisplayNameWithSupplier closedOnlyStyles = {
- {
- FillElementLayerStyle::displayName(),
- [] { return std::make_unique(); }
+ inline const static DisplayNameWithSupplier commonStyles = { };
+ inline const static DisplayNameWithSupplier closedOnlyStyles = {
+ {
+ FillElementLayerStyle::displayName(),
+ [] { return std::make_unique(); }
},
{
- StrokeElementLayerStyle::displayName(),
- [] { return std::make_unique(true); }
+ StrokeElementLayerStyle::displayName(),
+ [] { return std::make_unique(true); }
}
- };
- inline const static DisplayNameWithSupplier unclosedOnlyStyles = { {
- StrokeElementLayerStyle::displayName(),
- [] { return std::make_unique(false); }
- } };
+ };
+ inline const static DisplayNameWithSupplier unclosedOnlyStyles = { {
+ StrokeElementLayerStyle::displayName(),
+ [] { return std::make_unique(false); }
+ } };
- ElementType::ElementType elementType;
- DisplayNameWithSupplier unusedStyles;
- DisplayNameWithSupplier usedStyles;
- std::map> styles;
- size_t hash;
+ ElementType::ElementType elementType;
+ DisplayNameWithSupplier unusedStyles;
+ DisplayNameWithSupplier usedStyles;
+ std::map> styles;
+ size_t hash;
public:
- static LayerStyleContainer fromJson(ElementType::ElementType elementType, const QJsonArray& jsonArray);
+ static LayerStyleContainer fromJson(ElementType::ElementType elementType, const QJsonArray& jsonArray);
- LayerStyleContainer(ElementType::ElementType elementType);
- [[nodiscard]] std::vector toBaseStyles() const override;
- [[nodiscard]] QJsonArray toJson() const;
+ LayerStyleContainer(ElementType::ElementType elementType);
+ [[nodiscard]] std::vector toBaseStyles() const override;
+ [[nodiscard]] QJsonArray toJson() const;
+ void replaceMaterial(const Renderer::Material& origin, const Renderer::Material& target);
- [[nodiscard]] bool empty() const;
- [[nodiscard]] bool full() const;
- [[nodiscard]] std::map>::iterator begin();
- [[nodiscard]] std::map>::iterator end();
- [[nodiscard]] std::map>::const_iterator cbegin() const;
- [[nodiscard]] std::map>::const_iterator cend() const;
+ [[nodiscard]] bool empty() const;
+ [[nodiscard]] bool full() const;
+ [[nodiscard]] std::map>::iterator begin();
+ [[nodiscard]] std::map>::iterator end();
+ [[nodiscard]] std::map>::const_iterator cbegin() const;
+ [[nodiscard]] std::map>::const_iterator cend() const;
- [[nodiscard]] QStringList unusedStyleNames() const;
- [[nodiscard]] std::unique_ptr makeUnusedStyle(const QString& styleName) const;
- bool useStyle(const std::shared_ptr& style, bool forceOverride = false);
- bool overrideStyle(const std::shared_ptr& style);
- bool dropStyle(const QString& styleName);
- [[nodiscard]] std::shared_ptr getStyle(const QString& styleName) const;
- [[nodiscard]] float boundingBoxAffectValue() const;
- [[nodiscard]] size_t getHash() const;
+ [[nodiscard]] QStringList unusedStyleNames() const;
+ [[nodiscard]] std::unique_ptr makeUnusedStyle(const QString& styleName) const;
+ bool useStyle(const std::shared_ptr& style, bool forceOverride = false);
+ bool overrideStyle(const std::shared_ptr& style);
+ bool dropStyle(const QString& styleName);
+ [[nodiscard]] std::shared_ptr getStyle(const QString& styleName) const;
+ [[nodiscard]] float boundingBoxAffectValue() const;
+ [[nodiscard]] size_t getHash() const;
- [[nodiscard]] bool operator==(const LayerStyleContainer& other) const;
- /**
- * 类管道操作,后者覆盖前者,会返回一个新的LayerStyleContainer
- */
- [[nodiscard]] LayerStyleContainer operator|(const LayerStyleContainer& other) const;
- LayerStyleContainer& operator<<(const LayerStyleContainer& other);
+ [[nodiscard]] bool operator==(const LayerStyleContainer& other) const;
+ /**
+ * 类管道操作,后者覆盖前者,会返回一个新的LayerStyleContainer
+ */
+ [[nodiscard]] LayerStyleContainer operator|(const LayerStyleContainer& other) const;
+ LayerStyleContainer& operator<<(const LayerStyleContainer& other);
- /**
- * 需要在每次更改后手动调用
- */
- void computeNewHash();
+ /**
+ * 需要在每次更改后手动调用
+ */
+ void computeNewHash();
};
\ No newline at end of file
diff --git a/ArchitectureColoredPainting/src/Editor/LayerWrapper.cpp b/ArchitectureColoredPainting/src/Editor/LayerWrapper.cpp
index 7c52d1a..6ad8dc0 100644
--- a/ArchitectureColoredPainting/src/Editor/LayerWrapper.cpp
+++ b/ArchitectureColoredPainting/src/Editor/LayerWrapper.cpp
@@ -294,6 +294,13 @@ QJsonObject FolderLayerWrapper::toJson() const
return json;
}
+void FolderLayerWrapper::replaceMaterial(const Renderer::Material& origin, const Renderer::Material& target)
+{
+ for (auto& child : children)
+ if (child != nullptr)
+ child->replaceMaterial(origin, target);
+}
+
QJsonObject LeafLayerWrapper::toJson() const
{
QJsonObject json = LayerWrapper::toJson();
@@ -303,6 +310,11 @@ QJsonObject LeafLayerWrapper::toJson() const
return json;
}
+void LeafLayerWrapper::replaceMaterial(const Renderer::Material& origin, const Renderer::Material& target)
+{
+ styles->replaceMaterial(origin, target);
+}
+
int FolderLayerWrapper::getReferencedBy()const
{
if (this->elementManager != nullptr)
diff --git a/ArchitectureColoredPainting/src/Editor/LayerWrapper.h b/ArchitectureColoredPainting/src/Editor/LayerWrapper.h
index 6d4bfaa..8a964df 100644
--- a/ArchitectureColoredPainting/src/Editor/LayerWrapper.h
+++ b/ArchitectureColoredPainting/src/Editor/LayerWrapper.h
@@ -71,6 +71,7 @@ class LayerWrapper
virtual void del();
virtual void delSelf();
virtual QJsonObject toJson() const;
+ virtual void replaceMaterial(const Renderer::Material& origin, const Renderer::Material& target) = 0;
~LayerWrapper() = default;
virtual void collectUpReachable(std::set& reachable);
virtual void collectDownReachable(std::set& reachable);
@@ -105,6 +106,7 @@ class FolderLayerWrapper : public LayerWrapper
void delSelf() override;
QTreeWidgetItem* getQTreeItem() override;
QJsonObject toJson() const override;
+ void replaceMaterial(const Renderer::Material& origin, const Renderer::Material& target) override;
int getReferencedBy()const;
void paint(QPainter* painter, QTransform transform = QTransform(), bool force = false, LayerStyleContainer styles = LayerStyleContainer(ElementType::TYPE_ALL)) override;
void collectDownReachable(std::set& reachable) override;
@@ -125,6 +127,7 @@ class LeafLayerWrapper : public LayerWrapper
void refresh(LayerWrapper* layer = nullptr) override;
LeafLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent);
QJsonObject toJson() const override;
+ void replaceMaterial(const Renderer::Material& origin, const Renderer::Material& target) override;
void paint(QPainter* painter, QTransform transform = QTransform(), bool force = false, LayerStyleContainer styles = LayerStyleContainer(ElementType::TYPE_ALL)) override;
void collectDownReachable(std::set& reachable) override;
void collectDownUsedElements(std::set& elements, bool deep = true) override;
diff --git a/ArchitectureColoredPainting/src/Editor/Properties/MaterialReplaceDialog.cpp b/ArchitectureColoredPainting/src/Editor/Properties/MaterialReplaceDialog.cpp
new file mode 100644
index 0000000..8deeace
--- /dev/null
+++ b/ArchitectureColoredPainting/src/Editor/Properties/MaterialReplaceDialog.cpp
@@ -0,0 +1,53 @@
+#include "MaterialReplaceDialog.h"
+#include
+#include
+
+MaterialReplaceDialog::MaterialReplaceDialog(const EditorWidgetItem* editorWidgetItem, QWidget* parent)
+ : QDialog(parent),
+ editorWidgetItem(editorWidgetItem),
+ originColorPicker(new ColorPicker(ColorHelper::instance().getPrimary1(), this)),
+ originRoughnessField(new QtMaterialTextField(this)),
+ originMetallicField(new QtMaterialTextField(this)),
+ targetColorPicker(new ColorPicker(ColorHelper::instance().getPrimary1(), this)),
+ targetRoughnessField(new QtMaterialTextField(this)),
+ targetMetallicField(new QtMaterialTextField(this))
+{
+ setWindowTitle(QStringLiteral("材质替换"));
+
+ auto* vbox = new QVBoxLayout(this);
+
+ auto gridLayout = new QGridLayout(this);
+
+ auto* formLeft = new QFormLayout(this);
+ formLeft->addRow(QStringLiteral("原基础色"), originColorPicker);
+ formLeft->addRow(QStringLiteral("原粗糙度"), originRoughnessField);
+ formLeft->addRow(QStringLiteral("原金属度"), originMetallicField);
+ originRoughnessField->setText(QString::number(0.5));
+ originMetallicField->setText(QString::number(0));
+
+ auto* formRight = new QFormLayout(this);
+ formRight->addRow(QStringLiteral("目标基础色"), targetColorPicker);
+ formRight->addRow(QStringLiteral("目标粗糙度"), targetRoughnessField);
+ formRight->addRow(QStringLiteral("目标金属度"), targetMetallicField);
+ targetRoughnessField->setText(QString::number(0.5));
+ targetMetallicField->setText(QString::number(0));
+
+ gridLayout->addLayout(formLeft, 0, 0);
+ gridLayout->addLayout(formRight, 0, 1);
+
+ vbox->addLayout(gridLayout);
+ auto* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
+ vbox->addWidget(buttonBox);
+
+ connect(buttonBox, &QDialogButtonBox::accepted, this, &MaterialReplaceDialog::accept);
+ connect(buttonBox, &QDialogButtonBox::rejected, this, &MaterialReplaceDialog::reject);
+}
+
+void MaterialReplaceDialog::accept()
+{
+ editorWidgetItem->layerManager->getRoot()->replaceMaterial(
+ Renderer::Material(originColorPicker->getColor(), originMetallicField->text().toFloat(), originRoughnessField->text().toFloat()),
+ Renderer::Material(targetColorPicker->getColor(), targetMetallicField->text().toFloat(), targetRoughnessField->text().toFloat())
+ );
+ QDialog::accept();
+}
\ No newline at end of file
diff --git a/ArchitectureColoredPainting/src/Editor/Properties/MaterialReplaceDialog.h b/ArchitectureColoredPainting/src/Editor/Properties/MaterialReplaceDialog.h
new file mode 100644
index 0000000..78a70c9
--- /dev/null
+++ b/ArchitectureColoredPainting/src/Editor/Properties/MaterialReplaceDialog.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include
+
+#include "EditorWidgetItem.h"
+#include "EditorWidgetComponent/ColorPicker.h"
+#include "../Renderer/Painting/BaseStyle.h"
+
+class MaterialReplaceDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ MaterialReplaceDialog(const EditorWidgetItem* editorWidgetItem, QWidget* parent = nullptr);
+
+private slots:
+ void accept() override;
+
+private:
+ const EditorWidgetItem* editorWidgetItem;
+ ColorPicker* originColorPicker; QtMaterialTextField* originRoughnessField; QtMaterialTextField* originMetallicField;
+ ColorPicker* targetColorPicker; QtMaterialTextField* targetRoughnessField; QtMaterialTextField* targetMetallicField;
+};
+
diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.cpp b/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.cpp
index 30c076a..f4567de 100644
--- a/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.cpp
+++ b/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.cpp
@@ -1,6 +1,7 @@
#include "BaseStyle.h"
#include "MaterialStyleFill.h"
#include "MaterialStyleStroke.h"
+#include
using namespace Renderer;
using namespace glm;
@@ -107,3 +108,8 @@ std::unique_ptr Renderer::MaterialStyle::decoded(const std::vecto
return std::make_unique(encoded[0], strokeType, endType, std::move(materialStroke), widthMap);
}
}
+
+QDebug operator<<(QDebug d, const Renderer::Material& m)
+{
+ return d << m.color << " " << m.metallic << " " << m.roughness;
+}
diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.h b/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.h
index 115aefb..9ab27df 100644
--- a/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.h
+++ b/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.h
@@ -54,3 +54,5 @@ namespace Renderer
std::pair toVec() const;
};
}
+
+QDebug operator<<(QDebug, const Renderer::Material&);
\ No newline at end of file