Merge branch 'main' of http://101.34.228.45:3000/BigC/ArchitectureColoredPainting
commit
84bddf4447
|
@ -84,10 +84,26 @@
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
|
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1,0">
|
||||||
<property name="sizeConstraint">
|
<property name="sizeConstraint">
|
||||||
<enum>QLayout::SetDefaultConstraint</enum>
|
<enum>QLayout::SetDefaultConstraint</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="textureListWidget">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="Renderer::RendererGLWidget" name="openGLWidget">
|
<widget class="Renderer::RendererGLWidget" name="openGLWidget">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
|
|
@ -3,16 +3,14 @@
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
#include <QDebug>
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
LayerStyleDialog::LayerStyleDialog(
|
LayerStyleDialog::LayerStyleDialog(
|
||||||
QWidget* parent,
|
LayerStyleContainer& styles,
|
||||||
std::shared_ptr<LayerStyle> existedStyle,
|
std::shared_ptr<LayerStyle> existedStyle,
|
||||||
std::vector<std::shared_ptr<LayerStyle>>* excludeStyles
|
QWidget* parent
|
||||||
) : QDialog(parent)
|
) : QDialog(parent), styles(&styles)
|
||||||
{
|
{
|
||||||
QVBoxLayout* dialogLayout = new QVBoxLayout(this);
|
auto* dialogLayout = new QVBoxLayout(this);
|
||||||
dialogLayout->setAlignment(Qt::AlignmentFlag::AlignHCenter);
|
dialogLayout->setAlignment(Qt::AlignmentFlag::AlignHCenter);
|
||||||
this->setLayout(dialogLayout);
|
this->setLayout(dialogLayout);
|
||||||
|
|
||||||
|
@ -28,28 +26,14 @@ LayerStyleDialog::LayerStyleDialog(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::unordered_set<QString> excludeStyleNames;
|
QStringList unusedStyleNames = styles.unusedStyleNames();
|
||||||
for(auto &style : *excludeStyles)
|
auto* typeSelector = new QComboBox(this);
|
||||||
{
|
|
||||||
excludeStyleNames.insert(style->getStyleName());
|
|
||||||
}
|
|
||||||
|
|
||||||
QComboBox* typeSelector = new QComboBox(this);
|
if (!unusedStyleNames.empty())
|
||||||
|
|
||||||
for (auto& pair : LayerStyle::types)
|
|
||||||
{
|
{
|
||||||
if (!excludeStyleNames.contains(pair.first))
|
typeSelector->addItems(unusedStyleNames);
|
||||||
{
|
this->modifyingStyle = std::move(styles.makeUnusedStyle(unusedStyleNames[0]));
|
||||||
typeSelector->addItem(pair.first);
|
|
||||||
if (!this->modifyingStyle)
|
|
||||||
{
|
|
||||||
this->modifyingStyle = std::move(pair.second());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeSelector->count() > 0)
|
|
||||||
{
|
|
||||||
dialogLayout->addWidget(typeSelector);
|
dialogLayout->addWidget(typeSelector);
|
||||||
this->styleContainer = new QGridLayout(this);
|
this->styleContainer = new QGridLayout(this);
|
||||||
dialogLayout->addLayout(styleContainer);
|
dialogLayout->addLayout(styleContainer);
|
||||||
|
@ -57,11 +41,11 @@ LayerStyleDialog::LayerStyleDialog(
|
||||||
this->styleWidget = this->modifyingStyle->getInputWidget();
|
this->styleWidget = this->modifyingStyle->getInputWidget();
|
||||||
this->styleWidget->setParent(this);
|
this->styleWidget->setParent(this);
|
||||||
this->styleContainer->addWidget(styleWidget);
|
this->styleContainer->addWidget(styleWidget);
|
||||||
connect(typeSelector, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
connect(typeSelector, &QComboBox::currentTextChanged,
|
||||||
this, &LayerStyleDialog::onStyleTypeSelectorChanged);
|
this, &LayerStyleDialog::onStyleTypeSelectorChanged);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
|
auto* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
|
||||||
connect(buttonBox, &QDialogButtonBox::accepted, this, &LayerStyleDialog::accept);
|
connect(buttonBox, &QDialogButtonBox::accepted, this, &LayerStyleDialog::accept);
|
||||||
connect(buttonBox, &QDialogButtonBox::rejected, this, &LayerStyleDialog::reject);
|
connect(buttonBox, &QDialogButtonBox::rejected, this, &LayerStyleDialog::reject);
|
||||||
dialogLayout->addWidget(buttonBox);
|
dialogLayout->addWidget(buttonBox);
|
||||||
|
@ -73,7 +57,7 @@ void LayerStyleDialog::accept()
|
||||||
QDialog::accept();
|
QDialog::accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerStyleDialog::onStyleTypeSelectorChanged(int index)
|
void LayerStyleDialog::onStyleTypeSelectorChanged(const QString& current)
|
||||||
{
|
{
|
||||||
if (this->styleWidget)
|
if (this->styleWidget)
|
||||||
{
|
{
|
||||||
|
@ -81,8 +65,10 @@ void LayerStyleDialog::onStyleTypeSelectorChanged(int index)
|
||||||
this->styleWidget->setParent(nullptr);
|
this->styleWidget->setParent(nullptr);
|
||||||
delete styleWidget;
|
delete styleWidget;
|
||||||
}
|
}
|
||||||
this->modifyingStyle = std::move(LayerStyle::types[index].second());
|
this->modifyingStyle = std::move(styles->makeUnusedStyle(current));
|
||||||
this->styleWidget = this->modifyingStyle->getInputWidget();
|
this->styleWidget = this->modifyingStyle->getInputWidget();
|
||||||
this->styleWidget->setParent(this);
|
this->styleWidget->setParent(this);
|
||||||
this->styleContainer->addWidget(styleWidget, 0, 0, 1, 1);
|
this->styleContainer->addWidget(styleWidget, 0, 0, 1, 1);
|
||||||
|
this->styleWidget->adjustSize();
|
||||||
|
this->adjustSize();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,15 +9,17 @@ class LayerStyleDialog : public QDialog
|
||||||
private:
|
private:
|
||||||
QWidget* styleWidget;
|
QWidget* styleWidget;
|
||||||
QGridLayout* styleContainer;
|
QGridLayout* styleContainer;
|
||||||
|
LayerStyleContainer* styles;
|
||||||
std::unique_ptr<LayerStyle> modifyingStyle;
|
std::unique_ptr<LayerStyle> modifyingStyle;
|
||||||
public:
|
public:
|
||||||
LayerStyleDialog(
|
LayerStyleDialog(
|
||||||
QWidget* parent = nullptr,
|
LayerStyleContainer& styles,
|
||||||
std::shared_ptr<LayerStyle> existedStyle = nullptr,
|
std::shared_ptr<LayerStyle> existedStyle = nullptr,
|
||||||
std::vector<std::shared_ptr<LayerStyle>>* excludeStyles = nullptr);
|
QWidget* parent = nullptr
|
||||||
|
);
|
||||||
std::shared_ptr<LayerStyle> layerStyle;
|
std::shared_ptr<LayerStyle> layerStyle;
|
||||||
private slots:
|
private slots:
|
||||||
void onStyleTypeSelectorChanged(int index);
|
void onStyleTypeSelectorChanged(const QString& current);
|
||||||
void accept() override;
|
void accept() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
#include "ColorPicker.h"
|
#include "ColorPicker.h"
|
||||||
#include <qtmaterialraisedbutton.h>
|
#include <qtmaterialraisedbutton.h>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <lib/qtmaterialstyle.h>
|
||||||
|
|
||||||
#define radialStroke(stroke) std::dynamic_pointer_cast<Renderer::StrokeRadialGradient>(stroke->materialStroke)
|
|
||||||
constexpr int COLUMN_WIDTH = 0;
|
constexpr int COLUMN_WIDTH = 0;
|
||||||
constexpr int COLUMN_COLOR = 1;
|
constexpr int COLUMN_COLOR = 1;
|
||||||
constexpr int COLUMN_METALLIC = 2;
|
constexpr int COLUMN_METALLIC = 2;
|
||||||
|
@ -15,12 +15,12 @@ StrokeStyleWidget::StrokeStyleWidget(
|
||||||
QWidget* parent
|
QWidget* parent
|
||||||
) : QWidget(parent), stroke(stroke)
|
) : QWidget(parent), stroke(stroke)
|
||||||
{
|
{
|
||||||
QVBoxLayout* viewLayout = new QVBoxLayout(this);
|
auto* viewLayout = new QVBoxLayout(this);
|
||||||
this->setLayout(viewLayout);
|
this->setLayout(viewLayout);
|
||||||
|
|
||||||
initStrokeSettings();
|
initStrokeSettings();
|
||||||
QWidget* strokeProperties = new QWidget(this);
|
auto* strokeProperties = new QWidget(this);
|
||||||
QHBoxLayout* strokePropertiesLayout = new QHBoxLayout(strokeProperties);
|
auto* strokePropertiesLayout = new QHBoxLayout(strokeProperties);
|
||||||
strokePropertiesLayout->setMargin(0);
|
strokePropertiesLayout->setMargin(0);
|
||||||
|
|
||||||
strokeProperties->setLayout(strokePropertiesLayout);
|
strokeProperties->setLayout(strokePropertiesLayout);
|
||||||
|
@ -38,7 +38,7 @@ StrokeStyleWidget::StrokeStyleWidget(
|
||||||
void StrokeStyleWidget::initStrokeSettings()
|
void StrokeStyleWidget::initStrokeSettings()
|
||||||
{
|
{
|
||||||
this->enableGradual = new QtMaterialCheckBox(this);
|
this->enableGradual = new QtMaterialCheckBox(this);
|
||||||
enableGradual->setText(QStringLiteral("ÆôÓý¥±ä"));
|
enableGradual->setText(QStringLiteral("½¥±ä"));
|
||||||
enableGradual->setChecked(radialStroke(stroke)->gradual);
|
enableGradual->setChecked(radialStroke(stroke)->gradual);
|
||||||
connect(enableGradual, &QtMaterialCheckBox::toggled, [this](bool checked) {
|
connect(enableGradual, &QtMaterialCheckBox::toggled, [this](bool checked) {
|
||||||
radialStroke(this->stroke)->gradual = checked;
|
radialStroke(this->stroke)->gradual = checked;
|
||||||
|
@ -72,7 +72,7 @@ void StrokeStyleWidget::initStrokeSettings()
|
||||||
this->widthField = new QtMaterialTextField(this);
|
this->widthField = new QtMaterialTextField(this);
|
||||||
widthField->setLabel(QStringLiteral("±¾²àÃè±ß¿í¶È"));
|
widthField->setLabel(QStringLiteral("±¾²àÃè±ß¿í¶È"));
|
||||||
widthField->setText(QString::number(stroke->halfWidth));
|
widthField->setText(QString::number(stroke->halfWidth));
|
||||||
QDoubleValidator* widthValidator = new QDoubleValidator(0.1, std::numeric_limits<float>::max(), 3, widthField);
|
auto* widthValidator = new QDoubleValidator(0.1, std::numeric_limits<float>::max(), 3, widthField);
|
||||||
widthValidator->setNotation(QDoubleValidator::StandardNotation);
|
widthValidator->setNotation(QDoubleValidator::StandardNotation);
|
||||||
widthField->setValidator(widthValidator);
|
widthField->setValidator(widthValidator);
|
||||||
connect(widthField, &QtMaterialTextField::textChanged, [this](const QString& changed) {
|
connect(widthField, &QtMaterialTextField::textChanged, [this](const QString& changed) {
|
||||||
|
@ -106,8 +106,12 @@ void StrokeStyleWidget::initTable(std::shared_ptr<Renderer::StrokeRadialGradient
|
||||||
}
|
}
|
||||||
// ÐÂÔö°´Å¥
|
// ÐÂÔö°´Å¥
|
||||||
QtMaterialRaisedButton* addButton = new QtMaterialRaisedButton("+", strokeTable);
|
QtMaterialRaisedButton* addButton = new QtMaterialRaisedButton("+", strokeTable);
|
||||||
|
addButton->setBackgroundColor(QtMaterialStyle::instance().themeColor("primary1"));
|
||||||
strokeTable->setSpan(row, 0, 1, 5);
|
strokeTable->setSpan(row, 0, 1, 5);
|
||||||
strokeTable->setCellWidget(row, 0, addButton);
|
strokeTable->setCellWidget(row, 0, addButton);
|
||||||
|
strokeTable->setMinimumHeight(strokeTable->rowHeight(row) * 5);
|
||||||
|
strokeTable->setMinimumWidth(strokeTable->sizeHint().width());
|
||||||
|
addButton->setFixedHeight(strokeTable->rowHeight(row));
|
||||||
connect(addButton, &QtMaterialRaisedButton::clicked, [this]() {
|
connect(addButton, &QtMaterialRaisedButton::clicked, [this]() {
|
||||||
handlingRowInsert = true;
|
handlingRowInsert = true;
|
||||||
auto materialMap = &(radialStroke(this->stroke)->materialMap);
|
auto materialMap = &(radialStroke(this->stroke)->materialMap);
|
||||||
|
@ -129,37 +133,37 @@ void StrokeStyleWidget::initTable(std::shared_ptr<Renderer::StrokeRadialGradient
|
||||||
this->strokeTable->update();
|
this->strokeTable->update();
|
||||||
handlingRowInsert = false;
|
handlingRowInsert = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(strokeTable, &QTableWidget::currentItemChanged, this, &StrokeStyleWidget::onCurrentItemChanged);
|
connect(strokeTable, &QTableWidget::currentItemChanged, this, &StrokeStyleWidget::onCurrentItemChanged);
|
||||||
connect(strokeTable, &QTableWidget::cellChanged, this, &StrokeStyleWidget::onCellChanged);
|
connect(strokeTable, &QTableWidget::cellChanged, this, &StrokeStyleWidget::onCellChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StrokeStyleWidget::setTableRow(int row, float width, Renderer::Material& material)
|
void StrokeStyleWidget::setTableRow(int row, float width, Renderer::Material& material)
|
||||||
{
|
{
|
||||||
QTableWidgetItem* widthItem = new QTableWidgetItem;
|
auto* widthItem = new QTableWidgetItem;
|
||||||
widthItem->setData(Qt::EditRole, width);
|
widthItem->setData(Qt::EditRole, width);
|
||||||
strokeTable->setItem(row, COLUMN_WIDTH, widthItem);
|
strokeTable->setItem(row, COLUMN_WIDTH, widthItem);
|
||||||
|
|
||||||
QColor* colorPtr = &(material.color);
|
QColor* colorPtr = &(material.color);
|
||||||
QTableWidgetItem* colorItem = new QTableWidgetItem;
|
auto* colorItem = new QTableWidgetItem;
|
||||||
colorItem->setData(Qt::DisplayRole, *colorPtr);
|
colorItem->setData(Qt::DisplayRole, *colorPtr);
|
||||||
strokeTable->setItem(row, COLUMN_COLOR, colorItem);
|
strokeTable->setItem(row, COLUMN_COLOR, colorItem);
|
||||||
ColorPicker* colorPicker = new ColorPicker(*colorPtr, strokeTable);
|
auto* colorPicker = new ColorPicker(*colorPtr, strokeTable);
|
||||||
strokeTable->setCellWidget(row, COLUMN_COLOR, colorPicker);
|
strokeTable->setCellWidget(row, COLUMN_COLOR, colorPicker);
|
||||||
connect(colorPicker, &ColorPicker::colorChanged, [this, colorPtr](QColor color) {
|
connect(colorPicker, &ColorPicker::colorChanged, [this, colorPtr](QColor color) {
|
||||||
*colorPtr = color;
|
*colorPtr = color;
|
||||||
this->strokeTable->update();
|
this->strokeTable->update();
|
||||||
});
|
});
|
||||||
|
|
||||||
QTableWidgetItem* metallicItem = new QTableWidgetItem;
|
auto* metallicItem = new QTableWidgetItem;
|
||||||
metallicItem->setData(Qt::EditRole, material.metallicF());
|
metallicItem->setData(Qt::EditRole, material.metallicF());
|
||||||
strokeTable->setItem(row, COLUMN_METALLIC, metallicItem);
|
strokeTable->setItem(row, COLUMN_METALLIC, metallicItem);
|
||||||
|
|
||||||
QTableWidgetItem* roughnessItem = new QTableWidgetItem;
|
auto* roughnessItem = new QTableWidgetItem;
|
||||||
roughnessItem->setData(Qt::EditRole, material.roughnessF());
|
roughnessItem->setData(Qt::EditRole, material.roughnessF());
|
||||||
strokeTable->setItem(row, COLUMN_ROUGHNESS, roughnessItem);
|
strokeTable->setItem(row, COLUMN_ROUGHNESS, roughnessItem);
|
||||||
|
|
||||||
QtMaterialRaisedButton* removeButton = new QtMaterialRaisedButton("-", strokeTable);
|
auto* removeButton = new QtMaterialRaisedButton("-", strokeTable);
|
||||||
|
removeButton->setBackgroundColor(QtMaterialStyle::instance().themeColor("primary1"));
|
||||||
removeButton->setFixedSize(20, 20);
|
removeButton->setFixedSize(20, 20);
|
||||||
strokeTable->setCellWidget(row, COLUMN_OPERATIONS, removeButton);
|
strokeTable->setCellWidget(row, COLUMN_OPERATIONS, removeButton);
|
||||||
connect(removeButton, &QtMaterialRaisedButton::clicked, [this, row]() {
|
connect(removeButton, &QtMaterialRaisedButton::clicked, [this, row]() {
|
||||||
|
|
|
@ -48,11 +48,11 @@ 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(const LayerStyleContainer& styles) const {
|
||||||
return this->getPaintObject();
|
return this->getPaintObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
PixelPath GroupElement::getPaintObject(std::vector<std::shared_ptr<LayerStyle>>* styles) const {
|
PixelPath GroupElement::getPaintObject(const LayerStyleContainer& styles) const {
|
||||||
return getPaintObject();
|
return getPaintObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ QJsonObject GroupElement::toJson() const
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleElement::paint(QPainter* painter, QTransform transform, const vector<std::shared_ptr<LayerStyle>>& styles)
|
void SimpleElement::paint(QPainter* painter, QTransform transform, const LayerStyleContainer& styles)
|
||||||
{
|
{
|
||||||
painter->save();
|
painter->save();
|
||||||
painter->setTransform(transform);
|
painter->setTransform(transform);
|
||||||
|
@ -102,9 +102,6 @@ void SimpleElement::paint(QPainter* painter, QTransform transform, const vector<
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::shared_ptr<Renderer::ElementStyle> style;
|
|
||||||
style = styles[0];
|
|
||||||
|
|
||||||
double angle = atan(transform.m12() / transform.m11());
|
double angle = atan(transform.m12() / transform.m11());
|
||||||
double maxScale;
|
double maxScale;
|
||||||
if (fabs(cos(angle))>1e-5)
|
if (fabs(cos(angle))>1e-5)
|
||||||
|
@ -112,7 +109,7 @@ void SimpleElement::paint(QPainter* painter, QTransform transform, const vector<
|
||||||
else
|
else
|
||||||
maxScale = std::max(fabs(transform.m12() / sin(angle)), fabs(transform.m21() / sin(angle)));
|
maxScale = std::max(fabs(transform.m12() / sin(angle)), fabs(transform.m21() / sin(angle)));
|
||||||
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, styles, pixelRatio);
|
||||||
transform.translate(mov.x(), mov.y());
|
transform.translate(mov.x(), mov.y());
|
||||||
painter->setTransform(transform.scale(1 / pixelRatio, 1 / pixelRatio));
|
painter->setTransform(transform.scale(1 / pixelRatio, 1 / pixelRatio));
|
||||||
painter->drawImage(0, 0, img);
|
painter->drawImage(0, 0, img);
|
||||||
|
@ -120,7 +117,7 @@ void SimpleElement::paint(QPainter* painter, QTransform transform, const vector<
|
||||||
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 LayerStyleContainer& styles)
|
||||||
{
|
{
|
||||||
sourceLayer->paint(painter, transform);
|
sourceLayer->paint(painter, transform);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
#include "LayerWrapper.h"
|
#include "LayerWrapper.h"
|
||||||
#include "LayerStyle.h"
|
#include "LayerStyle.h"
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QPainterPath>
|
#include <QPainterPath>
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
|
@ -27,8 +26,8 @@ public:
|
||||||
// TODO: ¸ÄΪBitmapPath
|
// TODO: ¸ÄΪBitmapPath
|
||||||
virtual QJsonObject toJson() const = 0;
|
virtual QJsonObject toJson() const = 0;
|
||||||
virtual PixelPath getPaintObject() const = 0;
|
virtual PixelPath getPaintObject() const = 0;
|
||||||
virtual PixelPath getPaintObject(std::vector<std::shared_ptr<LayerStyle>>*) const = 0;
|
virtual PixelPath getPaintObject(const LayerStyleContainer& styles) 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 LayerStyleContainer& styles) = 0;
|
||||||
virtual QPixmap getPreview(QSize size) = 0;
|
virtual QPixmap getPreview(QSize size) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -47,8 +46,8 @@ public:
|
||||||
SimpleElement(QString filePath);
|
SimpleElement(QString filePath);
|
||||||
~SimpleElement() = default;
|
~SimpleElement() = default;
|
||||||
PixelPath getPaintObject() const override;
|
PixelPath getPaintObject() const override;
|
||||||
PixelPath getPaintObject(std::vector<std::shared_ptr<LayerStyle>>*) const override;
|
PixelPath getPaintObject(const LayerStyleContainer& styles) const override;
|
||||||
void paint(QPainter* painter, QTransform transform, const std::vector<std::shared_ptr<LayerStyle>> &styles) override;
|
void paint(QPainter* painter, QTransform transform, const LayerStyleContainer& styles) override;
|
||||||
QPixmap getPreview(QSize size) override;
|
QPixmap getPreview(QSize size) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -63,9 +62,9 @@ public:
|
||||||
GroupElement(FolderLayerWrapper* mSourceLayer);
|
GroupElement(FolderLayerWrapper* mSourceLayer);
|
||||||
~GroupElement() = default;
|
~GroupElement() = default;
|
||||||
PixelPath getPaintObject() const override;
|
PixelPath getPaintObject() const override;
|
||||||
PixelPath getPaintObject(std::vector<std::shared_ptr<LayerStyle>>*) const override;
|
PixelPath getPaintObject(const LayerStyleContainer& styles) 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 LayerStyleContainer& styles) override;
|
||||||
QPixmap getPreview(QSize size) override;
|
QPixmap getPreview(QSize size) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,31 +9,29 @@
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#define _USE_JOIN_VIEW_INPUT_RANGE
|
||||||
const std::vector<std::pair<QString, std::function<std::unique_ptr<LayerStyle>()>>> LayerStyle::types = {
|
#include <QJsonArray>
|
||||||
{
|
#include <ranges>
|
||||||
QStringLiteral("描边"),
|
|
||||||
[]() { return std::make_unique<StrokeElementLayerStyle>(); }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
QStringLiteral("填充"),
|
|
||||||
[]() { return std::make_unique<FillElementLayerStyle>(); }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<Renderer::BaseStyle> StrokeElementLayerStyle::toBaseStyles() const
|
std::vector<Renderer::BaseStyle> StrokeElementLayerStyle::toBaseStyles() const
|
||||||
{
|
{
|
||||||
std::vector<Renderer::BaseStyle> baseStyles;
|
std::vector<Renderer::BaseStyle> baseStyles;
|
||||||
if (enableEachSideIndependent)
|
if (enableEachSideIndependent)
|
||||||
{
|
{
|
||||||
baseStyles.push_back(Renderer::BaseStyle(std::make_shared<Renderer::TransformStyle>(),
|
if (!radialStroke(strokePair.first)->materialMap.empty())
|
||||||
strokePair.first));
|
{
|
||||||
baseStyles.push_back(Renderer::BaseStyle(std::make_shared<Renderer::TransformStyle>(),
|
baseStyles.push_back(Renderer::BaseStyle(std::make_shared<Renderer::TransformStyle>(),
|
||||||
strokePair.second));
|
strokePair.first));
|
||||||
|
}
|
||||||
|
if (!radialStroke(strokePair.second)->materialMap.empty())
|
||||||
|
{
|
||||||
|
baseStyles.push_back(Renderer::BaseStyle(std::make_shared<Renderer::TransformStyle>(),
|
||||||
|
strokePair.second));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (!radialStroke(strokePair.first)->materialMap.empty())
|
||||||
{
|
{
|
||||||
auto material = std::shared_ptr<MaterialStyle>(std::move(strokePair.first->clone()));
|
const auto material = std::shared_ptr(std::move(strokePair.first->clone()));
|
||||||
std::dynamic_pointer_cast<MaterialStyleStroke>(material)->strokeType = Renderer::StrokeType::kBothSides;
|
std::dynamic_pointer_cast<MaterialStyleStroke>(material)->strokeType = Renderer::StrokeType::kBothSides;
|
||||||
|
|
||||||
baseStyles.push_back(Renderer::BaseStyle(std::make_shared<Renderer::TransformStyle>(), material));
|
baseStyles.push_back(Renderer::BaseStyle(std::make_shared<Renderer::TransformStyle>(), material));
|
||||||
|
@ -41,50 +39,23 @@ std::vector<Renderer::BaseStyle> StrokeElementLayerStyle::toBaseStyles() const
|
||||||
return baseStyles;
|
return baseStyles;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString StrokeElementLayerStyle::getStyleName() const
|
|
||||||
{
|
|
||||||
return QStringLiteral("描边");
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget* StrokeElementLayerStyle::getInputWidget()
|
QWidget* StrokeElementLayerStyle::getInputWidget()
|
||||||
{
|
{
|
||||||
if (this->strokePair.first == nullptr)
|
auto* w = new QWidget;
|
||||||
{
|
auto* materialList = new QListView;
|
||||||
auto materialMap = std::map<float, Renderer::Material>();
|
|
||||||
this->strokePair.first = std::shared_ptr<Renderer::MaterialStyleStroke>(new Renderer::MaterialStyleStroke(
|
|
||||||
15,
|
|
||||||
Renderer::StrokeType::kLeftSide, Renderer::StrokeEndType::kFlat,
|
|
||||||
std::shared_ptr<Renderer::MaterialStroke>(new Renderer::StrokeRadialGradient(
|
|
||||||
materialMap, false
|
|
||||||
))
|
|
||||||
));
|
|
||||||
}
|
|
||||||
if (this->strokePair.second == nullptr)
|
|
||||||
{
|
|
||||||
auto materialMap = std::map<float, Renderer::Material>();
|
|
||||||
this->strokePair.second = std::shared_ptr<Renderer::MaterialStyleStroke>(new Renderer::MaterialStyleStroke(
|
|
||||||
15,
|
|
||||||
Renderer::StrokeType::kRightSide, Renderer::StrokeEndType::kFlat,
|
|
||||||
std::shared_ptr<Renderer::MaterialStroke>(new Renderer::StrokeRadialGradient(
|
|
||||||
materialMap, false
|
|
||||||
))
|
|
||||||
));
|
|
||||||
}
|
|
||||||
QWidget* w = new QWidget;
|
|
||||||
QListView* materialList = new QListView;
|
|
||||||
|
|
||||||
QVBoxLayout* layout = new QVBoxLayout(w);
|
auto* layout = new QVBoxLayout(w);
|
||||||
layout->setMargin(0);
|
layout->setMargin(0);
|
||||||
|
|
||||||
StrokeStyleWidget* leftStrokeView = new StrokeStyleWidget(this->strokePair.first, w);
|
auto* leftStrokeView = new StrokeStyleWidget(this->strokePair.first, w);
|
||||||
layout->addWidget(leftStrokeView);
|
layout->addWidget(leftStrokeView);
|
||||||
|
|
||||||
QtMaterialCheckBox* checkEachSideIndependent = new QtMaterialCheckBox(w);
|
auto* checkEachSideIndependent = new QtMaterialCheckBox(w);
|
||||||
checkEachSideIndependent->setText(QStringLiteral("启用两侧独立描边"));
|
checkEachSideIndependent->setText(QStringLiteral("ÓÒ²à¶ÀÁ¢Ãè±ß"));
|
||||||
checkEachSideIndependent->setChecked(enableEachSideIndependent);
|
checkEachSideIndependent->setChecked(enableEachSideIndependent);
|
||||||
layout->addWidget(checkEachSideIndependent);
|
layout->addWidget(checkEachSideIndependent);
|
||||||
|
|
||||||
StrokeStyleWidget* rightStrokeView = new StrokeStyleWidget(this->strokePair.second, w);
|
auto* rightStrokeView = new StrokeStyleWidget(this->strokePair.second, w);
|
||||||
layout->addWidget(rightStrokeView);
|
layout->addWidget(rightStrokeView);
|
||||||
rightStrokeView->setDisabled(!this->enableEachSideIndependent);
|
rightStrokeView->setDisabled(!this->enableEachSideIndependent);
|
||||||
|
|
||||||
|
@ -97,39 +68,180 @@ QWidget* StrokeElementLayerStyle::getInputWidget()
|
||||||
|
|
||||||
QWidget* StrokeElementLayerStyle::getListDisplayWidget() const
|
QWidget* StrokeElementLayerStyle::getListDisplayWidget() const
|
||||||
{
|
{
|
||||||
QWidget* w = new QWidget;
|
auto* w = new QWidget;
|
||||||
QLabel* name = new QLabel(w);
|
auto* name = new QLabel(w);
|
||||||
name->setText(QStringLiteral("Ãè±ß"));
|
name->setText(QStringLiteral("Ãè±ß"));
|
||||||
QHBoxLayout* layout = new QHBoxLayout(w);
|
auto* layout = new QHBoxLayout(w);
|
||||||
layout->setMargin(0);
|
layout->setMargin(0);
|
||||||
layout->addWidget(name);
|
layout->addWidget(name);
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LayerStyleContainer::computeNewHash()
|
||||||
|
{
|
||||||
|
hash = 0;
|
||||||
|
for (auto& f : styles
|
||||||
|
| std::views::values
|
||||||
|
| std::views::transform(&LayerStyle::toBaseStyles)
|
||||||
|
| std::views::join
|
||||||
|
| std::views::transform(&Renderer::BaseStyle::material)
|
||||||
|
| std::views::transform(&MaterialStyle::encoded)
|
||||||
|
| std::views::join)
|
||||||
|
{
|
||||||
|
const unsigned int u = *reinterpret_cast<unsigned int*>(&f);
|
||||||
|
hash ^= u + 0x9e3779b9 + (hash << 6) + (hash >> 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LayerStyleContainer LayerStyleContainer::fromJson(const QJsonArray& jsonArray)
|
||||||
|
{
|
||||||
|
LayerStyleContainer container;
|
||||||
|
for (const auto& style : jsonArray)
|
||||||
|
{
|
||||||
|
container.useStyle(LayerStyle::fromJson(style.toObject()));
|
||||||
|
}
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
LayerStyleContainer::LayerStyleContainer() : hash(0)
|
||||||
|
{
|
||||||
|
unusedStyles = { {
|
||||||
|
StrokeElementLayerStyle::displayName(),
|
||||||
|
[] { return std::make_unique<StrokeElementLayerStyle>(); }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
FillElementLayerStyle::displayName(),
|
||||||
|
[] { return std::make_unique<FillElementLayerStyle>(); }
|
||||||
|
} };
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Renderer::BaseStyle> LayerStyleContainer::toBaseStyles() const
|
||||||
|
{
|
||||||
|
std::vector<Renderer::BaseStyle> result;
|
||||||
|
for (const auto& style : styles | std::views::values)
|
||||||
|
{
|
||||||
|
auto baseStyles = style->toBaseStyles();
|
||||||
|
result.insert(result.end(),
|
||||||
|
std::make_move_iterator(baseStyles.begin()),
|
||||||
|
std::make_move_iterator(baseStyles.end()));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray LayerStyleContainer::toJson() const
|
||||||
|
{
|
||||||
|
QJsonArray json;
|
||||||
|
for (const auto& style : styles | std::views::values)
|
||||||
|
{
|
||||||
|
json.append(style->toJson());
|
||||||
|
}
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList LayerStyleContainer::unusedStyleNames() const
|
||||||
|
{
|
||||||
|
QStringList result;
|
||||||
|
for(const auto& name : unusedStyles | std::views::keys)
|
||||||
|
{
|
||||||
|
result << name;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<LayerStyle> LayerStyleContainer::makeUnusedStyle(const QString& styleName) const
|
||||||
|
{
|
||||||
|
return unusedStyles.at(styleName)();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LayerStyleContainer::empty() const
|
||||||
|
{
|
||||||
|
return styles.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LayerStyleContainer::full() const
|
||||||
|
{
|
||||||
|
return unusedStyles.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<QString, std::shared_ptr<LayerStyle>>::iterator LayerStyleContainer::begin()
|
||||||
|
{
|
||||||
|
return styles.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<QString, std::shared_ptr<LayerStyle>>::iterator LayerStyleContainer::end()
|
||||||
|
{
|
||||||
|
return styles.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LayerStyleContainer::useStyle(const std::shared_ptr<LayerStyle>& style)
|
||||||
|
{
|
||||||
|
auto styleNode = unusedStyles.extract(style->getDisplayName());
|
||||||
|
if (styleNode.empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
styles[styleNode.key()] = style;
|
||||||
|
usedStyles.insert(std::move(styleNode));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LayerStyleContainer::dropStyle(const QString& styleName)
|
||||||
|
{
|
||||||
|
auto styleNode = usedStyles.extract(styleName);
|
||||||
|
if (styleNode.empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
styles.erase(styleName);
|
||||||
|
unusedStyles.insert(std::move(styleNode));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t LayerStyleContainer::getHash() const
|
||||||
|
{
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
StrokeElementLayerStyle::StrokeElementLayerStyle()
|
||||||
|
{
|
||||||
|
const auto materialMap = std::map<float, Renderer::Material>();
|
||||||
|
this->strokePair.first = std::make_shared<MaterialStyleStroke>(
|
||||||
|
7,
|
||||||
|
Renderer::StrokeType::kLeftSide, Renderer::StrokeEndType::kFlat,
|
||||||
|
std::make_shared<Renderer::StrokeRadialGradient>(materialMap, false)
|
||||||
|
);
|
||||||
|
|
||||||
|
this->strokePair.second = std::make_shared<MaterialStyleStroke>(
|
||||||
|
7,
|
||||||
|
Renderer::StrokeType::kRightSide, Renderer::StrokeEndType::kFlat,
|
||||||
|
std::make_shared<Renderer::StrokeRadialGradient>(materialMap, false)
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
StrokeElementLayerStyle::StrokeElementLayerStyle(PMaterialStyleStroke left, PMaterialStyleStroke right)
|
StrokeElementLayerStyle::StrokeElementLayerStyle(PMaterialStyleStroke left, PMaterialStyleStroke right)
|
||||||
{
|
{
|
||||||
this->strokePair.first = left;
|
this->strokePair.first = left;
|
||||||
this->strokePair.second = right ? right : std::dynamic_pointer_cast<MaterialStyleStroke>(
|
this->strokePair.second = right ? right : std::static_pointer_cast<MaterialStyleStroke>(
|
||||||
std::shared_ptr<Renderer::MaterialStyle>(std::move(left->clone()))
|
std::shared_ptr(std::move(left->clone()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
StrokeElementLayerStyle::StrokeElementLayerStyle(const StrokeElementLayerStyle& other)
|
StrokeElementLayerStyle::StrokeElementLayerStyle(const StrokeElementLayerStyle& other)
|
||||||
{
|
{
|
||||||
strokePair.first = std::dynamic_pointer_cast<MaterialStyleStroke>(
|
strokePair.first = std::static_pointer_cast<MaterialStyleStroke>(
|
||||||
std::shared_ptr<Renderer::MaterialStyle>(std::move(other.strokePair.first->clone()))
|
std::shared_ptr(std::move(other.strokePair.first->clone()))
|
||||||
);
|
);
|
||||||
strokePair.second = std::dynamic_pointer_cast<MaterialStyleStroke>(
|
strokePair.second = std::static_pointer_cast<MaterialStyleStroke>(
|
||||||
std::shared_ptr<Renderer::MaterialStyle>(std::move(other.strokePair.second->clone()))
|
std::shared_ptr(std::move(other.strokePair.second->clone()))
|
||||||
);
|
);
|
||||||
enableEachSideIndependent = other.enableEachSideIndependent;
|
enableEachSideIndependent = other.enableEachSideIndependent;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject StrokeElementLayerStyle::toJson() const
|
QJsonObject StrokeElementLayerStyle::toJson() const
|
||||||
{
|
{
|
||||||
// todo: 修改打开逻辑
|
|
||||||
QJsonObject json;
|
QJsonObject json;
|
||||||
json["type"] = getTypeName();
|
json["type"] = typeName();
|
||||||
json["enableEachSideIndependent"] = enableEachSideIndependent;
|
json["enableEachSideIndependent"] = enableEachSideIndependent;
|
||||||
json["left"] = EncodeUtil::toBase64<GLfloat>(strokePair.first->encoded());
|
json["left"] = EncodeUtil::toBase64<GLfloat>(strokePair.first->encoded());
|
||||||
json["right"] = EncodeUtil::toBase64<GLfloat>(strokePair.second->encoded());
|
json["right"] = EncodeUtil::toBase64<GLfloat>(strokePair.second->encoded());
|
||||||
|
@ -143,28 +255,24 @@ std::unique_ptr<LayerStyle> StrokeElementLayerStyle::clone() const
|
||||||
|
|
||||||
std::vector<Renderer::BaseStyle> FillElementLayerStyle::toBaseStyles() const
|
std::vector<Renderer::BaseStyle> FillElementLayerStyle::toBaseStyles() const
|
||||||
{
|
{
|
||||||
|
// TODO: implement
|
||||||
return std::vector<Renderer::BaseStyle>();
|
return std::vector<Renderer::BaseStyle>();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FillElementLayerStyle::getStyleName() const
|
|
||||||
{
|
|
||||||
return QStringLiteral("填充");
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget* FillElementLayerStyle::getInputWidget()
|
QWidget* FillElementLayerStyle::getInputWidget()
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
QLineEdit* name = new QLineEdit;
|
auto* name = new QLineEdit;
|
||||||
name->setText(QStringLiteral("Ìî³ä"));
|
name->setText(QStringLiteral("Ìî³ä"));
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget* FillElementLayerStyle::getListDisplayWidget() const
|
QWidget* FillElementLayerStyle::getListDisplayWidget() const
|
||||||
{
|
{
|
||||||
QWidget* w = new QWidget;
|
auto* w = new QWidget;
|
||||||
QLabel* name = new QLabel(w);
|
auto* name = new QLabel(w);
|
||||||
name->setText(QStringLiteral("Ìî³ä"));
|
name->setText(QStringLiteral("Ìî³ä"));
|
||||||
QHBoxLayout* layout = new QHBoxLayout(w);
|
auto* layout = new QHBoxLayout(w);
|
||||||
layout->setMargin(0);
|
layout->setMargin(0);
|
||||||
layout->addWidget(name);
|
layout->addWidget(name);
|
||||||
return w;
|
return w;
|
||||||
|
@ -192,20 +300,20 @@ std::unique_ptr<LayerStyle> FillElementLayerStyle::clone() const
|
||||||
std::unique_ptr<LayerStyle> LayerStyle::fromJson(const QJsonObject& json)
|
std::unique_ptr<LayerStyle> LayerStyle::fromJson(const QJsonObject& json)
|
||||||
{
|
{
|
||||||
QString type = json["type"].toString();
|
QString type = json["type"].toString();
|
||||||
if (type == StrokeElementLayerStyle::getTypeName())
|
if (type == StrokeElementLayerStyle::typeName())
|
||||||
{
|
{
|
||||||
auto ptr = std::make_unique<StrokeElementLayerStyle>(
|
auto ptr = std::make_unique<StrokeElementLayerStyle>(
|
||||||
std::dynamic_pointer_cast<MaterialStyleStroke>(
|
std::static_pointer_cast<MaterialStyleStroke>(
|
||||||
std::shared_ptr<Renderer::MaterialStyle>(std::move(Renderer::MaterialStyle::decoded(EncodeUtil::fromBase64<GLfloat>(json["left"].toString()))))
|
std::shared_ptr(std::move(MaterialStyle::decoded(EncodeUtil::fromBase64<GLfloat>(json["left"].toString()))))
|
||||||
),
|
),
|
||||||
std::dynamic_pointer_cast<MaterialStyleStroke>(
|
std::static_pointer_cast<MaterialStyleStroke>(
|
||||||
std::shared_ptr<Renderer::MaterialStyle>(std::move(Renderer::MaterialStyle::decoded(EncodeUtil::fromBase64<GLfloat>(json["right"].toString()))))
|
std::shared_ptr(std::move(MaterialStyle::decoded(EncodeUtil::fromBase64<GLfloat>(json["right"].toString()))))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
ptr->enableEachSideIndependent = json["enableEachSideIndependent"].toBool();
|
ptr->enableEachSideIndependent = json["enableEachSideIndependent"].toBool();
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
else if (type == FillElementLayerStyle::getTypeName())
|
else if (type == FillElementLayerStyle::typeName())
|
||||||
{
|
{
|
||||||
return std::make_unique<FillElementLayerStyle>();
|
return std::make_unique<FillElementLayerStyle>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <map>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <QWidget>
|
#include <set>
|
||||||
#include <QObject>
|
#include <map>
|
||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
#include <QJsonArray>
|
||||||
#include "../Renderer/Painting/ElementStyle.h"
|
#include "../Renderer/Painting/ElementStyle.h"
|
||||||
#include "../Renderer/Painting/MaterialStyleStroke.h"
|
#include "../Renderer/Painting/MaterialStyleStroke.h"
|
||||||
#include "../Renderer/Painting/MaterialStyleFill.h"
|
#include "../Renderer/Painting/MaterialStyleFill.h"
|
||||||
|
@ -13,64 +13,90 @@
|
||||||
using Renderer::MaterialStyle;
|
using Renderer::MaterialStyle;
|
||||||
using Renderer::MaterialStyleStroke;
|
using Renderer::MaterialStyleStroke;
|
||||||
|
|
||||||
#define STYLE_TYPENAME(name) static QString getTypeName() { return name; }
|
#define STYLE_NAME(display_name, type_name) \
|
||||||
|
static QString displayName() { return QStringLiteral(display_name); } \
|
||||||
|
QString getDisplayName() const override { return QStringLiteral(display_name); } \
|
||||||
|
static QString typeName() { return type_name; }
|
||||||
|
#define radialStroke(stroke) std::static_pointer_cast<Renderer::StrokeRadialGradient>(stroke->materialStroke)
|
||||||
|
|
||||||
/**
|
|
||||||
* 在进行Style的添加时,首先创建空对象,然后直接调用getInputWidget()方法
|
|
||||||
* 在进行Style的修改时,直接调用getInputWidget()方法
|
|
||||||
*
|
|
||||||
* 对于LayerStyle的实现类,应该同时实现ElementStyle,并将相同种类的(如描边或填充)的style整合成一个类,
|
|
||||||
* 对于相同的类,一个图层应该只拥有一个
|
|
||||||
*/
|
|
||||||
class LayerStyle : public Renderer::ElementStyle
|
class LayerStyle : public Renderer::ElementStyle
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const static std::vector<std::pair<QString, std::function<std::unique_ptr<LayerStyle>()>>> types;
|
|
||||||
static std::unique_ptr<LayerStyle> fromJson(const QJsonObject& json);
|
static std::unique_ptr<LayerStyle> fromJson(const QJsonObject& json);
|
||||||
|
|
||||||
virtual QString getStyleName() const = 0;
|
virtual QString getDisplayName() const = 0;
|
||||||
virtual QWidget* getInputWidget() = 0;
|
virtual QWidget* getInputWidget() = 0;
|
||||||
virtual QWidget* getListDisplayWidget() const = 0;
|
virtual QWidget* getListDisplayWidget() const = 0;
|
||||||
virtual ~LayerStyle() {};
|
virtual ~LayerStyle() = default;
|
||||||
virtual QJsonObject toJson() const = 0;
|
virtual QJsonObject toJson() const = 0;
|
||||||
virtual std::unique_ptr<LayerStyle> clone() const = 0;
|
virtual std::unique_ptr<LayerStyle> clone() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class LayerStyleContainer : public Renderer::ElementStyle
|
||||||
|
{
|
||||||
|
using DisplayNameWithSupplier = std::map<QString, std::function<std::unique_ptr<LayerStyle>()>>;
|
||||||
|
private:
|
||||||
|
DisplayNameWithSupplier unusedStyles;
|
||||||
|
DisplayNameWithSupplier usedStyles;
|
||||||
|
std::map<QString, std::shared_ptr<LayerStyle>> styles;
|
||||||
|
size_t hash;
|
||||||
|
public:
|
||||||
|
static LayerStyleContainer fromJson(const QJsonArray& jsonArray);
|
||||||
|
|
||||||
|
LayerStyleContainer();
|
||||||
|
std::vector<Renderer::BaseStyle> toBaseStyles() const override;
|
||||||
|
QJsonArray toJson() const;
|
||||||
|
|
||||||
|
bool empty() const;
|
||||||
|
bool full() const;
|
||||||
|
std::map<QString, std::shared_ptr<LayerStyle>>::iterator begin();
|
||||||
|
std::map<QString, std::shared_ptr<LayerStyle>>::iterator end();
|
||||||
|
|
||||||
|
QStringList unusedStyleNames() const;
|
||||||
|
std::unique_ptr<LayerStyle> makeUnusedStyle(const QString& styleName) const;
|
||||||
|
bool useStyle(const std::shared_ptr<LayerStyle>& style);
|
||||||
|
bool dropStyle(const QString& styleName);
|
||||||
|
size_t getHash() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 需要在每次更改后手动调用
|
||||||
|
*/
|
||||||
|
void computeNewHash();
|
||||||
|
};
|
||||||
|
|
||||||
class StrokeElementLayerStyle : public LayerStyle
|
class StrokeElementLayerStyle : public LayerStyle
|
||||||
{
|
{
|
||||||
using PMaterialStyleStroke = std::shared_ptr<MaterialStyleStroke>;
|
using PMaterialStyleStroke = std::shared_ptr<MaterialStyleStroke>;
|
||||||
private:
|
|
||||||
std::pair<PMaterialStyleStroke, PMaterialStyleStroke> strokePair;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
STYLE_TYPENAME("stroke")
|
STYLE_NAME("描边","stroke")
|
||||||
|
|
||||||
StrokeElementLayerStyle() = default;
|
StrokeElementLayerStyle();
|
||||||
StrokeElementLayerStyle(PMaterialStyleStroke left, PMaterialStyleStroke right = nullptr);
|
StrokeElementLayerStyle(PMaterialStyleStroke left, PMaterialStyleStroke right = nullptr);
|
||||||
StrokeElementLayerStyle(const StrokeElementLayerStyle& other);
|
StrokeElementLayerStyle(const StrokeElementLayerStyle& other);
|
||||||
~StrokeElementLayerStyle() = default;
|
~StrokeElementLayerStyle() override = default;
|
||||||
|
|
||||||
std::vector<Renderer::BaseStyle> toBaseStyles() const override;
|
std::vector<Renderer::BaseStyle> toBaseStyles() const override;
|
||||||
QString getStyleName() const override;
|
|
||||||
QWidget* getInputWidget() override;
|
QWidget* getInputWidget() override;
|
||||||
QWidget* getListDisplayWidget() const override;
|
QWidget* getListDisplayWidget() const override;
|
||||||
QJsonObject toJson() const override;
|
QJsonObject toJson() const override;
|
||||||
std::unique_ptr<LayerStyle> clone() const override;
|
std::unique_ptr<LayerStyle> clone() const override;
|
||||||
|
|
||||||
|
std::pair<PMaterialStyleStroke, PMaterialStyleStroke> strokePair;
|
||||||
bool enableEachSideIndependent = false;
|
bool enableEachSideIndependent = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FillElementLayerStyle : public LayerStyle
|
class FillElementLayerStyle : public LayerStyle
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
STYLE_TYPENAME("fill")
|
STYLE_NAME("填充","fill")
|
||||||
|
|
||||||
std::vector<Renderer::BaseStyle> toBaseStyles() const override;
|
std::vector<Renderer::BaseStyle> toBaseStyles() const override;
|
||||||
QString getStyleName() const override;
|
|
||||||
QWidget* getInputWidget() override;
|
QWidget* getInputWidget() override;
|
||||||
QWidget* getListDisplayWidget() const override;
|
QWidget* getListDisplayWidget() const override;
|
||||||
FillElementLayerStyle() = default;
|
FillElementLayerStyle() = default;
|
||||||
FillElementLayerStyle(const FillElementLayerStyle& other);
|
FillElementLayerStyle(const FillElementLayerStyle& other);
|
||||||
~FillElementLayerStyle() = default;
|
~FillElementLayerStyle() override = default;
|
||||||
std::vector<std::shared_ptr<Renderer::MaterialStyleFill>> materialStyles;
|
std::vector<std::shared_ptr<Renderer::MaterialStyleFill>> materialStyles;
|
||||||
QJsonObject toJson() const override;
|
QJsonObject toJson() const override;
|
||||||
std::unique_ptr<LayerStyle> clone() const override;
|
std::unique_ptr<LayerStyle> clone() const override;
|
||||||
|
|
|
@ -80,10 +80,7 @@ LeafLayerWrapper::LeafLayerWrapper(QJsonObject json, ElementManager *elementMana
|
||||||
int elementIndex = json.value("element").toInt();
|
int elementIndex = json.value("element").toInt();
|
||||||
wrappedElement = elementManager->getElementById(elementIndex);
|
wrappedElement = elementManager->getElementById(elementIndex);
|
||||||
QJsonArray stylesArray = json.value("styles").toArray();
|
QJsonArray stylesArray = json.value("styles").toArray();
|
||||||
for (const auto& style : stylesArray)
|
styles = LayerStyleContainer::fromJson(stylesArray);
|
||||||
{
|
|
||||||
styles.push_back(LayerStyle::fromJson(style.toObject()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerWrapper::SimpleProperty::apply(PixelPath&cache)
|
void LayerWrapper::SimpleProperty::apply(PixelPath&cache)
|
||||||
|
@ -135,7 +132,7 @@ void LeafLayerWrapper::refresh(LayerWrapper* layer)
|
||||||
cache.clear();
|
cache.clear();
|
||||||
if (wrappedElement != nullptr)
|
if (wrappedElement != nullptr)
|
||||||
{
|
{
|
||||||
cache.addPath(wrappedElement->getPaintObject(&(this->styles)));
|
cache.addPath(wrappedElement->getPaintObject(this->styles));
|
||||||
}
|
}
|
||||||
LayerWrapper::refresh();
|
LayerWrapper::refresh();
|
||||||
}
|
}
|
||||||
|
@ -245,10 +242,7 @@ QJsonObject LeafLayerWrapper::toJson() const
|
||||||
QJsonObject json = LayerWrapper::toJson();
|
QJsonObject json = LayerWrapper::toJson();
|
||||||
json.insert("element", wrappedElement->index);
|
json.insert("element", wrappedElement->index);
|
||||||
json.insert("is-folder", false);
|
json.insert("is-folder", false);
|
||||||
QJsonArray stylesJson;
|
json.insert("styles", styles.toJson());
|
||||||
for (auto& style : styles)
|
|
||||||
stylesJson.push_back(style->toJson());
|
|
||||||
json.insert("styles", stylesJson);
|
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,8 +98,7 @@ class LeafLayerWrapper : public LayerWrapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GraphicElement *wrappedElement;
|
GraphicElement *wrappedElement;
|
||||||
//const vector<Renderer::ElementStyleStrokeDemo> styles;
|
LayerStyleContainer styles;
|
||||||
vector<std::shared_ptr<LayerStyle>> styles;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~LeafLayerWrapper() = default;
|
~LeafLayerWrapper() = default;
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QDialogButtonBox>
|
|
||||||
#include <qtmaterialraisedbutton.h>
|
#include <qtmaterialraisedbutton.h>
|
||||||
#include <qtmaterialflatbutton.h>
|
#include <qtmaterialflatbutton.h>
|
||||||
|
|
||||||
|
@ -82,38 +81,39 @@ void InfoDisplayWidget::generateLayerForm()
|
||||||
layout->addRow("scale-Y:", scaleY);
|
layout->addRow("scale-Y:", scaleY);
|
||||||
layout->setRowWrapPolicy(QFormLayout::DontWrapRows);
|
layout->setRowWrapPolicy(QFormLayout::DontWrapRows);
|
||||||
|
|
||||||
LeafLayerWrapper* leafP = dynamic_cast<LeafLayerWrapper*>(this->displayLayer);
|
if (auto* leafP = dynamic_cast<LeafLayerWrapper*>(this->displayLayer); leafP) {
|
||||||
if (leafP) {
|
auto* styleList = new QListWidget(this);
|
||||||
QListWidget* styleList = new QListWidget(this);
|
|
||||||
|
|
||||||
QListWidgetItem* header = new QListWidgetItem;
|
auto* header = new QListWidgetItem;
|
||||||
QWidget* headerWidget = new QWidget(styleList);
|
auto* headerWidget = new QWidget(styleList);
|
||||||
QHBoxLayout* headerLayout = new QHBoxLayout;
|
auto* headerLayout = new QHBoxLayout;
|
||||||
|
|
||||||
QLabel* headerLabel = new QLabel(headerWidget);
|
auto* headerLabel = new QLabel(headerWidget);
|
||||||
headerLabel->setText("样式列表");
|
headerLabel->setText("样式列表");
|
||||||
headerLabel->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
|
headerLabel->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
|
||||||
|
|
||||||
//QtMaterialRaisedButton* addStyleButton = new QtMaterialRaisedButton("+", headerWidget);
|
//QtMaterialRaisedButton* addStyleButton = new QtMaterialRaisedButton("+", headerWidget);
|
||||||
QPushButton* addStyleButton = new QPushButton("+", headerWidget);
|
auto* addStyleButton = new QPushButton("+", headerWidget);
|
||||||
addStyleButton->setFixedSize(QSize(20, 20));
|
addStyleButton->setFixedSize(QSize(20, 20));
|
||||||
if (leafP->styles.size() >= LayerStyle::types.size())
|
if (leafP->styles.full())
|
||||||
{
|
{
|
||||||
addStyleButton->setDisabled(true);
|
addStyleButton->setDisabled(true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
connect(addStyleButton, &QPushButton::clicked, [&, leafP]() {
|
connect(addStyleButton, &QPushButton::clicked, [&, leafP] {
|
||||||
LayerStyleDialog* dialog = new LayerStyleDialog(nullptr, nullptr, &(leafP->styles));
|
auto* dialog = new LayerStyleDialog(leafP->styles);
|
||||||
dialog->exec();
|
dialog->exec();
|
||||||
if (dialog->layerStyle)
|
if (dialog->layerStyle)
|
||||||
{
|
{
|
||||||
leafP->styles.push_back(dialog->layerStyle);
|
leafP->styles.useStyle(dialog->layerStyle);
|
||||||
emit requireRefreshPreview();
|
leafP->styles.computeNewHash();
|
||||||
emit requireSelfRefresh();
|
|
||||||
emit requireRefreshElementWidget();
|
emit requireRefreshPreview();
|
||||||
}
|
emit requireSelfRefresh();
|
||||||
dialog->deleteLater();
|
emit requireRefreshElementWidget();
|
||||||
|
}
|
||||||
|
dialog->deleteLater();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,32 +179,35 @@ void InfoDisplayWidget::generateLayerForm()
|
||||||
{
|
{
|
||||||
leafP->styles.push_back(std::shared_ptr<LayerStyle>(new StrokeElementLayerStyle()));
|
leafP->styles.push_back(std::shared_ptr<LayerStyle>(new StrokeElementLayerStyle()));
|
||||||
}*/
|
}*/
|
||||||
std::vector<std::shared_ptr<LayerStyle>>* styles = &(leafP->styles);
|
auto* styles = &leafP->styles;
|
||||||
for (auto styleIterator = styles->begin(); styleIterator != styles->end(); styleIterator++)
|
for (auto styleIterator = styles->begin(); styleIterator != styles->end(); ++styleIterator)
|
||||||
{
|
{
|
||||||
QListWidgetItem* item = new QListWidgetItem;
|
auto* item = new QListWidgetItem;
|
||||||
QWidget* w = new QWidget;
|
auto* w = new QWidget(this);
|
||||||
item->setSizeHint(QSize(50, 40));
|
item->setSizeHint(QSize(50, 40));
|
||||||
QHBoxLayout* layout = new QHBoxLayout;
|
auto* layout = new QHBoxLayout(w);
|
||||||
layout->setAlignment(Qt::AlignmentFlag::AlignRight);
|
layout->setAlignment(Qt::AlignmentFlag::AlignRight);
|
||||||
//QtMaterialFlatButton* detailButton = new QtMaterialFlatButton(w);
|
//QtMaterialFlatButton* detailButton = new QtMaterialFlatButton(w);
|
||||||
//QtMaterialFlatButton* removeButton = new QtMaterialFlatButton(w);
|
//QtMaterialFlatButton* removeButton = new QtMaterialFlatButton(w);
|
||||||
QPushButton* detailButton = new QPushButton(w);
|
auto* detailButton = new QPushButton(w);
|
||||||
QPushButton* removeButton = new QPushButton(w);
|
auto* removeButton = new QPushButton(w);
|
||||||
detailButton->setText("...");
|
detailButton->setText("...");
|
||||||
detailButton->setFixedSize(QSize(20, 20));
|
detailButton->setFixedSize(QSize(20, 20));
|
||||||
removeButton->setText("×");
|
removeButton->setText("×");
|
||||||
removeButton->setFixedSize(QSize(20, 20));
|
removeButton->setFixedSize(QSize(20, 20));
|
||||||
|
|
||||||
connect(detailButton, &QPushButton::clicked, this,
|
connect(detailButton, &QPushButton::clicked, this,
|
||||||
[this, styleIterator]()
|
[this, styles, styleIterator]
|
||||||
{
|
{
|
||||||
LayerStyleDialog* dialog = new LayerStyleDialog(nullptr, *styleIterator);
|
auto* dialog =
|
||||||
|
new LayerStyleDialog(*styles, styleIterator->second);
|
||||||
dialog->exec();
|
dialog->exec();
|
||||||
|
|
||||||
if (dialog->layerStyle)
|
if (dialog->layerStyle)
|
||||||
{
|
{
|
||||||
(*styleIterator) = dialog->layerStyle;
|
styleIterator->second = dialog->layerStyle;
|
||||||
|
styles->computeNewHash();
|
||||||
|
|
||||||
emit requireRefreshPreview();
|
emit requireRefreshPreview();
|
||||||
emit requireSelfRefresh();
|
emit requireSelfRefresh();
|
||||||
emit requireRefreshElementWidget();
|
emit requireRefreshElementWidget();
|
||||||
|
@ -213,15 +216,17 @@ void InfoDisplayWidget::generateLayerForm()
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(removeButton, &QPushButton::clicked, this,
|
connect(removeButton, &QPushButton::clicked, this,
|
||||||
[this, styleIterator, styles]()
|
[this, styleIterator, styles]
|
||||||
{
|
{
|
||||||
styles->erase(styleIterator);
|
styles->dropStyle(styleIterator->first);
|
||||||
|
styles->computeNewHash();
|
||||||
|
|
||||||
emit requireRefreshPreview();
|
emit requireRefreshPreview();
|
||||||
emit requireSelfRefresh();
|
emit requireSelfRefresh();
|
||||||
emit requireRefreshElementWidget();
|
emit requireRefreshElementWidget();
|
||||||
});
|
});
|
||||||
|
|
||||||
QWidget* styleDisplayWidget = (*styleIterator)->getListDisplayWidget();
|
QWidget* styleDisplayWidget = styleIterator->second->getListDisplayWidget();
|
||||||
styleDisplayWidget->setParent(w);
|
styleDisplayWidget->setParent(w);
|
||||||
styleDisplayWidget->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
|
styleDisplayWidget->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace Renderer
|
||||||
glm::vec3 Position;
|
glm::vec3 Position;
|
||||||
glm::vec3 Normal;
|
glm::vec3 Normal;
|
||||||
glm::vec2 TexCoords;
|
glm::vec2 TexCoords;
|
||||||
Vertex(const aiVector3D& position, const aiVector3D& Normal, const aiVector3D& TexCoords);
|
Vertex(const aiVector3D& position, const aiVector3D& normal, const aiVector3D& texCoords);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Texture
|
struct Texture
|
||||||
|
|
|
@ -32,14 +32,12 @@ Model::Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram,
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::draw() {
|
void Model::draw() {
|
||||||
//shaderProgram->bind();
|
|
||||||
for (auto& mesh : meshes) {
|
for (auto& mesh : meshes) {
|
||||||
mesh->draw();
|
mesh->draw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::drawShadow() {
|
void Model::drawShadow() {
|
||||||
//shaderProgram->bind();
|
|
||||||
for (auto& mesh : meshes) {
|
for (auto& mesh : meshes) {
|
||||||
mesh->drawShadow();
|
mesh->drawShadow();
|
||||||
}
|
}
|
||||||
|
@ -55,7 +53,7 @@ void Renderer::Model::loadModel(QString path)
|
||||||
const aiScene* scene = importer.ReadFile(modelFile.absoluteFilePath().toUtf8(), aiProcess_Triangulate);
|
const aiScene* scene = importer.ReadFile(modelFile.absoluteFilePath().toUtf8(), aiProcess_Triangulate);
|
||||||
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
|
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
|
||||||
{
|
{
|
||||||
qCritical() << "ERROR::ASSIMP::" << importer.GetErrorString() << endl;
|
qCritical() << "ERROR::ASSIMP::" << importer.GetErrorString();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
qDebug() << modelFile.absoluteFilePath() << "Loaded Successfully";
|
qDebug() << modelFile.absoluteFilePath() << "Loaded Successfully";
|
||||||
|
@ -63,9 +61,11 @@ void Renderer::Model::loadModel(QString path)
|
||||||
qDebug() << "NumMaterials: " << scene->mNumMaterials;
|
qDebug() << "NumMaterials: " << scene->mNumMaterials;
|
||||||
qDebug() << "NumTextures: " << scene->mNumTextures;
|
qDebug() << "NumTextures: " << scene->mNumTextures;
|
||||||
|
|
||||||
|
unloadModel();
|
||||||
|
|
||||||
|
|
||||||
if (QFile paintingConfigFile(directory.filePath(name + ".txt")); paintingConfigFile.open(QFile::ReadOnly | QIODevice::Text))
|
if (QFile paintingConfigFile(directory.filePath(name + ".txt")); paintingConfigFile.open(QFile::ReadOnly | QIODevice::Text))
|
||||||
{
|
{
|
||||||
paintingMap.clear();
|
|
||||||
QTextStream stream(&paintingConfigFile);
|
QTextStream stream(&paintingConfigFile);
|
||||||
while (!stream.atEnd())
|
while (!stream.atEnd())
|
||||||
{
|
{
|
||||||
|
@ -82,23 +82,36 @@ void Renderer::Model::loadModel(QString path)
|
||||||
qWarning() << "Painting Config Not Found!";
|
qWarning() << "Painting Config Not Found!";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
aiMatrix4x4 transform;
|
||||||
|
aiMatrix4x4::Scaling(aiVector3D(1 / 0.008), transform);
|
||||||
|
processNode(scene->mRootNode, scene, transform * scene->mRootNode->mTransformation);
|
||||||
|
AABB.clear();
|
||||||
|
AABB.emplace_back(minX, minY, minZ);
|
||||||
|
AABB.emplace_back(minX, minY, maxZ);
|
||||||
|
AABB.emplace_back(minX, maxY, minZ);
|
||||||
|
AABB.emplace_back(minX, maxY, maxZ);
|
||||||
|
AABB.emplace_back(maxX, minY, minZ);
|
||||||
|
AABB.emplace_back(maxX, minY, maxZ);
|
||||||
|
AABB.emplace_back(maxX, maxY, minZ);
|
||||||
|
AABB.emplace_back(maxX, maxY, maxZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::Model::unloadModel()
|
||||||
|
{
|
||||||
|
paintingMap.clear();
|
||||||
|
for(auto& i: paintingLoaded)
|
||||||
|
vtManager->deleteVirtualTexture(i.second);
|
||||||
|
paintingLoaded.clear();
|
||||||
|
texturesLoaded.clear();
|
||||||
|
meshes.clear();
|
||||||
|
|
||||||
minX = std::numeric_limits<float>::max();
|
minX = std::numeric_limits<float>::max();
|
||||||
maxX = std::numeric_limits<float>::min();
|
maxX = std::numeric_limits<float>::min();
|
||||||
minY = std::numeric_limits<float>::max();
|
minY = std::numeric_limits<float>::max();
|
||||||
maxY = std::numeric_limits<float>::min();
|
maxY = std::numeric_limits<float>::min();
|
||||||
minZ = std::numeric_limits<float>::max();
|
minZ = std::numeric_limits<float>::max();
|
||||||
maxZ = std::numeric_limits<float>::min();
|
maxZ = std::numeric_limits<float>::min();
|
||||||
aiMatrix4x4 transform;
|
|
||||||
aiMatrix4x4::Scaling(aiVector3D(1 / 0.008), transform);
|
|
||||||
processNode(scene->mRootNode, scene, transform * scene->mRootNode->mTransformation);
|
|
||||||
AABB.push_back(QVector3D(minX, minY, minZ));
|
|
||||||
AABB.push_back(QVector3D(minX, minY, maxZ));
|
|
||||||
AABB.push_back(QVector3D(minX, maxY, minZ));
|
|
||||||
AABB.push_back(QVector3D(minX, maxY, maxZ));
|
|
||||||
AABB.push_back(QVector3D(maxX, minY, minZ));
|
|
||||||
AABB.push_back(QVector3D(maxX, minY, maxZ));
|
|
||||||
AABB.push_back(QVector3D(maxX, maxY, minZ));
|
|
||||||
AABB.push_back(QVector3D(maxX, maxY, maxZ));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4)
|
void Model::processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4)
|
||||||
|
|
|
@ -15,6 +15,7 @@ namespace Renderer
|
||||||
void draw();
|
void draw();
|
||||||
void drawShadow();
|
void drawShadow();
|
||||||
void loadModel(QString path);
|
void loadModel(QString path);
|
||||||
|
void unloadModel();
|
||||||
Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, VirtualTextureManager* vtManager);
|
Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, VirtualTextureManager* vtManager);
|
||||||
private:
|
private:
|
||||||
QOpenGLContext* context = nullptr;
|
QOpenGLContext* context = nullptr;
|
||||||
|
@ -25,8 +26,8 @@ namespace Renderer
|
||||||
VirtualTextureManager* vtManager = nullptr;
|
VirtualTextureManager* vtManager = nullptr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param key BaseColor路径
|
* @brief key BaseColor路径 \n
|
||||||
* @param value json路径, 纹理坐标
|
* value json路径, 纹理坐标
|
||||||
*/
|
*/
|
||||||
std::unordered_map<std::string, std::tuple<std::string, glm::vec2, glm::vec2>> paintingMap;
|
std::unordered_map<std::string, std::tuple<std::string, glm::vec2, glm::vec2>> paintingMap;
|
||||||
std::unordered_map<std::string, GLuint> paintingLoaded;
|
std::unordered_map<std::string, GLuint> paintingLoaded;
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace Renderer
|
||||||
~RendererWidget();
|
~RendererWidget();
|
||||||
public slots:
|
public slots:
|
||||||
void currentTabChanged(int index);
|
void currentTabChanged(int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::RendererWidgetClass ui;
|
Ui::RendererWidgetClass ui;
|
||||||
};
|
};
|
||||||
|
|
|
@ -152,8 +152,26 @@ std::uint16_t Renderer::VirtualTextureManager::createVirtualTexture(Painting pai
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
paintings.emplace_back(baseColor, metallicRoughness, painting.buffers);
|
if (const auto it = std::find_if(paintings.begin(), paintings.end(), [](const PaintingHandle& i) { return i.baseColor == 0; });
|
||||||
return paintings.size();
|
it != paintings.end())
|
||||||
|
{
|
||||||
|
*it = { baseColor, metallicRoughness, painting.buffers };
|
||||||
|
return it - paintings.begin() + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
paintings.emplace_back(baseColor, metallicRoughness, painting.buffers);
|
||||||
|
return paintings.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::VirtualTextureManager::deleteVirtualTexture(std::uint16_t id)
|
||||||
|
{
|
||||||
|
auto& painting = getPaintingHandle(id);
|
||||||
|
glMain->DeleteTextures(2, (GLuint*)&painting);
|
||||||
|
painting.baseColor = 0;
|
||||||
|
painting.metallicRoughness = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer::PaintingHandle& Renderer::VirtualTextureManager::getPaintingHandle(std::uint16_t id)
|
Renderer::PaintingHandle& Renderer::VirtualTextureManager::getPaintingHandle(std::uint16_t id)
|
||||||
|
|
|
@ -24,11 +24,12 @@ namespace Renderer
|
||||||
VirtualTextureManager(GladGLContext* glMain);
|
VirtualTextureManager(GladGLContext* glMain);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief 创建彩绘虚拟纹理
|
||||||
* @param painting
|
* @param painting 彩绘
|
||||||
* @return 虚拟纹理id
|
* @return 虚拟纹理id
|
||||||
*/
|
*/
|
||||||
std::uint16_t createVirtualTexture(Painting painting);
|
std::uint16_t createVirtualTexture(Painting painting);
|
||||||
|
void deleteVirtualTexture(std::uint16_t id);
|
||||||
PaintingHandle& getPaintingHandle(std::uint16_t id);
|
PaintingHandle& getPaintingHandle(std::uint16_t id);
|
||||||
void tryUpdatePages(const std::vector<glm::u16vec2>& pageIds);
|
void tryUpdatePages(const std::vector<glm::u16vec2>& pageIds);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue