Skip to content
This repository has been archived by the owner on Sep 16, 2021. It is now read-only.

Commit

Permalink
use cached rendering for module library, fixes #115
Browse files Browse the repository at this point in the history
  • Loading branch information
cpdt committed Oct 29, 2018
1 parent e666e3f commit e1211c5
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 228 deletions.
4 changes: 2 additions & 2 deletions editor/resources/styles/ModulePreviewList.qss
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
margin: 5px 0 5px 10px;
}

QGraphicsView {
#image {
border: 2px solid #222;
border-radius: 5px;
}

QGraphicsView:hover {
#image:hover {
border-color: #444;
}
3 changes: 1 addition & 2 deletions editor/widgets/modulebrowser/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ set(SOURCE_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/ModuleBrowserPanel.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ModulePreviewButton.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ModulePreviewCanvas.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ModulePreviewList.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ModulePreviewView.cpp")
"${CMAKE_CURRENT_SOURCE_DIR}/ModulePreviewList.cpp")

target_sources(axiom_widgets PRIVATE ${SOURCE_FILES})
161 changes: 158 additions & 3 deletions editor/widgets/modulebrowser/ModulePreviewButton.cpp
Original file line number Diff line number Diff line change
@@ -1,27 +1,45 @@
#include "ModulePreviewButton.h"

#include <QtCore/QMimeData>
#include <QtGui/QContextMenuEvent>
#include <QtGui/QDrag>
#include <QtWidgets/QFileDialog>
#include <QtWidgets/QGraphicsView>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QMenu>
#include <QtWidgets/QMessageBox>

#include "ModulePreviewView.h"
#include "../node/NodeItem.h"
#include "../windows/MainWindow.h"
#include "../windows/ModulePropertiesWindow.h"
#include "ModulePreviewCanvas.h"
#include "editor/model/Library.h"
#include "editor/model/LibraryEntry.h"
#include "editor/model/objects/RootSurface.h"
#include "editor/model/serialize/LibrarySerializer.h"
#include "editor/model/serialize/ModelObjectSerializer.h"
#include "editor/model/serialize/ProjectSerializer.h"

using namespace AxiomGui;

ModulePreviewButton::ModulePreviewButton(MainWindow *window, AxiomModel::Library *library,
AxiomModel::LibraryEntry *entry, QWidget *parent)
: QFrame(parent), library(library), _entry(entry) {
: QFrame(parent), window(window), library(library), _entry(entry) {
setFixedWidth(110);

auto mainLayout = new QGridLayout(this);

mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->setRowStretch(0, 1);

mainLayout->addWidget(new ModulePreviewView(window, library, entry, this), 0, 0);
image = new QLabel(this);
image->setObjectName("image");
mainLayout->addWidget(image, 0, 0);
image->setMargin(0);
image->setContentsMargins(0, 0, 0, 0);

label = new QLabel(this);
label->setObjectName("label");
mainLayout->addWidget(label, 1, 0);
label->setMargin(0);
label->setContentsMargins(5, 0, 0, 0);
Expand All @@ -33,9 +51,114 @@ ModulePreviewButton::ModulePreviewButton(MainWindow *window, AxiomModel::Library

library->activeTagChanged.connect(this, &ModulePreviewButton::updateIsVisible);
library->activeSearchChanged.connect(this, &ModulePreviewButton::updateIsVisible);

entry->root()->history().stackChanged.connect(this, &ModulePreviewButton::updateImage);

updateImage();
updateIsVisible();
}

void ModulePreviewButton::mousePressEvent(QMouseEvent *event) {
QFrame::mousePressEvent(event);

if (event->button() == Qt::LeftButton) {
event->accept();
auto drag = new QDrag(this);

// serialize the surface and set mime data
auto centerPos = AxiomModel::GridSurface::findCenter(_entry->rootSurface()->grid().items().sequence());
QByteArray serializeArray;
QDataStream stream(&serializeArray, QIODevice::WriteOnly);
stream << centerPos;
AxiomModel::ModelObjectSerializer::serializeChunk(
stream, _entry->rootSurface()->uuid(),
AxiomModel::findDependents(
AxiomCommon::dynamicCast<AxiomModel::ModelObject *>(_entry->root()->pool().sequence().sequence()),
_entry->rootSurface()->uuid(), false));

auto mimeData = new QMimeData();
mimeData->setData("application/axiom-partial-surface", serializeArray);
drag->setMimeData(mimeData);

drag->exec();
}
}

void ModulePreviewButton::mouseDoubleClickEvent(QMouseEvent *event) {
window->showSurface(nullptr, _entry->rootSurface(), true, false);
}

void ModulePreviewButton::contextMenuEvent(QContextMenuEvent *event) {
event->accept();

QMenu menu;
auto editAction = menu.addAction("&Edit");
auto propertiesAction = menu.addAction("&Properties...");
menu.addSeparator();
auto exportAction = menu.addAction("E&xport...");
menu.addSeparator();
auto deleteAction = menu.addAction("&Delete");

auto selectedAction = menu.exec(event->globalPos());
if (selectedAction == editAction) {
window->showSurface(nullptr, _entry->rootSurface(), true, false);
} else if (selectedAction == propertiesAction) {
ModulePropertiesWindow propWindow(library);
propWindow.setEnteredName(_entry->name());

QStringList currentTags;
for (const auto &tag : _entry->tags()) {
currentTags.push_back(tag);
}
propWindow.setEnteredTags(currentTags);

if (propWindow.exec() == QDialog::Accepted) {
_entry->setName(propWindow.enteredName());

auto enteredTags = propWindow.enteredTags();
std::set<QString> newTags(enteredTags.begin(), enteredTags.end());

// remove old tags
std::set<QString> oldTags(_entry->tags());
for (const auto &oldTag : oldTags) {
if (newTags.find(oldTag) == newTags.end()) _entry->removeTag(oldTag);
}

// add new tags
for (const auto &newTag : newTags) {
_entry->addTag(newTag);
}
}
} else if (selectedAction == exportAction) {
auto selectedFile = QFileDialog::getSaveFileName(this, "Export Module", QString(),
tr("Axiom Library Files (*.axl);;All Files (*.*)"));
if (selectedFile.isNull()) return;

QFile file(selectedFile);
if (!file.open(QIODevice::WriteOnly)) {
QMessageBox(QMessageBox::Critical, "Failed to export module", "The file you selected couldn't be opened.",
QMessageBox::Ok)
.exec();
return;
}

QDataStream stream(&file);
AxiomModel::ProjectSerializer::writeHeader(stream, AxiomModel::ProjectSerializer::librarySchemaMagic);
AxiomModel::LibrarySerializer::serializeEntries(1, &_entry, &_entry + 1, stream);
file.close();
} else if (selectedAction == deleteAction) {
QMessageBox confirmBox(QMessageBox::Warning, "Confirm Delete",
"Are you sure you want to delete this module?\n\n"
"This operation cannot be undone.");
confirmBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
confirmBox.setDefaultButton(QMessageBox::Yes);

if (confirmBox.exec() == QMessageBox::Yes) {
_entry->remove();
}
}
}

void ModulePreviewButton::setName(QString name) {
QFontMetrics metrics(label->font());
auto elidedText = metrics.elidedText(name, Qt::ElideRight, label->width());
Expand All @@ -48,3 +171,35 @@ void ModulePreviewButton::updateIsVisible() {
library->activeSearch() == "" || _entry->name().contains(library->activeSearch(), Qt::CaseInsensitive);
setVisible(hasTag && hasSearch);
}

void ModulePreviewButton::updateImage() {
ModulePreviewCanvas canvas(_entry->rootSurface());
QGraphicsView view(&canvas);
view.setInteractive(false);
view.setRenderHint(QPainter::Antialiasing);
view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
view.setFixedSize(100, 100);
view.setStyleSheet("* { border: none; }");

// figure out the bounding box size of the scene
QRectF boundingRect;
for (const auto &item : view.scene()->items()) {
if (auto node = dynamic_cast<NodeItem *>(item)) {
auto br = node->drawBoundingRect();
br.moveTopLeft(node->scenePos());
boundingRect = boundingRect.united(br);
}
}
view.setSceneRect(boundingRect);

// figure out correct scaling with some padding
auto viewWidth = view.width() - 30;
auto viewHeight = view.height() - 30;
auto scaleFactor = boundingRect.width() > boundingRect.height() ? viewWidth / boundingRect.width()
: viewHeight / boundingRect.height();
view.centerOn(boundingRect.center());
view.scale(scaleFactor, scaleFactor);

image->setPixmap(view.grab());
}
11 changes: 11 additions & 0 deletions editor/widgets/modulebrowser/ModulePreviewButton.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,24 @@ namespace AxiomGui {

AxiomModel::LibraryEntry *entry() { return _entry; }

protected:
void mousePressEvent(QMouseEvent *event) override;

void mouseDoubleClickEvent(QMouseEvent *event) override;

void contextMenuEvent(QContextMenuEvent *event) override;

private:
MainWindow *window;
AxiomModel::Library *library;
AxiomModel::LibraryEntry *_entry;
QLabel *image;
QLabel *label;

void setName(QString name);

void updateIsVisible();

void updateImage();
};
}
10 changes: 0 additions & 10 deletions editor/widgets/modulebrowser/ModulePreviewCanvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,9 @@ ModulePreviewCanvas::ModulePreviewCanvas(NodeSurface *surface) {
for (const auto &connection : surface->connections().sequence()) {
connection->wire().then(this, [this](std::unique_ptr<ConnectionWire> &wire) { addWire(wire.get()); });
}

// connect to model
surface->nodes().events().itemAdded().connect(this, &ModulePreviewCanvas::addNode);
surface->connections().events().itemAdded().connect(this, [this](Connection *connection) {
connection->wire().then(this, [this](std::unique_ptr<ConnectionWire> &wire) { addWire(wire.get()); });
});
}

void ModulePreviewCanvas::addNode(AxiomModel::Node *node) {
node->posChanged.connect(this, &ModulePreviewCanvas::contentChanged);
node->sizeChanged.connect(this, &ModulePreviewCanvas::contentChanged);
node->removed.connect(this, &ModulePreviewCanvas::contentChanged);

auto item = new NodeItem(node, nullptr);
item->setZValue(1);
addItem(item);
Expand Down
4 changes: 0 additions & 4 deletions editor/widgets/modulebrowser/ModulePreviewCanvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ namespace AxiomGui {
public:
explicit ModulePreviewCanvas(AxiomModel::NodeSurface *surface);

signals:

void contentChanged();

private slots:

void addNode(AxiomModel::Node *node);
Expand Down
Loading

0 comments on commit e1211c5

Please sign in to comment.