Compare commits
11 Commits
c4281a444e
...
fbfc5f2759
Author | SHA1 | Date |
---|---|---|
yang.yongquan | fbfc5f2759 | |
ArgonarioD | bf71d17b5d | |
ArgonarioD | 4b2776d429 | |
karlis | 831541ff36 | |
karlis | 6a1c64a426 | |
wuyize | ae641bb87c | |
karlis | f25f2d2a81 | |
karlis | 8a34f57251 | |
karlis | f06fbbaef6 | |
ArgonarioD | 855dd2e075 | |
wuyize | b6e79ee6de |
|
@ -202,6 +202,7 @@
|
||||||
<QtMoc Include="src\Editor\EditorWidgetComponent\ColorPicker.h" />
|
<QtMoc Include="src\Editor\EditorWidgetComponent\ColorPicker.h" />
|
||||||
<QtMoc Include="src\Editor\RightBar\EditorSettingWidget.h" />
|
<QtMoc Include="src\Editor\RightBar\EditorSettingWidget.h" />
|
||||||
<QtMoc Include="src\Editor\EditorWidgetComponent\FillStyleWidget.h" />
|
<QtMoc Include="src\Editor\EditorWidgetComponent\FillStyleWidget.h" />
|
||||||
|
<ClInclude Include="src\ColorHelper.hpp" />
|
||||||
<ClInclude Include="src\Editor\LayerWrapper.h" />
|
<ClInclude Include="src\Editor\LayerWrapper.h" />
|
||||||
<ClInclude Include="src\Editor\util\EncodeUtil.hpp" />
|
<ClInclude Include="src\Editor\util\EncodeUtil.hpp" />
|
||||||
<ClInclude Include="src\Editor\util\JsonUtil.hpp" />
|
<ClInclude Include="src\Editor\util\JsonUtil.hpp" />
|
||||||
|
|
|
@ -519,6 +519,9 @@
|
||||||
<ClInclude Include="src\Editor\LayerWrapper.h">
|
<ClInclude Include="src\Editor\LayerWrapper.h">
|
||||||
<Filter>Header Files\Editor\Layer</Filter>
|
<Filter>Header Files\Editor\Layer</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\ColorHelper.hpp">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtRcc Include="res\MainWindow.qrc">
|
<QtRcc Include="res\MainWindow.qrc">
|
||||||
|
|
|
@ -180,6 +180,12 @@
|
||||||
<property name="accessibleName">
|
<property name="accessibleName">
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>10</width>
|
||||||
|
<height>10</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<column>
|
<column>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>图层名</string>
|
<string>图层名</string>
|
||||||
|
@ -190,6 +196,11 @@
|
||||||
<string>关联图元</string>
|
<string>关联图元</string>
|
||||||
</property>
|
</property>
|
||||||
</column>
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>可见</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
|
@ -1093,6 +1093,7 @@ void main()
|
||||||
bool onVeryBegin = false;
|
bool onVeryBegin = false;
|
||||||
bool onVeryEnd = false;
|
bool onVeryEnd = false;
|
||||||
vec2 tangentEndLast;
|
vec2 tangentEndLast;
|
||||||
|
vec2 tangentFirstBegin;
|
||||||
uint lastHitIndex = 0;
|
uint lastHitIndex = 0;
|
||||||
bool lastHitElement = false;
|
bool lastHitElement = false;
|
||||||
hitElement = false;
|
hitElement = false;
|
||||||
|
@ -1108,7 +1109,19 @@ void main()
|
||||||
pBegin = path[++pathIndex];
|
pBegin = path[++pathIndex];
|
||||||
p3Last = pBegin;
|
p3Last = pBegin;
|
||||||
p2Last = pBegin;
|
p2Last = pBegin;
|
||||||
onVeryBegin = true;
|
if(endType == 4)
|
||||||
|
{
|
||||||
|
//onVeryBegin = false;
|
||||||
|
vec2 lastP1 = path[pathSize-3];
|
||||||
|
vec2 lastP2 = path[pathSize-2];
|
||||||
|
vec2 lastP3 = path[pathSize-1];
|
||||||
|
if (lastP3 != lastP2)
|
||||||
|
tangentEndLast = normalize(lastP3 - lastP2);
|
||||||
|
else
|
||||||
|
tangentEndLast = normalize(lastP3 - lastP1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
onVeryBegin = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
mat4x2 p = mat4x2(p3Last, pTemp, path[++pathIndex], path[++pathIndex]);
|
mat4x2 p = mat4x2(p3Last, pTemp, path[++pathIndex], path[++pathIndex]);
|
||||||
|
@ -1119,7 +1132,13 @@ void main()
|
||||||
vec2 pTemp = path[pathIndex + 1];
|
vec2 pTemp = path[pathIndex + 1];
|
||||||
if (isinf(pTemp.x))
|
if (isinf(pTemp.x))
|
||||||
{
|
{
|
||||||
onVeryEnd = true;
|
if(endType == 4)
|
||||||
|
{
|
||||||
|
//onVeryEnd = false;
|
||||||
|
tangentBeginNext = tangentFirstBegin;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
onVeryEnd = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1180,6 +1199,8 @@ void main()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tangentEndLast = tangentEnd;
|
tangentEndLast = tangentEnd;
|
||||||
|
if(pathIndex == 0)
|
||||||
|
tangentFirstBegin = tangentBegin;
|
||||||
}
|
}
|
||||||
p3Last = p[3];
|
p3Last = p[3];
|
||||||
p2Last = p[2];
|
p2Last = p[2];
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
#pragma once
|
||||||
|
#include <lib/qtmaterialstyle.h>
|
||||||
|
#include <lib/qtmaterialtheme.h>
|
||||||
|
#include <QColorDialog>
|
||||||
|
|
||||||
|
class ColorHelper
|
||||||
|
{
|
||||||
|
QtMaterialTheme theme;
|
||||||
|
QColor primary1;
|
||||||
|
public:
|
||||||
|
|
||||||
|
void setPrimary1(const QColor& color)
|
||||||
|
{
|
||||||
|
theme.setColor("primary1", color);
|
||||||
|
primary1 = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] QColor getPrimary1() const
|
||||||
|
{
|
||||||
|
return primary1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorHelper()
|
||||||
|
{
|
||||||
|
setPrimary1(QColor::fromRgb(0, 90, 158));
|
||||||
|
QtMaterialStyle::instance().setTheme(&theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ColorHelper& instance()
|
||||||
|
{
|
||||||
|
static ColorHelper instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QColor execColorDialog(
|
||||||
|
const QColor& initial = instance().getPrimary1(),
|
||||||
|
QWidget* parent = nullptr,
|
||||||
|
const QString& title = ""
|
||||||
|
) {
|
||||||
|
auto dialog = QColorDialog(initial, parent);
|
||||||
|
if (!title.isEmpty())
|
||||||
|
{
|
||||||
|
dialog.setWindowTitle(title);
|
||||||
|
}
|
||||||
|
dialog.adjustSize();
|
||||||
|
dialog.exec();
|
||||||
|
return dialog.selectedColor();
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,5 +1,6 @@
|
||||||
#include "ColorPicker.h"
|
#include "ColorPicker.h"
|
||||||
#include <QColorDialog>
|
#include <QColorDialog>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
QString getStyleSheet(const QColor& color)
|
QString getStyleSheet(const QColor& color)
|
||||||
{
|
{
|
||||||
|
@ -26,9 +27,8 @@ QColor ColorPicker::getColor() const
|
||||||
|
|
||||||
void ColorPicker::onClicked()
|
void ColorPicker::onClicked()
|
||||||
{
|
{
|
||||||
QColorDialog dialog(this->color, this);
|
//const QColor newColor = QColorDialog::getColor(this->color, this);
|
||||||
dialog.exec();
|
const QColor newColor = ColorHelper::execColorDialog(this->color, this);
|
||||||
QColor newColor = dialog.selectedColor();
|
|
||||||
if (newColor.isValid() && this->color != newColor)
|
if (newColor.isValid() && this->color != newColor)
|
||||||
{
|
{
|
||||||
this->color = newColor;
|
this->color = newColor;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "../ColorHelper.hpp"
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
class ColorPicker : public QPushButton
|
class ColorPicker : public QPushButton
|
||||||
{
|
{
|
||||||
|
@ -6,7 +7,7 @@ class ColorPicker : public QPushButton
|
||||||
private:
|
private:
|
||||||
QColor color;
|
QColor color;
|
||||||
public:
|
public:
|
||||||
ColorPicker(const QColor& color = QColor::fromRgb(0, 0, 0), QWidget* parent = nullptr);
|
ColorPicker(const QColor& color = ColorHelper::instance().getPrimary1(), QWidget* parent = nullptr);
|
||||||
QColor getColor() const;
|
QColor getColor() const;
|
||||||
public slots:
|
public slots:
|
||||||
void onClicked();
|
void onClicked();
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <qtmaterialtextfield.h>
|
#include <qtmaterialtextfield.h>
|
||||||
|
|
||||||
FillStyleWidget::FillStyleWidget(std::shared_ptr<Renderer::MaterialStyleFill> fill, QWidget* parent)
|
FillStyleWidget::FillStyleWidget(std::shared_ptr<MaterialStyleFill> fill, QWidget* parent)
|
||||||
: QWidget(parent), fill(fill)
|
: QWidget(parent), fill(fill)
|
||||||
{
|
{
|
||||||
auto* layout = new QGridLayout(this);
|
auto* layout = new QGridLayout(this);
|
||||||
|
|
|
@ -1,28 +1,25 @@
|
||||||
#include "LayerStyleDialog.h"
|
#include "LayerStyleDialog.h"
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
|
|
||||||
LayerStyleDialog::LayerStyleDialog(
|
LayerStyleDialog::LayerStyleDialog(
|
||||||
LayerStyleContainer& styles,
|
LayerStyleContainer& styles,
|
||||||
std::shared_ptr<LayerStyle> existedStyle,
|
const std::shared_ptr<LayerStyle>& existedStyle,
|
||||||
QWidget* parent
|
QWidget* parent
|
||||||
) : QDialog(parent), styles(&styles)
|
) : QDialog(parent), styles(&styles)
|
||||||
{
|
{
|
||||||
auto* dialogLayout = new QVBoxLayout(this);
|
dialogLayout = new QGridLayout;
|
||||||
dialogLayout->setAlignment(Qt::AlignmentFlag::AlignHCenter);
|
dialogLayout->setAlignment(Qt::AlignmentFlag::AlignHCenter);
|
||||||
this->setLayout(dialogLayout);
|
this->setLayout(dialogLayout);
|
||||||
|
|
||||||
if (existedStyle)
|
if (existedStyle)
|
||||||
{
|
{
|
||||||
this->modifyingStyle = existedStyle->clone();
|
this->modifyingStyle = existedStyle->clone();
|
||||||
|
|
||||||
this->styleContainer = nullptr;
|
|
||||||
this->styleWidget = modifyingStyle->getInputWidget();
|
this->styleWidget = modifyingStyle->getInputWidget();
|
||||||
this->styleWidget->setParent(this);
|
this->styleWidget->setParent(this);
|
||||||
dialogLayout->addWidget(styleWidget);
|
dialogLayout->addWidget(styleWidget, 1, 0);
|
||||||
// do something
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -34,13 +31,12 @@ LayerStyleDialog::LayerStyleDialog(
|
||||||
typeSelector->addItems(unusedStyleNames);
|
typeSelector->addItems(unusedStyleNames);
|
||||||
this->modifyingStyle = std::move(styles.makeUnusedStyle(unusedStyleNames[0]));
|
this->modifyingStyle = std::move(styles.makeUnusedStyle(unusedStyleNames[0]));
|
||||||
|
|
||||||
dialogLayout->addWidget(typeSelector);
|
dialogLayout->addWidget(typeSelector, 0, 0);
|
||||||
this->styleContainer = new QGridLayout(this);
|
|
||||||
dialogLayout->addLayout(styleContainer);
|
|
||||||
|
|
||||||
this->styleWidget = this->modifyingStyle->getInputWidget();
|
this->styleWidget = this->modifyingStyle->getInputWidget();
|
||||||
this->styleWidget->setParent(this);
|
this->styleWidget->setParent(this);
|
||||||
this->styleContainer->addWidget(styleWidget);
|
this->dialogLayout->addWidget(styleWidget, 1, 0);
|
||||||
connect(typeSelector, &QComboBox::currentTextChanged,
|
connect(typeSelector, &QComboBox::currentTextChanged,
|
||||||
this, &LayerStyleDialog::onStyleTypeSelectorChanged);
|
this, &LayerStyleDialog::onStyleTypeSelectorChanged);
|
||||||
}
|
}
|
||||||
|
@ -48,7 +44,8 @@ LayerStyleDialog::LayerStyleDialog(
|
||||||
auto* 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, 2, 0);
|
||||||
|
this->adjustSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerStyleDialog::accept()
|
void LayerStyleDialog::accept()
|
||||||
|
@ -61,14 +58,14 @@ void LayerStyleDialog::onStyleTypeSelectorChanged(const QString& current)
|
||||||
{
|
{
|
||||||
if (this->styleWidget)
|
if (this->styleWidget)
|
||||||
{
|
{
|
||||||
this->styleContainer->removeWidget(this->styleWidget);
|
this->dialogLayout->removeWidget(this->styleWidget);
|
||||||
this->styleWidget->setParent(nullptr);
|
this->styleWidget->setParent(nullptr);
|
||||||
delete styleWidget;
|
delete styleWidget;
|
||||||
}
|
}
|
||||||
this->modifyingStyle = std::move(styles->makeUnusedStyle(current));
|
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->dialogLayout->addWidget(styleWidget, 1, 0);
|
||||||
this->styleWidget->adjustSize();
|
this->styleWidget->adjustSize();
|
||||||
this->adjustSize();
|
this->adjustSize();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,13 +8,13 @@ class LayerStyleDialog : public QDialog
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
QWidget* styleWidget;
|
QWidget* styleWidget;
|
||||||
QGridLayout* styleContainer;
|
QGridLayout* dialogLayout;
|
||||||
LayerStyleContainer* styles;
|
LayerStyleContainer* styles;
|
||||||
std::unique_ptr<LayerStyle> modifyingStyle;
|
std::unique_ptr<LayerStyle> modifyingStyle;
|
||||||
public:
|
public:
|
||||||
LayerStyleDialog(
|
LayerStyleDialog(
|
||||||
LayerStyleContainer& styles,
|
LayerStyleContainer& styles,
|
||||||
std::shared_ptr<LayerStyle> existedStyle = nullptr,
|
const std::shared_ptr<LayerStyle>& existedStyle = nullptr,
|
||||||
QWidget* parent = nullptr
|
QWidget* parent = nullptr
|
||||||
);
|
);
|
||||||
std::shared_ptr<LayerStyle> layerStyle;
|
std::shared_ptr<LayerStyle> layerStyle;
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
#include "StrokeStyleWidget.h"
|
#include "StrokeStyleWidget.h"
|
||||||
#include "ColorPicker.h"
|
#include "ColorPicker.h"
|
||||||
|
#include "../ColorHelper.hpp"
|
||||||
#include <qtmaterialraisedbutton.h>
|
#include <qtmaterialraisedbutton.h>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <lib/qtmaterialstyle.h>
|
#include <array>
|
||||||
|
#include <ranges>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
constexpr int COLUMN_WIDTH = 0;
|
constexpr int COLUMN_WIDTH = 0;
|
||||||
constexpr int COLUMN_COLOR = 1;
|
constexpr int COLUMN_COLOR = 1;
|
||||||
|
@ -10,11 +13,27 @@ constexpr int COLUMN_METALLIC = 2;
|
||||||
constexpr int COLUMN_ROUGHNESS = 3;
|
constexpr int COLUMN_ROUGHNESS = 3;
|
||||||
constexpr int COLUMN_OPERATIONS = 4;
|
constexpr int COLUMN_OPERATIONS = 4;
|
||||||
|
|
||||||
|
inline Renderer::Material newMaterial()
|
||||||
|
{
|
||||||
|
return {ColorHelper::instance().getPrimary1()};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool isClosedStroke(const std::shared_ptr<MaterialStyleStroke>& stroke)
|
||||||
|
{
|
||||||
|
return stroke->endType == Renderer::StrokeEndType::kClosed;
|
||||||
|
}
|
||||||
|
|
||||||
StrokeStyleWidget::StrokeStyleWidget(
|
StrokeStyleWidget::StrokeStyleWidget(
|
||||||
std::shared_ptr<MaterialStyleStroke> stroke,
|
const std::shared_ptr<MaterialStyleStroke>& stroke,
|
||||||
QWidget* parent
|
QWidget* parent
|
||||||
) : QWidget(parent), stroke(stroke)
|
) : QWidget(parent), stroke(stroke)
|
||||||
{
|
{
|
||||||
|
auto& materialMap = radialStroke(stroke)->materialMap;
|
||||||
|
if (materialMap.empty())
|
||||||
|
{
|
||||||
|
materialMap[1.f] = newMaterial();
|
||||||
|
}
|
||||||
|
|
||||||
auto* viewLayout = new QVBoxLayout(this);
|
auto* viewLayout = new QVBoxLayout(this);
|
||||||
this->setLayout(viewLayout);
|
this->setLayout(viewLayout);
|
||||||
|
|
||||||
|
@ -25,13 +44,20 @@ StrokeStyleWidget::StrokeStyleWidget(
|
||||||
|
|
||||||
strokeProperties->setLayout(strokePropertiesLayout);
|
strokeProperties->setLayout(strokePropertiesLayout);
|
||||||
strokePropertiesLayout->addWidget(enableGradual);
|
strokePropertiesLayout->addWidget(enableGradual);
|
||||||
strokePropertiesLayout->addWidget(endTypeBox);
|
if (!isClosedStroke(stroke))
|
||||||
|
{
|
||||||
|
strokePropertiesLayout->addWidget(endTypeBox);
|
||||||
|
}
|
||||||
|
|
||||||
viewLayout->addWidget(strokeProperties);
|
viewLayout->addWidget(strokeProperties);
|
||||||
viewLayout->addWidget(widthField);
|
viewLayout->addWidget(widthField);
|
||||||
|
|
||||||
initTable(std::dynamic_pointer_cast<Renderer::StrokeRadialGradient>(stroke->materialStroke));
|
initTable(radialStroke(stroke));
|
||||||
viewLayout->addWidget(strokeTable);
|
viewLayout->addWidget(strokeTable);
|
||||||
|
|
||||||
|
initAddButton();
|
||||||
|
viewLayout->addWidget(addButton);
|
||||||
|
|
||||||
this->adjustSize();
|
this->adjustSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,30 +70,23 @@ void StrokeStyleWidget::initStrokeSettings()
|
||||||
radialStroke(this->stroke)->gradual = checked;
|
radialStroke(this->stroke)->gradual = checked;
|
||||||
});
|
});
|
||||||
|
|
||||||
#define endTypeBoxLabel(start, end) QStringLiteral(start##" -> "##end)
|
if (!isClosedStroke(stroke))
|
||||||
this->endTypeBox = new QComboBox(this);
|
{
|
||||||
endTypeBox->addItem(endTypeBoxLabel("圆头", "圆头")); // kRound
|
this->endTypeBox = new QComboBox(this);
|
||||||
endTypeBox->addItem(endTypeBoxLabel("平头", "圆头")); // kFlatRound
|
for (const auto& displayName : MaterialStyleStroke::strokeEndTypeNames | std::views::keys)
|
||||||
endTypeBox->addItem(endTypeBoxLabel("圆头", "平头")); // kRoundFlat
|
|
||||||
endTypeBox->addItem(endTypeBoxLabel("平头", "平头")); // kFlat
|
|
||||||
endTypeBox->setCurrentIndex(static_cast<int>(this->stroke->endType));
|
|
||||||
connect(endTypeBox, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index) {
|
|
||||||
switch (index)
|
|
||||||
{
|
{
|
||||||
case 0:
|
endTypeBox->addItem(displayName);
|
||||||
this->stroke->endType = Renderer::StrokeEndType::kRound;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
this->stroke->endType = Renderer::StrokeEndType::kFlatRound;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
this->stroke->endType = Renderer::StrokeEndType::kRoundFlat;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
this->stroke->endType = Renderer::StrokeEndType::kFlat;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
});
|
endTypeBox->setCurrentIndex(static_cast<int>(this->stroke->endType));
|
||||||
|
connect(endTypeBox, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index) {
|
||||||
|
const auto& [displayName, endType] = MaterialStyleStroke::strokeEndTypeNames[index];
|
||||||
|
this->stroke->endType = endType;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->endTypeBox = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
this->widthField = new QtMaterialTextField(this);
|
this->widthField = new QtMaterialTextField(this);
|
||||||
widthField->setLabel(QStringLiteral("本侧描边宽度"));
|
widthField->setLabel(QStringLiteral("本侧描边宽度"));
|
||||||
|
@ -83,13 +102,12 @@ void StrokeStyleWidget::initStrokeSettings()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: 新增时参数校验
|
void StrokeStyleWidget::initTable(const std::shared_ptr<Renderer::StrokeRadialGradient>& materialStroke)
|
||||||
void StrokeStyleWidget::initTable(std::shared_ptr<Renderer::StrokeRadialGradient> materialStroke)
|
|
||||||
{
|
{
|
||||||
this->strokeTable = new QTableWidget(this);
|
this->strokeTable = new QTableWidget(this);
|
||||||
strokeTable->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow);
|
strokeTable->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow);
|
||||||
strokeTable->setColumnCount(5);
|
strokeTable->setColumnCount(5);
|
||||||
strokeTable->setRowCount(materialStroke->materialMap.size() + 1);
|
strokeTable->setRowCount(materialStroke->materialMap.size());
|
||||||
QStringList headers;
|
QStringList headers;
|
||||||
headers << QStringLiteral("离心距离占比")
|
headers << QStringLiteral("离心距离占比")
|
||||||
<< QStringLiteral("颜色")
|
<< QStringLiteral("颜色")
|
||||||
|
@ -97,44 +115,45 @@ void StrokeStyleWidget::initTable(std::shared_ptr<Renderer::StrokeRadialGradient
|
||||||
<< QStringLiteral("粗糙度")
|
<< QStringLiteral("粗糙度")
|
||||||
<< QStringLiteral("其他操作");
|
<< QStringLiteral("其他操作");
|
||||||
strokeTable->setHorizontalHeaderLabels(headers);
|
strokeTable->setHorizontalHeaderLabels(headers);
|
||||||
|
strokeTable->setMinimumHeight(strokeTable->rowHeight(0) * 5);
|
||||||
|
strokeTable->setMinimumWidth(strokeTable->sizeHint().width());
|
||||||
int row = 0;
|
int row = 0;
|
||||||
// 内容
|
// 内容
|
||||||
for (auto & strokePair : materialStroke->materialMap)
|
for (auto& [width, material] : std::views::reverse(materialStroke->materialMap))
|
||||||
{
|
{
|
||||||
setTableRow(row, strokePair.first, strokePair.second);
|
setTableRow(row, width, material);
|
||||||
row++;
|
row++;
|
||||||
}
|
}
|
||||||
// 新增按钮
|
connect(strokeTable, &QTableWidget::currentItemChanged, this, &StrokeStyleWidget::onCurrentItemChanged);
|
||||||
QtMaterialRaisedButton* addButton = new QtMaterialRaisedButton("+", strokeTable);
|
connect(strokeTable, &QTableWidget::cellChanged, this, &StrokeStyleWidget::onCellChanged);
|
||||||
addButton->setBackgroundColor(QtMaterialStyle::instance().themeColor("primary1"));
|
}
|
||||||
strokeTable->setSpan(row, 0, 1, 5);
|
|
||||||
strokeTable->setCellWidget(row, 0, addButton);
|
void StrokeStyleWidget::initAddButton()
|
||||||
strokeTable->setMinimumHeight(strokeTable->rowHeight(row) * 5);
|
{
|
||||||
strokeTable->setMinimumWidth(strokeTable->sizeHint().width());
|
this->addButton = new QtMaterialRaisedButton("+", strokeTable);
|
||||||
addButton->setFixedHeight(strokeTable->rowHeight(row));
|
addButton->setFixedHeight(this->strokeTable->rowHeight(0));
|
||||||
connect(addButton, &QtMaterialRaisedButton::clicked, [this]() {
|
addButton->setBackgroundColor(ColorHelper::instance().getPrimary1());
|
||||||
|
connect(addButton, &QtMaterialRaisedButton::clicked, [this] {
|
||||||
handlingRowInsert = true;
|
handlingRowInsert = true;
|
||||||
auto materialMap = &(radialStroke(this->stroke)->materialMap);
|
auto& materialMap = radialStroke(this->stroke)->materialMap;
|
||||||
float newWidth = 0;
|
float newWidth;
|
||||||
if (materialMap->size() == 0)
|
if (materialMap.empty())
|
||||||
{
|
{
|
||||||
newWidth = 0.1;
|
newWidth = 1.f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto lastPair = materialMap->rbegin();
|
const auto firstPair = materialMap.begin();
|
||||||
newWidth = lastPair->first + 0.01;
|
newWidth = firstPair->first / 2;
|
||||||
}
|
}
|
||||||
Renderer::Material newMaterial(QColor::fromRgb(0, 0, 0));
|
const Renderer::Material newMaterial(ColorHelper::instance().getPrimary1());
|
||||||
(*materialMap)[newWidth] = newMaterial;
|
materialMap[newWidth] = newMaterial;
|
||||||
int newRow = this->strokeTable->rowCount() - 1;
|
const int newRow = this->strokeTable->rowCount();
|
||||||
this->strokeTable->insertRow(newRow);
|
this->strokeTable->insertRow(newRow);
|
||||||
setTableRow(newRow, newWidth, (*materialMap)[newWidth]);
|
setTableRow(newRow, newWidth, materialMap[newWidth]);
|
||||||
this->strokeTable->update();
|
this->strokeTable->update();
|
||||||
handlingRowInsert = false;
|
handlingRowInsert = false;
|
||||||
});
|
});
|
||||||
connect(strokeTable, &QTableWidget::currentItemChanged, this, &StrokeStyleWidget::onCurrentItemChanged);
|
|
||||||
connect(strokeTable, &QTableWidget::cellChanged, this, &StrokeStyleWidget::onCellChanged);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StrokeStyleWidget::setTableRow(int row, float width, Renderer::Material& material)
|
void StrokeStyleWidget::setTableRow(int row, float width, Renderer::Material& material)
|
||||||
|
@ -143,14 +162,14 @@ void StrokeStyleWidget::setTableRow(int row, float width, Renderer::Material& ma
|
||||||
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;
|
||||||
auto* 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);
|
||||||
auto* 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 = std::move(color);
|
||||||
this->strokeTable->update();
|
this->strokeTable->update();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -163,10 +182,10 @@ void StrokeStyleWidget::setTableRow(int row, float width, Renderer::Material& ma
|
||||||
strokeTable->setItem(row, COLUMN_ROUGHNESS, roughnessItem);
|
strokeTable->setItem(row, COLUMN_ROUGHNESS, roughnessItem);
|
||||||
|
|
||||||
auto* removeButton = new QtMaterialRaisedButton("-", strokeTable);
|
auto* removeButton = new QtMaterialRaisedButton("-", strokeTable);
|
||||||
removeButton->setBackgroundColor(QtMaterialStyle::instance().themeColor("primary1"));
|
removeButton->setBackgroundColor(ColorHelper::instance().getPrimary1());
|
||||||
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] {
|
||||||
radialStroke(this->stroke)->materialMap.erase(this->strokeTable->item(row, COLUMN_WIDTH)->text().toFloat());
|
radialStroke(this->stroke)->materialMap.erase(this->strokeTable->item(row, COLUMN_WIDTH)->text().toFloat());
|
||||||
this->strokeTable->removeRow(row);
|
this->strokeTable->removeRow(row);
|
||||||
});
|
});
|
||||||
|
@ -175,7 +194,7 @@ void StrokeStyleWidget::setTableRow(int row, float width, Renderer::Material& ma
|
||||||
void StrokeStyleWidget::onCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous)
|
void StrokeStyleWidget::onCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous)
|
||||||
{
|
{
|
||||||
if (!current) return;
|
if (!current) return;
|
||||||
int column = current->column();
|
const int column = current->column();
|
||||||
if (column != COLUMN_COLOR && column != COLUMN_OPERATIONS)
|
if (column != COLUMN_COLOR && column != COLUMN_OPERATIONS)
|
||||||
{
|
{
|
||||||
this->currentItemValue = current->data(Qt::EditRole);
|
this->currentItemValue = current->data(Qt::EditRole);
|
||||||
|
@ -185,23 +204,27 @@ void StrokeStyleWidget::onCurrentItemChanged(QTableWidgetItem* current, QTableWi
|
||||||
void StrokeStyleWidget::onCellChanged(int row, int column)
|
void StrokeStyleWidget::onCellChanged(int row, int column)
|
||||||
{
|
{
|
||||||
if (handlingRowInsert) return;
|
if (handlingRowInsert) return;
|
||||||
auto changedItem = strokeTable->item(row, column);
|
const auto changedItem = strokeTable->item(row, column);
|
||||||
auto changedItemValue = changedItem->text().toFloat();
|
const auto changedItemValue = changedItem->text().toFloat();
|
||||||
if (changedItemValue < 0 || 1 < changedItemValue)
|
if (changedItemValue < 0 || 1 < changedItemValue)
|
||||||
{
|
{
|
||||||
changedItem->setData(Qt::EditRole, this->currentItemValue.toFloat());
|
changedItem->setData(Qt::EditRole, this->currentItemValue.toFloat());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto changedWidth = strokeTable->item(row, COLUMN_WIDTH)->data(Qt::EditRole).toFloat();
|
const auto changedWidth = strokeTable->item(row, COLUMN_WIDTH)->data(Qt::EditRole).toFloat();
|
||||||
switch (column)
|
switch (column)
|
||||||
{
|
{
|
||||||
case COLUMN_WIDTH:
|
case COLUMN_WIDTH:
|
||||||
{
|
{
|
||||||
float oldWidth = this->currentItemValue.toFloat();
|
float oldWidth = this->currentItemValue.toFloat();
|
||||||
auto node = radialStroke(stroke)->materialMap.extract(oldWidth);
|
auto node = radialStroke(stroke)->materialMap.extract(oldWidth);
|
||||||
|
if (node.empty())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
node.key() = changedWidth;
|
node.key() = changedWidth;
|
||||||
radialStroke(stroke)->materialMap.insert(std::move(node));
|
radialStroke(stroke)->materialMap.insert(std::move(node));
|
||||||
strokeTable->sortItems(COLUMN_WIDTH);
|
strokeTable->sortItems(COLUMN_WIDTH, Qt::DescendingOrder);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case COLUMN_METALLIC:
|
case COLUMN_METALLIC:
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <qtmaterialtextfield.h>
|
#include <qtmaterialtextfield.h>
|
||||||
#include <qtmaterialcheckbox.h>
|
#include <qtmaterialcheckbox.h>
|
||||||
|
#include <qtmaterialraisedbutton.h>
|
||||||
class StrokeStyleWidget : public QWidget
|
class StrokeStyleWidget : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -16,15 +17,17 @@ private:
|
||||||
QComboBox* endTypeBox;
|
QComboBox* endTypeBox;
|
||||||
QtMaterialTextField* widthField;
|
QtMaterialTextField* widthField;
|
||||||
QTableWidget* strokeTable;
|
QTableWidget* strokeTable;
|
||||||
|
QtMaterialRaisedButton* addButton;
|
||||||
bool handlingRowInsert = false;
|
bool handlingRowInsert = false;
|
||||||
|
|
||||||
void initStrokeSettings();
|
void initStrokeSettings();
|
||||||
void initTable(std::shared_ptr<Renderer::StrokeRadialGradient> materialStroke);
|
void initTable(const std::shared_ptr<Renderer::StrokeRadialGradient>& materialStroke);
|
||||||
|
void initAddButton();
|
||||||
void setTableRow(int row, float width, Renderer::Material& material);
|
void setTableRow(int row, float width, Renderer::Material& material);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StrokeStyleWidget(std::shared_ptr<Renderer::MaterialStyleStroke> stroke, QWidget* parent = nullptr);
|
StrokeStyleWidget(const std::shared_ptr<MaterialStyleStroke>& stroke, QWidget* parent = nullptr);
|
||||||
std::shared_ptr<Renderer::MaterialStyleStroke> stroke;
|
std::shared_ptr<MaterialStyleStroke> stroke;
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void onCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous);
|
void onCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous);
|
||||||
|
|
|
@ -25,6 +25,7 @@ EditorWidgetItem::EditorWidgetItem(QString filePath,QWidget *parent) : QWidget(p
|
||||||
treeWidget->refresh();
|
treeWidget->refresh();
|
||||||
previewWindow->refresh();
|
previewWindow->refresh();
|
||||||
};
|
};
|
||||||
|
connect(previewWindow, &PreviewWindow::triggerCentralRefresh, centralRefresh);
|
||||||
connect(layerInfoDisplayWidget, &InfoDisplayWidget::triggerCentralRefresh, centralRefresh);
|
connect(layerInfoDisplayWidget, &InfoDisplayWidget::triggerCentralRefresh, centralRefresh);
|
||||||
connect(elementInfoDisplayWidget, &ElementPoolWidget::triggerCentralRefresh, centralRefresh);
|
connect(elementInfoDisplayWidget, &ElementPoolWidget::triggerCentralRefresh, centralRefresh);
|
||||||
connect(treeWidget, &LayerTreeWidget::triggerCentralRefresh, centralRefresh);
|
connect(treeWidget, &LayerTreeWidget::triggerCentralRefresh, centralRefresh);
|
||||||
|
@ -33,15 +34,15 @@ EditorWidgetItem::EditorWidgetItem(QString filePath,QWidget *parent) : QWidget(p
|
||||||
connect(previewWindow, &PreviewWindow::refreshElementPreviewByIndex, elementInfoDisplayWidget, &ElementPoolWidget::refreshPictureByIndex);
|
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);
|
||||||
connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireRefreshElementWidget, elementInfoDisplayWidget, &ElementPoolWidget::refresh);
|
// connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireRefreshElementWidget, elementInfoDisplayWidget, &ElementPoolWidget::refresh);
|
||||||
connect(treeWidget, &LayerTreeWidget::displayLayerChange, this, &EditorWidgetItem::onLayerChange);
|
connect(treeWidget, &LayerTreeWidget::displayLayerChange, this, &EditorWidgetItem::onLayerChange);
|
||||||
connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireRefreshPreview, this,
|
// connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireRefreshPreview, this,
|
||||||
&EditorWidgetItem::triggerRefreshPreview);
|
// &EditorWidgetItem::triggerRefreshPreview);
|
||||||
connect(treeWidget, &LayerTreeWidget::requireRefreshPreview, this,
|
// connect(treeWidget, &LayerTreeWidget::requireRefreshPreview, this,
|
||||||
&EditorWidgetItem::triggerRefreshPreview);
|
// &EditorWidgetItem::triggerRefreshPreview);
|
||||||
connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireSelfRefresh, layerInfoDisplayWidget, &InfoDisplayWidget::triggerSelfRefresh);
|
//connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireSelfRefresh, layerInfoDisplayWidget, &InfoDisplayWidget::triggerSelfRefresh);
|
||||||
connect(elementInfoDisplayWidget, &ElementPoolWidget::refreshLayerTree, treeWidget, &LayerTreeWidget::refresh);
|
// connect(elementInfoDisplayWidget, &ElementPoolWidget::refreshLayerTree, treeWidget, &LayerTreeWidget::refresh);
|
||||||
// &EditorWidget::triggerRefreshPreview);
|
// &EditorWidget::triggerRefreshPreview);
|
||||||
// test
|
// test
|
||||||
QFile settingFile;
|
QFile settingFile;
|
||||||
|
@ -73,9 +74,10 @@ EditorWidgetItem::EditorWidgetItem(QString filePath,QWidget *parent) : QWidget(p
|
||||||
this->projectName = source.value("project-name").toString();
|
this->projectName = source.value("project-name").toString();
|
||||||
qDebug() << this->backgroundColor;
|
qDebug() << this->backgroundColor;
|
||||||
qDebug() << this->projectName;
|
qDebug() << this->projectName;
|
||||||
QTimer::singleShot(300, this, [this]() {
|
QTimer::singleShot(300, this, [this, centralRefresh]() {
|
||||||
handleBackgroundColorChange(this->backgroundColor);
|
handleBackgroundColorChange(this->backgroundColor);
|
||||||
handleProjectNameChange(this->projectName);
|
handleProjectNameChange(this->projectName);
|
||||||
|
centralRefresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,7 @@ bool SimpleElement::isClosed() const
|
||||||
|
|
||||||
void GroupElement::paint(QPainter* painter, QTransform transform, const LayerStyleContainer& styles)
|
void GroupElement::paint(QPainter* painter, QTransform transform, const LayerStyleContainer& styles)
|
||||||
{
|
{
|
||||||
sourceLayer->paint(painter, transform);
|
sourceLayer->paint(painter, transform, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GroupElement::isClosed() const
|
bool GroupElement::isClosed() const
|
||||||
|
|
|
@ -13,8 +13,21 @@ LayerWrapper *LayerManager::getRoot() const
|
||||||
}
|
}
|
||||||
void LayerManager::paint(QPainter *painter, QSize size,LayerWrapper* selecetedLayer) const
|
void LayerManager::paint(QPainter *painter, QSize size,LayerWrapper* selecetedLayer) const
|
||||||
{
|
{
|
||||||
|
painter->save();
|
||||||
root->getCache();
|
root->getCache();
|
||||||
root->paint(painter);
|
root->paint(painter);
|
||||||
|
painter->restore();
|
||||||
|
painter->save();
|
||||||
|
// painter->setBrush(QBrush(Qt::white));
|
||||||
|
//painter->setCompositionMode(QPainter::CompositionMode_Difference);
|
||||||
|
if (selecetedLayer != nullptr)
|
||||||
|
{
|
||||||
|
painter->setPen(QPen(Qt::gray, 2, Qt::DashLine));
|
||||||
|
selecetedLayer->paintVisualBounding(painter);
|
||||||
|
//painter->setPen(QPen(Qt::gray, 2, Qt::DashDotLine));
|
||||||
|
//selecetedLayer->paintVisualBounding(painter);
|
||||||
|
}
|
||||||
|
painter->restore();
|
||||||
}
|
}
|
||||||
bool LayerManager::singleSelectedCheck() const
|
bool LayerManager::singleSelectedCheck() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "./EditorWidgetComponent/StrokeStyleWidget.h"
|
#include "./EditorWidgetComponent/StrokeStyleWidget.h"
|
||||||
#include "./EditorWidgetComponent/FillStyleWidget.h"
|
#include "./EditorWidgetComponent/FillStyleWidget.h"
|
||||||
#include "./util/EncodeUtil.hpp"
|
#include "./util/EncodeUtil.hpp"
|
||||||
|
#include "../ColorHelper.hpp"
|
||||||
#include <qtmaterialcheckbox.h>
|
#include <qtmaterialcheckbox.h>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
@ -77,7 +78,7 @@ QWidget* StrokeElementLayerStyle::getListDisplayWidget() const
|
||||||
void LayerStyleContainer::computeNewHash()
|
void LayerStyleContainer::computeNewHash()
|
||||||
{
|
{
|
||||||
hash = 0;
|
hash = 0;
|
||||||
for (auto& f : styles
|
for (auto& f : styles
|
||||||
| std::views::values
|
| std::views::values
|
||||||
| std::views::transform(&LayerStyle::toBaseStyles)
|
| std::views::transform(&LayerStyle::toBaseStyles)
|
||||||
| std::views::join
|
| std::views::join
|
||||||
|
@ -206,11 +207,11 @@ bool LayerStyleContainer::dropStyle(const QString& styleName)
|
||||||
|
|
||||||
float LayerStyleContainer::boundingBoxAffectValue() const {
|
float LayerStyleContainer::boundingBoxAffectValue() const {
|
||||||
float maxLineWidth = 0;
|
float maxLineWidth = 0;
|
||||||
const auto strokeStyle = styles.at(StrokeElementLayerStyle::displayName());
|
const auto strokeStyle = styles.find(StrokeElementLayerStyle::displayName());
|
||||||
if (strokeStyle != nullptr)
|
if (strokeStyle != styles.end())
|
||||||
{
|
{
|
||||||
if (const auto strokeElementLayerStyle =
|
if (const auto strokeElementLayerStyle =
|
||||||
std::dynamic_pointer_cast<StrokeElementLayerStyle>(strokeStyle);
|
std::dynamic_pointer_cast<StrokeElementLayerStyle>(strokeStyle->second);
|
||||||
strokeElementLayerStyle != nullptr)
|
strokeElementLayerStyle != nullptr)
|
||||||
{
|
{
|
||||||
const auto& leftStyleStroke = strokeElementLayerStyle->strokePair.first;
|
const auto& leftStyleStroke = strokeElementLayerStyle->strokePair.first;
|
||||||
|
@ -247,18 +248,18 @@ std::unique_ptr<StrokeElementLayerStyle> StrokeElementLayerStyle::fromJson(const
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
StrokeElementLayerStyle::StrokeElementLayerStyle()
|
StrokeElementLayerStyle::StrokeElementLayerStyle(bool isClosed)
|
||||||
{
|
{
|
||||||
const auto materialMap = std::map<float, Renderer::Material>();
|
const auto materialMap = std::map<float, Renderer::Material>();
|
||||||
this->strokePair.first = std::make_shared<MaterialStyleStroke>(
|
this->strokePair.first = std::make_shared<MaterialStyleStroke>(
|
||||||
7,
|
7,
|
||||||
Renderer::StrokeType::kLeftSide, Renderer::StrokeEndType::kFlat,
|
Renderer::StrokeType::kLeftSide, isClosed ? Renderer::StrokeEndType::kClosed : Renderer::StrokeEndType::kFlat,
|
||||||
std::make_shared<Renderer::StrokeRadialGradient>(materialMap, false)
|
std::make_shared<Renderer::StrokeRadialGradient>(materialMap, false)
|
||||||
);
|
);
|
||||||
|
|
||||||
this->strokePair.second = std::make_shared<MaterialStyleStroke>(
|
this->strokePair.second = std::make_shared<MaterialStyleStroke>(
|
||||||
7,
|
7,
|
||||||
Renderer::StrokeType::kRightSide, Renderer::StrokeEndType::kFlat,
|
Renderer::StrokeType::kRightSide, isClosed ? Renderer::StrokeEndType::kClosed : Renderer::StrokeEndType::kFlat,
|
||||||
std::make_shared<Renderer::StrokeRadialGradient>(materialMap, false)
|
std::make_shared<Renderer::StrokeRadialGradient>(materialMap, false)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -536,7 +537,7 @@ FillElementLayerStyle::FillElementLayerStyle(const PMaterialStyleFill& fillMater
|
||||||
if (!fillMaterialStyle)
|
if (!fillMaterialStyle)
|
||||||
{
|
{
|
||||||
this->fillMaterialStyle = std::make_shared<MaterialStyleFill>(
|
this->fillMaterialStyle = std::make_shared<MaterialStyleFill>(
|
||||||
std::make_shared<Renderer::FillPlain>(Renderer::Material(QColor::fromRgb(0, 0, 0)))
|
std::make_shared<Renderer::FillPlain>(ColorHelper::instance().getPrimary1())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ public:
|
||||||
STYLE_NAME("Ãè±ß", "stroke")
|
STYLE_NAME("Ãè±ß", "stroke")
|
||||||
static std::unique_ptr<StrokeElementLayerStyle> fromJson(const QJsonObject& json);
|
static std::unique_ptr<StrokeElementLayerStyle> fromJson(const QJsonObject& json);
|
||||||
|
|
||||||
StrokeElementLayerStyle();
|
StrokeElementLayerStyle(bool isClosed);
|
||||||
StrokeElementLayerStyle(const PMaterialStyleStroke& left, const PMaterialStyleStroke& right = nullptr);
|
StrokeElementLayerStyle(const PMaterialStyleStroke& left, const PMaterialStyleStroke& right = nullptr);
|
||||||
StrokeElementLayerStyle(const StrokeElementLayerStyle& other);
|
StrokeElementLayerStyle(const StrokeElementLayerStyle& other);
|
||||||
~StrokeElementLayerStyle() override = default;
|
~StrokeElementLayerStyle() override = default;
|
||||||
|
@ -88,17 +88,23 @@ public:
|
||||||
class LayerStyleContainer : public Renderer::ElementStyle
|
class LayerStyleContainer : public Renderer::ElementStyle
|
||||||
{
|
{
|
||||||
using DisplayNameWithSupplier = std::map<QString, std::function<std::unique_ptr<LayerStyle>()>>;
|
using DisplayNameWithSupplier = std::map<QString, std::function<std::unique_ptr<LayerStyle>()>>;
|
||||||
private:
|
|
||||||
|
|
||||||
inline const static DisplayNameWithSupplier commonStyles = { {
|
private:
|
||||||
|
inline const static DisplayNameWithSupplier commonStyles = { };
|
||||||
|
inline const static DisplayNameWithSupplier closedOnlyStyles = {
|
||||||
|
{
|
||||||
|
FillElementLayerStyle::displayName(),
|
||||||
|
[] { return std::make_unique<FillElementLayerStyle>(); }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
StrokeElementLayerStyle::displayName(),
|
||||||
|
[] { return std::make_unique<StrokeElementLayerStyle>(true); }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
inline const static DisplayNameWithSupplier unclosedOnlyStyles = { {
|
||||||
StrokeElementLayerStyle::displayName(),
|
StrokeElementLayerStyle::displayName(),
|
||||||
[] { return std::make_unique<StrokeElementLayerStyle>(); }
|
[] { return std::make_unique<StrokeElementLayerStyle>(false); }
|
||||||
} };
|
} };
|
||||||
inline const static DisplayNameWithSupplier closedOnlyStyles = { {
|
|
||||||
FillElementLayerStyle::displayName(),
|
|
||||||
[] { return std::make_unique<FillElementLayerStyle>(); }
|
|
||||||
} };
|
|
||||||
inline const static DisplayNameWithSupplier unclosedOnlyStyles = { };
|
|
||||||
|
|
||||||
DisplayNameWithSupplier unusedStyles;
|
DisplayNameWithSupplier unusedStyles;
|
||||||
DisplayNameWithSupplier usedStyles;
|
DisplayNameWithSupplier usedStyles;
|
||||||
|
|
|
@ -47,6 +47,7 @@ LayerWrapper::LayerWrapper(QJsonObject json, FolderLayerWrapper*parent, ElementM
|
||||||
transformJson.value("scale").toObject().value("y").toDouble()};
|
transformJson.value("scale").toObject().value("y").toDouble()};
|
||||||
property.rotation = {transformJson.value("rotation").toDouble()};
|
property.rotation = {transformJson.value("rotation").toDouble()};
|
||||||
selected = false;
|
selected = false;
|
||||||
|
hidden = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FolderLayerWrapper::FolderLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent)
|
FolderLayerWrapper::FolderLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent)
|
||||||
|
@ -199,6 +200,7 @@ void FolderLayerWrapper::delSelf() {
|
||||||
QTreeWidgetItem* LayerWrapper::getQTreeItem()
|
QTreeWidgetItem* LayerWrapper::getQTreeItem()
|
||||||
{
|
{
|
||||||
this->qTreeWidgetItem->setData(0, Qt::UserRole, QVariant::fromValue(this));
|
this->qTreeWidgetItem->setData(0, Qt::UserRole, QVariant::fromValue(this));
|
||||||
|
this->qTreeWidgetItem->setCheckState(0, Qt::Checked);
|
||||||
return this->qTreeWidgetItem;
|
return this->qTreeWidgetItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,31 +282,34 @@ int FolderLayerWrapper::getReferencedBy()const
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerWrapper::paint(QPainter* painter, QTransform transform, bool ignoreSelected)
|
void LayerWrapper::paint(QPainter* painter, QTransform transform, bool force)
|
||||||
{
|
{
|
||||||
if (!ignoreSelected && this->selected)
|
// if (this->selected)
|
||||||
{
|
// {
|
||||||
painter->save();
|
// painter->save();
|
||||||
painter->setTransform(transform, ignoreSelected);
|
//painter->setPen(QPen(Qt::red, 2));
|
||||||
painter->setPen(QPen(Qt::gray, 2));
|
//painter->setTransform(transform);
|
||||||
painter->setPen(Qt::DashLine);
|
//painter->drawRect(this->cache.getBoundingRect());
|
||||||
painter->drawRect(cache.getBoundingRect());
|
//painter->restore();
|
||||||
painter->restore();
|
// }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FolderLayerWrapper::paint(QPainter* painter, QTransform transform, bool ignoreSelected)
|
void FolderLayerWrapper::paint(QPainter* painter, QTransform transform, bool force)
|
||||||
{
|
{
|
||||||
LayerWrapper::paint(painter, transform, ignoreSelected);
|
if (hidden && !force)
|
||||||
|
return;
|
||||||
|
LayerWrapper::paint(painter, transform, force);
|
||||||
transform = property.transform * transform;
|
transform = property.transform * transform;
|
||||||
//qDebug() << transform;
|
//qDebug() << transform;
|
||||||
for (auto& child : children)
|
for (auto& child : children)
|
||||||
child->paint(painter, transform, ignoreSelected);
|
child->paint(painter, transform, force);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LeafLayerWrapper::paint(QPainter* painter, QTransform transform, bool ignoreSelected)
|
void LeafLayerWrapper::paint(QPainter* painter, QTransform transform, bool force)
|
||||||
{
|
{
|
||||||
LayerWrapper::paint(painter, transform, ignoreSelected);
|
if (hidden && !force)
|
||||||
|
return;
|
||||||
|
LayerWrapper::paint(painter, transform, force);
|
||||||
transform = property.transform * transform;
|
transform = property.transform * transform;
|
||||||
//qDebug() << transform;
|
//qDebug() << transform;
|
||||||
if (wrappedElement != nullptr)
|
if (wrappedElement != nullptr)
|
||||||
|
@ -347,11 +352,12 @@ void FolderLayerWrapper::collectDownReachable(std::set<LayerWrapper*>& reachable
|
||||||
|
|
||||||
void LayerWrapper::refreshTreeItem()
|
void LayerWrapper::refreshTreeItem()
|
||||||
{
|
{
|
||||||
|
hidden = qTreeWidgetItem->checkState(0) == Qt::Unchecked;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LeafLayerWrapper::refreshTreeItem()
|
void LeafLayerWrapper::refreshTreeItem()
|
||||||
{
|
{
|
||||||
|
LayerWrapper::refreshTreeItem();
|
||||||
if (typeid(*wrappedElement) == typeid(GroupElement))
|
if (typeid(*wrappedElement) == typeid(GroupElement))
|
||||||
{
|
{
|
||||||
this->qTreeWidgetItem->setText(0, "@ " + this->property.name);
|
this->qTreeWidgetItem->setText(0, "@ " + this->property.name);
|
||||||
|
@ -366,6 +372,7 @@ void LeafLayerWrapper::refreshTreeItem()
|
||||||
|
|
||||||
void FolderLayerWrapper::refreshTreeItem()
|
void FolderLayerWrapper::refreshTreeItem()
|
||||||
{
|
{
|
||||||
|
LayerWrapper::refreshTreeItem();
|
||||||
for (auto& child : this->children) {
|
for (auto& child : this->children) {
|
||||||
child->refreshTreeItem();
|
child->refreshTreeItem();
|
||||||
}
|
}
|
||||||
|
@ -428,4 +435,21 @@ bool LeafLayerWrapper::referencingGroupElement() const
|
||||||
bool LayerWrapper::canApplyStyles() const
|
bool LayerWrapper::canApplyStyles() const
|
||||||
{
|
{
|
||||||
return typeid(*this) == typeid(LeafLayerWrapper) && !referencingGroupElement();
|
return typeid(*this) == typeid(LeafLayerWrapper) && !referencingGroupElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LayerWrapper::paintVisualBounding(QPainter* painter) const
|
||||||
|
{
|
||||||
|
if (hidden)
|
||||||
|
return;
|
||||||
|
QTransform transform;
|
||||||
|
auto layer = this->parent;
|
||||||
|
while (layer != nullptr)
|
||||||
|
{
|
||||||
|
transform = transform * layer->property.transform;
|
||||||
|
layer = layer->parent;
|
||||||
|
}
|
||||||
|
painter->save();
|
||||||
|
painter->setTransform(transform);
|
||||||
|
painter->drawRect(cache.getBoundingRect());
|
||||||
|
painter->restore();
|
||||||
}
|
}
|
|
@ -37,6 +37,7 @@ class LayerWrapper
|
||||||
public:
|
public:
|
||||||
QTreeWidgetItem* qTreeWidgetItem;
|
QTreeWidgetItem* qTreeWidgetItem;
|
||||||
bool selected;
|
bool selected;
|
||||||
|
bool hidden;
|
||||||
struct SimpleProperty
|
struct SimpleProperty
|
||||||
{
|
{
|
||||||
QString name = "";
|
QString name = "";
|
||||||
|
@ -58,7 +59,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(), bool ignoreSelected = false);
|
virtual void paint(QPainter* painter, QTransform transform=QTransform(), bool force = 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
|
||||||
|
@ -74,6 +75,7 @@ class LayerWrapper
|
||||||
virtual size_t referencedCount(bool excludeSelf = false) const;
|
virtual size_t referencedCount(bool excludeSelf = false) const;
|
||||||
virtual bool deleteable(bool excludeSubTree = false) const;
|
virtual bool deleteable(bool excludeSubTree = false) const;
|
||||||
virtual bool referencingGroupElement() const;
|
virtual bool referencingGroupElement() const;
|
||||||
|
virtual void paintVisualBounding(QPainter* painter) const;
|
||||||
bool canApplyStyles() const;
|
bool canApplyStyles() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -97,7 +99,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(), bool ignoreSelected = false) override;
|
void paint(QPainter* painter, QTransform transform = QTransform(), bool force = false) override;
|
||||||
void collectDownReachable(std::set<LayerWrapper*>& reachable) override;
|
void collectDownReachable(std::set<LayerWrapper*>& reachable) override;
|
||||||
void refreshTreeItem() override;
|
void refreshTreeItem() override;
|
||||||
size_t referencedCount(bool excludeSelf = false) const override;
|
size_t referencedCount(bool excludeSelf = false) const override;
|
||||||
|
@ -115,7 +117,7 @@ class LeafLayerWrapper : public LayerWrapper
|
||||||
void refresh(LayerWrapper* layer = nullptr) override;
|
void refresh(LayerWrapper* layer = nullptr) override;
|
||||||
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(), bool ignoreSelected = false) override;
|
void paint(QPainter* painter, QTransform transform = QTransform(), bool force = false) override;
|
||||||
void collectDownReachable(std::set<LayerWrapper*>& reachable) override;
|
void collectDownReachable(std::set<LayerWrapper*>& reachable) override;
|
||||||
QTreeWidgetItem* getQTreeItem() override;
|
QTreeWidgetItem* getQTreeItem() override;
|
||||||
void refreshTreeItem() override;
|
void refreshTreeItem() override;
|
||||||
|
|
|
@ -78,7 +78,8 @@ PixelPath PixelPath::trans(QTransform& mat)const
|
||||||
painter.setTransform(mat);
|
painter.setTransform(mat);
|
||||||
painter.drawPixmap(0, 0, pixmap);
|
painter.drawPixmap(0, 0, pixmap);
|
||||||
result.painterPath.addPath(this->painterPath);
|
result.painterPath.addPath(this->painterPath);
|
||||||
result.boundingRect = mat.mapRect(boundingRect);
|
result.painterPath = mat.map(result.painterPath);
|
||||||
|
result.boundingRect = result.painterPath.boundingRect();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "PreviewWindow.h"
|
#include "PreviewWindow.h"
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
PreviewWindow::PreviewWindow(QWidget *parent) : QOpenGLWidget(parent)
|
PreviewWindow::PreviewWindow(QWidget *parent) : QOpenGLWidget(parent)
|
||||||
{
|
{
|
||||||
|
@ -84,7 +85,17 @@ void PreviewWindow::mouseMoveEvent(QMouseEvent* event)
|
||||||
int dx = event->x() - m_lastPos.x();
|
int dx = event->x() - m_lastPos.x();
|
||||||
int dy = event->y() - m_lastPos.y();
|
int dy = event->y() - m_lastPos.y();
|
||||||
if (currentLayer != nullptr) {
|
if (currentLayer != nullptr) {
|
||||||
if (event->buttons() & Qt::LeftButton) {
|
if (QApplication::keyboardModifiers() == Qt::ControlModifier && (event->buttons() & Qt::LeftButton))
|
||||||
|
{
|
||||||
|
currentLayer->property.scale.setX(std::max(0.0, currentLayer->property.scale.x() + dx / 50.0));
|
||||||
|
currentLayer->property.scale.setY(std::max(0.0, currentLayer->property.scale.y() + dy / 50.0));
|
||||||
|
}
|
||||||
|
else if (QApplication::keyboardModifiers() == (Qt::ControlModifier | Qt::ShiftModifier) && (event->buttons() & Qt::LeftButton))
|
||||||
|
{
|
||||||
|
currentLayer->property.scale.setX(std::max(0.0, currentLayer->property.scale.x() * (1.0 + dx / 50.0)));
|
||||||
|
currentLayer->property.scale.setY(std::max(0.0, currentLayer->property.scale.y() * (1.0 + dx / 50.0)));
|
||||||
|
}
|
||||||
|
else if (event->buttons() & Qt::LeftButton) {
|
||||||
// 如果按下的是左键,那么平移图形
|
// 如果按下的是左键,那么平移图形
|
||||||
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);
|
||||||
|
@ -100,19 +111,18 @@ void PreviewWindow::mouseMoveEvent(QMouseEvent* event)
|
||||||
auto index = -1;
|
auto index = -1;
|
||||||
if (typeid(*layer) == typeid(FolderLayerWrapper))
|
if (typeid(*layer) == typeid(FolderLayerWrapper))
|
||||||
index = dynamic_cast<FolderLayerWrapper*>(layer)->getReferencedBy();
|
index = dynamic_cast<FolderLayerWrapper*>(layer)->getReferencedBy();
|
||||||
if (index != -1)
|
|
||||||
emit refreshElementPreviewByIndex(index);
|
|
||||||
layer = layer->getParent();
|
layer = layer->getParent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 更新上一次的位置
|
// 更新上一次的位置
|
||||||
|
emit triggerCentralRefresh();
|
||||||
m_lastPos = event->pos();
|
m_lastPos = event->pos();
|
||||||
this->repaint();
|
this->repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewWindow::mouseReleaseEvent(QMouseEvent* event)
|
void PreviewWindow::mouseReleaseEvent(QMouseEvent* event)
|
||||||
{
|
{
|
||||||
emit layerInfoChanged();
|
//emit layerInfoChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewWindow::setBackgroundColor(QColor color)
|
void PreviewWindow::setBackgroundColor(QColor color)
|
||||||
|
|
|
@ -46,4 +46,5 @@ class PreviewWindow : public QOpenGLWidget, protected QOpenGLFunctions
|
||||||
void layerInfoChanged();
|
void layerInfoChanged();
|
||||||
void refreshElementPreview(GraphicElement*);
|
void refreshElementPreview(GraphicElement*);
|
||||||
void refreshElementPreviewByIndex(int);
|
void refreshElementPreviewByIndex(int);
|
||||||
|
void triggerCentralRefresh();
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "EditorSettingWidget.h"
|
#include "EditorSettingWidget.h"
|
||||||
|
#include "../ColorHelper.hpp"
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QColorDialog>
|
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
|
|
||||||
EditorSettingWidget::EditorSettingWidget(QWidget* parent)
|
EditorSettingWidget::EditorSettingWidget(QWidget* parent)
|
||||||
|
@ -8,7 +8,7 @@ EditorSettingWidget::EditorSettingWidget(QWidget* parent)
|
||||||
{
|
{
|
||||||
ui.setupUi(this);
|
ui.setupUi(this);
|
||||||
connect(ui.backgroundColorButton, &QPushButton::clicked, this, [this]() {
|
connect(ui.backgroundColorButton, &QPushButton::clicked, this, [this]() {
|
||||||
QColor color = QColorDialog::getColor(Qt::white, this, QString::fromLocal8Bit("Ñ¡Ôñ±³¾°ÑÕÉ«"));
|
QColor color = ColorHelper::execColorDialog(Qt::white, this, QString::fromLocal8Bit("Ñ¡Ôñ±³¾°ÑÕÉ«"));
|
||||||
if (color.isValid())
|
if (color.isValid())
|
||||||
{
|
{
|
||||||
emit backgroundColorChanged(color);
|
emit backgroundColorChanged(color);
|
||||||
|
|
|
@ -21,12 +21,11 @@ void InfoDisplayWidget::generateLayerForm()
|
||||||
{
|
{
|
||||||
while (this->layout()->count() > 0 && (item = this->layout()->takeAt(0)) != nullptr)
|
while (this->layout()->count() > 0 && (item = this->layout()->takeAt(0)) != nullptr)
|
||||||
{
|
{
|
||||||
delete item->widget();
|
item->widget()->deleteLater();
|
||||||
delete item;
|
delete item;
|
||||||
}
|
}
|
||||||
delete this->layout();
|
delete this->layout();
|
||||||
}
|
}
|
||||||
|
|
||||||
QFormLayout *layout = new QFormLayout();
|
QFormLayout *layout = new QFormLayout();
|
||||||
layout->setRowWrapPolicy(QFormLayout::WrapAllRows);
|
layout->setRowWrapPolicy(QFormLayout::WrapAllRows);
|
||||||
if (this->displayLayer == nullptr)
|
if (this->displayLayer == nullptr)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include "./EditorWidgetComponent/LayerCreateWidget.h"
|
#include "./EditorWidgetComponent/LayerCreateWidget.h"
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
LayerTreeWidget::LayerTreeWidget(QWidget *parent)
|
LayerTreeWidget::LayerTreeWidget(QWidget *parent)
|
||||||
{
|
{
|
||||||
|
@ -26,6 +27,10 @@ LayerTreeWidget::LayerTreeWidget(QWidget *parent)
|
||||||
}
|
}
|
||||||
emit triggerCentralRefresh();
|
emit triggerCentralRefresh();
|
||||||
});
|
});
|
||||||
|
connect(this, &QTreeWidget::itemChanged, this, [=]() {
|
||||||
|
emit triggerCentralRefresh();
|
||||||
|
});
|
||||||
|
|
||||||
// connect(this, &QTreeWidget::itemDoubleClicked, this, &LayerTreeWidget::onItemDoubleClicked);
|
// connect(this, &QTreeWidget::itemDoubleClicked, this, &LayerTreeWidget::onItemDoubleClicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
using Renderer::Painting;
|
using Renderer::Painting;
|
||||||
using Renderer::Element;
|
using Renderer::BaseElement;
|
||||||
using Renderer::ElementTransform;
|
using Renderer::ElementTransform;
|
||||||
using Renderer::BaseElement;
|
using Renderer::BaseElement;
|
||||||
using glm::bvec2;
|
using glm::bvec2;
|
||||||
|
@ -18,231 +18,119 @@ using std::queue;
|
||||||
const double PaintingUtil::pi = acos(-1);
|
const double PaintingUtil::pi = acos(-1);
|
||||||
|
|
||||||
struct LayerNode {
|
struct LayerNode {
|
||||||
LayerWrapper* nowLayer;
|
LayerWrapper* nowLayer;
|
||||||
QTransform transfrom;
|
QTransform transfrom;
|
||||||
};
|
};
|
||||||
|
|
||||||
QJsonObject PaintingUtil::readJsonFile(QString jsonFilePath) {
|
QJsonObject PaintingUtil::readJsonFile(QString jsonFilePath) {
|
||||||
QFile jsonFile(jsonFilePath);
|
QFile jsonFile(jsonFilePath);
|
||||||
jsonFile.open(QFile::ReadOnly);
|
qDebug() << jsonFilePath;
|
||||||
QByteArray fileContent = jsonFile.readAll().trimmed();
|
jsonFile.open(QFile::ReadOnly);
|
||||||
jsonFile.close();
|
QByteArray fileContent = jsonFile.readAll().trimmed();
|
||||||
QJsonParseError jError;
|
jsonFile.close();
|
||||||
QJsonDocument jsonDoc(QJsonDocument::fromJson(fileContent, &jError));
|
QJsonParseError jError;
|
||||||
return jsonDoc.object();
|
QJsonDocument jsonDoc(QJsonDocument::fromJson(fileContent, &jError));
|
||||||
|
return jsonDoc.object();
|
||||||
}
|
}
|
||||||
|
|
||||||
Painting PaintingUtil::transfromToPainting(QString jsonFilePath) {
|
Painting PaintingUtil::transfromToPainting(QString jsonFilePath) {
|
||||||
Painting painting;
|
Painting painting;
|
||||||
glm::bvec2 flip(0, 0);
|
glm::bvec2 flip(0, 0);
|
||||||
QJsonObject jsonObj = readJsonFile(jsonFilePath);
|
QJsonObject jsonObj = readJsonFile(jsonFilePath);
|
||||||
qDebug() << jsonObj;
|
qDebug() << jsonObj;
|
||||||
shared_ptr<ElementManager> elementManager = make_shared<ElementManager>(jsonObj, Renderer::ElementRenderer::instance());
|
shared_ptr<ElementManager> elementManager = make_shared<ElementManager>(jsonObj, Renderer::ElementRenderer::instance());
|
||||||
shared_ptr<LayerManager> layerManager = make_shared<LayerManager>(jsonObj, elementManager.get());
|
shared_ptr<LayerManager> layerManager = make_shared<LayerManager>(jsonObj, elementManager.get());
|
||||||
//qDebug() << elementManager->toJson();
|
//qDebug() << elementManager->toJson();
|
||||||
//qDebug() << layerManager->toJson();
|
//qDebug() << layerManager->toJson();
|
||||||
//qDebug() << ((SimpleElement*)((LeafLayerWrapper*)((FolderLayerWrapper*)((FolderLayerWrapper*)layerManager->getRoot())->children[0].get())->children[0].get())->wrappedElement)->painterPath;
|
//qDebug() << ((SimpleElement*)((LeafLayerWrapper*)((FolderLayerWrapper*)((FolderLayerWrapper*)layerManager->getRoot())->children[0].get())->children[0].get())->wrappedElement)->painterPath;
|
||||||
//qDebug() << ((LeafLayerWrapper*)((FolderLayerWrapper*)((FolderLayerWrapper*)layerManager->getRoot())->children[0].get())->children[0].get())->getCache().painterPath;
|
//qDebug() << ((LeafLayerWrapper*)((FolderLayerWrapper*)((FolderLayerWrapper*)layerManager->getRoot())->children[0].get())->children[0].get())->getCache().painterPath;
|
||||||
queue<LayerNode> layerQueue;
|
//qDebug() << elementManager->toJson();
|
||||||
LayerWrapper* root = layerManager->getRoot();
|
//qDebug() << layerManager->toJson();
|
||||||
root->getCache();
|
//qDebug() << ((SimpleElement*)((LeafLayerWrapper*)((FolderLayerWrapper*)((FolderLayerWrapper*)layerManager->getRoot())->children[0].get())->children[0].get())->wrappedElement)->painterPath;
|
||||||
double maxLineWidth = getMaxLineWidth(root);
|
//qDebug() << ((LeafLayerWrapper*)((FolderLayerWrapper*)((FolderLayerWrapper*)layerManager->getRoot())->children[0].get())->children[0].get())->getCache().painterPath;
|
||||||
layerQueue.push({ root, root->property.transform });
|
queue<LayerNode> layerQueue;
|
||||||
while (!layerQueue.empty()) {
|
LayerWrapper* root = layerManager->getRoot();
|
||||||
auto layerNode = layerQueue.front();
|
root->getCache();
|
||||||
layerQueue.pop();
|
//double maxLineWidth = getMaxLineWidth(root);
|
||||||
FolderLayerWrapper* nowLayer = handleLayerWrapper(layerNode.nowLayer, maxLineWidth, layerNode.transfrom, painting);
|
layerQueue.push({ root, root->property.transform });
|
||||||
if (nowLayer != nullptr) {
|
while (!layerQueue.empty()) {
|
||||||
for (auto sonLayer : nowLayer->children) {
|
auto layerNode = layerQueue.front();
|
||||||
layerQueue.push({ sonLayer.get(), layerNode.transfrom});
|
layerQueue.pop();
|
||||||
}
|
FolderLayerWrapper* nowLayer = handleLayerWrapper(layerNode.nowLayer, layerNode.transfrom, painting);
|
||||||
}
|
if (nowLayer != nullptr) {
|
||||||
}
|
for (auto sonLayer : nowLayer->children) {
|
||||||
|
layerQueue.push({ sonLayer.get(), layerNode.transfrom });
|
||||||
return painting;
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return painting;
|
||||||
}
|
}
|
||||||
|
|
||||||
FolderLayerWrapper* PaintingUtil::handleLayerWrapper(LayerWrapper* nowLayer, double& maxLineWidth, QTransform& transform, Painting& painting) {
|
FolderLayerWrapper* PaintingUtil::handleLayerWrapper(LayerWrapper* nowLayer, QTransform& transform, Painting& painting) {
|
||||||
LeafLayerWrapper* leafLayer = dynamic_cast<LeafLayerWrapper*>(nowLayer);
|
LeafLayerWrapper* leafLayer = dynamic_cast<LeafLayerWrapper*>(nowLayer);
|
||||||
|
|
||||||
transform = nowLayer->property.transform * transform;
|
transform = nowLayer->property.transform * transform;
|
||||||
|
|
||||||
if (leafLayer != nullptr) {
|
if (leafLayer != nullptr) {
|
||||||
|
|
||||||
GroupElement* wrapperElement = dynamic_cast<GroupElement*>(leafLayer->wrappedElement);
|
GroupElement* wrapperElement = dynamic_cast<GroupElement*>(leafLayer->wrappedElement);
|
||||||
if (wrapperElement != nullptr) {
|
if (wrapperElement != nullptr) {
|
||||||
transform = wrapperElement->sourceLayer->property.transform * transform;
|
transform = wrapperElement->sourceLayer->property.transform * transform;
|
||||||
return wrapperElement->sourceLayer;
|
return wrapperElement->sourceLayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
PixelPath pixelPath = nowLayer->getCache();
|
PixelPath pixelPath = nowLayer->getCache();
|
||||||
QPainterPath painterPath = pixelPath.getPainterPath();
|
QPainterPath painterPath = pixelPath.getPainterPath();
|
||||||
QRectF bound = painterPath.boundingRect();
|
QRectF bound = painterPath.boundingRect();
|
||||||
//qDebug() << leafLayer<<"------" << painterPath;
|
//qDebug() << leafLayer<<"------" << painterPath;
|
||||||
//qDebug() << transform;
|
// transform to -1£¬ 1
|
||||||
//Element element;
|
QTransform trans;
|
||||||
//ElementTransform elementTrans;
|
double maxLen = std::max(bound.width(), bound.height());
|
||||||
//element.ratio = bound.width() / bound.height();
|
qDebug() << maxLen << bound;
|
||||||
// transform to initial painterPath
|
trans.scale(1 / maxLen, 1 / maxLen);
|
||||||
// transfrom to -1£¬ 1
|
trans.translate(-bound.center().x(), -bound.center().y());
|
||||||
QTransform trans;
|
|
||||||
trans.translate(-centerX, -centerY)
|
|
||||||
.scale(1 / nowLayer->property.scale.x(), 1 / nowLayer->property.scale.y())
|
|
||||||
.rotate(-nowLayer->property.rotation)
|
|
||||||
.translate(centerX, centerY)
|
|
||||||
.translate(-nowLayer->property.offset.x(), -nowLayer->property.offset.y());
|
|
||||||
QPainterPath painterPath = trans.map(pixelPath.getPainterPath());
|
|
||||||
// transfrom to -1£¬ 1
|
|
||||||
QTransform trans;
|
|
||||||
double maxLen = std::max(bound.width(), bound.height()) + maxLineWidth * 2;
|
|
||||||
qDebug() << maxLen << bound;
|
|
||||||
trans.scale(1 / maxLen, 1 / maxLen);
|
|
||||||
trans.translate(-bound.center().x(), -bound.center().y());
|
|
||||||
|
|
||||||
qDebug() << trans.map(painterPath);
|
|
||||||
shared_ptr<vector<vector<Renderer::Point> >> contour = std::make_shared<vector<vector<Renderer::Point> >>(PainterPathUtil::transformToLines(trans.map(painterPath)));
|
|
||||||
QSize screenSize = QSize(1024, 1024);
|
|
||||||
//element.style = std::make_shared<Renderer::ElementStyleStrokeDemo>(0.06);
|
|
||||||
|
|
||||||
|
|
||||||
painterPath = transform.map(painterPath);
|
|
||||||
qDebug() << painterPath;
|
|
||||||
bound = painterPath.boundingRect();
|
|
||||||
|
|
||||||
ElementTransform elementTransform;
|
painterPath = trans.map(painterPath);
|
||||||
transform = transform * trans;
|
shared_ptr<vector<vector<Renderer::Point> >> contour = std::make_shared<vector<vector<Renderer::Point> >>(PainterPathUtil::transformToLines(painterPath));
|
||||||
//elementTransform.bound = glm::vec4(-1, -1, 1, 1);
|
QSize screenSize = QSize(1024, 1024);
|
||||||
elementTransform.bound = glm::vec4(
|
|
||||||
2 * (bound.x() - maxLineWidth) / screenSize.width() - 1,
|
|
||||||
2 * (bound.y() - maxLineWidth) / screenSize.height() - 1,
|
|
||||||
2 * (bound.x() + bound.width() + maxLineWidth) / screenSize.width() - 1,
|
|
||||||
2 * (bound.y() + bound.height() + maxLineWidth) / screenSize.height() - 1
|
|
||||||
);
|
|
||||||
qDebug() << elementTransform.bound.x << elementTransform.bound.y << elementTransform.bound.z << elementTransform.bound.z;
|
|
||||||
transform = transform.inverted();
|
|
||||||
elementTransform.transform = glm::mat3x2(
|
|
||||||
transform.m11(), transform.m12(), transform.m21(),
|
|
||||||
transform.m22(), transform.m31(), transform.m32()
|
|
||||||
);
|
|
||||||
qDebug() << transform;
|
|
||||||
elementTransform.zIndex = 0;
|
|
||||||
|
|
||||||
auto baseStyles = leafLayer->styles.toBaseStyles();
|
ElementTransform elementTransform;
|
||||||
BaseElement element; element.contour = contour;
|
transform = trans.inverted() * transform * QTransform::fromScale(2. / screenSize.width(), 2. / screenSize.height()) * QTransform::fromTranslate(-1, -1) * QTransform::fromScale(1, -1);
|
||||||
for (auto baseStyle : baseStyles) {
|
|
||||||
if (baseStyle.material->type() == Renderer::MaterialStyleType::kStroke) {
|
|
||||||
auto material = dynamic_cast<MaterialStyleStroke*>(baseStyle.material.get());
|
|
||||||
material->halfWidth = material->halfWidth / maxLen;
|
|
||||||
qDebug() << material->halfWidth;
|
|
||||||
}
|
|
||||||
element.style = baseStyle.material;
|
|
||||||
painting.addElement(element, elementTransform);
|
|
||||||
}
|
|
||||||
|
|
||||||
//qDebug() << bound;
|
auto baseStyles = leafLayer->styles.toBaseStyles();
|
||||||
|
Renderer::BaseElement element;
|
||||||
|
element.contour = contour;
|
||||||
|
for (auto& baseStyle : baseStyles) {
|
||||||
|
double lineWidth = 0;
|
||||||
|
if (baseStyle.material->type() == Renderer::MaterialStyleType::kStroke) {
|
||||||
|
auto material = std::static_pointer_cast<MaterialStyleStroke>(baseStyle.material);
|
||||||
|
material->halfWidth /= maxLen;
|
||||||
|
lineWidth = material->halfWidth;
|
||||||
|
qDebug() << material->halfWidth;
|
||||||
|
}
|
||||||
|
QPainterPathStroker stroker;
|
||||||
|
stroker.setWidth(lineWidth);
|
||||||
|
stroker.setCapStyle(Qt::RoundCap);
|
||||||
|
QPainterPath strokePath = stroker.createStroke(painterPath);
|
||||||
|
auto rect = transform.map(strokePath).boundingRect();
|
||||||
|
elementTransform.bound = glm::vec4(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height());
|
||||||
|
qDebug() << elementTransform.bound.x << elementTransform.bound.y << elementTransform.bound.z << elementTransform.bound.z;
|
||||||
|
transform = transform.inverted();
|
||||||
|
elementTransform.transform = glm::mat3x2(
|
||||||
|
transform.m11(), transform.m12(), transform.m21(),
|
||||||
|
transform.m22(), transform.m31(), transform.m32()
|
||||||
|
);
|
||||||
|
//qDebug() << transform;
|
||||||
|
elementTransform.zIndex = 0;
|
||||||
|
|
||||||
// TODO ¸ÄÓþØÕó
|
element.style = baseStyle.material;
|
||||||
|
painting.addElement(element, elementTransform);
|
||||||
|
}
|
||||||
|
|
||||||
/* elementTrans.center = glm::vec2(
|
return nullptr;
|
||||||
(2 * bound.center().x() - screenSize.width()) / screenSize.width(),
|
}
|
||||||
(2 * bound.center().y() - screenSize.height()) / screenSize.height()
|
|
||||||
);
|
|
||||||
qDebug() << elementTrans.center.x << elementTrans.center.y;
|
|
||||||
decomposeTransform(transform, elementTrans.rotation, elementTrans.scale);
|
|
||||||
elementTrans.scale = glm::vec2(
|
|
||||||
bound.width() * 2 / screenSize.width(),
|
|
||||||
bound.height() * 2 / screenSize.height()
|
|
||||||
);
|
|
||||||
elementTrans.flip = glm::bvec2(
|
|
||||||
nowLayer->property.flipHorizontally,
|
|
||||||
nowLayer->property.flipVertically
|
|
||||||
);
|
|
||||||
qDebug() << elementTrans.scale.x << elementTrans.scale.y;
|
|
||||||
painting.addElement(element, elementTrans);*/
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
FolderLayerWrapper* folderLayer = dynamic_cast<FolderLayerWrapper*>(nowLayer);
|
|
||||||
return folderLayer;
|
|
||||||
}
|
|
||||||
void PaintingUtil::decomposeTransform(QTransform trans, float& angle, glm::vec2& scale) {
|
|
||||||
//qDebug() << trans;
|
|
||||||
trans.setMatrix(
|
|
||||||
trans.m11(), trans.m12(), trans.m13(),
|
|
||||||
trans.m21(), trans.m22(), trans.m23(),
|
|
||||||
0, 0, 1);
|
|
||||||
//qDebug() << trans.dx() << trans.dy();
|
|
||||||
int count = 0;
|
|
||||||
double norm = 0, n = 0;
|
|
||||||
QTransform R = trans, Rit, Rnext;
|
|
||||||
do {
|
|
||||||
++count;
|
|
||||||
Rit = R.transposed().inverted();
|
|
||||||
Rnext.setMatrix(
|
|
||||||
(R.m11() + Rit.m11()) / 2,
|
|
||||||
(R.m12() + Rit.m12()) / 2,
|
|
||||||
(R.m13() + Rit.m13()) / 2,
|
|
||||||
(R.m21() + Rit.m21()) / 2,
|
|
||||||
(R.m22() + Rit.m22()) / 2,
|
|
||||||
(R.m23() + Rit.m23()) / 2,
|
|
||||||
(R.m31() + Rit.m31()) / 2,
|
|
||||||
(R.m32() + Rit.m32()) / 2,
|
|
||||||
(R.m33() + Rit.m33()) / 2
|
|
||||||
);
|
|
||||||
norm = 0;
|
|
||||||
norm = max(norm,
|
|
||||||
fabs(R.m11() - Rnext.m11())
|
|
||||||
+ fabs(R.m12() - Rnext.m12())
|
|
||||||
+ fabs(R.m13() - Rnext.m13()));
|
|
||||||
norm = max(norm,
|
|
||||||
fabs(R.m21() - Rnext.m21())
|
|
||||||
+ fabs(R.m22() - Rnext.m22())
|
|
||||||
+ fabs(R.m23() - Rnext.m23()));
|
|
||||||
norm = max(norm,
|
|
||||||
fabs(R.m31() - Rnext.m31())
|
|
||||||
+ fabs(R.m32() - Rnext.m32())
|
|
||||||
+ fabs(R.m33() - Rnext.m33()));
|
|
||||||
R = Rnext;
|
|
||||||
} while (count < 100 && norm > 0.0001);
|
|
||||||
double cosValue = max(-1.0, min(R.m11(), 1.0));
|
|
||||||
double sinValue = max(-1.0, min(R.m12(), 1.0));
|
|
||||||
angle = acos(cosValue) * 180 / pi;
|
|
||||||
if (sinValue < 0) {
|
|
||||||
angle = 360 - angle;
|
|
||||||
}
|
|
||||||
qDebug() << angle;
|
|
||||||
//R = R.inverted() * trans;
|
|
||||||
//scale = glm::vec2(R.m11(), R.m22());
|
|
||||||
//qDebug() << scale.x << scale.y;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
double PaintingUtil::getMaxLineWidth(LayerWrapper* root) {
|
FolderLayerWrapper* folderLayer = dynamic_cast<FolderLayerWrapper*>(nowLayer);
|
||||||
double maxWidth = 0;
|
return folderLayer;
|
||||||
queue<LayerWrapper* > layerQueue;
|
|
||||||
layerQueue.push(root);
|
|
||||||
while (!layerQueue.empty()) {
|
|
||||||
auto layer = layerQueue.front();
|
|
||||||
layerQueue.pop();
|
|
||||||
FolderLayerWrapper* nextLayer = nullptr;
|
|
||||||
LeafLayerWrapper* leafLayer = dynamic_cast<LeafLayerWrapper*>(layer);
|
|
||||||
if (leafLayer != nullptr) {
|
|
||||||
GroupElement* wrapperElement = dynamic_cast<GroupElement*>(leafLayer->wrappedElement);
|
|
||||||
if (wrapperElement != nullptr) {
|
|
||||||
nextLayer = wrapperElement->sourceLayer;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
maxWidth = std::max(maxWidth, (double)leafLayer->styles.boundingBoxAffectValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
nextLayer = dynamic_cast<FolderLayerWrapper*>(layer);
|
|
||||||
}
|
|
||||||
if (nextLayer != nullptr) {
|
|
||||||
for (auto sonLayer : nextLayer->children) {
|
|
||||||
layerQueue.push(sonLayer.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return maxWidth;
|
|
||||||
}
|
}
|
|
@ -7,11 +7,9 @@ class PaintingUtil
|
||||||
private:
|
private:
|
||||||
static const double pi;
|
static const double pi;
|
||||||
static QJsonObject readJsonFile(QString jsonFilePath);
|
static QJsonObject readJsonFile(QString jsonFilePath);
|
||||||
static FolderLayerWrapper* handleLayerWrapper(LayerWrapper* nowLayer, double& maxLineWidth, QTransform& transform, Renderer::Painting& painting);
|
static FolderLayerWrapper* handleLayerWrapper(LayerWrapper* nowLayer, QTransform& transform, Renderer::Painting& painting);
|
||||||
static double getMaxLineWidth(LayerWrapper* root);
|
//static double getMaxLineWidth(LayerWrapper* root);
|
||||||
public:
|
public:
|
||||||
static Renderer::Painting transfromToPainting(QString jsonFilePath);
|
static Renderer::Painting transfromToPainting(QString jsonFilePath);
|
||||||
static void decomposeTransform(QTransform trans, float& angle, glm::vec2& scale);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,4 +21,9 @@ void ::FluentMenu::paintEvent(QPaintEvent* event)
|
||||||
painter.drawRoundedRect(QRectF(shadowRadius - i, shadowRadius - i, width() - (shadowRadius - i) * 2, height() - (shadowRadius - i) * 2), borderRadius + i, borderRadius + i);
|
painter.drawRoundedRect(QRectF(shadowRadius - i, shadowRadius - i, width() - (shadowRadius - i) * 2, height() - (shadowRadius - i) * 2), borderRadius + i, borderRadius + i);
|
||||||
}
|
}
|
||||||
QMenu::paintEvent(event);
|
QMenu::paintEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QAction* FluentMenu::exec(const QPoint& pos, QAction* at)
|
||||||
|
{
|
||||||
|
return QMenu::exec(parentWidget()->mapToGlobal(parentWidget()->mapFromGlobal(pos) + QPoint(-shadowRadius, -shadowRadius)), at);
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ class FluentMenu : public QMenu
|
||||||
public:
|
public:
|
||||||
explicit FluentMenu(QWidget* parent = nullptr);
|
explicit FluentMenu(QWidget* parent = nullptr);
|
||||||
void paintEvent(QPaintEvent* event) override;
|
void paintEvent(QPaintEvent* event) override;
|
||||||
|
QAction* exec(const QPoint& pos, QAction* at = nullptr);
|
||||||
int shadowRadius = 16;
|
int shadowRadius = 16;
|
||||||
int borderRadius = 6;
|
int borderRadius = 6;
|
||||||
int itemBorderRadius = 4;
|
int itemBorderRadius = 4;
|
||||||
|
|
|
@ -244,8 +244,9 @@ GLuint Renderer::Model::loadPainting(std::string path)
|
||||||
return iter->second;
|
return iter->second;
|
||||||
|
|
||||||
Painting painting;
|
Painting painting;
|
||||||
|
path = "../test.json";
|
||||||
if (auto file = QFileInfo(QString(path.c_str())); file.isFile())
|
if (auto file = QFileInfo(QString(path.c_str())); file.isFile())
|
||||||
painting = PaintingUtil::transfromToPainting(file.path());
|
painting = PaintingUtil::transfromToPainting(file.filePath());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug() << path.c_str() << "Not Found, Using Default Painting";
|
qDebug() << path.c_str() << "Not Found, Using Default Painting";
|
||||||
|
|
|
@ -20,8 +20,7 @@ QVector4D BvhTree::Union(QVector4D a, QVector4D b) {
|
||||||
|
|
||||||
QVector4D BvhTree::merge(BvhPtr lp, BvhPtr rp) {
|
QVector4D BvhTree::merge(BvhPtr lp, BvhPtr rp) {
|
||||||
QVector4D a = lp->bound, b = rp->bound;
|
QVector4D a = lp->bound, b = rp->bound;
|
||||||
/*
|
/*if (lp->isLeaf) {
|
||||||
if (lp->isLeaf) {
|
|
||||||
a = BvhTreeData::boundWithRotation(a, lp->getRightSon());
|
a = BvhTreeData::boundWithRotation(a, lp->getRightSon());
|
||||||
}
|
}
|
||||||
if (rp->isLeaf) {
|
if (rp->isLeaf) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "MaterialStyleStroke.h"
|
#include "MaterialStyleStroke.h"
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
using namespace Renderer;
|
using namespace Renderer;
|
||||||
|
|
||||||
|
@ -105,8 +106,8 @@ std::unique_ptr<MaterialStyle> Renderer::MaterialStyleStroke::clone() const
|
||||||
|
|
||||||
bool Renderer::MaterialStyleStroke::operator==(const MaterialStyle& m) const
|
bool Renderer::MaterialStyleStroke::operator==(const MaterialStyle& m) const
|
||||||
{
|
{
|
||||||
return type() == m.type()
|
return type() == m.type()
|
||||||
&& halfWidth == static_cast<const MaterialStyleStroke&>(m).halfWidth
|
&& halfWidth == static_cast<const MaterialStyleStroke&>(m).halfWidth
|
||||||
&& strokeType == static_cast<const MaterialStyleStroke&>(m).strokeType
|
&& strokeType == static_cast<const MaterialStyleStroke&>(m).strokeType
|
||||||
&& endType == static_cast<const MaterialStyleStroke&>(m).endType
|
&& endType == static_cast<const MaterialStyleStroke&>(m).endType
|
||||||
&& *materialStroke == *static_cast<const MaterialStyleStroke&>(m).materialStroke;
|
&& *materialStroke == *static_cast<const MaterialStyleStroke&>(m).materialStroke;
|
||||||
|
@ -117,4 +118,10 @@ float Renderer::MaterialStyleStroke::getHalfWidth() const
|
||||||
return halfWidth;
|
return halfWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define endTypeBoxLabel(start, end) QStringLiteral(start##" -> "##end)
|
||||||
|
const std::array<std::pair<QString, StrokeEndType>, 4> Renderer::MaterialStyleStroke::strokeEndTypeNames = {
|
||||||
|
std::pair{endTypeBoxLabel("Բͷ", "Բͷ"), StrokeEndType::kRound},
|
||||||
|
std::pair{endTypeBoxLabel("ƽͷ", "Բͷ"), StrokeEndType::kFlatRound},
|
||||||
|
std::pair{endTypeBoxLabel("Բͷ", "ƽͷ"), StrokeEndType::kRoundFlat},
|
||||||
|
std::pair{endTypeBoxLabel("ƽͷ", "ƽͷ"), StrokeEndType::kFlat}
|
||||||
|
};
|
|
@ -43,7 +43,7 @@ namespace Renderer
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class StrokeType { kBothSides = 2, kLeftSide = 1, kRightSide = 0 };
|
enum class StrokeType { kBothSides = 2, kLeftSide = 1, kRightSide = 0 };
|
||||||
enum class StrokeEndType { kRound = 0b00, kFlat = 0b11, kRoundFlat = 0b10, kFlatRound = 0b01 };
|
enum class StrokeEndType { kRound = 0b00, kFlat = 0b11, kRoundFlat = 0b10, kFlatRound = 0b01, kClosed = 0b100/*用于封闭图形*/ };
|
||||||
|
|
||||||
class MaterialStyleStroke : public MaterialStyle
|
class MaterialStyleStroke : public MaterialStyle
|
||||||
{
|
{
|
||||||
|
@ -59,5 +59,6 @@ namespace Renderer
|
||||||
StrokeType strokeType;
|
StrokeType strokeType;
|
||||||
StrokeEndType endType;
|
StrokeEndType endType;
|
||||||
std::shared_ptr<MaterialStroke> materialStroke;
|
std::shared_ptr<MaterialStroke> materialStroke;
|
||||||
|
static const std::array<std::pair<QString, StrokeEndType>, 4> strokeEndTypeNames;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ Renderer::RendererWidget::RendererWidget(QWidget* parent)
|
||||||
ui.openButton->setChecked(false);
|
ui.openButton->setChecked(false);
|
||||||
});
|
});
|
||||||
QObject::connect(ui.openButton, &QPushButton::clicked, [&, menu]() {
|
QObject::connect(ui.openButton, &QPushButton::clicked, [&, menu]() {
|
||||||
menu->exec(ui.openButton->mapToGlobal(QPoint(-menu->shadowRadius, ui.openButton->height() - menu->shadowRadius)));
|
menu->exec(ui.openButton->mapToGlobal(QPoint(0, ui.openButton->height())));
|
||||||
});
|
});
|
||||||
|
|
||||||
QObject::connect(ui.horizontalSlider, &QSlider::valueChanged,
|
QObject::connect(ui.horizontalSlider, &QSlider::valueChanged,
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
|
#include "ColorHelper.hpp"
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QtWidgets/QApplication>
|
#include <QtWidgets/QApplication>
|
||||||
#include <FramelessHelper/Core/private/framelessconfig_p.h>
|
#include <FramelessHelper/Core/private/framelessconfig_p.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <format>
|
#include <format>
|
||||||
#include "consoleapi2.h"
|
#include "consoleapi2.h"
|
||||||
#include <lib/qtmaterialstyle.h>
|
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
|
@ -51,9 +51,7 @@ int main(int argc, char* argv[])
|
||||||
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||||
QApplication a(argc, argv);
|
QApplication a(argc, argv);
|
||||||
Q_INIT_RESOURCE(resources);
|
Q_INIT_RESOURCE(resources);
|
||||||
QtMaterialTheme theme;
|
ColorHelper::instance();
|
||||||
theme.setColor("primary1", QColor(0, 90, 158));
|
|
||||||
QtMaterialStyle::instance().setTheme(&theme);
|
|
||||||
//FramelessHelper::Core::setApplicationOSThemeAware();
|
//FramelessHelper::Core::setApplicationOSThemeAware();
|
||||||
FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur);
|
FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur);
|
||||||
//FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
//FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
||||||
|
|
|
@ -42,17 +42,38 @@ 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<MaterialStyleFill>(
|
std::make_shared<MaterialStyleFill>(std::make_shared<FillPlain>(Material(QColor(255,255,0))))) };
|
||||||
std::make_shared<FillPlain>(Material(QColor(255,255,0))))) };
|
}
|
||||||
|
} style;
|
||||||
|
TestGLWidget w(style, path);
|
||||||
|
w.show();
|
||||||
|
a.exec();
|
||||||
|
}
|
||||||
|
TEST_METHOD(TestFillPlainAndStrokeRadialGradient)
|
||||||
|
{
|
||||||
|
QApplication a(argc, argv);
|
||||||
|
class Style : public Renderer::ElementStyle
|
||||||
|
{
|
||||||
|
virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override
|
||||||
|
{
|
||||||
|
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)}}
|
||||||
|
};
|
||||||
|
return { BaseStyle(std::make_shared<TransformStyle>(),
|
||||||
|
std::make_shared<MaterialStyleFill>(
|
||||||
|
std::make_shared<FillPlain>(Material(QColor(255,255,0))))),
|
||||||
|
BaseStyle(std::make_shared<TransformStyle>(),
|
||||||
|
std::make_shared<MaterialStyleStroke>(10, StrokeType::kBothSides, StrokeEndType::kRound,
|
||||||
|
std::make_shared<StrokeRadialGradient>(materialMap, false))) };
|
||||||
}
|
}
|
||||||
} style;
|
} style;
|
||||||
TestGLWidget w(style, path);
|
TestGLWidget w(style, path);
|
||||||
w.show();
|
w.show();
|
||||||
a.exec();
|
a.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_CLASS(ElementRendererStokeTypeTest)
|
TEST_CLASS(ElementRendererStokeTypeTest)
|
||||||
|
|
|
@ -122,20 +122,6 @@ namespace UnitTest
|
||||||
};
|
};
|
||||||
TEST_CLASS(PaintingUtilTest)
|
TEST_CLASS(PaintingUtilTest)
|
||||||
{
|
{
|
||||||
TEST_METHOD(TransfromTest)
|
|
||||||
{
|
|
||||||
qInstallMessageHandler(messageHandler);
|
|
||||||
QPainterPath path;
|
|
||||||
path.addRect(0, 0, 20, 20);
|
|
||||||
QTransform trans;
|
|
||||||
qDebug() << path.boundingRect();
|
|
||||||
//qDebug() << trans;
|
|
||||||
//qDebug() << acos(-0.707107);
|
|
||||||
glm::vec2 scale;
|
|
||||||
float rotate;
|
|
||||||
PaintingUtil::decomposeTransform(trans, rotate, scale);
|
|
||||||
qDebug() << rotate;
|
|
||||||
qDebug() << scale.x << scale.y;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
46
test.json
46
test.json
|
@ -24,7 +24,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"height": 1080,
|
"height": 1080,
|
||||||
"project-name": "",
|
"project-name": "ÑùÀý1",
|
||||||
"root-layer": {
|
"root-layer": {
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
"styles": [
|
"styles": [
|
||||||
{
|
{
|
||||||
"enableEachSideIndependent": false,
|
"enableEachSideIndependent": false,
|
||||||
"left": "AACgQAEAIZwAf///AAAA/w==",
|
"left": "AAAAQAEAIZwAf///qqr//w==",
|
||||||
"right": "AADgQAAACJw=",
|
"right": "AADgQAAACJw=",
|
||||||
"type": "stroke"
|
"type": "stroke"
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,30 @@
|
||||||
"y": 1
|
"y": 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"element": 0,
|
||||||
|
"is-folder": false,
|
||||||
|
"name": "Leaf2",
|
||||||
|
"styles": [
|
||||||
|
{
|
||||||
|
"enableEachSideIndependent": true,
|
||||||
|
"left": "AAAAQAEAIZwAf////1UA/w==",
|
||||||
|
"right": "AADgQAAACJw=",
|
||||||
|
"type": "stroke"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transform": {
|
||||||
|
"offset": {
|
||||||
|
"x": 150,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"rotation": 0,
|
||||||
|
"scale": {
|
||||||
|
"x": 1.5,
|
||||||
|
"y": 1.5
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"is-folder": true,
|
"is-folder": true,
|
||||||
|
@ -68,6 +92,24 @@
|
||||||
"y": 1
|
"y": 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"element": 1,
|
||||||
|
"is-folder": false,
|
||||||
|
"name": "ReferencingGroupLayer",
|
||||||
|
"styles": [
|
||||||
|
],
|
||||||
|
"transform": {
|
||||||
|
"offset": {
|
||||||
|
"x": 100,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"rotation": 45,
|
||||||
|
"scale": {
|
||||||
|
"x": 1,
|
||||||
|
"y": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"is-folder": true,
|
"is-folder": true,
|
||||||
|
|
Loading…
Reference in New Issue