在项目菜单中增加替换材质功能

main v0.2.0
wuyize 2023-08-18 17:53:33 +08:00
parent b465b90195
commit df71b04e4c
13 changed files with 547 additions and 393 deletions

View File

@ -110,6 +110,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\Editor\Properties\MaterialReplaceDialog.cpp" />
<ClCompile Include="src\Editor\util\JsonMerger.cpp" />
<ClCompile Include="src\Editor\Properties\ProjectPropertyWidget.cpp" />
<ClCompile Include="src\Editor\Properties\ProjectPropertyDialog.cpp" />
@ -222,6 +223,7 @@
<QtMoc Include="src\Editor\Properties\CanvasPropertyWidget.h" />
<QtMoc Include="src\Editor\Properties\ProjectPropertyDialog.h" />
<QtMoc Include="src\Editor\Properties\ProjectPropertyWidget.h" />
<QtMoc Include="src\Editor\Properties\MaterialReplaceDialog.h" />
<ClInclude Include="src\Editor\util\JsonMerger.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="src\Editor\Properties\PropertyWidget.h" />

View File

@ -288,6 +288,9 @@
<ClCompile Include="src\Editor\util\JsonMerger.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Editor\Properties\MaterialReplaceDialog.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<QtMoc Include="src\Renderer\RendererGLWidget.h">
@ -359,6 +362,9 @@
<QtMoc Include="src\Editor\Properties\ProjectPropertyWidget.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="src\Editor\Properties\MaterialReplaceDialog.h">
<Filter>Header Files</Filter>
</QtMoc>
</ItemGroup>
<ItemGroup>
<None Include="..\data.json" />

View File

@ -1,6 +1,7 @@
#include "EditorWidget.h"
#include "EditorWidgetItem.h"
#include "Properties/ProjectPropertyDialog.h"
#include "Properties/MaterialReplaceDialog.h"
#include <QInputDialog>
#include <QMenu>
#include <QFileDialog>
@ -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<EditorWidgetItem*>(this->tabWidget->currentWidget());
const auto dialog = new MaterialReplaceDialog(currentEditorWidgetItem, this);
dialog->exec();
});
}

View File

@ -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;

View File

@ -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;

View File

@ -16,421 +16,441 @@
std::vector<Renderer::BaseStyle> StrokeElementLayerStyle::toBaseStyles() const
{
std::vector<Renderer::BaseStyle> baseStyles;
if (enableEachSideIndependent)
{
if (!radialStroke(strokePair.first)->materialMap.empty())
{
baseStyles.push_back({ std::make_shared<Renderer::TransformStyle>(), strokePair.first });
}
if (!radialStroke(strokePair.second)->materialMap.empty())
{
baseStyles.push_back({ std::make_shared<Renderer::TransformStyle>(), strokePair.second });
}
}
else if (!radialStroke(strokePair.first)->materialMap.empty())
{
const auto material = std::shared_ptr(std::move(strokePair.first->clone()));
std::static_pointer_cast<MaterialStyleStroke>(material)->strokeType = Renderer::StrokeType::kBothSides;
std::vector<Renderer::BaseStyle> baseStyles;
if (enableEachSideIndependent)
{
if (!radialStroke(strokePair.first)->materialMap.empty())
{
baseStyles.push_back({ std::make_shared<Renderer::TransformStyle>(), strokePair.first });
}
if (!radialStroke(strokePair.second)->materialMap.empty())
{
baseStyles.push_back({ std::make_shared<Renderer::TransformStyle>(), strokePair.second });
}
}
else if (!radialStroke(strokePair.first)->materialMap.empty())
{
const auto material = std::shared_ptr(std::move(strokePair.first->clone()));
std::static_pointer_cast<MaterialStyleStroke>(material)->strokeType = Renderer::StrokeType::kBothSides;
baseStyles.push_back({ std::make_shared<Renderer::TransformStyle>(), material });
}
return baseStyles;
baseStyles.push_back({ std::make_shared<Renderer::TransformStyle>(), 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<unsigned int*>(&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<unsigned int*>(&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<Renderer::BaseStyle> LayerStyleContainer::toBaseStyles() const
{
std::vector<Renderer::BaseStyle> 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<Renderer::BaseStyle> 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<LayerStyle> 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<QString, std::shared_ptr<LayerStyle>>::iterator LayerStyleContainer::begin()
{
return styles.begin();
return styles.begin();
}
std::map<QString, std::shared_ptr<LayerStyle>>::iterator LayerStyleContainer::end()
{
return styles.end();
return styles.end();
}
std::map<QString, std::shared_ptr<LayerStyle>>::const_iterator LayerStyleContainer::cbegin() const
{
return styles.cbegin();
return styles.cbegin();
}
std::map<QString, std::shared_ptr<LayerStyle>>::const_iterator LayerStyleContainer::cend() const
{
return styles.cend();
return styles.cend();
}
bool LayerStyleContainer::useStyle(const std::shared_ptr<LayerStyle>& 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<LayerStyle>& 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<LayerStyle> 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<StrokeElementLayerStyle>(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<StrokeElementLayerStyle>(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> StrokeElementLayerStyle::fromJson(const QJsonObject& json)
{
auto ptr = std::make_unique<StrokeElementLayerStyle>(
std::static_pointer_cast<MaterialStyleStroke>(
std::shared_ptr(std::move(MaterialStyle::decoded(EncodeUtil::fromBase64<GLfloat>(json["left"].toString()))))
),
std::static_pointer_cast<MaterialStyleStroke>(
std::shared_ptr(std::move(MaterialStyle::decoded(EncodeUtil::fromBase64<GLfloat>(json["right"].toString()))))
)
);
ptr->enableEachSideIndependent = json["enableEachSideIndependent"].toBool();
return ptr;
auto ptr = std::make_unique<StrokeElementLayerStyle>(
std::static_pointer_cast<MaterialStyleStroke>(
std::shared_ptr(std::move(MaterialStyle::decoded(EncodeUtil::fromBase64<GLfloat>(json["left"].toString()))))
),
std::static_pointer_cast<MaterialStyleStroke>(
std::shared_ptr(std::move(MaterialStyle::decoded(EncodeUtil::fromBase64<GLfloat>(json["right"].toString()))))
)
);
ptr->enableEachSideIndependent = json["enableEachSideIndependent"].toBool();
return ptr;
}
StrokeElementLayerStyle::StrokeElementLayerStyle(bool isClosed)
{
const auto materialMap = std::map<float, Renderer::Material>();
this->strokePair.first = std::make_shared<MaterialStyleStroke>(
7,
Renderer::StrokeType::kLeftSide, isClosed ? Renderer::StrokeEndType::kClosed : Renderer::StrokeEndType::kFlat,
std::make_shared<Renderer::StrokeRadialGradient>(materialMap, false)
);
const auto materialMap = std::map<float, Renderer::Material>();
this->strokePair.first = std::make_shared<MaterialStyleStroke>(
7,
Renderer::StrokeType::kLeftSide, isClosed ? Renderer::StrokeEndType::kClosed : Renderer::StrokeEndType::kFlat,
std::make_shared<Renderer::StrokeRadialGradient>(materialMap, false)
);
this->strokePair.second = std::make_shared<MaterialStyleStroke>(
7,
Renderer::StrokeType::kRightSide, isClosed ? Renderer::StrokeEndType::kClosed : Renderer::StrokeEndType::kFlat,
std::make_shared<Renderer::StrokeRadialGradient>(materialMap, false)
);
this->strokePair.second = std::make_shared<MaterialStyleStroke>(
7,
Renderer::StrokeType::kRightSide, isClosed ? Renderer::StrokeEndType::kClosed : Renderer::StrokeEndType::kFlat,
std::make_shared<Renderer::StrokeRadialGradient>(materialMap, false)
);
}
StrokeElementLayerStyle::StrokeElementLayerStyle(const PMaterialStyleStroke& left, const PMaterialStyleStroke& right)
{
this->strokePair.first = left;
this->strokePair.second = right ? right : std::static_pointer_cast<MaterialStyleStroke>(
std::shared_ptr(std::move(left->clone()))
);
this->strokePair.first = left;
this->strokePair.second = right ? right : std::static_pointer_cast<MaterialStyleStroke>(
std::shared_ptr(std::move(left->clone()))
);
}
StrokeElementLayerStyle::StrokeElementLayerStyle(const StrokeElementLayerStyle& other)
{
strokePair.first = std::static_pointer_cast<MaterialStyleStroke>(
std::shared_ptr(std::move(other.strokePair.first->clone()))
);
strokePair.second = std::static_pointer_cast<MaterialStyleStroke>(
std::shared_ptr(std::move(other.strokePair.second->clone()))
);
enableEachSideIndependent = other.enableEachSideIndependent;
strokePair.first = std::static_pointer_cast<MaterialStyleStroke>(
std::shared_ptr(std::move(other.strokePair.first->clone()))
);
strokePair.second = std::static_pointer_cast<MaterialStyleStroke>(
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<GLfloat>(strokePair.first->encoded());
json["right"] = EncodeUtil::toBase64<GLfloat>(strokePair.second->encoded());
return json;
auto json = LayerStyle::toJson();
json["enableEachSideIndependent"] = enableEachSideIndependent;
json["left"] = EncodeUtil::toBase64<GLfloat>(strokePair.first->encoded());
json["right"] = EncodeUtil::toBase64<GLfloat>(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<Renderer::StrokeRadialGradient>(style->materialStroke)->materialMap | std::views::values)
if (material == origin)
material = target;
}
}
std::unique_ptr<LayerStyle> StrokeElementLayerStyle::clone() const
{
return std::make_unique<StrokeElementLayerStyle>(StrokeElementLayerStyle(*this));
return std::make_unique<StrokeElementLayerStyle>(StrokeElementLayerStyle(*this));
}
std::unique_ptr<LayerStyle> StrokeElementLayerStyle::fitForElementType(ElementType::ElementType type) const
{
auto result = std::unique_ptr<StrokeElementLayerStyle>(reinterpret_cast<StrokeElementLayerStyle*>(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<StrokeElementLayerStyle>(reinterpret_cast<StrokeElementLayerStyle*>(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<const StrokeElementLayerStyle*>(&other);
const auto otherStyle = dynamic_cast<const StrokeElementLayerStyle*>(&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> FillElementLayerStyle::fromJson(const QJsonObject& json)
{
auto ptr = std::make_unique<FillElementLayerStyle>(
std::static_pointer_cast<MaterialStyleFill>(
std::shared_ptr(std::move(MaterialStyle::decoded(EncodeUtil::fromBase64<GLfloat>(json["material"].toString()))))
)
);
return ptr;
auto ptr = std::make_unique<FillElementLayerStyle>(
std::static_pointer_cast<MaterialStyleFill>(
std::shared_ptr(std::move(MaterialStyle::decoded(EncodeUtil::fromBase64<GLfloat>(json["material"].toString()))))
)
);
return ptr;
}
std::vector<Renderer::BaseStyle> FillElementLayerStyle::toBaseStyles() const
{
return { {std::make_shared<Renderer::TransformStyle>(), fillMaterialStyle} };
return { {std::make_shared<Renderer::TransformStyle>(), 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<MaterialStyleFill>(
std::make_shared<Renderer::FillPlain>(ColorHelper::instance().getPrimary1())
);
this->fillMaterialStyle = std::make_shared<MaterialStyleFill>(
std::make_shared<Renderer::FillPlain>(ColorHelper::instance().getPrimary1())
);
}
}
FillElementLayerStyle::FillElementLayerStyle(const FillElementLayerStyle& other)
{
this->fillMaterialStyle = std::static_pointer_cast<MaterialStyleFill>(
std::shared_ptr(std::move(other.fillMaterialStyle->clone()))
);
this->fillMaterialStyle = std::static_pointer_cast<MaterialStyleFill>(
std::shared_ptr(std::move(other.fillMaterialStyle->clone()))
);
}
QJsonObject FillElementLayerStyle::toJson() const
{
auto json = LayerStyle::toJson();
json["material"] = EncodeUtil::toBase64<GLfloat>(fillMaterialStyle->encoded());
return json;
auto json = LayerStyle::toJson();
json["material"] = EncodeUtil::toBase64<GLfloat>(fillMaterialStyle->encoded());
return json;
}
void FillElementLayerStyle::replaceMaterial(const Renderer::Material& origin, const Renderer::Material& target)
{
auto materialFill = std::dynamic_pointer_cast<Renderer::FillPlain>(fillMaterialStyle->materialFill);
if (materialFill->material == origin)
materialFill->material = target;
}
std::unique_ptr<LayerStyle> FillElementLayerStyle::clone() const
{
return std::make_unique<FillElementLayerStyle>(FillElementLayerStyle(*this));
return std::make_unique<FillElementLayerStyle>(FillElementLayerStyle(*this));
}
std::unique_ptr<LayerStyle> 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<const FillElementLayerStyle*>(&other);
if (!otherStyle)
{
return false;
}
return this->fillMaterialStyle == otherStyle->fillMaterialStyle;
if (!LayerStyle::operator==(other))
{
return false;
}
const auto otherStyle = dynamic_cast<const FillElementLayerStyle*>(&other);
if (!otherStyle)
{
return false;
}
return this->fillMaterialStyle == otherStyle->fillMaterialStyle;
}
std::unique_ptr<LayerStyle> 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();
}

View File

@ -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<LayerStyle> fromJson(const QJsonObject& json);
virtual ~LayerStyle() = default;
static std::unique_ptr<LayerStyle> 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<LayerStyle> clone() const = 0;
virtual std::unique_ptr<LayerStyle> 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<LayerStyle> clone() const = 0;
virtual std::unique_ptr<LayerStyle> 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<MaterialStyleStroke>;
using PMaterialStyleStroke = std::shared_ptr<MaterialStyleStroke>;
public:
STYLE_NAME("描边", "stroke")
static std::unique_ptr<StrokeElementLayerStyle> fromJson(const QJsonObject& json);
STYLE_NAME("描边", "stroke")
static std::unique_ptr<StrokeElementLayerStyle> 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<Renderer::BaseStyle> toBaseStyles() const override;
QWidget* getInputWidget() override;
QWidget* getListDisplayWidget() const override;
QJsonObject toJson() const override;
std::unique_ptr<LayerStyle> clone() const override;
std::unique_ptr<LayerStyle> fitForElementType(ElementType::ElementType type) const override;
std::vector<Renderer::BaseStyle> 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<LayerStyle> clone() const override;
std::unique_ptr<LayerStyle> fitForElementType(ElementType::ElementType type) const override;
bool operator==(const LayerStyle& other) const override;
bool operator==(const LayerStyle& other) const override;
std::pair<PMaterialStyleStroke, PMaterialStyleStroke> strokePair;
bool enableEachSideIndependent = false;
std::pair<PMaterialStyleStroke, PMaterialStyleStroke> strokePair;
bool enableEachSideIndependent = false;
};
class FillElementLayerStyle : public LayerStyle
{
using PMaterialStyleFill = std::shared_ptr<MaterialStyleFill>;
using PMaterialStyleFill = std::shared_ptr<MaterialStyleFill>;
public:
STYLE_NAME("填充", "fill")
static std::unique_ptr<FillElementLayerStyle> fromJson(const QJsonObject& json);
STYLE_NAME("填充", "fill")
static std::unique_ptr<FillElementLayerStyle> 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<Renderer::BaseStyle> toBaseStyles() const override;
QWidget* getInputWidget() override;
QWidget* getListDisplayWidget() const override;
QJsonObject toJson() const override;
std::unique_ptr<LayerStyle> clone() const override;
std::unique_ptr<LayerStyle> fitForElementType(ElementType::ElementType type) const override;
std::vector<Renderer::BaseStyle> 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<LayerStyle> clone() const override;
std::unique_ptr<LayerStyle> 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<QString, std::function<std::unique_ptr<LayerStyle>()>>;
using DisplayNameWithSupplier = std::map<QString, std::function<std::unique_ptr<LayerStyle>()>>;
private:
inline const static DisplayNameWithSupplier commonStyles = { };
inline const static DisplayNameWithSupplier closedOnlyStyles = {
{
FillElementLayerStyle::displayName(),
[] { return std::make_unique<FillElementLayerStyle>(); }
inline const static DisplayNameWithSupplier commonStyles = { };
inline const static DisplayNameWithSupplier closedOnlyStyles = {
{
FillElementLayerStyle::displayName(),
[] { return std::make_unique<FillElementLayerStyle>(); }
},
{
StrokeElementLayerStyle::displayName(),
[] { return std::make_unique<StrokeElementLayerStyle>(true); }
StrokeElementLayerStyle::displayName(),
[] { return std::make_unique<StrokeElementLayerStyle>(true); }
}
};
inline const static DisplayNameWithSupplier unclosedOnlyStyles = { {
StrokeElementLayerStyle::displayName(),
[] { return std::make_unique<StrokeElementLayerStyle>(false); }
} };
};
inline const static DisplayNameWithSupplier unclosedOnlyStyles = { {
StrokeElementLayerStyle::displayName(),
[] { return std::make_unique<StrokeElementLayerStyle>(false); }
} };
ElementType::ElementType elementType;
DisplayNameWithSupplier unusedStyles;
DisplayNameWithSupplier usedStyles;
std::map<QString, std::shared_ptr<LayerStyle>> styles;
size_t hash;
ElementType::ElementType elementType;
DisplayNameWithSupplier unusedStyles;
DisplayNameWithSupplier usedStyles;
std::map<QString, std::shared_ptr<LayerStyle>> 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<Renderer::BaseStyle> toBaseStyles() const override;
[[nodiscard]] QJsonArray toJson() const;
LayerStyleContainer(ElementType::ElementType elementType);
[[nodiscard]] std::vector<Renderer::BaseStyle> 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<QString, std::shared_ptr<LayerStyle>>::iterator begin();
[[nodiscard]] std::map<QString, std::shared_ptr<LayerStyle>>::iterator end();
[[nodiscard]] std::map<QString, std::shared_ptr<LayerStyle>>::const_iterator cbegin() const;
[[nodiscard]] std::map<QString, std::shared_ptr<LayerStyle>>::const_iterator cend() const;
[[nodiscard]] bool empty() const;
[[nodiscard]] bool full() const;
[[nodiscard]] std::map<QString, std::shared_ptr<LayerStyle>>::iterator begin();
[[nodiscard]] std::map<QString, std::shared_ptr<LayerStyle>>::iterator end();
[[nodiscard]] std::map<QString, std::shared_ptr<LayerStyle>>::const_iterator cbegin() const;
[[nodiscard]] std::map<QString, std::shared_ptr<LayerStyle>>::const_iterator cend() const;
[[nodiscard]] QStringList unusedStyleNames() const;
[[nodiscard]] std::unique_ptr<LayerStyle> makeUnusedStyle(const QString& styleName) const;
bool useStyle(const std::shared_ptr<LayerStyle>& style, bool forceOverride = false);
bool overrideStyle(const std::shared_ptr<LayerStyle>& style);
bool dropStyle(const QString& styleName);
[[nodiscard]] std::shared_ptr<LayerStyle> getStyle(const QString& styleName) const;
[[nodiscard]] float boundingBoxAffectValue() const;
[[nodiscard]] size_t getHash() const;
[[nodiscard]] QStringList unusedStyleNames() const;
[[nodiscard]] std::unique_ptr<LayerStyle> makeUnusedStyle(const QString& styleName) const;
bool useStyle(const std::shared_ptr<LayerStyle>& style, bool forceOverride = false);
bool overrideStyle(const std::shared_ptr<LayerStyle>& style);
bool dropStyle(const QString& styleName);
[[nodiscard]] std::shared_ptr<LayerStyle> 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();
};

View File

@ -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)

View File

@ -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<LayerWrapper*>& reachable);
virtual void collectDownReachable(std::set<LayerWrapper*>& 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<LayerWrapper*>& 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<LayerWrapper*>& reachable) override;
void collectDownUsedElements(std::set<GraphicElement*>& elements, bool deep = true) override;

View File

@ -0,0 +1,53 @@
#include "MaterialReplaceDialog.h"
#include <QFormLayout>
#include <QDialogButtonBox>
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();
}

View File

@ -0,0 +1,24 @@
#pragma once
#include <QDialog>
#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;
};

View File

@ -1,6 +1,7 @@
#include "BaseStyle.h"
#include "MaterialStyleFill.h"
#include "MaterialStyleStroke.h"
#include <QDebug>
using namespace Renderer;
using namespace glm;
@ -107,3 +108,8 @@ std::unique_ptr<MaterialStyle> Renderer::MaterialStyle::decoded(const std::vecto
return std::make_unique<MaterialStyleStroke>(encoded[0], strokeType, endType, std::move(materialStroke), widthMap);
}
}
QDebug operator<<(QDebug d, const Renderer::Material& m)
{
return d << m.color << " " << m.metallic << " " << m.roughness;
}

View File

@ -54,3 +54,5 @@ namespace Renderer
std::pair<glm::vec4, glm::vec2> toVec() const;
};
}
QDebug operator<<(QDebug, const Renderer::Material&);