diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj
index a0e5563..91c9f62 100644
--- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj
+++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj
@@ -153,7 +153,7 @@
-
+
@@ -189,7 +189,7 @@
-
+
@@ -197,6 +197,7 @@
+
diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters
index e019bc3..71f1e04 100644
--- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters
+++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters
@@ -216,7 +216,7 @@
Source Files\Editor\Style
-
+
Source Files\Editor\Style
@@ -254,7 +254,7 @@
Header Files
-
+
Header Files\Editor\Style
@@ -477,6 +477,9 @@
Header Files\Editor\Style
+
+ Header Files\Editor\util
+
diff --git a/ArchitectureColoredPainting/res/Shaders/painting.comp b/ArchitectureColoredPainting/res/Shaders/painting.comp
index c0af01c..3e8ede4 100644
--- a/ArchitectureColoredPainting/res/Shaders/painting.comp
+++ b/ArchitectureColoredPainting/res/Shaders/painting.comp
@@ -1149,7 +1149,7 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point
p[2] *= ratio;
p[3] *= ratio;
- vec2 tangentBeginNext;
+ vec2 tangentBeginNext = vec2(0);
if (contourIterator + 1 < contourIndex + 1 + lineCount)
{
uint lineIndex = elementIndexs[contourIterator + 1];
@@ -1217,10 +1217,10 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point
bool hit = d < minDistance;
if (onBegin)
hit =
- hit && shouldFillBeginCap(localUV, percent[0] < 1e-5, endType, p[0], tangentBegin, p3Last - p2Last);
+ hit && shouldFillBeginCap(localUV, contourIterator == contourIndex + 1, endType, p[0], tangentBegin, p3Last - p2Last);
if (onEnd)
hit = hit &&
- shouldFillEndCap(localUV, percent[1] > 1 - 1e-5, endType, p[3], tangentEnd, tangentBeginNext);
+ shouldFillEndCap(localUV, tangentBeginNext==vec2(0), endType, p[3], tangentEnd, tangentBeginNext);
if (hit)
{
diff --git a/ArchitectureColoredPainting/res/Shaders/painting.frag b/ArchitectureColoredPainting/res/Shaders/painting.frag
index 5fed343..4f69ed9 100644
--- a/ArchitectureColoredPainting/res/Shaders/painting.frag
+++ b/ArchitectureColoredPainting/res/Shaders/painting.frag
@@ -36,11 +36,6 @@ void main()
lod++;
gMetallicRoughness = mt.rg;
-// int pageSize = textureSize(texture_basecolor, levels-1).x;
-
-// uint pageId = 0;
-// for(uint i = 0; i < lodExpect; i++)
-// pageId += 1<<(2*(levels-1-i));
uint w = 1<<(levels-1-lodExpect);
ivec2 page = ivec2(TexCoords * vec2(w));
page = clamp(page, ivec2(0), ivec2(w-1));
@@ -49,7 +44,6 @@ void main()
gPaintingIndex = uvec2(0);
else
gPaintingIndex = uvec2((paintingId<<4)+lodExpect, (page.y<<8)+page.x);
- gPaintingTexCoord = vec2(1., 1.) - TexCoords * 2;
return;
}
\ No newline at end of file
diff --git a/ArchitectureColoredPainting/res/Shaders/painting.vert b/ArchitectureColoredPainting/res/Shaders/painting.vert
index 9c5f22f..f294dc6 100644
--- a/ArchitectureColoredPainting/res/Shaders/painting.vert
+++ b/ArchitectureColoredPainting/res/Shaders/painting.vert
@@ -14,7 +14,6 @@ uniform mat4 projection;
void main()
{
TexCoords = aTexCoords;
- TexCoords.y = -TexCoords.y;
WorldPos = vec3(model * vec4(aPos, 1.0));
Normal = mat3(model) * aNormal;
diff --git a/ArchitectureColoredPainting/src/Editor/EditorWidgetComponent/StrokeStyleWidget.cpp b/ArchitectureColoredPainting/src/Editor/EditorWidgetComponent/StrokeStyleWidget.cpp
new file mode 100644
index 0000000..00283ca
--- /dev/null
+++ b/ArchitectureColoredPainting/src/Editor/EditorWidgetComponent/StrokeStyleWidget.cpp
@@ -0,0 +1,216 @@
+#include "StrokeStyleWidget.h"
+#include "ColorPicker.h"
+#include
+#include
+
+#define radialStroke(stroke) std::dynamic_pointer_cast(stroke->materialStroke)
+constexpr int COLUMN_WIDTH = 0;
+constexpr int COLUMN_COLOR = 1;
+constexpr int COLUMN_METALLIC = 2;
+constexpr int COLUMN_ROUGHNESS = 3;
+constexpr int COLUMN_OPERATIONS = 4;
+
+// FIXME: Material的控件有显示bug
+StrokeStyleWidget::StrokeStyleWidget(
+ std::shared_ptr stroke,
+ QWidget* parent
+) : QWidget(parent), stroke(stroke)
+{
+ QVBoxLayout* viewLayout = new QVBoxLayout(this);
+ this->setLayout(viewLayout);
+
+ initStrokeSettings();
+ QWidget* strokeProperties = new QWidget(this);
+ QHBoxLayout* strokePropertiesLayout = new QHBoxLayout(strokeProperties);
+ strokePropertiesLayout->setMargin(0);
+
+ strokeProperties->setLayout(strokePropertiesLayout);
+ strokePropertiesLayout->addWidget(enableGradual);
+ strokePropertiesLayout->addWidget(endTypeBox);
+
+ viewLayout->addWidget(strokeProperties);
+ viewLayout->addWidget(widthField);
+
+ initTable(std::dynamic_pointer_cast(stroke->materialStroke));
+ viewLayout->addWidget(strokeTable);
+ this->adjustSize();
+}
+
+void StrokeStyleWidget::initStrokeSettings()
+{
+ this->enableGradual = new QtMaterialCheckBox(this);
+ enableGradual->setText(QStringLiteral("启用渐变"));
+ enableGradual->setChecked(radialStroke(stroke)->gradual);
+ connect(enableGradual, &QtMaterialCheckBox::toggled, [this](bool checked) {
+ radialStroke(this->stroke)->gradual = checked;
+ });
+
+#define endTypeBoxLabel(start, end) QStringLiteral(start##" -> "##end)
+ this->endTypeBox = new QComboBox(this);
+ endTypeBox->addItem(endTypeBoxLabel("圆头", "圆头")); // kRound
+ endTypeBox->addItem(endTypeBoxLabel("平头", "圆头")); // kFlatRound
+ endTypeBox->addItem(endTypeBoxLabel("圆头", "平头")); // kRoundFlat
+ endTypeBox->addItem(endTypeBoxLabel("平头", "平头")); // kFlat
+ endTypeBox->setCurrentIndex(static_cast(this->stroke->endType));
+ connect(endTypeBox, QOverload::of(&QComboBox::currentIndexChanged), [this](int index) {
+ switch (index)
+ {
+ case 0:
+ this->stroke->endType = Renderer::StrokeEndType::kRound;
+ break;
+ case 1:
+ this->stroke->endType = Renderer::StrokeEndType::kFlatRound;
+ break;
+ case 2:
+ this->stroke->endType = Renderer::StrokeEndType::kRoundFlat;
+ break;
+ case 3:
+ this->stroke->endType = Renderer::StrokeEndType::kFlat;
+ break;
+ }
+ });
+
+ this->widthField = new QtMaterialTextField(this);
+ widthField->setLabel(QStringLiteral("本侧描边宽度"));
+ widthField->setText(QString::number(stroke->halfWidth));
+ QDoubleValidator* widthValidator = new QDoubleValidator(0.1, std::numeric_limits::max(), 3, widthField);
+ widthValidator->setNotation(QDoubleValidator::StandardNotation);
+ widthField->setValidator(widthValidator);
+ connect(widthField, &QtMaterialTextField::textChanged, [this](const QString& changed) {
+ if (this->widthField->hasAcceptableInput())
+ {
+ this->stroke->halfWidth = changed.toFloat();
+ }
+ });
+}
+
+// TODO: 新增时参数校验
+void StrokeStyleWidget::initTable(std::shared_ptr materialStroke)
+{
+ this->strokeTable = new QTableWidget(this);
+ strokeTable->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow);
+ strokeTable->setColumnCount(5);
+ strokeTable->setRowCount(materialStroke->materialMap.size() + 1);
+ QStringList headers;
+ headers << QStringLiteral("离心距离占比")
+ << QStringLiteral("颜色")
+ << QStringLiteral("金属度")
+ << QStringLiteral("粗糙度")
+ << QStringLiteral("其他操作");
+ strokeTable->setHorizontalHeaderLabels(headers);
+ int row = 0;
+ // 内容
+ for (auto & strokePair : materialStroke->materialMap)
+ {
+ setTableRow(row, strokePair.first, strokePair.second);
+ row++;
+ }
+ // 新增按钮
+ QtMaterialRaisedButton* addButton = new QtMaterialRaisedButton("+", strokeTable);
+ strokeTable->setSpan(row, 0, 1, 5);
+ strokeTable->setCellWidget(row, 0, addButton);
+ connect(addButton, &QtMaterialRaisedButton::clicked, [this]() {
+ handlingRowInsert = true;
+ auto materialMap = &(radialStroke(this->stroke)->materialMap);
+ float newWidth = 0;
+ if (materialMap->size() == 0)
+ {
+ newWidth = 0.1;
+ }
+ else
+ {
+ auto lastPair = materialMap->rbegin();
+ newWidth = lastPair->first + 0.01;
+ }
+ Renderer::Material newMaterial = { QColor::fromRgb(0,0,0), 0.f, .8f };
+ (*materialMap)[newWidth] = newMaterial;
+ int newRow = this->strokeTable->rowCount() - 1;
+ this->strokeTable->insertRow(newRow);
+ setTableRow(newRow, newWidth, (*materialMap)[newWidth]);
+ this->strokeTable->update();
+ handlingRowInsert = false;
+ });
+
+ connect(strokeTable, &QTableWidget::currentItemChanged, this, &StrokeStyleWidget::onCurrentItemChanged);
+ connect(strokeTable, &QTableWidget::cellChanged, this, &StrokeStyleWidget::onCellChanged);
+}
+
+void StrokeStyleWidget::setTableRow(int row, float width, Renderer::Material& material)
+{
+ QTableWidgetItem* widthItem = new QTableWidgetItem;
+ widthItem->setData(Qt::EditRole, width);
+ strokeTable->setItem(row, COLUMN_WIDTH, widthItem);
+
+ QColor* colorPtr = &(material.color);
+ QTableWidgetItem* colorItem = new QTableWidgetItem;
+ colorItem->setData(Qt::DisplayRole, *colorPtr);
+ strokeTable->setItem(row, COLUMN_COLOR, colorItem);
+ ColorPicker* colorPicker = new ColorPicker(*colorPtr, strokeTable);
+ strokeTable->setCellWidget(row, COLUMN_COLOR, colorPicker);
+ connect(colorPicker, &ColorPicker::colorChanged, [this, colorPtr](QColor color) {
+ *colorPtr = color;
+ this->strokeTable->update();
+ });
+
+ QTableWidgetItem* metallicItem = new QTableWidgetItem;
+ metallicItem->setData(Qt::EditRole, material.metallic);
+ strokeTable->setItem(row, COLUMN_METALLIC, metallicItem);
+
+ QTableWidgetItem* roughnessItem = new QTableWidgetItem;
+ roughnessItem->setData(Qt::EditRole, material.roughness);
+ strokeTable->setItem(row, COLUMN_ROUGHNESS, roughnessItem);
+
+ QtMaterialRaisedButton* removeButton = new QtMaterialRaisedButton("-", strokeTable);
+ removeButton->setFixedSize(20, 20);
+ strokeTable->setCellWidget(row, COLUMN_OPERATIONS, removeButton);
+ connect(removeButton, &QtMaterialRaisedButton::clicked, [this, row]() {
+ if (this->strokeTable->rowCount() <= 1) return;
+ radialStroke(this->stroke)->materialMap.erase(this->strokeTable->item(row, COLUMN_WIDTH)->text().toFloat());
+ this->strokeTable->removeRow(row);
+ });
+}
+
+void StrokeStyleWidget::onCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous)
+{
+ if (!current) return;
+ int column = current->column();
+ if (column != COLUMN_COLOR && column != COLUMN_OPERATIONS)
+ {
+ this->currentItemValue = current->data(Qt::EditRole);
+ }
+}
+
+void StrokeStyleWidget::onCellChanged(int row, int column)
+{
+ if (handlingRowInsert) return;
+ auto changedItem = strokeTable->item(row, column);
+ auto changedItemValue = changedItem->text().toFloat();
+ if (changedItemValue < 0 || 1 < changedItemValue)
+ {
+ changedItem->setData(Qt::EditRole, this->currentItemValue.toFloat());
+ return;
+ }
+ auto changedWidth = strokeTable->item(row, COLUMN_WIDTH)->data(Qt::EditRole).toFloat();
+ switch (column)
+ {
+ case COLUMN_WIDTH:
+ {
+ float oldWidth = this->currentItemValue.toFloat();
+ auto node = radialStroke(stroke)->materialMap.extract(oldWidth);
+ node.key() = changedWidth;
+ radialStroke(stroke)->materialMap.insert(std::move(node));
+ strokeTable->sortItems(COLUMN_WIDTH);
+ break;
+ }
+ case COLUMN_METALLIC:
+ {
+ radialStroke(stroke)->materialMap[changedWidth].metallic = changedItemValue;
+ break;
+ }
+ case COLUMN_ROUGHNESS:
+ {
+ radialStroke(stroke)->materialMap[changedWidth].roughness = changedItemValue;
+ break;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ArchitectureColoredPainting/src/Editor/EditorWidgetComponent/StrokeStyleWidget.h b/ArchitectureColoredPainting/src/Editor/EditorWidgetComponent/StrokeStyleWidget.h
new file mode 100644
index 0000000..6d5dbdd
--- /dev/null
+++ b/ArchitectureColoredPainting/src/Editor/EditorWidgetComponent/StrokeStyleWidget.h
@@ -0,0 +1,33 @@
+#pragma once
+#include "LayerStyle.h"
+#include "../Renderer/Painting/MaterialStyleStroke.h"
+#include
+#include
+#include
+#include
+#include
+class StrokeStyleWidget : public QWidget
+{
+ Q_OBJECT
+private:
+ QVariant currentItemValue;
+
+ QtMaterialCheckBox* enableGradual;
+ QComboBox* endTypeBox;
+ QtMaterialTextField* widthField;
+ QTableWidget* strokeTable;
+ bool handlingRowInsert = false;
+
+ void initStrokeSettings();
+ void initTable(std::shared_ptr materialStroke);
+ void setTableRow(int row, float width, Renderer::Material& material);
+
+public:
+ StrokeStyleWidget(std::shared_ptr stroke, QWidget* parent = nullptr);
+ std::shared_ptr stroke;
+
+protected slots:
+ void onCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous);
+ void onCellChanged(int row, int column);
+};
+
diff --git a/ArchitectureColoredPainting/src/Editor/LayerStyle.cpp b/ArchitectureColoredPainting/src/Editor/LayerStyle.cpp
index e44e855..9b65355 100644
--- a/ArchitectureColoredPainting/src/Editor/LayerStyle.cpp
+++ b/ArchitectureColoredPainting/src/Editor/LayerStyle.cpp
@@ -1,5 +1,6 @@
#include "LayerStyle.h"
-#include "./EditorWidgetComponent/StrokeStyleListView.h"
+#include "./EditorWidgetComponent/StrokeStyleWidget.h"
+#include "./util/JsonUtil.hpp"
#include
#include
#include
@@ -50,8 +51,7 @@ QWidget* StrokeElementLayerStyle::getInputWidget()
if (this->strokePair.first == nullptr)
{
auto materialMap = std::map();
- materialMap[0.3] = Renderer::Material{ QColor(0,255,255), 0.f, .8f };
- materialMap[1.0] = Renderer::Material{ QColor(80,25,255), 0.f, .8f };
+ materialMap[1.0] = Renderer::Material{ QColor(0, 0, 0), 0.f, .8f };
this->strokePair.first = std::shared_ptr(new Renderer::MaterialStyleStroke(
15,
Renderer::StrokeType::kLeftSide, Renderer::StrokeEndType::kFlat,
@@ -63,8 +63,7 @@ QWidget* StrokeElementLayerStyle::getInputWidget()
if (this->strokePair.second == nullptr)
{
auto materialMap = std::map();
- materialMap[0.3] = Renderer::Material{ QColor(0,255,255), 0.f, .8f };
- materialMap[1.0] = Renderer::Material{ QColor(80,25,255), 0.f, .8f };
+ materialMap[1.0] = Renderer::Material{ QColor(0, 0, 0), 0.f, .8f };
this->strokePair.second = std::shared_ptr(new Renderer::MaterialStyleStroke(
15,
Renderer::StrokeType::kRightSide, Renderer::StrokeEndType::kFlat,
@@ -79,9 +78,7 @@ QWidget* StrokeElementLayerStyle::getInputWidget()
QVBoxLayout* layout = new QVBoxLayout(w);
layout->setMargin(0);
- StrokeStyleListView* leftStrokeView = new StrokeStyleListView(
- std::dynamic_pointer_cast(this->strokePair.first->materialStroke), w
- );
+ StrokeStyleWidget* leftStrokeView = new StrokeStyleWidget(this->strokePair.first, w);
layout->addWidget(leftStrokeView);
QtMaterialCheckBox* checkEachSideIndependent = new QtMaterialCheckBox(w);
@@ -89,9 +86,7 @@ QWidget* StrokeElementLayerStyle::getInputWidget()
checkEachSideIndependent->setChecked(enableEachSideIndependent);
layout->addWidget(checkEachSideIndependent);
- StrokeStyleListView* rightStrokeView = new StrokeStyleListView(
- std::dynamic_pointer_cast(this->strokePair.second->materialStroke), w
- );
+ StrokeStyleWidget* rightStrokeView = new StrokeStyleWidget(this->strokePair.second, w);
layout->addWidget(rightStrokeView);
rightStrokeView->setDisabled(!this->enableEachSideIndependent);
@@ -124,6 +119,16 @@ StrokeElementLayerStyle::StrokeElementLayerStyle(const StrokeElementLayerStyle&
enableEachSideIndependent = other.enableEachSideIndependent;
}
+QJsonObject StrokeElementLayerStyle::toJson() const
+{
+ QJsonObject json;
+ json.insert("type", "stroke");
+ json.insert("enableEachSideIndependent", enableEachSideIndependent);
+ json.insert("left", JsonUtil::toQJsonArray(strokePair.first->encoded()));
+ json.insert("right", JsonUtil::toQJsonArray(strokePair.second->encoded()));
+ return json;
+}
+
std::unique_ptr StrokeElementLayerStyle::clone() const
{
return std::make_unique(StrokeElementLayerStyle(*this));
@@ -167,7 +172,17 @@ FillElementLayerStyle::FillElementLayerStyle(const FillElementLayerStyle& other)
}
}
+QJsonObject FillElementLayerStyle::toJson() const
+{
+ return QJsonObject();
+}
+
std::unique_ptr FillElementLayerStyle::clone() const
{
return std::make_unique(FillElementLayerStyle(*this));
}
+
+std::unique_ptr LayerStyle::fromJson(const QJsonObject& json)
+{
+ return std::unique_ptr();
+}
diff --git a/ArchitectureColoredPainting/src/Editor/LayerStyle.h b/ArchitectureColoredPainting/src/Editor/LayerStyle.h
index 7d5fb25..6717299 100644
--- a/ArchitectureColoredPainting/src/Editor/LayerStyle.h
+++ b/ArchitectureColoredPainting/src/Editor/LayerStyle.h
@@ -5,6 +5,7 @@
#include
#include
#include
+#include
#include "../Renderer/Painting/ElementStyle.h"
#include "../Renderer/Painting/MaterialStyleStroke.h"
#include "../Renderer/Painting/MaterialStyleFill.h"
@@ -23,10 +24,13 @@ class LayerStyle : public Renderer::ElementStyle
{
public:
const static std::vector()>>> types;
+ static std::unique_ptr fromJson(const QJsonObject& json);
+
virtual QString getStyleName() const = 0;
virtual QWidget* getInputWidget() = 0;
virtual QWidget* getListDisplayWidget() const = 0;
virtual ~LayerStyle() {};
+ virtual QJsonObject toJson() const = 0;
virtual std::unique_ptr clone() const = 0;
};
@@ -43,6 +47,7 @@ public:
StrokeElementLayerStyle() = default;
StrokeElementLayerStyle(const StrokeElementLayerStyle& other);
~StrokeElementLayerStyle() = default;
+ QJsonObject toJson() const override;
std::unique_ptr clone() const override;
bool enableEachSideIndependent = false;
@@ -59,5 +64,6 @@ public:
FillElementLayerStyle(const FillElementLayerStyle& other);
~FillElementLayerStyle() = default;
std::vector> materialStyles;
+ QJsonObject toJson() const override;
std::unique_ptr clone() const override;
};
\ No newline at end of file
diff --git a/ArchitectureColoredPainting/src/Editor/LayerWrapper.cpp b/ArchitectureColoredPainting/src/Editor/LayerWrapper.cpp
index 4119277..d5229e9 100644
--- a/ArchitectureColoredPainting/src/Editor/LayerWrapper.cpp
+++ b/ArchitectureColoredPainting/src/Editor/LayerWrapper.cpp
@@ -240,6 +240,10 @@ QJsonObject LeafLayerWrapper::toJson() const
QJsonObject json = LayerWrapper::toJson();
json.insert("element", wrappedElement->index);
json.insert("is-folder", false);
+ QJsonArray stylesJson;
+ for (auto& style : styles)
+ stylesJson.push_back(style->toJson());
+ json.insert("styles", stylesJson);
return json;
}
diff --git a/ArchitectureColoredPainting/src/Editor/LayerWrapper.h b/ArchitectureColoredPainting/src/Editor/LayerWrapper.h
index ef825df..9a76c3b 100644
--- a/ArchitectureColoredPainting/src/Editor/LayerWrapper.h
+++ b/ArchitectureColoredPainting/src/Editor/LayerWrapper.h
@@ -6,6 +6,7 @@
#include
#include
#include
+#include
#include
#include
#include
diff --git a/ArchitectureColoredPainting/src/Editor/util/JsonUtil.hpp b/ArchitectureColoredPainting/src/Editor/util/JsonUtil.hpp
new file mode 100644
index 0000000..e393f38
--- /dev/null
+++ b/ArchitectureColoredPainting/src/Editor/util/JsonUtil.hpp
@@ -0,0 +1,14 @@
+#pragma once
+#include
+
+namespace JsonUtil
+{
+#include
+ template
+ QJsonArray toQJsonArray(const std::vector& vec)
+ {
+ QJsonArray array;
+ std::copy(vec.begin(), vec.end(), std::back_inserter(array));
+ return array;
+ }
+}
diff --git a/ArchitectureColoredPainting/src/Renderer/Model.cpp b/ArchitectureColoredPainting/src/Renderer/Model.cpp
index 917ecc9..4f62c3b 100644
--- a/ArchitectureColoredPainting/src/Renderer/Model.cpp
+++ b/ArchitectureColoredPainting/src/Renderer/Model.cpp
@@ -52,7 +52,7 @@ void Renderer::Model::loadModel(QString path)
directory = modelFile.dir();
Assimp::Importer importer;
- const aiScene* scene = importer.ReadFile(modelFile.absoluteFilePath().toUtf8(), aiProcess_Triangulate /*| aiProcess_FlipUVs*/);
+ const aiScene* scene = importer.ReadFile(modelFile.absoluteFilePath().toUtf8(), aiProcess_Triangulate);
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
{
qCritical() << "ERROR::ASSIMP::" << importer.GetErrorString() << endl;
@@ -229,8 +229,104 @@ GLuint Renderer::Model::loadPainting(std::string path)
if (iter != paintingLoaded.end())
return iter->second;
- Painting painting = PaintingUtil::transfromToPainting("../data.json");
+ Painting painting;
+ if (auto file = QFileInfo(QString(path.c_str())); file.isFile())
+ painting = PaintingUtil::transfromToPainting(file.path());
+ else
+ {
+ qDebug() << path.c_str() << "Not Found, Using Default Painting";
+ vector, float>> contours;
+ QPainterPath painterPaths[3];
+ QQuickSvgParser::parsePathDataFast("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z",
+ painterPaths[0]);
+ if (!SvgFileLoader().loadSvgFile("../svg/2.svg", painterPaths[1]))
+ qCritical() << "load error";
+ /*QQuickSvgParser::parsePathDataFast("M292.82,107.78s0,0,0,0,0,3.59,0,7.62c0,3.85,0,5.78.06,6.43a19.94,19.94,0,0,0,2.87,7.58,15.85,15.85,0,0,0,6.61,6.23A14.75,14.75,0,0,0,310,137a11.69,11.69,0,0,0,7.59-2.92,11,11,0,0,0,3.2-6.84c.15-1.27.58-4.84-1.79-7.64a8.54,8.54,0,0,0-3.56-2.44c-1.32-.52-3.32-1.31-5.06-.33a5.41,5.41,0,0,0-2.14,3,3.48,3.48,0,0,0-.16,2.71c.78,1.86,3.36,2.14,3.47,2.15",
+ painterPaths[1]);*/
+ QQuickSvgParser::parsePathDataFast("M377,459.61a11.26,11.26,0,0,1,11.27-11.27H696.12a11.27,11.27,0,0,0,11-8.62A359.84,359.84,0,0,0,708,280.56a11.26,11.26,0,0,0-11-8.73H388.27A11.26,11.26,0,0,1,377,260.57h0a11.26,11.26,0,0,1,11.27-11.26H683.71A11.32,11.32,0,0,0,694.28,234C649.8,113.69,542.57,23.85,412.3,4.12a11.22,11.22,0,0,0-12.76,11.17v158.9a11.26,11.26,0,0,0,11.26,11.27H583.12a11.32,11.32,0,0,0,9.26-17.75c-31.67-46.59-78.51-75.2-109.11-90.07a11.25,11.25,0,0,0-16.13,10.17V115.2a11.24,11.24,0,0,0,6.22,10.07l7.51,3.76a11.28,11.28,0,0,1,5,15.12h0a11.27,11.27,0,0,1-15.11,5l-20-10a11.27,11.27,0,0,1-6.22-10.07V54a11.27,11.27,0,0,1,14.62-10.75c5.11,1.59,125.66,40.35,172.24,149A11.27,11.27,0,0,1,621.11,208H388.27A11.26,11.26,0,0,1,377,196.73V11.36A11.32,11.32,0,0,0,365.89.08C363.34,0,360.79,0,358.22,0s-5.11,0-7.66.08a11.32,11.32,0,0,0-11.11,11.28V196.74A11.26,11.26,0,0,1,328.18,208H95.35A11.27,11.27,0,0,1,85,192.3c46.57-108.67,167.12-147.42,172.23-149A11.26,11.26,0,0,1,271.86,54v75.11a11.25,11.25,0,0,1-6.23,10.07l-20,10a11.27,11.27,0,0,1-15.11-5h0a11.26,11.26,0,0,1,5-15.11l7.52-3.76a11.27,11.27,0,0,0,6.22-10.07V87.82a11.25,11.25,0,0,0-16.14-10.16c-30.6,14.87-77.45,43.48-109.1,90.07a11.3,11.3,0,0,0,9.25,17.74H305.66a11.26,11.26,0,0,0,11.27-11.26V15.31A11.22,11.22,0,0,0,304.17,4.14C173.88,23.86,66.66,113.71,22.17,234a11.32,11.32,0,0,0,10.56,15.29H328.18a11.26,11.26,0,0,1,11.27,11.26v0a11.26,11.26,0,0,1-11.27,11.26H19.52a11.26,11.26,0,0,0-11,8.72,359.84,359.84,0,0,0,.83,159.16,11.26,11.26,0,0,0,11,8.61H328.18a11.26,11.26,0,0,1,11.27,11.27h0a11.26,11.26,0,0,1-11.27,11.26h-294a11.32,11.32,0,0,0-10.53,15.4C69,604.65,175.3,692.78,304.16,712.3a11.21,11.21,0,0,0,12.76-11.16V542.22A11.26,11.26,0,0,0,305.66,531h-166c-9.53,0-14.89,11.22-8.69,18.47,34.09,39.77,74.45,65.66,101.77,80.18a11.25,11.25,0,0,0,16.53-10V591a11.26,11.26,0,0,1,11.26-11.26h0A11.26,11.26,0,0,1,271.85,591v63.85A11.27,11.27,0,0,1,256.8,665.5c-4.45-1.59-109.58-40-171-139.9a11.27,11.27,0,0,1,9.59-17.17H328.18a11.26,11.26,0,0,1,11.27,11.26V705.08a11.32,11.32,0,0,0,11.11,11.28q3.82.07,7.66.08c2.57,0,5.12,0,7.67-.08A11.32,11.32,0,0,0,377,705.08V519.69a11.25,11.25,0,0,1,11.27-11.26H621.1a11.26,11.26,0,0,1,9.59,17.16c-61.46,99.87-166.59,138.3-171,139.9a11.27,11.27,0,0,1-15-10.61V591a11.26,11.26,0,0,1,11.26-11.26h0A11.26,11.26,0,0,1,467.14,591v28.6a11.25,11.25,0,0,0,16.53,10c27.33-14.53,67.68-40.42,101.77-80.19,6.2-7.23.85-18.46-8.69-18.46h-166a11.26,11.26,0,0,0-11.26,11.26V701.12a11.21,11.21,0,0,0,12.76,11.17c128.86-19.51,235.14-107.66,280.48-226a11.33,11.33,0,0,0-10.53-15.41h-294A11.25,11.25,0,0,1,377,459.61ZM35.27,399.53V316.9a11.26,11.26,0,0,1,11.27-11.26H669.92a11.25,11.25,0,0,1,11.26,11.26v82.63a11.25,11.25,0,0,1-11.26,11.26H46.54a11.27,11.27,0,0,1-11.27-11.26Z",
+ painterPaths[2]);
+
+ for (auto& i : painterPaths)
+ {
+ auto [contour, ratio] = PainterPathUtil::toNormalizedLines(i);
+ contours.emplace_back(std::make_shared(contour), ratio);
+ }
+
+ vector> style = {
+ std::make_shared(),
+ std::make_shared(0.02),
+ std::make_shared(0.2)
+ };
+
+ vector> element = {
+ std::make_shared(Element{ contours[0].first, style[0], contours[0].second}),
+ std::make_shared(Element{ contours[1].first, style[2], contours[1].second}),
+ std::make_shared(Element{ contours[2].first, style[0], contours[2].second}),
+ };
+
+ if (path == "0.json")
+ {
+ painting.addElement(*element[0], ElementTransform{ glm::vec2(-0.45,-0.45), glm::vec2(0.5,0.5) / 2.f, 0, glm::bvec2(false), 0 });
+ painting.addElement(*element[1], ElementTransform{ glm::vec2(-0.45, 0.45), glm::vec2(0.5,0.5) / 2.f, 0, glm::bvec2(false), 0 });
+ painting.addElement(*element[2], ElementTransform{ glm::vec2(0.50,-0.45), glm::vec2(0.6,0.7) / 2.f, 0, glm::bvec2(false), 0 });
+ }
+ else if (path == "1.json")
+ {
+ float widths[] = { 0.43, 0.43 * 0.25 / 0.15, 0.43 * 0.25 / 0.15 };
+ QPainterPath painterPaths[6];
+ for (int i = 0; i < 6; i++)
+ if (!SvgFileLoader().loadSvgFile(QString(std::format("../svg/{}.svg", i + 1).c_str()), painterPaths[i]))
+ qCritical() << "load error";
+
+ vector, float>> contours;
+ for (int i = 0; i < 3; i++)
+ {
+ auto [contour, ratio] = PainterPathUtil::toNormalizedLines(painterPaths[i], widths[i]);
+ contours.emplace_back(std::make_shared(contour), ratio);
+ }
+ class StyleStrokeRadialGradient : public Renderer::ElementStyle
+ {
+ public:
+ float width;
+ StrokeType type;
+ StyleStrokeRadialGradient(float width, StrokeType type) :width(width), type(type) {};
+ virtual std::vector toBaseStyles() const override
+ {
+ std::map materialMap = {
+ {0.09, Material{QColor(255,255,255),0,0.8}},
+ {0.63, Material{QColor(165,176,207),0,0.8}},
+ {1.00, Material{QColor(58,64,151),0,0.8}}
+ };
+ return { BaseStyle(std::make_shared(),
+ std::make_shared(width, type, StrokeEndType::kFlat,
+ std::make_shared(materialMap, false))) };
+ }
+ };
+ vector> style = {
+ std::make_shared(widths[0], StrokeType::kLeftSide),
+ std::make_shared(widths[1], StrokeType::kRightSide),
+ std::make_shared(widths[2], StrokeType::kLeftSide),
+ };
+ vector> element = {
+ std::make_shared(Element{ contours[0].first, style[0], contours[0].second}),
+ std::make_shared(Element{ contours[1].first, style[1], contours[1].second}),
+ std::make_shared(Element{ contours[2].first, style[2], contours[2].second}),
+ };
+ painting.addElement(*element[0], ElementTransform{ glm::vec2(-0.45,0.45), glm::vec2(0.25), 0, glm::bvec2(false), 0 });
+ painting.addElement(*element[1], ElementTransform{ glm::vec2(-0.535,0.33), glm::vec2(0.15), 0, glm::bvec2(false), 0 });
+ painting.addElement(*element[2], ElementTransform{ glm::vec2(-0.535,0.23), glm::vec2(0.15), 0, glm::bvec2(false), 0 });
+ }
+ else
+ {
+ for (int i = 0; i < 1000; i++)
+ {
+ float x = (float)rand() / RAND_MAX * 2 - 1;
+ float y = (float)rand() / RAND_MAX * 2 - 1;
+ painting.addElement(*element[i % 3], ElementTransform{ glm::vec2(x,y), glm::vec2(0.025), (float)rand() / RAND_MAX * 360, glm::bvec2(false), 0 });
+ }
+ }
+ }
painting.generateBuffers(glFunc);
auto index = vtManager->createVirtualTexture(painting);
diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.cpp b/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.cpp
index f1b2088..a22470c 100644
--- a/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.cpp
+++ b/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.cpp
@@ -1,6 +1,43 @@
#include "BaseStyle.h"
+#include "MaterialStyleFill.h"
+#include "MaterialStyleStroke.h"
using namespace Renderer;
+using namespace glm;
+
+Renderer::Material::Material(const QColor& color, float metallic, float roughness)
+ : color(color)
+{
+ setMetallicF(metallic);
+ setRoughnessF(roughness);
+}
+
+Renderer::Material::Material(const glm::vec4& color, const glm::vec2& metallicRoughness)
+ : color(QColor::fromRgbF(color.r, color.g, color.b, color.a))
+{
+ setMetallicF(metallicRoughness.r);
+ setRoughnessF(metallicRoughness.g);
+}
+
+float Renderer::Material::metallicF() const
+{
+ return metallic / 255.f;
+}
+
+float Renderer::Material::roughnessF() const
+{
+ return roughness / 255.f;
+}
+
+void Renderer::Material::setMetallicF(float metallic)
+{
+ this->metallic = metallic * 255;
+}
+
+void Renderer::Material::setRoughnessF(float roughness)
+{
+ this->roughness = roughness * 255;
+}
bool Renderer::Material::operator==(const Material& m) const
{
@@ -9,5 +46,52 @@ bool Renderer::Material::operator==(const Material& m) const
std::pair Renderer::Material::toVec() const
{
- return { glm::vec4(color.redF(), color.greenF(), color.blueF(), color.alphaF()), glm::vec2(metallic, roughness)};
+ return { glm::vec4(color.redF(), color.greenF(), color.blueF(), color.alphaF()), glm::vec2(metallicF(), roughnessF())};
+}
+
+std::unique_ptr Renderer::MaterialStyle::decoded(const std::vector& encoded)
+{
+ if (encoded[0] <= 0) /// MaterialStyleFill
+ {
+ std::unique_ptr materiallFill;
+ glm::vec4 head = glm::unpackUnorm4x8(glm::floatBitsToUint(encoded[0]));
+ if (head.z == 0)
+ {
+ materiallFill = std::make_unique(Material(glm::unpackUnorm4x8(glm::floatBitsToUint(encoded[1])), glm::vec2(head.r, head.g)));
+ }
+ return std::make_unique(std::move(materiallFill));
+ }
+ else /// MaterialStyleStroke
+ {
+ std::unique_ptr materialStroke;
+ uint headUint = floatBitsToUint(encoded[1]);
+ vec4 head = unpackUnorm4x8(headUint);
+ StrokeType strokeType = (StrokeType)floor(head.b * 10);
+ StrokeEndType endType = (StrokeEndType)(int(round(head.b * 100)) % 10);
+ switch (int(head.a * 100) % 10)
+ {
+ /// Plain
+ case 0: {
+ materialStroke = std::make_unique(Material(glm::unpackUnorm4x8(glm::floatBitsToUint(encoded[2])), glm::vec2(head.r, head.g)));
+ break;
+ }
+ /// RadialGradient
+ case 1: {
+ uint size = headUint % (1 << 15);
+ bool gradual = (headUint & (1 << 15)) != 0;
+ std::map materialMap;
+ for (uint i = 0; i < size; i++)
+ {
+ auto data = floatBitsToUint(encoded[2 + i * 2]);
+ auto level = unpackUnorm2x16(data).y;
+ auto color = unpackUnorm4x8(floatBitsToUint(encoded[3 + i * 2]));
+ auto metallicRoughness = unpackUnorm4x8(data);
+ materialMap.emplace(level, Material(color, glm::vec2(metallicRoughness.r, metallicRoughness.g)));
+ }
+ materialStroke = std::make_unique(materialMap, gradual);
+ break;
+ }
+ }
+ return std::make_unique(encoded[0], strokeType, endType, std::move(materialStroke));
+ }
}
diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.h b/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.h
index 6a1e7a8..051221f 100644
--- a/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.h
+++ b/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.h
@@ -25,6 +25,7 @@ namespace Renderer
virtual std::vector encoded() const = 0;
virtual std::unique_ptr clone() const = 0;
virtual bool operator==(const MaterialStyle&) const = 0;
+ static std::unique_ptr decoded(const std::vector& encoded);
};
struct BaseStyle
@@ -36,8 +37,16 @@ namespace Renderer
struct Material
{
QColor color;
- float metallic;
- float roughness;
+ std::uint8_t metallic;
+ std::uint8_t roughness;
+
+ Material() = default;
+ Material(const QColor& color, float metallic = 0, float roughness = 0.5);
+ Material(const glm::vec4& color, const glm::vec2& metallicRoughness);
+ float metallicF() const;
+ float roughnessF() const;
+ void setMetallicF(float metallic);
+ void setRoughnessF(float roughness);
bool operator==(const Material&) const;
std::pair toVec() const;
};
diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/MaterialStyleFill.cpp b/ArchitectureColoredPainting/src/Renderer/Painting/MaterialStyleFill.cpp
index 318895c..ec29f9b 100644
--- a/ArchitectureColoredPainting/src/Renderer/Painting/MaterialStyleFill.cpp
+++ b/ArchitectureColoredPainting/src/Renderer/Painting/MaterialStyleFill.cpp
@@ -3,7 +3,12 @@
using namespace Renderer;
Renderer::FillPlain::FillPlain(QColor color, float metallic, float roughness)
- : color(color), metallic(metallic), roughness(roughness)
+ : material(color, metallic, roughness)
+{
+}
+
+Renderer::FillPlain::FillPlain(const Material& material)
+ : material(material)
{
}
@@ -14,8 +19,9 @@ MaterialFillType Renderer::FillPlain::type() const
std::vector Renderer::FillPlain::encoded() const
{
- return { glm::uintBitsToFloat(glm::packUnorm4x8(glm::vec4(metallic, roughness, 0, 1))),
- glm::uintBitsToFloat(glm::packUnorm4x8(glm::vec4(color.redF(), color.greenF(), color.blueF(), color.alphaF())))};
+ auto pair = material.toVec();
+ return { glm::uintBitsToFloat(glm::packUnorm4x8(glm::vec4(pair.second, 0, 1))),
+ glm::uintBitsToFloat(glm::packUnorm4x8(pair.first))};
}
std::unique_ptr Renderer::FillPlain::clone() const
@@ -26,9 +32,7 @@ std::unique_ptr Renderer::FillPlain::clone() const
bool Renderer::FillPlain::operator==(const MaterialFill& m) const
{
return type() == m.type()
- && color == static_cast(m).color
- && metallic == static_cast(m).metallic
- && roughness == static_cast(m).roughness;
+ && material == static_cast(m).material;
}
diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/MaterialStyleFill.h b/ArchitectureColoredPainting/src/Renderer/Painting/MaterialStyleFill.h
index e3c1001..1910c65 100644
--- a/ArchitectureColoredPainting/src/Renderer/Painting/MaterialStyleFill.h
+++ b/ArchitectureColoredPainting/src/Renderer/Painting/MaterialStyleFill.h
@@ -18,14 +18,13 @@ namespace Renderer
{
public:
FillPlain(QColor color, float metallic, float roughness);
+ FillPlain(const Material& material);
virtual MaterialFillType type() const override;
virtual std::vector encoded() const override;
virtual std::unique_ptr clone() const override;
virtual bool operator==(const MaterialFill&) const override;
- QColor color;
- float metallic;
- float roughness;
+ Material material;
};
class MaterialStyleFill : public MaterialStyle
diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/MaterialStyleStroke.cpp b/ArchitectureColoredPainting/src/Renderer/Painting/MaterialStyleStroke.cpp
index 371cb86..3c8686b 100644
--- a/ArchitectureColoredPainting/src/Renderer/Painting/MaterialStyleStroke.cpp
+++ b/ArchitectureColoredPainting/src/Renderer/Painting/MaterialStyleStroke.cpp
@@ -76,8 +76,8 @@ bool Renderer::StrokeRadialGradient::operator==(const MaterialStroke& m) const
&& materialMap == static_cast(m).materialMap;
}
-Renderer::MaterialStyleStroke::MaterialStyleStroke(float width, StrokeType strokeType, StrokeEndType endType, std::shared_ptr materialStroke)
- : halfWidth(width/2), strokeType(strokeType), endType(endType), materialStroke(materialStroke)
+Renderer::MaterialStyleStroke::MaterialStyleStroke(float halfWidth, StrokeType strokeType, StrokeEndType endType, std::shared_ptr materialStroke)
+ : halfWidth(halfWidth), strokeType(strokeType), endType(endType), materialStroke(materialStroke)
{
}
@@ -100,7 +100,7 @@ std::vector Renderer::MaterialStyleStroke::encoded() const
std::unique_ptr Renderer::MaterialStyleStroke::clone() const
{
- return std::make_unique(halfWidth*2, strokeType, endType, materialStroke->clone());
+ return std::make_unique(halfWidth, strokeType, endType, materialStroke->clone());
}
bool Renderer::MaterialStyleStroke::operator==(const MaterialStyle& m) const
diff --git a/UnitTest/ElementRendererTest.cpp b/UnitTest/ElementRendererTest.cpp
index 7a0c035..ca1fbca 100644
--- a/UnitTest/ElementRendererTest.cpp
+++ b/UnitTest/ElementRendererTest.cpp
@@ -40,7 +40,7 @@ namespace UnitTest
{1.00, Material{QColor(58,64,151)}}
};
return { BaseStyle(std::make_shared(),
- std::make_shared(60, StrokeType::kBothSides, StrokeEndType::kRound,
+ std::make_shared(30, StrokeType::kBothSides, StrokeEndType::kRound,
std::make_shared(materialMap, false))) };
}
} style;
@@ -61,7 +61,7 @@ namespace UnitTest
{1.00, Material{QColor(58,64,151)}}
};
return { BaseStyle(std::make_shared(),
- std::make_shared(60, StrokeType::kBothSides, StrokeEndType::kFlat,
+ std::make_shared(30, StrokeType::kBothSides, StrokeEndType::kFlat,
std::make_shared(materialMap, false))) };
}
} style;
@@ -82,7 +82,7 @@ namespace UnitTest
{1.00, Material{QColor(58,64,151)}}
};
return { BaseStyle(std::make_shared(),
- std::make_shared(60, StrokeType::kLeftSide, StrokeEndType::kRound,
+ std::make_shared(30, StrokeType::kLeftSide, StrokeEndType::kRound,
std::make_shared(materialMap, false))) };
}
} style;
@@ -103,7 +103,7 @@ namespace UnitTest
{1.00, Material{QColor(58,64,151)}}
};
return { BaseStyle(std::make_shared(),
- std::make_shared(60, StrokeType::kLeftSide, StrokeEndType::kFlat,
+ std::make_shared(30, StrokeType::kLeftSide, StrokeEndType::kFlat,
std::make_shared(materialMap, false))) };
}
} style;
@@ -124,7 +124,7 @@ namespace UnitTest
{1.00, Material{QColor(58,64,151)}}
};
return { BaseStyle(std::make_shared(),
- std::make_shared(160, StrokeType::kRightSide, StrokeEndType::kFlatRound,
+ std::make_shared(80, StrokeType::kRightSide, StrokeEndType::kFlatRound,
std::make_shared(materialMap, false))) };
}
} style;
@@ -149,7 +149,7 @@ namespace UnitTest
virtual std::vector toBaseStyles() const override
{
return { BaseStyle(std::make_shared(),
- std::make_shared(60, StrokeType::kBothSides, StrokeEndType::kRound,
+ std::make_shared(30, StrokeType::kBothSides, StrokeEndType::kRound,
std::make_shared(QColor(255,255,255),1,1))) };
}
} style;
@@ -170,7 +170,7 @@ namespace UnitTest
{1.00, Material{QColor(58,64,151)}}
};
return { BaseStyle(std::make_shared(),
- std::make_shared(60, StrokeType::kBothSides, StrokeEndType::kRound,
+ std::make_shared(30, StrokeType::kBothSides, StrokeEndType::kRound,
std::make_shared(materialMap, false))) };
}
} style;
diff --git a/UnitTest/StyleTest.cpp b/UnitTest/StyleTest.cpp
new file mode 100644
index 0000000..f3bf969
--- /dev/null
+++ b/UnitTest/StyleTest.cpp
@@ -0,0 +1,54 @@
+#include "CppUnitTest.h"
+#include
+#include
+#include "Renderer/Painting/ElementStyle.h"
+#include
+
+
+using namespace Microsoft::VisualStudio::CppUnitTestFramework;
+using namespace Renderer;
+
+namespace UnitTest
+{
+ TEST_CLASS(StyleTest)
+ {
+ public:
+ TEST_METHOD(TestEncodeDecode)
+ {
+ std::map materialMap = {
+ {0.20, Material{QColor(255,255,255)}},
+ {0.60, Material{QColor(165,176,207)}},
+ {1.00, Material{QColor(58,64,151)}}
+ };
+ auto style = std::make_unique(
+ 30, StrokeType::kBothSides, StrokeEndType::kRound,
+ std::make_shared(materialMap, false)
+ );
+ /* auto style = std::make_shared(
+ 30, StrokeType::kBothSides, StrokeEndType::kRound,
+ std::make_shared(Material(QColor(255, 255, 255)))
+ );*/
+ std::shared_ptr decoded = MaterialStyle::decoded(style->encoded());
+ /* Assert::IsTrue(decoded->type() == MaterialStyleType::kStroke);
+ Assert::IsTrue(std::static_pointer_cast(decoded)->halfWidth == 30);
+ Assert::IsTrue(std::static_pointer_cast(decoded)->strokeType == StrokeType::kBothSides);
+ Assert::IsTrue(std::static_pointer_cast(decoded)->endType == StrokeEndType::kRound);
+ std::shared_ptr materialStroke = std::static_pointer_cast(decoded)->materialStroke;
+ Assert::IsTrue(materialStroke->type() == MaterialStrokeType::kPlain);
+ Material material = std::static_pointer_cast(materialStroke)->material;
+ Assert::IsTrue(material == Material(QColor(255, 255, 255)));
+ Logger::WriteMessage(std::format("({} {} {} {}), ({} {})\n",
+ material.color.red(),
+ material.color.green(),
+ material.color.blue(),
+ material.color.alpha(),
+ material.metallic,
+ material.roughness
+ ).c_str());*/
+
+
+ Assert::IsTrue(*style == *decoded);
+
+ }
+ };
+}
\ No newline at end of file
diff --git a/UnitTest/UnitTest.vcxproj b/UnitTest/UnitTest.vcxproj
index 402f061..3c5c76d 100644
--- a/UnitTest/UnitTest.vcxproj
+++ b/UnitTest/UnitTest.vcxproj
@@ -117,6 +117,7 @@
input
%(Filename).moc
+
diff --git a/UnitTest/UnitTest.vcxproj.filters b/UnitTest/UnitTest.vcxproj.filters
index 2a74cbc..2265b74 100644
--- a/UnitTest/UnitTest.vcxproj.filters
+++ b/UnitTest/UnitTest.vcxproj.filters
@@ -48,5 +48,8 @@
Source Files
+
+ Source Files
+
\ No newline at end of file