diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj index 2ca822f..f32e302 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj @@ -61,14 +61,14 @@ - stdcpp20 + stdcpp17 $(SolutionDir)QGoodWindow;%(AdditionalIncludeDirectories);$(Qt_INCLUDEPATH_) - stdcpp20 - $(SolutionDir)QGoodWindow;%(AdditionalIncludeDirectories); + stdcpp17 + $(SolutionDir)ArchitectureColoredPainting\src\Editor\RightBar;$(SolutionDir)ArchitectureColoredPainting\src\Editor\;$(SolutionDir)QGoodWindow;%(AdditionalIncludeDirectories) @@ -105,6 +105,8 @@ + + @@ -162,6 +164,8 @@ + + diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters index f6b745d..70e0c28 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters @@ -173,6 +173,13 @@ Source Files\Editor\third-party modules + Source Files\Editor\third-party modules + + + Source Files + + + Source Files Source Files\Renderer\Painting @@ -206,6 +213,12 @@ Header Files\Editor + + Header Files + + + Header Files + @@ -333,9 +346,6 @@ Header Files\Editor - - Header Files\Editor - Header Files\Renderer\Painting @@ -357,6 +367,13 @@ Header Files\Editor\util + + Header Files\Editor + Header Files\Editor\third-party modules\qquick + + + Header Files\Editor\util + Header Files\Renderer\Painting diff --git a/ArchitectureColoredPainting/EditorWidget.ui b/ArchitectureColoredPainting/EditorWidget.ui index 7f00648..38ca891 100644 --- a/ArchitectureColoredPainting/EditorWidget.ui +++ b/ArchitectureColoredPainting/EditorWidget.ui @@ -27,18 +27,60 @@ 0 - - - - - 纹理编辑 - - - - - - - + + + + + + 纹理编辑 + + + Qt::AlignCenter + + + + + + + + + + + + + + + + + + 0 + + + + Layer + + + + + Element + + + + + + + + Qt::CustomContextMenu + + + + + + + + + + @@ -49,6 +91,17 @@ QOpenGLWidget
PreviewWindow.h
+ + LayerTreeWidget + QTreeWidget +
LayerTreeWidget.h
+
+ + InfoDisplayWidget + QWidget +
InfoDisplayWidget.h
+ 1 +
diff --git a/ArchitectureColoredPainting/Shaders/painting.comp b/ArchitectureColoredPainting/Shaders/painting.comp index 7f27e23..34e5a91 100644 --- a/ArchitectureColoredPainting/Shaders/painting.comp +++ b/ArchitectureColoredPainting/Shaders/painting.comp @@ -876,6 +876,49 @@ void drawLine(in float d, in uint styleIndex, out vec4 elementColor, out vec2 me } } +void drawLine(in float d, in uint styleIndex, out vec4 elementColor, out vec2 metallicRoughness) +{ + elementColor = vec4(1); + metallicRoughness = vec2(0.8); + switch(int(elementData[styleIndex+3])) + { + case 0: + { + elementColor = vec4(elementData[styleIndex+7],elementData[styleIndex+8],elementData[styleIndex+9],1); + metallicRoughness = vec2(elementData[styleIndex+10],elementData[styleIndex+11]); + break; + } + case 1: + { + elementColor = vec4(mix(vec3(0), vec3(1), d), 1); + metallicRoughness = vec2(0,0.8); + break; + } + case 2: + { + float levels[] = {0.25,0.5,0.75}; + vec3 colors[] = {vec3(1,0,0), vec3(0,1,0), vec3(0,0,1), vec3(1,1,0)}; + int i = 0; + while(i<3) + { + if(d(tabWidget->widget(0)); + elementInfoDisplayWidget = dynamic_cast(tabWidget->widget(1)); + connect(treeWidget, &LayerTreeWidget::displayLayerChange, this, &EditorWidget::onLayerChange); + connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireRefreshPreview, this, + &EditorWidget::triggerRefreshPreview); + // &EditorWidget::triggerRefreshPreview); + // test QFile settingFile; settingFile.setFileName("../data.json"); settingFile.open(QFile::ReadOnly); @@ -19,6 +28,10 @@ EditorWidget::EditorWidget(QWidget *parent) : QWidget(parent) elementManager = new ElementManager(source); layerManager = new LayerManager(source, elementManager); previewWindow->initialize(layerManager); + if (layerManager->getRoot() != nullptr) + { + treeWidget->addTopLevelItem(layerManager->getRoot()->qTreeItem); + } } EditorWidget::~EditorWidget() @@ -28,3 +41,16 @@ EditorWidget::~EditorWidget() void EditorWidget::paintEvent(QPaintEvent *event) { } + +void EditorWidget::onLayerChange(LayerWrapper *layer) +{ + displayLayer = layer; + // TODO : notify InfoDisplayWidget and update + dynamic_cast(tabWidget->widget(0))->setLayer(layer); + this->update(); +} + +void EditorWidget::triggerRefreshPreview() +{ + previewWindow->update(); +} diff --git a/ArchitectureColoredPainting/src/Editor/EditorWidget.h b/ArchitectureColoredPainting/src/Editor/EditorWidget.h index 14ce226..3e7a3f5 100644 --- a/ArchitectureColoredPainting/src/Editor/EditorWidget.h +++ b/ArchitectureColoredPainting/src/Editor/EditorWidget.h @@ -1,24 +1,38 @@ #pragma once #include "ElementManager.h" +#include "InfoDisplayWidget.h" #include "LayerManager.h" +#include "LayerTreeWidget.h" #include "PreviewWindow.h" #include "ui_EditorWidget.h" #include +#include #include - class EditorWidget : public QWidget { Q_OBJECT private: - Ui::EditorWidgetClass ui; + // DATA PART PreviewWindow *previewWindow; ElementManager *elementManager; LayerManager *layerManager; + // QT GUI PART + Ui::EditorWidgetClass ui; + LayerTreeWidget *treeWidget; + QTabWidget *tabWidget; + InfoDisplayWidget *layerInfoDisplayWidget, *elementInfoDisplayWidget; + // QT DATA PART + LayerWrapper *displayLayer; + GraphicElement *displayElement; public: EditorWidget(QWidget *parent = nullptr); ~EditorWidget(); void paintEvent(QPaintEvent *event) override; + + private slots: + void onLayerChange(LayerWrapper *layer); + void triggerRefreshPreview(); }; diff --git a/ArchitectureColoredPainting/src/Editor/GraphicElement.cpp b/ArchitectureColoredPainting/src/Editor/GraphicElement.cpp index 567ccc1..fd1078f 100644 --- a/ArchitectureColoredPainting/src/Editor/GraphicElement.cpp +++ b/ArchitectureColoredPainting/src/Editor/GraphicElement.cpp @@ -11,12 +11,14 @@ void SimpleElement::loadSvgFile(const QString& filePath) // TODO ʽ SvgFileLoader loader; loader.loadSvgFile(filePath, painterPath); + qDebug() << "load svg file success "<drawPath(root->getCache()); @@ -57,3 +61,11 @@ bool LayerManager::changeParent(FolderLayerWrapper *newParent) const selectedLayers[0]->setParent(newParent); return true; } +void LayerManager::addLayer(LayerWrapper *layer) +{ + layerSet.insert(layer); +} +void LayerManager::removeLayer(LayerWrapper *layer) +{ + layerSet.erase(layer); +} diff --git a/ArchitectureColoredPainting/src/Editor/LayerManager.h b/ArchitectureColoredPainting/src/Editor/LayerManager.h index 370861a..a3a9742 100644 --- a/ArchitectureColoredPainting/src/Editor/LayerManager.h +++ b/ArchitectureColoredPainting/src/Editor/LayerManager.h @@ -3,9 +3,11 @@ #include "LayerWrapper.h" #include #include +#include #include #include using std::pair; +using std::set; using std::vector; class ElementManager; class LayerWrapper; @@ -21,8 +23,13 @@ class LayerManager LayerPtrs involvedLeafLayersCache; bool singleSelectedCheck() const; bool multipleSelectedCheck() const; + set layerSet; public: + void addLayer(LayerWrapper *layer); + void removeLayer(LayerWrapper *layer); + LayerWrapper *getRoot() const; + LayerManager() = default; LayerManager(QJsonObject source, ElementManager *elementManager); void paint(QPainter *painter) const; bool rename(QString newName) const; diff --git a/ArchitectureColoredPainting/src/Editor/LayerWrapper.cpp b/ArchitectureColoredPainting/src/Editor/LayerWrapper.cpp index 96ea1af..e06bc7a 100644 --- a/ArchitectureColoredPainting/src/Editor/LayerWrapper.cpp +++ b/ArchitectureColoredPainting/src/Editor/LayerWrapper.cpp @@ -33,15 +33,23 @@ LayerWrapper::LayerWrapper(QJsonObject json, LayerWrapper *parent) { this->parent = shared_ptr(parent); auto transformJson = json.value("transform").toObject(); - property.offset = { transformJson.value("offset").toObject().value("x").toDouble(), transformJson.value("offset").toObject().value("y").toDouble() }; - property.scale = { transformJson.value("scale").toObject().value("x").toDouble(), transformJson.value("scale").toObject().value("y").toDouble() }; - property.rotation = { transformJson.value("rotation").toDouble()}; + property.name = json.value("name").toString(); + property.offset = {transformJson.value("offset").toObject().value("x").toDouble(), + transformJson.value("offset").toObject().value("y").toDouble()}; + property.scale = {transformJson.value("scale").toObject().value("x").toDouble(), + transformJson.value("scale").toObject().value("y").toDouble()}; + property.rotation = {transformJson.value("rotation").toDouble()}; + qTreeItem = new QTreeWidgetItem(); + qTreeItem->setText(0, property.name); + if (parent != nullptr) + parent->qTreeItem->addChild(qTreeItem); + qTreeItem->setData(0, Qt::UserRole, QVariant::fromValue(this)); } FolderLayerWrapper::FolderLayerWrapper(QJsonObject json, ElementManager *elementManager, LayerWrapper *parent) : LayerWrapper(json, parent) { - qDebug() << json.value("name").toString()<<" "<getPaintObject()); } LayerWrapper::refresh(); @@ -113,3 +122,12 @@ void FolderLayerWrapper::removeAllChild() { children.clear(); } + +namespace LayerEvent +{ + +static void onDoubleClick(QTreeWidgetItem *qItem, LayerWrapper *layerWrapper) +{ +} + +} // namespace LayerEvent diff --git a/ArchitectureColoredPainting/src/Editor/LayerWrapper.h b/ArchitectureColoredPainting/src/Editor/LayerWrapper.h index 0aefcc0..b36fb74 100644 --- a/ArchitectureColoredPainting/src/Editor/LayerWrapper.h +++ b/ArchitectureColoredPainting/src/Editor/LayerWrapper.h @@ -7,7 +7,9 @@ #include #include #include +#include #include +#include #include #include using std::shared_ptr; @@ -19,6 +21,7 @@ class ElementManager; class LayerWrapper { + protected: shared_ptr parent; QPointF referencePoint; @@ -26,6 +29,7 @@ class LayerWrapper QPainterPath cache; public: + QTreeWidgetItem *qTreeItem; struct SimpleProperty { QString name = ""; @@ -42,6 +46,11 @@ class LayerWrapper LayerWrapper *getParent() const; // invoke by manager, then invoke parent's applyStyles LayerWrapper(QJsonObject json, LayerWrapper *parent); LayerWrapper() = default; + // TODO : export Function + // virtual LayerWrapper *addChild() = 0; // Leaf Child Only + // virtual LayerWrapper *addParent() = 0; // Folder Parent Only + // virtual void deleteSelf() const = 0; + // virtual void deleteAll() const = 0; }; class FolderLayerWrapper : public LayerWrapper @@ -68,3 +77,5 @@ class LeafLayerWrapper : public LayerWrapper LeafLayerWrapper() = default; LeafLayerWrapper(QJsonObject json, ElementManager *elementManager, LayerWrapper *parent); }; + +Q_DECLARE_METATYPE(LayerWrapper *) diff --git a/ArchitectureColoredPainting/src/Editor/RightBar/InfoDisplayWidget.cpp b/ArchitectureColoredPainting/src/Editor/RightBar/InfoDisplayWidget.cpp new file mode 100644 index 0000000..82f5c97 --- /dev/null +++ b/ArchitectureColoredPainting/src/Editor/RightBar/InfoDisplayWidget.cpp @@ -0,0 +1,80 @@ +#include "InfoDisplayWidget.h" +#include +#include +void InfoDisplayWidget::setLayer(LayerWrapper *layer) +{ + this->displayLayer = layer; + generateLayerForm(); +} +void InfoDisplayWidget::setElement(GraphicElement *element) +{ + this->displayElement = element; + generateElementForm(); +} +void InfoDisplayWidget::generateLayerForm() +{ + QLayoutItem *item; + if (this->layout() != nullptr) + { + while ((item = this->layout()->takeAt(0)) != nullptr) + { + delete item->widget(); + delete item; + } + delete this->layout(); + } + + QFormLayout *layout = new QFormLayout(); + layout->setRowWrapPolicy(QFormLayout::WrapAllRows); + if (this->displayLayer == nullptr) + { + layout->addRow("no selected layer", new QLabel()); + } + else + { + QLineEdit *name = new QLineEdit(this->displayLayer->property.name, this); + QLineEdit *rotation = new QLineEdit(QString::number(this->displayLayer->property.rotation, 'f', 0), this); + QLineEdit *offsetX = new QLineEdit(QString::number(this->displayLayer->property.offset.x()), this); + QLineEdit *offsetY = new QLineEdit(QString::number(this->displayLayer->property.offset.y()), this); + QLineEdit *scaleX = new QLineEdit(QString::number(this->displayLayer->property.scale.x()), this); + QLineEdit *scaleY = new QLineEdit(QString::number(this->displayLayer->property.scale.y()), this); + name->setDisabled(true); + rotation->setValidator(new QIntValidator(-1000, 1000, this)); + connect(rotation, &QLineEdit::textChanged, [=](QString content) { + this->displayLayer->property.rotation = content.toDouble(); + emit requireRefreshPreview(); + }); + offsetX->setValidator(new QIntValidator(-1000, 1000, this)); + connect(offsetX, &QLineEdit::textChanged, [=](QString content) { + this->displayLayer->property.offset = {content.toDouble(), this->displayLayer->property.offset.y()}; + emit requireRefreshPreview(); + }); + offsetY->setValidator(new QIntValidator(-1000, 1000, this)); + connect(offsetY, &QLineEdit::textChanged, [=](QString content) { + this->displayLayer->property.offset = {this->displayLayer->property.offset.x(), content.toDouble()}; + emit requireRefreshPreview(); + }); + scaleX->setValidator(new QDoubleValidator(0.01, 100, 4, this)); + connect(scaleX, &QLineEdit::textChanged, [=](QString content) { + this->displayLayer->property.scale = {content.toDouble(), this->displayLayer->property.scale.y()}; + emit requireRefreshPreview(); + }); + scaleY->setValidator(new QDoubleValidator(0.01, 100, 4, this)); + connect(scaleY, &QLineEdit::textChanged, [=](QString content) { + this->displayLayer->property.scale = {this->displayLayer->property.scale.x(), content.toDouble()}; + emit requireRefreshPreview(); + }); + + layout->addRow("layer name:", name); + layout->addRow("rotation:", rotation); + layout->addRow("offset-X:", offsetX); + layout->addRow("offset-Y:", offsetY); + layout->addRow("scale-X:", scaleX); + layout->addRow("scale-Y:", scaleY); + layout->setRowWrapPolicy(QFormLayout::DontWrapRows); + } + this->setLayout(layout); +} +void InfoDisplayWidget::generateElementForm() +{ +} diff --git a/ArchitectureColoredPainting/src/Editor/RightBar/InfoDisplayWidget.h b/ArchitectureColoredPainting/src/Editor/RightBar/InfoDisplayWidget.h new file mode 100644 index 0000000..c95586d --- /dev/null +++ b/ArchitectureColoredPainting/src/Editor/RightBar/InfoDisplayWidget.h @@ -0,0 +1,23 @@ +#pragma once +#include "GraphicElement.h" +#include "LayerWrapper.h" +#include +#include +#include + +class InfoDisplayWidget : public QWidget +{ + Q_OBJECT + private: + LayerWrapper *displayLayer; + GraphicElement *displayElement; + + public: + void setLayer(LayerWrapper *layer); + void setElement(GraphicElement *element); + void generateLayerForm(); + void generateElementForm(); + + signals: + void requireRefreshPreview(); +}; diff --git a/ArchitectureColoredPainting/src/Editor/RightBar/LayerTreeWidget.cpp b/ArchitectureColoredPainting/src/Editor/RightBar/LayerTreeWidget.cpp new file mode 100644 index 0000000..bb59b9b --- /dev/null +++ b/ArchitectureColoredPainting/src/Editor/RightBar/LayerTreeWidget.cpp @@ -0,0 +1,59 @@ +#include "LayerTreeWidget.h" +#include +#include +LayerTreeWidget::LayerTreeWidget(QWidget *parent) +{ + emit displayLayerChange(nullptr); + this->selectedItem = nullptr; + this->copiedItem = nullptr; + this->setContextMenuPolicy(Qt::CustomContextMenu); + this->setHeaderLabel("Layer Content"); + connect(this, &QTreeWidget::customContextMenuRequested, this, &LayerTreeWidget::popMenu); + connect(this, &QTreeWidget::currentItemChanged, [=](QTreeWidgetItem *currentItem) { + this->selectedItem = currentItem; + emit displayLayerChange(this->selectedItem->data(0, Qt::UserRole).value()); + }); + // connect(this, &QTreeWidget::itemDoubleClicked, this, &LayerTreeWidget::onItemDoubleClicked); +} + +// void LayerTreeWidget::mouseDoubleClickEvent(QMouseEvent *event) +//{ +// // stay empty to avoid the default behavior +// } +// +// void LayerTreeWidget::onItemDoubleClicked(QTreeWidgetItem *item, int column) +//{ +// this->selectedItem = item; +// // TODO +// } + +void LayerTreeWidget::popMenu(const QPoint &pos) +{ + QMenu menu; + QTreeWidgetItem *item = itemAt(pos); + this->selectedItem = item; + // TODO + menu.addAction("Add Child", this, &LayerTreeWidget::onRenameEvent); + menu.addAction("Rename", this, &LayerTreeWidget::onRenameEvent); + menu.addAction("Copy", this, &LayerTreeWidget::onRenameEvent); + if (item != nullptr && item->childCount() > 0) + menu.addAction("Delete (Self Only)", this, &LayerTreeWidget::onRenameEvent); + menu.addAction("Delete", this, &LayerTreeWidget::onRenameEvent); + menu.exec(mapToGlobal(pos)); +} + +void LayerTreeWidget::onRenameEvent() +{ + if (this->selectedItem == nullptr) + return; + qDebug() << this->selectedItem->data(0, Qt::UserRole).value()->property.name; + bool bOk = false; + QString sName = + QInputDialog::getText(this, "Rename", "New Name:", QLineEdit::Normal, this->selectedItem->text(0), &bOk); + if (bOk && !sName.isEmpty()) + { + this->selectedItem->setText(0, sName); + this->selectedItem->data(0, Qt::UserRole).value()->property.name = sName; + } + emit displayLayerChange(this->selectedItem->data(0, Qt::UserRole).value()); +} diff --git a/ArchitectureColoredPainting/src/Editor/RightBar/LayerTreeWidget.h b/ArchitectureColoredPainting/src/Editor/RightBar/LayerTreeWidget.h new file mode 100644 index 0000000..e8510a1 --- /dev/null +++ b/ArchitectureColoredPainting/src/Editor/RightBar/LayerTreeWidget.h @@ -0,0 +1,21 @@ +#pragma once +#include "LayerWrapper.h" +#include +#include +class LayerTreeWidget : public QTreeWidget +{ + Q_OBJECT + private: + QTreeWidgetItem *selectedItem; + LayerWrapper *copiedItem; + + public: + LayerTreeWidget(QWidget *parent = nullptr); + void onRenameEvent(); + void popMenu(const QPoint &pos); + // void mouseDoubleClickEvent(QMouseEvent *event) override; + // void onItemDoubleClicked(QTreeWidgetItem *item, int column = 0); + + signals: + void displayLayerChange(LayerWrapper *); +}; diff --git a/data.json b/data.json index b5abde9..20889e6 100644 --- a/data.json +++ b/data.json @@ -6,7 +6,7 @@ "name": "ababa", "type": "svg-file", "data": { - "include": "./svg/ababa.svg" + "include": "./svg/2.svg" } }, { diff --git a/svg/0.svg b/svg/0.svg new file mode 100644 index 0000000..7e3ea82 --- /dev/null +++ b/svg/0.svg @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/svg/1.svg b/svg/1.svg new file mode 100644 index 0000000..602a167 --- /dev/null +++ b/svg/1.svg @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/svg/2.svg b/svg/2.svg new file mode 100644 index 0000000..92bd7ef --- /dev/null +++ b/svg/2.svg @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/svg/3.svg b/svg/3.svg new file mode 100644 index 0000000..28600f3 --- /dev/null +++ b/svg/3.svg @@ -0,0 +1 @@ +3 \ No newline at end of file diff --git a/svg/4.svg b/svg/4.svg new file mode 100644 index 0000000..d5f56ec --- /dev/null +++ b/svg/4.svg @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/svg/5.svg b/svg/5.svg new file mode 100644 index 0000000..addc399 --- /dev/null +++ b/svg/5.svg @@ -0,0 +1 @@ +5 \ No newline at end of file diff --git a/svg/6.svg b/svg/6.svg new file mode 100644 index 0000000..4bb0826 --- /dev/null +++ b/svg/6.svg @@ -0,0 +1 @@ +6 \ No newline at end of file diff --git a/svg/原图.png b/svg/原图.png new file mode 100644 index 0000000..499036a Binary files /dev/null and b/svg/原图.png differ