diff --git a/editor/mainwindow.cpp b/editor/mainwindow.cpp index e132cb8..0f9df6a 100644 --- a/editor/mainwindow.cpp +++ b/editor/mainwindow.cpp @@ -72,16 +72,16 @@ MainWindow::MainWindow(QWidget *parent) connect(ui->actionSave, &QAction::triggered, this, [&]() { std::optional path; if (!dataModel->HasFile()) - path = QFileDialog::getSaveFileName(this, QString::fromStdString("Save " + dataModel->name), "", "*.obl").toStdString(); + path = openFileDialog("Openblocks Level (*.obl)", ".obl", QFileDialog::AcceptSave, QString::fromStdString("Save " + dataModel->name)); if (path == "") return; dataModel->SaveToFile(path); }); connect(ui->actionOpen, &QAction::triggered, this, [&]() { - std::string path = QFileDialog::getOpenFileName(this, "Load file", "", "*.obl").toStdString(); - if (path == "") return; - std::shared_ptr newModel = DataModel::LoadFromFile(path); + std::optional path = openFileDialog("Openblocks Level (*.obl)", ".obl", QFileDialog::AcceptOpen); + if (!path) return; + std::shared_ptr newModel = DataModel::LoadFromFile(path.value()); dataModel = newModel; delete ui->explorerView->selectionModel(); ui->explorerView->reset(); @@ -159,6 +159,40 @@ MainWindow::MainWindow(QWidget *parent) selectedParent->AddChild(inst); } }); + + connect(ui->actionSaveModel, &QAction::triggered, this, [&]() { + std::optional path = openFileDialog("Openblocks Model (*.obm)", ".obm", QFileDialog::AcceptSave); + if (!path) return; + std::ofstream outStream(path.value()); + + // Serialized XML for exporting + pugi::xml_document modelDoc; + pugi::xml_node modelRoot = modelDoc.append_child("openblocks"); + + for (InstanceRefWeak inst : getSelection()) { + if (inst.expired()) continue; + inst.lock()->Serialize(&modelRoot); + } + + modelDoc.save(outStream); + }); + + connect(ui->actionInsertModel, &QAction::triggered, this, [&]() { + if (getSelection().size() != 1 || getSelection()[0].expired()) return; + InstanceRef selectedParent = getSelection()[0].lock(); + + std::optional path = openFileDialog("Openblocks Model (*.obm)", ".obm", QFileDialog::AcceptOpen); + if (!path) return; + std::ifstream inStream(path.value()); + + pugi::xml_document modelDoc; + modelDoc.load(inStream); + + for (pugi::xml_node instNode : modelDoc.child("openblocks").children("Item")) { + InstanceRef inst = Instance::Deserialize(&instNode); + selectedParent->AddChild(inst); + } + }); // Update handles addSelectionListener([&](auto oldSelection, auto newSelection, bool fromExplorer) { @@ -239,6 +273,18 @@ void MainWindow::updateToolbars() { : HandlesType::ScaleHandles; } +std::optional MainWindow::openFileDialog(QString filter, QString defaultExtension, QFileDialog::AcceptMode acceptMode, QString title) { + QFileDialog dialog(this); + if (title != "") dialog.setWindowTitle(title); + dialog.setNameFilters(QStringList { filter, "All Files (*)" }); + dialog.setDefaultSuffix(defaultExtension); + dialog.setAcceptMode(acceptMode); + if (!dialog.exec()) + return std::nullopt; + + return dialog.selectedFiles().front().toStdString(); +} + MainWindow::~MainWindow() { delete ui; diff --git a/editor/mainwindow.h b/editor/mainwindow.h index 064828c..7117432 100644 --- a/editor/mainwindow.h +++ b/editor/mainwindow.h @@ -7,6 +7,7 @@ #include "qmenu.h" #include #include +#include enum SelectedTool { SELECT, @@ -44,5 +45,7 @@ private: void updateToolbars(); void timerEvent(QTimerEvent*) override; + + std::optional openFileDialog(QString filter, QString defaultExtension, QFileDialog::AcceptMode acceptMode, QString title = ""); }; #endif // MAINWINDOW_H diff --git a/editor/mainwindow.ui b/editor/mainwindow.ui index 0efb9c7..f333260 100644 --- a/editor/mainwindow.ui +++ b/editor/mainwindow.ui @@ -41,7 +41,7 @@ 0 0 1027 - 22 + 30 @@ -406,6 +406,28 @@ QAction::MenuRole::NoRole + + + Save Model to File + + + Saves objects to file as XML model + + + QAction::MenuRole::NoRole + + + + + Insert Model from File + + + Insert model from XML file + + + QAction::MenuRole::NoRole + + diff --git a/editor/panes/explorerview.cpp b/editor/panes/explorerview.cpp index 61f1ae4..c057c0a 100644 --- a/editor/panes/explorerview.cpp +++ b/editor/panes/explorerview.cpp @@ -81,4 +81,7 @@ void ExplorerView::buildContextMenu() { contextMenu.addAction(M_mainWindow->ui->actionCut); contextMenu.addAction(M_mainWindow->ui->actionPaste); contextMenu.addAction(M_mainWindow->ui->actionPasteInto); + contextMenu.addSeparator(); + contextMenu.addAction(M_mainWindow->ui->actionSaveModel); + contextMenu.addAction(M_mainWindow->ui->actionInsertModel); } \ No newline at end of file