Compare commits

...

2 commits

7 changed files with 188 additions and 42 deletions

View file

@ -73,7 +73,7 @@ void main() {
} }
vec4 studPx = texture(studs, vec3(vTexCoords, vSurfaceZ)); vec4 studPx = texture(studs, vec3(vTexCoords, vSurfaceZ));
FragColor = vec4(mix(result, vec3(studPx), studPx.w), 1-transparency); FragColor = vec4(mix(result, vec3(studPx), studPx.w), 1) * (1-transparency);
} }
vec3 calculateDirectionalLight(DirLight light) { vec3 calculateDirectionalLight(DirLight light) {

View file

@ -233,6 +233,8 @@ void renderHandles() {
} }
// 2d square overlay // 2d square overlay
glDisable(GL_CULL_FACE);
identityShader->use(); identityShader->use();
identityShader->set("aColor", glm::vec3(0.f, 1.f, 1.f)); identityShader->set("aColor", glm::vec3(0.f, 1.f, 1.f));

View file

@ -12,6 +12,9 @@
#include <QAbstractItemView> #include <QAbstractItemView>
#include <memory> #include <memory>
#include <optional> #include <optional>
#include <qglobal.h>
#include <qwindowdefs.h>
#include <sstream>
#include "common.h" #include "common.h"
#include "editorcommon.h" #include "editorcommon.h"
@ -21,7 +24,8 @@
#include "physics/simulation.h" #include "physics/simulation.h"
#include "objects/part.h" #include "objects/part.h"
#include "qfiledialog.h" #include "qfiledialog.h"
#include "qitemselectionmodel.h" #include "qclipboard.h"
#include "qmimedata.h"
#include "qobject.h" #include "qobject.h"
#include "qsysinfo.h" #include "qsysinfo.h"
@ -37,7 +41,7 @@ MainWindow::MainWindow(QWidget *parent)
timer.start(33, this); timer.start(33, this);
setMouseTracking(true); setMouseTracking(true);
ConnectSelectionChangeHandler(); ui->explorerView->buildContextMenu();
connect(ui->actionToolSelect, &QAction::triggered, this, [&]() { selectedTool = SelectedTool::SELECT; updateToolbars(); }); connect(ui->actionToolSelect, &QAction::triggered, this, [&]() { selectedTool = SelectedTool::SELECT; updateToolbars(); });
connect(ui->actionToolMove, &QAction::triggered, this, [&](bool state) { selectedTool = state ? SelectedTool::MOVE : SelectedTool::SELECT; updateToolbars(); }); connect(ui->actionToolMove, &QAction::triggered, this, [&](bool state) { selectedTool = state ? SelectedTool::MOVE : SelectedTool::SELECT; updateToolbars(); });
@ -82,7 +86,78 @@ MainWindow::MainWindow(QWidget *parent)
delete ui->explorerView->selectionModel(); delete ui->explorerView->selectionModel();
ui->explorerView->reset(); ui->explorerView->reset();
ui->explorerView->setModel(new ExplorerModel(dataModel)); ui->explorerView->setModel(new ExplorerModel(dataModel));
ConnectSelectionChangeHandler(); });
connect(ui->actionDelete, &QAction::triggered, this, [&]() {
for (InstanceRefWeak inst : getSelection()) {
if (inst.expired()) continue;
inst.lock()->SetParent(std::nullopt);
}
setSelection(std::vector<InstanceRefWeak> {});
});
connect(ui->actionCopy, &QAction::triggered, this, [&]() {
pugi::xml_document rootDoc;
for (InstanceRefWeak inst : getSelection()) {
if (inst.expired()) continue;
inst.lock()->Serialize(&rootDoc);
}
std::ostringstream encoded;
rootDoc.save(encoded);
QMimeData* mimeData = new QMimeData;
mimeData->setData("application/xml", QByteArray::fromStdString(encoded.str()));
QApplication::clipboard()->setMimeData(mimeData);
});
connect(ui->actionCut, &QAction::triggered, this, [&]() {
pugi::xml_document rootDoc;
for (InstanceRefWeak inst : getSelection()) {
if (inst.expired()) continue;
inst.lock()->Serialize(&rootDoc);
inst.lock()->SetParent(std::nullopt);
}
std::ostringstream encoded;
rootDoc.save(encoded);
QMimeData* mimeData = new QMimeData;
mimeData->setData("application/xml", QByteArray::fromStdString(encoded.str()));
QApplication::clipboard()->setMimeData(mimeData);
});
connect(ui->actionPaste, &QAction::triggered, this, [&]() {
const QMimeData* mimeData = QApplication::clipboard()->mimeData();
if (!mimeData || !mimeData->hasFormat("application/xml")) return;
QByteArray bytes = mimeData->data("application/xml");
std::string encoded = bytes.toStdString();
pugi::xml_document rootDoc;
rootDoc.load_string(encoded.c_str());
for (pugi::xml_node instNode : rootDoc.children()) {
InstanceRef inst = Instance::Deserialize(&instNode);
workspace()->AddChild(inst);
}
});
connect(ui->actionPasteInto, &QAction::triggered, this, [&]() {
if (getSelection().size() != 1 || getSelection()[0].expired()) return;
InstanceRef selectedParent = getSelection()[0].lock();
const QMimeData* mimeData = QApplication::clipboard()->mimeData();
if (!mimeData || !mimeData->hasFormat("application/xml")) return;
QByteArray bytes = mimeData->data("application/xml");
std::string encoded = bytes.toStdString();
pugi::xml_document rootDoc;
rootDoc.load_string(encoded.c_str());
for (pugi::xml_node instNode : rootDoc.children()) {
InstanceRef inst = Instance::Deserialize(&instNode);
selectedParent->AddChild(inst);
}
}); });
// Update handles // Update handles
@ -127,17 +202,6 @@ MainWindow::MainWindow(QWidget *parent)
syncPartPhysics(ui->mainWidget->lastPart); syncPartPhysics(ui->mainWidget->lastPart);
} }
void MainWindow::ConnectSelectionChangeHandler() {
// connect(ui->explorerView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [&](const QItemSelection &selected, const QItemSelection &deselected) {
// if (selected.count() == 0) return;
// std::optional<InstanceRef> inst = selected.count() == 0 ? std::nullopt
// : std::make_optional(((Instance*)selected.indexes()[0].internalPointer())->shared_from_this());
// ui->propertiesView->setSelected(inst);
// });
}
static std::chrono::time_point lastTime = std::chrono::steady_clock::now(); static std::chrono::time_point lastTime = std::chrono::steady_clock::now();
void MainWindow::timerEvent(QTimerEvent* evt) { void MainWindow::timerEvent(QTimerEvent* evt) {
if (evt->timerId() != timer.timerId()) { if (evt->timerId() != timer.timerId()) {

View file

@ -44,6 +44,5 @@ private:
void updateToolbars(); void updateToolbars();
void timerEvent(QTimerEvent*) override; void timerEvent(QTimerEvent*) override;
void ConnectSelectionChangeHandler();
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

View file

@ -115,6 +115,12 @@
<addaction name="actionToolScale"/> <addaction name="actionToolScale"/>
<addaction name="actionToolRotate"/> <addaction name="actionToolRotate"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionDelete"/>
<addaction name="actionCopy"/>
<addaction name="actionCut"/>
<addaction name="actionPaste"/>
<addaction name="actionPasteInto"/>
<addaction name="separator"/>
<addaction name="actionGridSnap1"/> <addaction name="actionGridSnap1"/>
<addaction name="actionGridSnap05"/> <addaction name="actionGridSnap05"/>
<addaction name="actionGridSnapOff"/> <addaction name="actionGridSnapOff"/>
@ -315,6 +321,91 @@
<enum>QAction::MenuRole::NoRole</enum> <enum>QAction::MenuRole::NoRole</enum>
</property> </property>
</action> </action>
<action name="actionCopy">
<property name="icon">
<iconset theme="edit-copy"/>
</property>
<property name="text">
<string>Copy</string>
</property>
<property name="toolTip">
<string>Copy objects to clipboard</string>
</property>
<property name="shortcut">
<string>Ctrl+C</string>
</property>
<property name="menuRole">
<enum>QAction::MenuRole::NoRole</enum>
</property>
</action>
<action name="actionCut">
<property name="icon">
<iconset theme="edit-cut"/>
</property>
<property name="text">
<string>Cut</string>
</property>
<property name="toolTip">
<string>Cut objects into clipboard</string>
</property>
<property name="shortcut">
<string>Ctrl+X</string>
</property>
<property name="menuRole">
<enum>QAction::MenuRole::NoRole</enum>
</property>
</action>
<action name="actionPaste">
<property name="icon">
<iconset theme="edit-paste"/>
</property>
<property name="text">
<string>Paste</string>
</property>
<property name="toolTip">
<string>Paste objects from clipboard</string>
</property>
<property name="shortcut">
<string>Ctrl+V</string>
</property>
<property name="menuRole">
<enum>QAction::MenuRole::NoRole</enum>
</property>
</action>
<action name="actionPasteInto">
<property name="icon">
<iconset theme="edit-paste"/>
</property>
<property name="text">
<string>Paste Into</string>
</property>
<property name="toolTip">
<string>Paste objects from clipboard into selected object</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+V</string>
</property>
<property name="menuRole">
<enum>QAction::MenuRole::NoRole</enum>
</property>
</action>
<action name="actionDelete">
<property name="icon">
<iconset theme="edit-delete"/>
</property>
<property name="text">
<string>Delete Object</string>
</property>
<property name="toolTip">
<string>Delete selected objects</string>
</property>
<property name="shortcut">
<string>Del</string>
</property>
<property name="menuRole">
<enum>QAction::MenuRole::NoRole</enum>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

View file

@ -1,13 +1,16 @@
#include "explorerview.h" #include "explorerview.h"
#include "explorermodel.h" #include "explorermodel.h"
#include "mainwindow.h"
#include "../ui_mainwindow.h"
#include "common.h" #include "common.h"
#include "objects/base/instance.h" #include "objects/base/instance.h"
#include "objects/workspace.h"
#include "qabstractitemmodel.h" #include "qabstractitemmodel.h"
#include "qaction.h" #include <qaction.h>
#include "qnamespace.h" #include <qnamespace.h>
#include <qitemselectionmodel.h> #include <qitemselectionmodel.h>
#define M_mainWindow dynamic_cast<MainWindow*>(window())
ExplorerView::ExplorerView(QWidget* parent): ExplorerView::ExplorerView(QWidget* parent):
QTreeView(parent), QTreeView(parent),
model(ExplorerModel(std::dynamic_pointer_cast<Instance>(dataModel))) { model(ExplorerModel(std::dynamic_pointer_cast<Instance>(dataModel))) {
@ -57,8 +60,6 @@ ExplorerView::ExplorerView(QWidget* parent):
this->selectionModel()->select(index, QItemSelectionModel::SelectionFlag::Select); this->selectionModel()->select(index, QItemSelectionModel::SelectionFlag::Select);
} }
}); });
buildContextMenu();
} }
ExplorerView::~ExplorerView() { ExplorerView::~ExplorerView() {
@ -67,19 +68,17 @@ ExplorerView::~ExplorerView() {
void ExplorerView::keyPressEvent(QKeyEvent* event) { void ExplorerView::keyPressEvent(QKeyEvent* event) {
switch (event->key()) { switch (event->key()) {
case Qt::Key_Delete: case Qt::Key_Delete:
actionDelete->trigger(); M_mainWindow->ui->actionDelete->trigger();
break; break;
} }
} }
void ExplorerView::buildContextMenu() {
// This will leak memory. Anyway...
contextMenu.addAction(this->actionDelete = new QAction(QIcon("assets/icons/editor/delete"), "Delete"));
connect(actionDelete, &QAction::triggered, this, [&]() { void ExplorerView::buildContextMenu() {
QModelIndexList selectedIndexes = this->selectionModel()->selectedIndexes(); contextMenu.addAction(M_mainWindow->ui->actionDelete);
for (QModelIndex index : selectedIndexes) { contextMenu.addSeparator();
model.fromIndex(index)->SetParent(std::nullopt); contextMenu.addAction(M_mainWindow->ui->actionCopy);
} contextMenu.addAction(M_mainWindow->ui->actionCut);
}); contextMenu.addAction(M_mainWindow->ui->actionPaste);
contextMenu.addAction(M_mainWindow->ui->actionPasteInto);
} }

View file

@ -20,18 +20,9 @@ public:
void keyPressEvent(QKeyEvent*) override; void keyPressEvent(QKeyEvent*) override;
// void dropEvent(QDropEvent*) override; // void dropEvent(QDropEvent*) override;
void buildContextMenu();
private: private:
ExplorerModel model; ExplorerModel model;
QMenu contextMenu; QMenu contextMenu;
// TODO: Move these to a separate top-level namespace so these can be
// accessed from multiple locations
QAction* actionDelete;
QAction* actionCopy;
QAction* actionCut;
QAction* actionPaste;
QAction* actionPasteInto;
QAction* actionSelectChildren;
void buildContextMenu();
}; };