diff --git a/lightpreview/glview.cpp b/lightpreview/glview.cpp index 3f7245b2..ee6c0e12 100644 --- a/lightpreview/glview.cpp +++ b/lightpreview/glview.cpp @@ -900,6 +900,7 @@ void GLView::setCamera(const qvec3d &origin, const qvec3d &fwd) { m_cameraOrigin = {(float)origin[0], (float)origin[1], (float)origin[2]}; m_cameraFwd = {(float)fwd[0], (float)fwd[1], (float)fwd[2]}; + update(); } void GLView::setLighmapOnly(bool lighmapOnly) @@ -1918,4 +1919,9 @@ void GLView::applyFlyMovement(float duration_seconds) qvec3f GLView::cameraPosition() const { return qvec3f{m_cameraOrigin[0], m_cameraOrigin[1], m_cameraOrigin[2]}; +} + +qvec3f GLView::cameraForward() const +{ + return qvec3f{m_cameraFwd[0], m_cameraFwd[1], m_cameraFwd[2]}; } \ No newline at end of file diff --git a/lightpreview/glview.h b/lightpreview/glview.h index e41d1773..17cb3b48 100644 --- a/lightpreview/glview.h +++ b/lightpreview/glview.h @@ -279,4 +279,5 @@ signals: public: qvec3f cameraPosition() const; + qvec3f cameraForward() const; }; diff --git a/lightpreview/mainwindow.cpp b/lightpreview/mainwindow.cpp index 9583f7e1..c56e46d7 100644 --- a/lightpreview/mainwindow.cpp +++ b/lightpreview/mainwindow.cpp @@ -103,6 +103,81 @@ static QStringList GetRecents() return recents; } +// Camera Bookmarks + +static constexpr auto CAMERA_BOOKMARKS_SETTINGS_KEY = "camera_bookmarks"; +static constexpr size_t MAX_CAMERA_BOOKMARKS = 10; + +struct camera_bookmark_t { + qvec3f origin; + qvec3f forward; +}; + +static void ClearCameraBookmarks() +{ + QSettings s; + s.setValue(CAMERA_BOOKMARKS_SETTINGS_KEY, QStringList()); +} + +static QString CameraBookmarkToQString(const camera_bookmark_t &b) { + return QString("%1 %2 %3 %4 %5 %6") + .arg(b.origin[0]) + .arg(b.origin[1]) + .arg(b.origin[2]) + .arg(b.forward[0]) + .arg(b.forward[1]) + .arg(b.forward[2]); +} + +static std::optional CameraBookmarkFromQString(const QString &string) { + QStringList parts = string.split(' ', Qt::SkipEmptyParts); + if (parts.length() != 6) + return std::nullopt; + + camera_bookmark_t result; + result.origin[0] = parts[0].toFloat(); + result.origin[1] = parts[1].toFloat(); + result.origin[2] = parts[2].toFloat(); + + result.forward[0] = parts[3].toFloat(); + result.forward[1] = parts[4].toFloat(); + result.forward[2] = parts[5].toFloat(); + + return {result}; +} + +/** + * Updates the recent camera bookmarks settings by pushing the given camera pos to the front + * and trimming the list to MAX_CAMERA_BOOKMARKS. + */ +static void AddCameraBookmark(const camera_bookmark_t &b) +{ + QSettings s; + QStringList qt_strings = s.value(CAMERA_BOOKMARKS_SETTINGS_KEY).toStringList(); + + qt_strings.push_front(CameraBookmarkToQString(b)); + + while (qt_strings.size() > MAX_CAMERA_BOOKMARKS) { + qt_strings.pop_back(); + } + + s.setValue(CAMERA_BOOKMARKS_SETTINGS_KEY, qt_strings); +} + +static std::vector GetCameraBookmarks() +{ + QSettings s; + QStringList qt_strings = s.value(CAMERA_BOOKMARKS_SETTINGS_KEY).toStringList(); + + std::vector result; + for (const QString &qt_string : qt_strings) { + if (auto parsed = CameraBookmarkFromQString(qt_string); parsed) { + result.push_back(*parsed); + } + } + return result; +} + // ETLogWidget ETLogWidget::ETLogWidget(QWidget *parent) : QTabWidget(parent) @@ -442,6 +517,34 @@ void MainWindow::updateRecentsSubmenu(const QStringList &recents) }); } +void MainWindow::updateCameraBookmarksSubmenu() { + cameraBookmarksMenu->clear(); + + cameraBookmarksMenu->addAction(tr("Bookmark Current Camera Position"), this, [this]() { + camera_bookmark_t b { + .origin = this->glView->cameraPosition(), + .forward = this->glView->cameraForward() + }; + AddCameraBookmark(b); + this->updateCameraBookmarksSubmenu(); + }); + cameraBookmarksMenu->addSeparator(); + + auto bookmarks = GetCameraBookmarks(); + for (const auto &bookmark : bookmarks) { + auto *action = cameraBookmarksMenu->addAction(CameraBookmarkToQString(bookmark)); + connect(action, &QAction::triggered, this, [this, bookmark]() { + this->glView->setCamera(bookmark.origin, bookmark.forward); + }); + } + + cameraBookmarksMenu->addSeparator(); + cameraBookmarksMenu->addAction(tr("Clear Camera Bookmarks"), this, [this]() { + ClearCameraBookmarks(); + this->updateCameraBookmarksSubmenu(); + }); +} + MainWindow::~MainWindow() { } static void OpenHelpFile(const QString &file) { @@ -485,6 +588,8 @@ void MainWindow::setupMenu() // view menu viewMenu = menuBar()->addMenu(tr("&View")); + cameraBookmarksMenu = viewMenu->addMenu(tr("Camera Bookmarks")); + updateCameraBookmarksSubmenu(); // help menu diff --git a/lightpreview/mainwindow.h b/lightpreview/mainwindow.h index 08580e06..b329668b 100644 --- a/lightpreview/mainwindow.h +++ b/lightpreview/mainwindow.h @@ -91,6 +91,7 @@ private: void logWidgetSetText(ETLogTab tab, const std::string &str); void createStatusBar(); void updateRecentsSubmenu(const QStringList &recents); + void updateCameraBookmarksSubmenu(); void setupMenu(); void fileOpen(); void takeScreenshot(); @@ -128,6 +129,7 @@ private: QVBoxLayout *lightstyles = nullptr; QMenu *viewMenu = nullptr; + QMenu *cameraBookmarksMenu = nullptr; QMenu *openRecentMenu = nullptr; ETLogWidget *m_outputLogWidget = nullptr;