From 78c24ad373f997f1138c2e2645c253d89aaeb4ae Mon Sep 17 00:00:00 2001 From: wuyize Date: Wed, 15 Mar 2023 22:43:51 +0800 Subject: [PATCH 1/3] =?UTF-8?q?FIX:=20painting=E6=B8=B2=E6=9F=93bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../res/Shaders/painting.comp | 6 +- .../res/Shaders/painting.frag | 6 -- .../res/Shaders/painting.vert | 1 - .../src/Renderer/Model.cpp | 100 +++++++++++++++++- 4 files changed, 101 insertions(+), 12 deletions(-) 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/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); From 03a06ce426232cd28351516ac5012c22dfd9f60e Mon Sep 17 00:00:00 2001 From: ArgonarioD Date: Thu, 16 Mar 2023 02:13:25 +0800 Subject: [PATCH 2/3] =?UTF-8?q?[editor/style]=20=E8=BF=9B=E4=B8=80?= =?UTF-8?q?=E6=AD=A5=E5=AE=8C=E5=96=84StrokeStyle=E7=9B=B8=E5=85=B3=20[str?= =?UTF-8?q?oke]=20=E5=88=9D=E6=AD=A5=E5=AE=8C=E6=88=90StrokeStyle=E5=BA=8F?= =?UTF-8?q?=E5=88=97=E5=8C=96=20[editor/util]=20=E6=96=B0=E5=A2=9EJsonUtil?= =?UTF-8?q?=20[stroke]=20=E5=AE=8C=E6=88=90=E6=B7=BB=E5=8A=A0=E5=8D=95?= =?UTF-8?q?=E5=B1=82=E6=8F=8F=E8=BE=B9=E5=8A=9F=E8=83=BD=20[stroke]=20?= =?UTF-8?q?=E5=AE=8C=E6=88=90=E8=AE=BE=E7=BD=AE=E6=8E=A7=E4=BB=B6=20[strok?= =?UTF-8?q?e]=20=E5=B0=86StrokeStyleListView=E4=BF=AE=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=E4=BA=86StrokeStyleWidget?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ArchitectureColoredPainting.vcxproj | 5 +- ...rchitectureColoredPainting.vcxproj.filters | 7 +- .../StrokeStyleWidget.cpp | 216 ++++++++++++++++++ .../EditorWidgetComponent/StrokeStyleWidget.h | 33 +++ .../src/Editor/LayerStyle.cpp | 37 ++- .../src/Editor/LayerStyle.h | 6 + .../src/Editor/LayerWrapper.cpp | 4 + .../src/Editor/LayerWrapper.h | 1 + .../src/Editor/util/JsonUtil.hpp | 14 ++ 9 files changed, 308 insertions(+), 15 deletions(-) create mode 100644 ArchitectureColoredPainting/src/Editor/EditorWidgetComponent/StrokeStyleWidget.cpp create mode 100644 ArchitectureColoredPainting/src/Editor/EditorWidgetComponent/StrokeStyleWidget.h create mode 100644 ArchitectureColoredPainting/src/Editor/util/JsonUtil.hpp 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/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 4c73d5d..0e9b8f4 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 7df5d13..f753dcb 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; + } +} From 15a41d61a53dc0a53a6cb370cb88c6e0a2da4b32 Mon Sep 17 00:00:00 2001 From: wuyize Date: Thu, 16 Mar 2023 14:48:28 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E5=AE=9E=E7=8E=B0MaterialStyle=E7=9A=84dec?= =?UTF-8?q?oded=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/Renderer/Painting/BaseStyle.cpp | 86 ++++++++++++++++++- .../src/Renderer/Painting/BaseStyle.h | 13 ++- .../Renderer/Painting/MaterialStyleFill.cpp | 16 ++-- .../src/Renderer/Painting/MaterialStyleFill.h | 5 +- .../Renderer/Painting/MaterialStyleStroke.cpp | 6 +- UnitTest/ElementRendererTest.cpp | 14 +-- UnitTest/StyleTest.cpp | 54 ++++++++++++ UnitTest/UnitTest.vcxproj | 1 + UnitTest/UnitTest.vcxproj.filters | 3 + 9 files changed, 176 insertions(+), 22 deletions(-) create mode 100644 UnitTest/StyleTest.cpp 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