wuyize 2023-03-14 22:44:43 +08:00
commit cf3dd43a4a
14 changed files with 223 additions and 31 deletions

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>1124</width>
<height>1010</height>
<width>1473</width>
<height>1103</height>
</rect>
</property>
<property name="minimumSize">
@ -56,7 +56,20 @@
<widget class="QWidget" name="LeftBar" native="true"/>
</item>
<item>
<widget class="PreviewWindow" name="Preview"/>
<widget class="PreviewWindow" name="Preview">
<property name="minimumSize">
<size>
<width>1080</width>
<height>1080</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>1080</width>
<height>1080</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="RightBar" native="true">

View File

@ -14,6 +14,8 @@ EditorWidgetItem::EditorWidgetItem(QString filePath,QWidget *parent) : QWidget(p
elementInfoDisplayWidget = dynamic_cast<ElementPoolWidget *>(tabWidget->widget(1));
qDebug() << layerInfoDisplayWidget;
qDebug() << elementInfoDisplayWidget;
connect(previewWindow, &PreviewWindow::layerInfoChanged, layerInfoDisplayWidget, &InfoDisplayWidget::triggerSelfRefresh);
connect(treeWidget, &LayerTreeWidget::displayLayerChange, previewWindow, &PreviewWindow::currentLayerChanged);
connect(treeWidget, &LayerTreeWidget::requireRefreshElementWidget, elementInfoDisplayWidget, &ElementPoolWidget::refresh);
connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireRefreshElementWidget, elementInfoDisplayWidget, &ElementPoolWidget::refresh);
connect(treeWidget, &LayerTreeWidget::displayLayerChange, this, &EditorWidgetItem::onLayerChange);
@ -57,7 +59,11 @@ EditorWidgetItem::~EditorWidgetItem()
void EditorWidgetItem::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
// 设置画刷的颜色为灰色,并填充整个窗口区域
painter.setBrush(Qt::gray);
painter.drawRect(this->rect());
}
void EditorWidgetItem::onLayerChange(LayerWrapper *layer)

View File

@ -47,6 +47,7 @@ PixelPath SimpleElement::getPaintObject(std::vector<std::shared_ptr<LayerStyle>>
PixelPath result;
Renderer::ElementStyleStrokeDemo demo(2);
auto [img, mov] = renderer->drawElement(painterPath, demo, 1.0);
//qDebug() << mov;
//qDebug() << img << " ------";
result.addImage(img, mov);
//result.addPath(painterPath);
@ -83,3 +84,27 @@ QJsonObject GraphicElement::toJson() const
result.insert("name", name);
return result;
}
void SimpleElement::paint(QPainter* painter, QTransform transform, vector<std::shared_ptr<LayerStyle>> styles)
{
painter->save();
painter->setTransform(transform);
if (styles.empty())
{
painter->drawPath(painterPath);
}
else
{
// TODO:Ó¦ÓÃstyle
Renderer::ElementStyleStrokeDemo demo(2);
auto [img, mov] = renderer->drawElement(painterPath, demo, 1.0);
painter->drawImage(mov, img);
}
painter->restore();
}
void GroupElement::paint(QPainter* painter, QTransform transform, vector<std::shared_ptr<LayerStyle>> styles)
{
sourceLayer->paint(painter, transform);
}

View File

@ -28,6 +28,7 @@ public:
virtual QJsonObject toJson() const;
virtual PixelPath getPaintObject() const = 0;
virtual PixelPath getPaintObject(std::vector<std::shared_ptr<LayerStyle>>*) const = 0;
virtual void paint(QPainter* painter, QTransform transform, std::vector<std::shared_ptr<LayerStyle>> styles) = 0;
};
class SimpleElement : public GraphicElement
@ -44,6 +45,7 @@ public:
~SimpleElement() = default;
PixelPath getPaintObject() const override;
PixelPath getPaintObject(std::vector<std::shared_ptr<LayerStyle>>*) const override;
void paint(QPainter* painter, QTransform transform, std::vector<std::shared_ptr<LayerStyle>> styles) override;
};
class GroupElement : public GraphicElement
@ -58,6 +60,7 @@ public:
PixelPath getPaintObject() const override;
PixelPath getPaintObject(std::vector<std::shared_ptr<LayerStyle>>*) const override;
void setSourceLayer(FolderLayerWrapper* sourceLayer);
void paint(QPainter* painter, QTransform transform, std::vector<std::shared_ptr<LayerStyle>> styles) override;
};
//******************************** BitmapPath ********************************//

View File

@ -11,10 +11,10 @@ LayerWrapper *LayerManager::getRoot() const
{
return root;
}
void LayerManager::paint(QPainter *painter, QSize size) const
void LayerManager::paint(QPainter *painter, QSize size,LayerWrapper* selecetedLayer) const
{
auto p = root->getCache().resizedPixel(size);
painter->drawPixmap(0, 0, p);
root->getCache();
root->paint(painter);
}
bool LayerManager::singleSelectedCheck() const
{

View File

@ -32,7 +32,7 @@ class LayerManager
LayerManager() = default;
LayerManager(QJsonObject source, ElementManager* elementManager);
QJsonObject toJson() const;
void paint(QPainter *painter, QSize size) const;
void paint(QPainter *painter, QSize size, LayerWrapper* selecetedLayer=nullptr) const;
bool rename(QString newName) const;
bool combine() const;
// bool seperate() const;

View File

@ -23,9 +23,13 @@ FolderLayerWrapper*LayerWrapper::getParent() const
return this == nullptr ? nullptr : this->parent;
}
PixelPath LayerWrapper::getCache()
PixelPath LayerWrapper::getCache(LayerWrapper* selectedLayer)
{
this->refresh();
this->refresh(selectedLayer);
if (selectedLayer == this)
{
this->cache.highLight();
}
return cache;
}
@ -42,6 +46,7 @@ LayerWrapper::LayerWrapper(QJsonObject json, FolderLayerWrapper*parent, ElementM
property.scale = {transformJson.value("scale").toObject().value("x").toDouble(),
transformJson.value("scale").toObject().value("y").toDouble()};
property.rotation = {transformJson.value("rotation").toDouble()};
selected = false;
}
FolderLayerWrapper::FolderLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent)
@ -75,35 +80,52 @@ LeafLayerWrapper::LeafLayerWrapper(QJsonObject json, ElementManager *elementMana
int elementIndex = json.value("element").toInt();
wrappedElement = elementManager->getElementById(elementIndex);
}
void LayerWrapper::SimpleProperty::apply(PixelPath&cache) const
void LayerWrapper::SimpleProperty::apply(PixelPath&cache)
{
transform.reset();
double centerX = cache.getBoundingRect().center().x();
double centerY = cache.getBoundingRect().center().y();
//qDebug() << name << " " << cache.boundingRect().center();
//qDebug() << name << " " << cache.boundingRect();
transform.translate(centerX, centerY);
transform.translate(offset.x(), offset.y());
transform.rotate(rotation);
transform.scale(scale.x(), scale.y());
transform.translate(-centerX, -centerY);
cache = cache.trans(transform);
}
QTransform LayerWrapper::getTransform()
{
QTransform trans;
double centerX = cache.getBoundingRect().center().x();
double centerY = cache.getBoundingRect().center().y();
//qDebug() << name << " " << cache.boundingRect().center();
//qDebug() << name << " " << cache.boundingRect();
trans.translate(offset.x(), offset.y());
trans.translate(-centerX, -centerY);
trans.rotate(rotation);
trans.scale(scale.x(), scale.y());
trans.translate(centerX, centerY);
cache = cache.trans(trans);
trans.translate(property.offset.x(), property.offset.y());
trans.rotate(property.rotation);
trans.scale(property.scale.x(), property.scale.y());
trans.translate(-centerX, -centerY);
return trans;
}
void LayerWrapper::refresh()
void LayerWrapper::refresh(LayerWrapper* layer)
{
property.apply(cache);
}
void FolderLayerWrapper::refresh()
void FolderLayerWrapper::refresh(LayerWrapper* layer)
{
cache.clear();
for (auto& child : children) {
cache.addPath(child.get()->getCache());
cache.addPath(child.get()->getCache(layer));
}
LayerWrapper::refresh();
}
void LeafLayerWrapper::refresh()
void LeafLayerWrapper::refresh(LayerWrapper* layer)
{
cache.clear();
if (wrappedElement != nullptr)
@ -228,3 +250,36 @@ int FolderLayerWrapper::getReferencedBy()const
else
return -1;
}
void LayerWrapper::paint(QPainter* painter, QTransform transform)
{
if (this->selected)
{
painter->save();
painter->setTransform(transform);
painter->setPen(QPen(Qt::gray, 2));
painter->setPen(Qt::DashLine);
painter->drawRect(cache.getBoundingRect());
painter->restore();
}
}
void FolderLayerWrapper::paint(QPainter* painter, QTransform transform)
{
LayerWrapper::paint(painter, transform);
transform = property.transform * transform;
qDebug() << transform;
for (auto& child : children)
child->paint(painter, transform);
}
void LeafLayerWrapper::paint(QPainter* painter, QTransform transform)
{
LayerWrapper::paint(painter, transform);
transform = property.transform * transform;
qDebug() << transform;
if (wrappedElement != nullptr)
{
wrappedElement->paint(painter, transform, styles);
}
}

View File

@ -35,6 +35,7 @@ class LayerWrapper
public:
QTreeWidgetItem* qTreeWidgetItem;
bool selected;
struct SimpleProperty
{
QString name = "";
@ -43,17 +44,20 @@ class LayerWrapper
double rotation = 0;
bool flipHorizontally = 0;
bool flipVertically = 0;
QTransform transform;
// TODO: 将QPainterPath改为BitmapPath
void apply(PixelPath&cache) const;
void apply(PixelPath&cache);
} property;
virtual void setParent(FolderLayerWrapper*newParent);
virtual void refresh();
virtual void refresh(LayerWrapper* layer = nullptr);
virtual QTreeWidgetItem* getQTreeItem();
// TODO: 将QPainterPath改为BitmapPath/QImage或者直接将其删除绘制时直接使用BitmapPath的paint方法
virtual PixelPath getCache();
virtual PixelPath getCache(LayerWrapper* selectedLayer=nullptr);
QTransform getTransform();
FolderLayerWrapper*getParent() const; // invoke by manager, then invoke parent's applyStyles
LayerWrapper(QJsonObject json, FolderLayerWrapper*parent, ElementManager* elementManager=nullptr);
LayerWrapper() = default;
virtual void paint(QPainter* painter, QTransform transform=QTransform());
// TODO : export Function
// virtual LayerWrapper *addChild() = 0; // Leaf Child Only
// virtual LayerWrapper *addParent() = 0; // Folder Parent Only
@ -75,7 +79,7 @@ class FolderLayerWrapper : public LayerWrapper
public:
~FolderLayerWrapper() = default;
void refresh() override;
void refresh(LayerWrapper* layer=nullptr) override;
FolderLayerWrapper() = default;
FolderLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent);
void addChild(shared_ptr<LayerWrapper> child);
@ -86,6 +90,7 @@ class FolderLayerWrapper : public LayerWrapper
QTreeWidgetItem* getQTreeItem() override;
QJsonObject toJson() const override;
int getReferencedBy()const;
void paint(QPainter* painter, QTransform transform = QTransform()) override;
};
class LeafLayerWrapper : public LayerWrapper
@ -97,10 +102,11 @@ class LeafLayerWrapper : public LayerWrapper
public:
~LeafLayerWrapper() = default;
void refresh() override;
void refresh(LayerWrapper* layer = nullptr) override;
LeafLayerWrapper() = default;
LeafLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent);
QJsonObject toJson() const override;
void paint(QPainter* painter, QTransform transform = QTransform()) override;
};
Q_DECLARE_METATYPE(LayerWrapper *)

View File

@ -103,3 +103,18 @@ QPixmap PixelPath::getDetail()const
result = pixmap.copy(rect);
return result;
}
void PixelPath::highLight()
{
// 创建一个QPainter对象关联到QPixmap对象
QPainter painter(&pixmap);
// 设置画笔的颜色、宽度和样式
painter.setPen(QPen(Qt::black, 1, Qt::DashLine));
// 绘制一个矩形,指定左上角和右下角的坐标
painter.drawRect(boundingRect);
// 结束绘制
painter.end();
}

View File

@ -26,4 +26,5 @@ public:
PixelPath trans(QTransform& mat)const;
QPixmap resizedPixel(QSize size)const;
QPixmap getDetail()const;
void highLight();
};

View File

@ -2,6 +2,7 @@
PreviewWindow::PreviewWindow(QWidget *parent) : QOpenGLWidget(parent)
{
this->setFixedSize(QSize(1080, 1080));
this->renderer = Renderer::ElementRenderer::instance();
QSurfaceFormat surfaceFormat;
surfaceFormat.setSamples(16);
@ -10,6 +11,7 @@ PreviewWindow::PreviewWindow(QWidget *parent) : QOpenGLWidget(parent)
painter->setRenderHint(QPainter::SmoothPixmapTransform);
painter->setRenderHint(QPainter::HighQualityAntialiasing);
layerManager = nullptr;
currentLayer = nullptr;
}
void PreviewWindow::initialize(LayerManager *layerManager,QSize windowSize)
@ -46,7 +48,7 @@ void PreviewWindow::paintGL()
painter->begin(this);
painter->setRenderHint(QPainter::Antialiasing);
painter->setRenderHint(QPainter::HighQualityAntialiasing);
layerManager->paint(painter,this->size());
layerManager->paint(painter,this->size(),currentLayer);
painter->end();
}
@ -57,3 +59,47 @@ void PreviewWindow::resizeGL(int w, int h)
Renderer::ElementRenderer* const PreviewWindow::getRenderer()const {
return this->renderer;
}
void PreviewWindow::currentLayerChanged(LayerWrapper* layer)
{
this->currentLayer = layer;
}
void PreviewWindow::refresh()
{
this->repaint();
}
void PreviewWindow::mousePressEvent(QMouseEvent* event)
{
// 当鼠标按下时,记录当前的位置
m_lastPos = event->pos();
}
void PreviewWindow::mouseMoveEvent(QMouseEvent* event)
{
// 当鼠标移动时,计算移动的距离,并根据需要更新图形的状态
int dx = event->x() - m_lastPos.x();
int dy = event->y() - m_lastPos.y();
if (currentLayer != nullptr) {
if (event->buttons() & Qt::LeftButton) {
// 如果按下的是左键,那么平移图形
currentLayer->property.offset.setX(currentLayer->property.offset.x() + dx);
currentLayer->property.offset.setY(currentLayer->property.offset.y() + dy);
qDebug() << dx << "----" << dy;
}
else if (event->buttons() & Qt::RightButton) {
// 如果按下的是右键,那么旋转图形
qreal angle = dx;
currentLayer->property.rotation += angle;
}
}
// 更新上一次的位置
m_lastPos = event->pos();
this->repaint();
}
void PreviewWindow::mouseReleaseEvent(QMouseEvent* event)
{
emit layerInfoChanged();
}

View File

@ -7,6 +7,7 @@
#include <QJsonObject>
#include <QJsonValue>
#include <QOpenGLFunctions>
#include <QMouseEvent>
#include <QOpenGLWidget>
#include "../Renderer/Preview/ElementRenderer.h"
@ -19,6 +20,12 @@ class PreviewWindow : public QOpenGLWidget, protected QOpenGLFunctions
LayerManager *layerManager;
Renderer::ElementRenderer* renderer;
QSize logicalSize;
QRectF viewportRect;
LayerWrapper* currentLayer;
QPointF m_lastPos;
void mousePressEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
public:
PreviewWindow(QWidget *parent = nullptr);
@ -28,4 +35,11 @@ class PreviewWindow : public QOpenGLWidget, protected QOpenGLFunctions
void paintGL() override;
void resizeGL(int w, int h) override;
Renderer::ElementRenderer* const getRenderer()const;
public slots:
void currentLayerChanged(LayerWrapper*);
void refresh();
signals:
void layerInfoChanged();
};

View File

@ -12,11 +12,19 @@ LayerTreeWidget::LayerTreeWidget(QWidget *parent)
this->setHeaderLabel("Layer Content");
connect(this, &QTreeWidget::customContextMenuRequested, this, &LayerTreeWidget::popMenu);
connect(this, &QTreeWidget::currentItemChanged, [=](QTreeWidgetItem *currentItem) {
if (this->selectedItem != nullptr) {
this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper*>()->selected = false;
}
this->selectedItem = currentItem;
if(this->selectedItem !=nullptr)
emit displayLayerChange(this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper *>());
else
emit displayLayerChange(nullptr);
if (this->selectedItem != nullptr) {
auto layer = this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper*>();
layer->selected = true;
emit displayLayerChange(layer);
}
else {
emit displayLayerChange(nullptr);
}
emit requireRefreshPreview();
});
// connect(this, &QTreeWidget::itemDoubleClicked, this, &LayerTreeWidget::onItemDoubleClicked);
}

View File

@ -20,7 +20,7 @@ class LayerTreeWidget : public QTreeWidget
// void mouseDoubleClickEvent(QMouseEvent *event) override;
// void onItemDoubleClicked(QTreeWidgetItem *item, int column = 0);
signals:
signals:
void displayLayerChange(LayerWrapper *);
void requireRefreshPreview();
void requireRefreshElementWidget();