parent
b465b90195
commit
df71b04e4c
|
@ -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" />
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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]
|
||||
{
|
||||
|
@ -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();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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* 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* checkEachSideIndependent = new QtMaterialCheckBox(w);
|
||||
checkEachSideIndependent->setText(QStringLiteral("ÓÒ²à¶ÀÁ¢Ãè±ß"));
|
||||
checkEachSideIndependent->setChecked(enableEachSideIndependent);
|
||||
layout->addWidget(checkEachSideIndependent);
|
||||
|
||||
auto* rightStrokeView = new StrokeStyleWidget(this->strokePair.second, w);
|
||||
layout->addWidget(rightStrokeView);
|
||||
rightStrokeView->setDisabled(!this->enableEachSideIndependent);
|
||||
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;
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
};
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -54,3 +54,5 @@ namespace Renderer
|
|||
std::pair<glm::vec4, glm::vec2> toVec() const;
|
||||
};
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug, const Renderer::Material&);
|
Loading…
Reference in New Issue