dev-LayerStyle
ArgonarioD 2023-03-16 15:47:59 +08:00
commit 50a1bdaff4
20 changed files with 248 additions and 105 deletions

View File

@ -15,6 +15,7 @@ EditorWidgetItem::EditorWidgetItem(QString filePath,QWidget *parent) : QWidget(p
elementInfoDisplayWidget->enableEdit(); elementInfoDisplayWidget->enableEdit();
qDebug() << layerInfoDisplayWidget; qDebug() << layerInfoDisplayWidget;
qDebug() << elementInfoDisplayWidget; qDebug() << elementInfoDisplayWidget;
connect(previewWindow, &PreviewWindow::refreshElementPreviewByIndex, elementInfoDisplayWidget, &ElementPoolWidget::refreshPictureByIndex);
connect(previewWindow, &PreviewWindow::layerInfoChanged, layerInfoDisplayWidget, &InfoDisplayWidget::triggerSelfRefresh); connect(previewWindow, &PreviewWindow::layerInfoChanged, layerInfoDisplayWidget, &InfoDisplayWidget::triggerSelfRefresh);
connect(treeWidget, &LayerTreeWidget::displayLayerChange, previewWindow, &PreviewWindow::currentLayerChanged); connect(treeWidget, &LayerTreeWidget::displayLayerChange, previewWindow, &PreviewWindow::currentLayerChanged);
connect(treeWidget, &LayerTreeWidget::requireRefreshElementWidget, elementInfoDisplayWidget, &ElementPoolWidget::refresh); connect(treeWidget, &LayerTreeWidget::requireRefreshElementWidget, elementInfoDisplayWidget, &ElementPoolWidget::refresh);

View File

@ -2,7 +2,6 @@
ElementManager::ElementManager(QJsonObject source,Renderer::ElementRenderer* renderer) ElementManager::ElementManager(QJsonObject source,Renderer::ElementRenderer* renderer)
{ {
auto elementsJson = source.value("elements").toArray(); auto elementsJson = source.value("elements").toArray();
qDebug() << elementsJson.size();
int index = 0; int index = 0;
for (auto elementJson : elementsJson) for (auto elementJson : elementsJson)
{ {
@ -68,9 +67,6 @@ int ElementManager::getLayerReferencedBy(const FolderLayerWrapper* layer)
{ {
for (int i = 0; i < elements.size(); i++) for (int i = 0; i < elements.size(); i++)
if (typeid(*elements[i]) == typeid(GroupElement)) { if (typeid(*elements[i]) == typeid(GroupElement)) {
qDebug() << ((GroupElement*)elements[i])->sourceLayer;
qDebug() << layer;
qDebug() << "------------";
if (((GroupElement*)elements[i])->sourceLayer == layer) if (((GroupElement*)elements[i])->sourceLayer == layer)
return i; return i;
} }
@ -97,7 +93,6 @@ void ElementManager::createSimpleElement(QString name, QString filePath) {
data.insert("include", filePath); data.insert("include", filePath);
json.insert("data", data); json.insert("data", data);
auto element = new SimpleElement(json); auto element = new SimpleElement(json);
qDebug() << element->painterPath;
element->name = name; element->name = name;
addElement(element); addElement(element);
} }

View File

@ -37,23 +37,8 @@ void ElementPoolWidget::setElementList(std::vector<GraphicElement*> elements) {
pictureList->clear(); pictureList->clear();
this->elements = elements; this->elements = elements;
for (int index = 0; index < elements.size(); index++) { for (int index = 0; index < elements.size(); index++) {
//
//QString strPath = QString("C:\\Users\\86177\\Pictures\\Screenshots\\test.png");
//QPixmap itemPixmap(strPath);
//QPixmap itemPixmap(QSize(200, 200));
//itemPixmap.fill(Qt::red);
QPixmap itemPixmap = elements[index]->getPaintObject().getDetail();
qDebug() << this->parentWidget()->size();
//auto p = new QWidget();
//auto lb = new QLabel(p);
//lb->setPixmap(itemPixmap);
//lb->setFixedSize(1920, 1080);
//p->setFixedSize(1920, 1080);
//lb->show();
//p->show();
QListWidgetItem* pItem = new QListWidgetItem( QListWidgetItem* pItem = new QListWidgetItem(
itemPixmap.scaled(QSize(iconWidth - 25, iconHeight - 25)), elements[index]->getPreview(QSize(iconWidth - 25, iconHeight - 25)),
elements[index]->name); elements[index]->name);
pItem->setSizeHint(QSize(iconWidth, iconHeight)); pItem->setSizeHint(QSize(iconWidth, iconHeight));
pictureList->insertItem(index, pItem); pictureList->insertItem(index, pItem);
@ -88,13 +73,21 @@ void ElementPoolWidget::refresh() {
void ElementPoolWidget::refreshPicture(GraphicElement* element) { void ElementPoolWidget::refreshPicture(GraphicElement* element) {
for (int i = 0; i < elements.size(); i++) { for (int i = 0; i < elements.size(); i++) {
if (element == elements[i]) { if (element == elements[i]) {
pictureList->item(i)->setIcon(element->getPaintObject().getDetail().scaled(QSize(iconWidth - 25, iconHeight - 25))); pictureList->item(i)->setIcon(elements[i]->getPreview(QSize(iconWidth - 25, iconHeight - 25)));
// update(); // update();
return; return;
} }
} }
} }
void ElementPoolWidget::refreshPictureByIndex(int index) {
if (index >= 0 && index < elements.size())
{
pictureList->item(index)->setIcon(elements[index]->getPreview(QSize(iconWidth - 25, iconHeight - 25)));
// update();
}
}
void ElementPoolWidget::enableEdit() void ElementPoolWidget::enableEdit()
{ {
connect(this->pictureList, &QListWidget::customContextMenuRequested, this, &ElementPoolWidget::popMenu); connect(this->pictureList, &QListWidget::customContextMenuRequested, this, &ElementPoolWidget::popMenu);

View File

@ -30,6 +30,7 @@ public slots:
int pictureItemClicked(QListWidgetItem* item); int pictureItemClicked(QListWidgetItem* item);
void refresh(); void refresh();
void refreshPicture(GraphicElement* element); void refreshPicture(GraphicElement* element);
void refreshPictureByIndex(int index);
void popMenu(const QPoint& pos); void popMenu(const QPoint& pos);
}; };

View File

@ -49,35 +49,7 @@ PixelPath GroupElement::getPaintObject() const
//TODO: apply styles and send back //TODO: apply styles and send back
PixelPath SimpleElement::getPaintObject(std::vector<std::shared_ptr<LayerStyle>>* styles) const { PixelPath SimpleElement::getPaintObject(std::vector<std::shared_ptr<LayerStyle>>* styles) const {
PixelPath result; return this->getPaintObject();
std::shared_ptr<Renderer::ElementStyle> style;
if ((*styles).empty())
{
return this->getPaintObject();
}
else
{
style = (*styles)[0];
/*qDebug() << std::dynamic_pointer_cast<Renderer::StrokePlain>(
std::dynamic_pointer_cast<StrokeElementLayerStyle>(style)->materialStyles[0]->materialStroke
)->material.color.name();*/
/*qDebug() << std::dynamic_pointer_cast<Renderer::StrokeRadialGradient>(
std::dynamic_pointer_cast<StrokeElementLayerStyle>(style)->materialStyles[0]->materialStroke
)->materialMap[1.0].color;*/
}
auto [img, mov] = Renderer::ElementRenderer::instance()->drawElement(painterPath, *style, 1.0);
//qDebug() << img << " ------";
result.addImage(img, mov);
result.addPath(painterPath);
//result.addPath(painterPath);
// QImage img(80,80,QImage::Format_ARGB32);
// QPainter pt(&img);
//pt.setPen(QPen(Qt::red, 2));
//pt.drawLine(0, 0, 80, 80);
//pt.end();
//result.addImage(img, QPoint(0, 0));
return result;
} }
PixelPath GroupElement::getPaintObject(std::vector<std::shared_ptr<LayerStyle>>* styles) const { PixelPath GroupElement::getPaintObject(std::vector<std::shared_ptr<LayerStyle>>* styles) const {
@ -132,35 +104,48 @@ void SimpleElement::paint(QPainter* painter, QTransform transform, const vector<
{ {
Renderer::ElementStyleStrokeDemo demo(2); Renderer::ElementStyleStrokeDemo demo(2);
std::shared_ptr<Renderer::ElementStyle> style; std::shared_ptr<Renderer::ElementStyle> style;
if (styles.empty()) style = styles[0];
{
style = std::make_shared<Renderer::ElementStyleStrokeDemo>(2);
}
else
{
style = styles[0];
/*qDebug() << std::dynamic_pointer_cast<Renderer::StrokePlain>(
std::dynamic_pointer_cast<StrokeElementLayerStyle>(style)->materialStyles[0]->materialStroke
)->material.color.name();*/
/*qDebug() << std::dynamic_pointer_cast<Renderer::StrokeRadialGradient>(
std::dynamic_pointer_cast<StrokeElementLayerStyle>(style)->materialStyles[0]->materialStroke
)->materialMap[1.0].color;*/
}
QVector2D scale(transform.m11(), transform.m22()); QVector2D scale(transform.m11(), transform.m22());
scale /= transform.m33(); scale /= transform.m33();
double maxScale = std::max(scale.x(), scale.y()); double maxScale = std::max(scale.x(), scale.y());
double pixelRatio = maxScale * QGuiApplication::primaryScreen()->devicePixelRatio(); double pixelRatio = maxScale * QGuiApplication::primaryScreen()->devicePixelRatio();
auto [img, mov] = Renderer::ElementRenderer::instance()->drawElement(painterPath, *style, pixelRatio); auto [img, mov] = Renderer::ElementRenderer::instance()->drawElement(painterPath, *style, pixelRatio);
transform.translate(mov.x(), mov.y());
painter->setTransform(transform.scale(1 / pixelRatio, 1 / pixelRatio)); painter->setTransform(transform.scale(1 / pixelRatio, 1 / pixelRatio));
//img = img.scaled(img.width() / pixelRatio, img.height() / pixelRatio, Qt::KeepAspectRatio, Qt::SmoothTransformation); painter->drawImage(0, 0, img);
painter->drawImage(mov, img);
} }
painter->restore(); painter->restore();
} }
void GroupElement::paint(QPainter* painter, QTransform transform, const vector<std::shared_ptr<LayerStyle>> &styles) void GroupElement::paint(QPainter* painter, QTransform transform, const vector<std::shared_ptr<LayerStyle>> &styles)
{ {
sourceLayer->paint(painter, transform); sourceLayer->paint(painter, transform);
}
QPixmap SimpleElement::getPreview(QSize size)
{
QPixmap result(size + QSize(5,5));
QPainter painter(&result);
painter.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::SmoothPixmapTransform);
painter.scale(size.width() / painterPath.boundingRect().width(), size.height() / painterPath.boundingRect().height());
painter.drawPath(painterPath);
return result;
}
QPixmap GroupElement::getPreview(QSize size)
{
auto cache = sourceLayer->getCache();
QPixmap result(QSize(1024, 1024));
QPainter painter(&result);
painter.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::SmoothPixmapTransform);
sourceLayer->paint(&painter, QTransform(), true);
painter.end();
QRect rect (cache.getBoundingRect().toRect());
rect.setTopLeft(rect.topLeft() - QPoint(5, 5));
rect.setBottomRight(rect.bottomRight() + QPoint(5, 5));
result = result.copy(rect);
return result.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
} }

View File

@ -29,6 +29,7 @@ public:
virtual PixelPath getPaintObject() const = 0; virtual PixelPath getPaintObject() const = 0;
virtual PixelPath getPaintObject(std::vector<std::shared_ptr<LayerStyle>>*) const = 0; virtual PixelPath getPaintObject(std::vector<std::shared_ptr<LayerStyle>>*) const = 0;
virtual void paint(QPainter* painter, QTransform transform, const std::vector<std::shared_ptr<LayerStyle>> &styles) = 0; virtual void paint(QPainter* painter, QTransform transform, const std::vector<std::shared_ptr<LayerStyle>> &styles) = 0;
virtual QPixmap getPreview(QSize size) = 0;
}; };
class SimpleElement : public GraphicElement class SimpleElement : public GraphicElement
@ -48,6 +49,7 @@ public:
PixelPath getPaintObject() const override; PixelPath getPaintObject() const override;
PixelPath getPaintObject(std::vector<std::shared_ptr<LayerStyle>>*) const override; PixelPath getPaintObject(std::vector<std::shared_ptr<LayerStyle>>*) const override;
void paint(QPainter* painter, QTransform transform, const std::vector<std::shared_ptr<LayerStyle>> &styles) override; void paint(QPainter* painter, QTransform transform, const std::vector<std::shared_ptr<LayerStyle>> &styles) override;
QPixmap getPreview(QSize size) override;
}; };
class GroupElement : public GraphicElement class GroupElement : public GraphicElement
@ -64,6 +66,7 @@ public:
PixelPath getPaintObject(std::vector<std::shared_ptr<LayerStyle>>*) const override; PixelPath getPaintObject(std::vector<std::shared_ptr<LayerStyle>>*) const override;
void setSourceLayer(FolderLayerWrapper* sourceLayer); void setSourceLayer(FolderLayerWrapper* sourceLayer);
void paint(QPainter* painter, QTransform transform, const std::vector<std::shared_ptr<LayerStyle>> &styles) override; void paint(QPainter* painter, QTransform transform, const std::vector<std::shared_ptr<LayerStyle>> &styles) override;
QPixmap getPreview(QSize size) override;
}; };
//******************************** BitmapPath ********************************// //******************************** BitmapPath ********************************//

View File

@ -255,12 +255,12 @@ int FolderLayerWrapper::getReferencedBy()const
return -1; return -1;
} }
void LayerWrapper::paint(QPainter* painter, QTransform transform) void LayerWrapper::paint(QPainter* painter, QTransform transform, bool ignoreSelected)
{ {
if (this->selected) if (!ignoreSelected && this->selected)
{ {
painter->save(); painter->save();
painter->setTransform(transform); painter->setTransform(transform, ignoreSelected);
painter->setPen(QPen(Qt::gray, 2)); painter->setPen(QPen(Qt::gray, 2));
painter->setPen(Qt::DashLine); painter->setPen(Qt::DashLine);
painter->drawRect(cache.getBoundingRect()); painter->drawRect(cache.getBoundingRect());
@ -268,18 +268,18 @@ void LayerWrapper::paint(QPainter* painter, QTransform transform)
} }
} }
void FolderLayerWrapper::paint(QPainter* painter, QTransform transform) void FolderLayerWrapper::paint(QPainter* painter, QTransform transform, bool ignoreSelected)
{ {
LayerWrapper::paint(painter, transform); LayerWrapper::paint(painter, transform, ignoreSelected);
transform = property.transform * transform; transform = property.transform * transform;
//qDebug() << transform; //qDebug() << transform;
for (auto& child : children) for (auto& child : children)
child->paint(painter, transform); child->paint(painter, transform, ignoreSelected);
} }
void LeafLayerWrapper::paint(QPainter* painter, QTransform transform) void LeafLayerWrapper::paint(QPainter* painter, QTransform transform, bool ignoreSelected)
{ {
LayerWrapper::paint(painter, transform); LayerWrapper::paint(painter, transform, ignoreSelected);
transform = property.transform * transform; transform = property.transform * transform;
//qDebug() << transform; //qDebug() << transform;
if (wrappedElement != nullptr) if (wrappedElement != nullptr)

View File

@ -58,7 +58,7 @@ class LayerWrapper
FolderLayerWrapper*getParent() const; // invoke by manager, then invoke parent's applyStyles FolderLayerWrapper*getParent() const; // invoke by manager, then invoke parent's applyStyles
LayerWrapper(QJsonObject json, FolderLayerWrapper*parent, ElementManager* elementManager=nullptr); LayerWrapper(QJsonObject json, FolderLayerWrapper*parent, ElementManager* elementManager=nullptr);
LayerWrapper() = default; LayerWrapper() = default;
virtual void paint(QPainter* painter, QTransform transform=QTransform()); virtual void paint(QPainter* painter, QTransform transform=QTransform(), bool ignoreSelected = false);
// TODO : export Function // TODO : export Function
// virtual LayerWrapper *addChild() = 0; // Leaf Child Only // virtual LayerWrapper *addChild() = 0; // Leaf Child Only
// virtual LayerWrapper *addParent() = 0; // Folder Parent Only // virtual LayerWrapper *addParent() = 0; // Folder Parent Only
@ -91,7 +91,7 @@ class FolderLayerWrapper : public LayerWrapper
QTreeWidgetItem* getQTreeItem() override; QTreeWidgetItem* getQTreeItem() override;
QJsonObject toJson() const override; QJsonObject toJson() const override;
int getReferencedBy()const; int getReferencedBy()const;
void paint(QPainter* painter, QTransform transform = QTransform()) override; void paint(QPainter* painter, QTransform transform = QTransform(), bool ignoreSelected = false) override;
}; };
class LeafLayerWrapper : public LayerWrapper class LeafLayerWrapper : public LayerWrapper
@ -107,7 +107,7 @@ class LeafLayerWrapper : public LayerWrapper
LeafLayerWrapper() = default; LeafLayerWrapper() = default;
LeafLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent); LeafLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent);
QJsonObject toJson() const override; QJsonObject toJson() const override;
void paint(QPainter* painter, QTransform transform = QTransform()) override; void paint(QPainter* painter, QTransform transform = QTransform(), bool ignoreSelected = false) override;
}; };
Q_DECLARE_METATYPE(LayerWrapper *) Q_DECLARE_METATYPE(LayerWrapper *)

View File

@ -13,8 +13,8 @@ public:
QPainterPath painterPath; QPainterPath painterPath;
int w,h; int w,h;
public: public:
PixelPath(int w=1024, int h= 1024); PixelPath(int w=16, int h= 16);
PixelPath(QPainterPath painterPath,int w = 1024, int h = 1024); PixelPath(QPainterPath painterPath,int w = 16, int h = 16);
~PixelPath() = default; ~PixelPath() = default;
QRectF getBoundingRect() const; QRectF getBoundingRect() const;
QPixmap getPixmap() const; QPixmap getPixmap() const;

View File

@ -87,13 +87,22 @@ void PreviewWindow::mouseMoveEvent(QMouseEvent* event)
// 如果按下的是左键,那么平移图形 // 如果按下的是左键,那么平移图形
currentLayer->property.offset.setX(currentLayer->property.offset.x() + dx); currentLayer->property.offset.setX(currentLayer->property.offset.x() + dx);
currentLayer->property.offset.setY(currentLayer->property.offset.y() + dy); currentLayer->property.offset.setY(currentLayer->property.offset.y() + dy);
qDebug() << dx << "----" << dy;
} }
else if (event->buttons() & Qt::RightButton) { else if (event->buttons() & Qt::RightButton) {
// 如果按下的是右键,那么旋转图形 // 如果按下的是右键,那么旋转图形
qreal angle = dx; qreal angle = dx;
currentLayer->property.rotation += angle; currentLayer->property.rotation += angle;
} }
auto layer = currentLayer;
while (layer != nullptr)
{
auto index = -1;
if (typeid(*layer) == typeid(FolderLayerWrapper))
index = dynamic_cast<FolderLayerWrapper*>(layer)->getReferencedBy();
if (index != -1)
emit refreshElementPreviewByIndex(index);
layer = layer->getParent();
}
} }
// 更新上一次的位置 // 更新上一次的位置
m_lastPos = event->pos(); m_lastPos = event->pos();

View File

@ -42,4 +42,6 @@ class PreviewWindow : public QOpenGLWidget, protected QOpenGLFunctions
signals: signals:
void layerInfoChanged(); void layerInfoChanged();
void refreshElementPreview(GraphicElement*);
void refreshElementPreviewByIndex(int);
}; };

View File

@ -1,6 +1,43 @@
#include "BaseStyle.h" #include "BaseStyle.h"
#include "MaterialStyleFill.h"
#include "MaterialStyleStroke.h"
using namespace Renderer; 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 bool Renderer::Material::operator==(const Material& m) const
{ {
@ -9,5 +46,52 @@ bool Renderer::Material::operator==(const Material& m) const
std::pair<glm::vec4, glm::vec2> Renderer::Material::toVec() const std::pair<glm::vec4, glm::vec2> 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<MaterialStyle> Renderer::MaterialStyle::decoded(const std::vector<GLfloat>& encoded)
{
if (encoded[0] <= 0) /// MaterialStyleFill
{
std::unique_ptr<MaterialFill> materiallFill;
glm::vec4 head = glm::unpackUnorm4x8(glm::floatBitsToUint(encoded[0]));
if (head.z == 0)
{
materiallFill = std::make_unique<FillPlain>(Material(glm::unpackUnorm4x8(glm::floatBitsToUint(encoded[1])), glm::vec2(head.r, head.g)));
}
return std::make_unique<MaterialStyleFill>(std::move(materiallFill));
}
else /// MaterialStyleStroke
{
std::unique_ptr<MaterialStroke> 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<StrokePlain>(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<float, Material> 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<StrokeRadialGradient>(materialMap, gradual);
break;
}
}
return std::make_unique<MaterialStyleStroke>(encoded[0], strokeType, endType, std::move(materialStroke));
}
} }

View File

@ -25,6 +25,7 @@ namespace Renderer
virtual std::vector<GLfloat> encoded() const = 0; virtual std::vector<GLfloat> encoded() const = 0;
virtual std::unique_ptr<MaterialStyle> clone() const = 0; virtual std::unique_ptr<MaterialStyle> clone() const = 0;
virtual bool operator==(const MaterialStyle&) const = 0; virtual bool operator==(const MaterialStyle&) const = 0;
static std::unique_ptr<MaterialStyle> decoded(const std::vector<GLfloat>& encoded);
}; };
struct BaseStyle struct BaseStyle
@ -36,8 +37,16 @@ namespace Renderer
struct Material struct Material
{ {
QColor color; QColor color;
float metallic; std::uint8_t metallic;
float roughness; 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; bool operator==(const Material&) const;
std::pair<glm::vec4, glm::vec2> toVec() const; std::pair<glm::vec4, glm::vec2> toVec() const;
}; };

View File

@ -3,7 +3,12 @@
using namespace Renderer; using namespace Renderer;
Renderer::FillPlain::FillPlain(QColor color, float metallic, float roughness) 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<GLfloat> Renderer::FillPlain::encoded() const std::vector<GLfloat> Renderer::FillPlain::encoded() const
{ {
return { glm::uintBitsToFloat(glm::packUnorm4x8(glm::vec4(metallic, roughness, 0, 1))), auto pair = material.toVec();
glm::uintBitsToFloat(glm::packUnorm4x8(glm::vec4(color.redF(), color.greenF(), color.blueF(), color.alphaF())))}; return { glm::uintBitsToFloat(glm::packUnorm4x8(glm::vec4(pair.second, 0, 1))),
glm::uintBitsToFloat(glm::packUnorm4x8(pair.first))};
} }
std::unique_ptr<MaterialFill> Renderer::FillPlain::clone() const std::unique_ptr<MaterialFill> Renderer::FillPlain::clone() const
@ -26,9 +32,7 @@ std::unique_ptr<MaterialFill> Renderer::FillPlain::clone() const
bool Renderer::FillPlain::operator==(const MaterialFill& m) const bool Renderer::FillPlain::operator==(const MaterialFill& m) const
{ {
return type() == m.type() return type() == m.type()
&& color == static_cast<const FillPlain&>(m).color && material == static_cast<const FillPlain&>(m).material;
&& metallic == static_cast<const FillPlain&>(m).metallic
&& roughness == static_cast<const FillPlain&>(m).roughness;
} }

View File

@ -18,14 +18,13 @@ namespace Renderer
{ {
public: public:
FillPlain(QColor color, float metallic, float roughness); FillPlain(QColor color, float metallic, float roughness);
FillPlain(const Material& material);
virtual MaterialFillType type() const override; virtual MaterialFillType type() const override;
virtual std::vector<GLfloat> encoded() const override; virtual std::vector<GLfloat> encoded() const override;
virtual std::unique_ptr<MaterialFill> clone() const override; virtual std::unique_ptr<MaterialFill> clone() const override;
virtual bool operator==(const MaterialFill&) const override; virtual bool operator==(const MaterialFill&) const override;
QColor color; Material material;
float metallic;
float roughness;
}; };
class MaterialStyleFill : public MaterialStyle class MaterialStyleFill : public MaterialStyle

View File

@ -76,8 +76,8 @@ bool Renderer::StrokeRadialGradient::operator==(const MaterialStroke& m) const
&& materialMap == static_cast<const StrokeRadialGradient&>(m).materialMap; && materialMap == static_cast<const StrokeRadialGradient&>(m).materialMap;
} }
Renderer::MaterialStyleStroke::MaterialStyleStroke(float width, StrokeType strokeType, StrokeEndType endType, std::shared_ptr<MaterialStroke> materialStroke) Renderer::MaterialStyleStroke::MaterialStyleStroke(float halfWidth, StrokeType strokeType, StrokeEndType endType, std::shared_ptr<MaterialStroke> materialStroke)
: halfWidth(width/2), strokeType(strokeType), endType(endType), materialStroke(materialStroke) : halfWidth(halfWidth), strokeType(strokeType), endType(endType), materialStroke(materialStroke)
{ {
} }
@ -100,7 +100,7 @@ std::vector<GLfloat> Renderer::MaterialStyleStroke::encoded() const
std::unique_ptr<MaterialStyle> Renderer::MaterialStyleStroke::clone() const std::unique_ptr<MaterialStyle> Renderer::MaterialStyleStroke::clone() const
{ {
return std::make_unique<MaterialStyleStroke>(halfWidth*2, strokeType, endType, materialStroke->clone()); return std::make_unique<MaterialStyleStroke>(halfWidth, strokeType, endType, materialStroke->clone());
} }
bool Renderer::MaterialStyleStroke::operator==(const MaterialStyle& m) const bool Renderer::MaterialStyleStroke::operator==(const MaterialStyle& m) const

View File

@ -40,7 +40,7 @@ namespace UnitTest
{1.00, Material{QColor(58,64,151)}} {1.00, Material{QColor(58,64,151)}}
}; };
return { BaseStyle(std::make_shared<TransformStyle>(), return { BaseStyle(std::make_shared<TransformStyle>(),
std::make_shared<MaterialStyleStroke>(60, StrokeType::kBothSides, StrokeEndType::kRound, std::make_shared<MaterialStyleStroke>(30, StrokeType::kBothSides, StrokeEndType::kRound,
std::make_shared<StrokeRadialGradient>(materialMap, false))) }; std::make_shared<StrokeRadialGradient>(materialMap, false))) };
} }
} style; } style;
@ -61,7 +61,7 @@ namespace UnitTest
{1.00, Material{QColor(58,64,151)}} {1.00, Material{QColor(58,64,151)}}
}; };
return { BaseStyle(std::make_shared<TransformStyle>(), return { BaseStyle(std::make_shared<TransformStyle>(),
std::make_shared<MaterialStyleStroke>(60, StrokeType::kBothSides, StrokeEndType::kFlat, std::make_shared<MaterialStyleStroke>(30, StrokeType::kBothSides, StrokeEndType::kFlat,
std::make_shared<StrokeRadialGradient>(materialMap, false))) }; std::make_shared<StrokeRadialGradient>(materialMap, false))) };
} }
} style; } style;
@ -82,7 +82,7 @@ namespace UnitTest
{1.00, Material{QColor(58,64,151)}} {1.00, Material{QColor(58,64,151)}}
}; };
return { BaseStyle(std::make_shared<TransformStyle>(), return { BaseStyle(std::make_shared<TransformStyle>(),
std::make_shared<MaterialStyleStroke>(60, StrokeType::kLeftSide, StrokeEndType::kRound, std::make_shared<MaterialStyleStroke>(30, StrokeType::kLeftSide, StrokeEndType::kRound,
std::make_shared<StrokeRadialGradient>(materialMap, false))) }; std::make_shared<StrokeRadialGradient>(materialMap, false))) };
} }
} style; } style;
@ -103,7 +103,7 @@ namespace UnitTest
{1.00, Material{QColor(58,64,151)}} {1.00, Material{QColor(58,64,151)}}
}; };
return { BaseStyle(std::make_shared<TransformStyle>(), return { BaseStyle(std::make_shared<TransformStyle>(),
std::make_shared<MaterialStyleStroke>(60, StrokeType::kLeftSide, StrokeEndType::kFlat, std::make_shared<MaterialStyleStroke>(30, StrokeType::kLeftSide, StrokeEndType::kFlat,
std::make_shared<StrokeRadialGradient>(materialMap, false))) }; std::make_shared<StrokeRadialGradient>(materialMap, false))) };
} }
} style; } style;
@ -124,7 +124,7 @@ namespace UnitTest
{1.00, Material{QColor(58,64,151)}} {1.00, Material{QColor(58,64,151)}}
}; };
return { BaseStyle(std::make_shared<TransformStyle>(), return { BaseStyle(std::make_shared<TransformStyle>(),
std::make_shared<MaterialStyleStroke>(160, StrokeType::kRightSide, StrokeEndType::kFlatRound, std::make_shared<MaterialStyleStroke>(80, StrokeType::kRightSide, StrokeEndType::kFlatRound,
std::make_shared<StrokeRadialGradient>(materialMap, false))) }; std::make_shared<StrokeRadialGradient>(materialMap, false))) };
} }
} style; } style;
@ -149,7 +149,7 @@ namespace UnitTest
virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override
{ {
return { BaseStyle(std::make_shared<TransformStyle>(), return { BaseStyle(std::make_shared<TransformStyle>(),
std::make_shared<MaterialStyleStroke>(60, StrokeType::kBothSides, StrokeEndType::kRound, std::make_shared<MaterialStyleStroke>(30, StrokeType::kBothSides, StrokeEndType::kRound,
std::make_shared<StrokePlain>(QColor(255,255,255),1,1))) }; std::make_shared<StrokePlain>(QColor(255,255,255),1,1))) };
} }
} style; } style;
@ -170,7 +170,7 @@ namespace UnitTest
{1.00, Material{QColor(58,64,151)}} {1.00, Material{QColor(58,64,151)}}
}; };
return { BaseStyle(std::make_shared<TransformStyle>(), return { BaseStyle(std::make_shared<TransformStyle>(),
std::make_shared<MaterialStyleStroke>(60, StrokeType::kBothSides, StrokeEndType::kRound, std::make_shared<MaterialStyleStroke>(30, StrokeType::kBothSides, StrokeEndType::kRound,
std::make_shared<StrokeRadialGradient>(materialMap, false))) }; std::make_shared<StrokeRadialGradient>(materialMap, false))) };
} }
} style; } style;

54
UnitTest/StyleTest.cpp Normal file
View File

@ -0,0 +1,54 @@
#include "CppUnitTest.h"
#include <QGuiApplication>
#include <QtWidgets/QApplication>
#include "Renderer/Painting/ElementStyle.h"
#include <Renderer/Painting/MaterialStyleStroke.h>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Renderer;
namespace UnitTest
{
TEST_CLASS(StyleTest)
{
public:
TEST_METHOD(TestEncodeDecode)
{
std::map<float, Material> 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<MaterialStyleStroke>(
30, StrokeType::kBothSides, StrokeEndType::kRound,
std::make_shared<StrokeRadialGradient>(materialMap, false)
);
/* auto style = std::make_shared<MaterialStyleStroke>(
30, StrokeType::kBothSides, StrokeEndType::kRound,
std::make_shared<StrokePlain>(Material(QColor(255, 255, 255)))
);*/
std::shared_ptr<MaterialStyle> decoded = MaterialStyle::decoded(style->encoded());
/* Assert::IsTrue(decoded->type() == MaterialStyleType::kStroke);
Assert::IsTrue(std::static_pointer_cast<MaterialStyleStroke>(decoded)->halfWidth == 30);
Assert::IsTrue(std::static_pointer_cast<MaterialStyleStroke>(decoded)->strokeType == StrokeType::kBothSides);
Assert::IsTrue(std::static_pointer_cast<MaterialStyleStroke>(decoded)->endType == StrokeEndType::kRound);
std::shared_ptr<MaterialStroke> materialStroke = std::static_pointer_cast<MaterialStyleStroke>(decoded)->materialStroke;
Assert::IsTrue(materialStroke->type() == MaterialStrokeType::kPlain);
Material material = std::static_pointer_cast<StrokePlain>(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);
}
};
}

View File

@ -117,6 +117,7 @@
<DynamicSource Condition="'$(Configuration)|$(Platform)'=='Release|x64'">input</DynamicSource> <DynamicSource Condition="'$(Configuration)|$(Platform)'=='Release|x64'">input</DynamicSource>
<QtMocFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Filename).moc</QtMocFileName> <QtMocFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Filename).moc</QtMocFileName>
</ClCompile> </ClCompile>
<ClCompile Include="StyleTest.cpp" />
<ClCompile Include="UnitTest.cpp" /> <ClCompile Include="UnitTest.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -48,5 +48,8 @@
<ClCompile Include="PaintingTest.cpp"> <ClCompile Include="PaintingTest.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="StyleTest.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>