From eed83ac85a7193ff6eead9ec527b7aebc600790a Mon Sep 17 00:00:00 2001 From: ksuprynowicz <ksuprynowicz@post.pl> Date: Fri, 22 Jul 2022 23:23:46 +0200 Subject: [PATCH 1/5] Added screenshot format selection with PNG, JPEG and WEBM support --- interface/src/ui/PreferencesDialog.cpp | 22 ++++++++++++ interface/src/ui/Snapshot.cpp | 47 ++++++++++++++++++++++++-- interface/src/ui/Snapshot.h | 46 +++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index adeb0d1dcd..3a3eb0d801 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -258,6 +258,28 @@ void setupPreferences() { preferences->addPreference(new CheckPreference(SNAPSHOTS, "Display snapshot notifications", getter, setter)); } + { + auto getter = []()->int { return DependencyManager::get<Snapshot>()->getAvailableSnapshotFormats().indexOf(DependencyManager::get<Snapshot>()->getSnapshotFormat()); }; + auto setter = [](int value) { DependencyManager::get<Snapshot>()->setSnapshotFormat(DependencyManager::get<Snapshot>()->getAvailableSnapshotFormats()[value]); }; + auto preference = new RadioButtonsPreference(SNAPSHOTS, "Snapshot format", getter, setter); + QStringList items; + items << DependencyManager::get<Snapshot>()->getAvailableSnapshotFormats(); + preference->setHeading("Snapshot format"); + preference->setItems(items); + preferences->addPreference(preference); + } + + { + auto getter = []()->int { return DependencyManager::get<Snapshot>()->getAvailableAnimatedSnapshotFormats().indexOf(DependencyManager::get<Snapshot>()->getAnimatedSnapshotFormat()); }; + auto setter = [](int value) { DependencyManager::get<Snapshot>()->setAnimatedSnapshotFormat(DependencyManager::get<Snapshot>()->getAvailableAnimatedSnapshotFormats()[value]); }; + auto preference = new RadioButtonsPreference(SNAPSHOTS, "Animated snapshot format", getter, setter); + QStringList items; + items << DependencyManager::get<Snapshot>()->getAvailableAnimatedSnapshotFormats(); + preference->setHeading("Animated snapshot format"); + preference->setItems(items); + preferences->addPreference(preference); + } + { auto getter = []()->bool { return !Menu::getInstance()->isOptionChecked(MenuOption::DisableActivityLogger); }; auto setter = [](bool value) { Menu::getInstance()->setIsOptionChecked(MenuOption::DisableActivityLogger, !value); }; diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index e736ed9430..d26eaf8545 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -4,6 +4,7 @@ // // Created by Stojce Slavkovski on 1/26/14. // Copyright 2014 High Fidelity, Inc. +// Copyright 2022 Overte e.V. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -44,12 +45,13 @@ // filename format: overte-snap-by-%username%-on-%date%_%time%_@-%location%.png // %1 <= username, %2 <= date and time, %3 <= current location -const QString FILENAME_PATH_FORMAT = "overte-snap-by-%1-on-%2.png"; +const QString FILENAME_PATH_FORMAT = "overte-snap-by-%1-on-%2"; +const QString DEFAULT_FORMAT = "png"; const QString DATETIME_FORMAT = "yyyy-MM-dd_hh-mm-ss"; const QString SNAPSHOTS_DIRECTORY = "Snapshots"; const QString URL = "overte_url"; static const int SNAPSHOT_360_TIMER_INTERVAL = 350; -static const QList<QString> SUPPORTED_IMAGE_FORMATS = { "jpg", "jpeg", "png" }; +static const QList<QString> SUPPORTED_IMAGE_FORMATS = { "jpg", "jpeg", "png", "webp" }; Snapshot::Snapshot() { _snapshotTimer.setSingleShot(false); @@ -110,6 +112,7 @@ QString Snapshot::saveSnapshot(QImage image, const QString& filename, const QStr return ""; } + static const float CUBEMAP_SIDE_PIXEL_DIMENSION = 2048.0f; static const float SNAPSHOT_360_FOV = 90.0f; static const float SNAPSHOT_360_NEARCLIP = 0.3f; @@ -389,7 +392,11 @@ QFile* Snapshot::savedFileForSnapshot(QImage& shot, imageQuality = 50; } } else { - filename = FILENAME_PATH_FORMAT.arg(username, now.toString(DATETIME_FORMAT)); + QString selectedFormat(DEFAULT_FORMAT); + if (_snapshotFormat.get() != "") { + selectedFormat = _snapshotFormat.get(); + } + filename = FILENAME_PATH_FORMAT.arg(username, now.toString(DATETIME_FORMAT)) + "." + selectedFormat; QFileInfo snapshotFileInfo(filename); QString filenameSuffix = snapshotFileInfo.suffix(); filenameSuffix = filenameSuffix.toLower(); @@ -516,3 +523,37 @@ QString Snapshot::getSnapshotsLocation() { void Snapshot::setSnapshotsLocation(const QString& location) { _snapshotsLocation.set(location); } + +QString Snapshot::getSnapshotFormat(){ + return _snapshotFormat.get(); +} + +void Snapshot::setSnapshotFormat(const QString& format){ + if (getAvailableSnapshotFormats().contains(format)) { + _snapshotFormat.set(format); + qDebug() << "Snapshot format set: " << format; + } else { + qDebug() << "Snapshot format not supported: " << format; + } +} + +QString Snapshot::getAnimatedSnapshotFormat(){ + return _animatedSnapshotFormat.get(); +} + +void Snapshot::setAnimatedSnapshotFormat(const QString& format){ + if (getAvailableAnimatedSnapshotFormats().contains(format)) { + _animatedSnapshotFormat.set(format); + qDebug() << "Snapshot format set: " << format; + } else { + qDebug() << "Snapshot format not supported: " << format; + } +} + +QStringList Snapshot::getAvailableSnapshotFormats() { + return QStringList({"png", "jpg", "webp"}); +} + +QStringList Snapshot::getAvailableAnimatedSnapshotFormats() { + return QStringList({"gif"}); +} diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index f6c57b0e42..ad55186be4 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -65,6 +65,8 @@ public: Setting::Handle<QString> _snapshotsLocation{ "snapshotsLocation" }; Setting::Handle<bool> _snapshotNotifications{ "snapshotNotifications", true }; + Setting::Handle<QString> _snapshotFormat{ "snapshotFormat" }; + Setting::Handle<QString> _animatedSnapshotFormat{ "animatedSnapshotFormat" }; void uploadSnapshot(const QString& filename, const QUrl& href = QUrl("")); signals: @@ -97,6 +99,50 @@ public slots: * @param {String} location - The path to save snapshots to. */ Q_INVOKABLE void setSnapshotsLocation(const QString& location); + + /*@jsdoc + * Gets the currently selected snapshot format. + * @function Snapshot.getSnapshotFormat + * @returns {string} Currently selected snapshot format. + */ + Q_INVOKABLE QString getSnapshotFormat(); + + /*@jsdoc + * Sets the snapshot format. + * @function Snapshot.setSnapshotFormat + * @param {String} format - one of the format names returned by Snapshot.getAvailableSnapshotFormats(). + */ + Q_INVOKABLE void setSnapshotFormat(const QString& format); + + /*@jsdoc + * Gets the currently selected animated snapshot format. + * @function Snapshot.getAnimatedSnapshotFormat + * @returns {Array.<string>} Currently selected snapshot format. + */ + Q_INVOKABLE QString getAnimatedSnapshotFormat(); + + /*@jsdoc + * Sets the snapshot format. + * @function Snapshot.setAnimatedSnapshotFormat + * @param {String} format - one of the format names returned by Snapshot.getAvailableSnapshotFormats(). + */ + Q_INVOKABLE void setAnimatedSnapshotFormat(const QString& format); + + /*@jsdoc + * Returns a list of supported snapshot formats. + * @function Snapshot.getAvailableSnapshotFormats + * @returns {Array.<string>} List of supported snapshot formats. + */ + Q_INVOKABLE QStringList getAvailableSnapshotFormats(); + + /*@jsdoc + * Returns a list of supported animated snapshot formats. + * @function Snapshot.getAvailableAnimatedSnapshotFormats + * @returns {Array.<string>} List of supported animated snapshot formats. + */ + Q_INVOKABLE QStringList getAvailableAnimatedSnapshotFormats(); + + private slots: void takeNextSnapshot(); From c2572000e2788c96b9d5ca859fb3696522d30654 Mon Sep 17 00:00:00 2001 From: ksuprynowicz <ksuprynowicz@post.pl> Date: Fri, 22 Jul 2022 23:37:11 +0200 Subject: [PATCH 2/5] Removed excessive debug messages --- interface/src/ui/Snapshot.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index d26eaf8545..aaffbade3c 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -531,7 +531,6 @@ QString Snapshot::getSnapshotFormat(){ void Snapshot::setSnapshotFormat(const QString& format){ if (getAvailableSnapshotFormats().contains(format)) { _snapshotFormat.set(format); - qDebug() << "Snapshot format set: " << format; } else { qDebug() << "Snapshot format not supported: " << format; } @@ -544,7 +543,6 @@ QString Snapshot::getAnimatedSnapshotFormat(){ void Snapshot::setAnimatedSnapshotFormat(const QString& format){ if (getAvailableAnimatedSnapshotFormats().contains(format)) { _animatedSnapshotFormat.set(format); - qDebug() << "Snapshot format set: " << format; } else { qDebug() << "Snapshot format not supported: " << format; } From df56e047f300ea9e0ad8595c077bbd436d0a85bb Mon Sep 17 00:00:00 2001 From: ksuprynowicz <ksuprynowicz@post.pl> Date: Sat, 30 Jul 2022 16:24:45 +0200 Subject: [PATCH 3/5] Reordered snapshot options --- interface/src/ui/PreferencesDialog.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 3a3eb0d801..36df5c93f4 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -238,15 +238,6 @@ void setupPreferences() { auto preference = new BrowsePreference(SNAPSHOTS, "Put my snapshots here", getter, setter); preferences->addPreference(preference); } - { - auto getter = []()->float { return SnapshotAnimated::snapshotAnimatedDuration.get(); }; - auto setter = [](float value) { SnapshotAnimated::snapshotAnimatedDuration.set(value); }; - auto preference = new SpinnerPreference(SNAPSHOTS, "Animated Snapshot Duration", getter, setter); - preference->setMin(1); - preference->setMax(5); - preference->setStep(1); - preferences->addPreference(preference); - } { auto getter = []()->bool { @@ -280,6 +271,16 @@ void setupPreferences() { preferences->addPreference(preference); } + { + auto getter = []()->float { return SnapshotAnimated::snapshotAnimatedDuration.get(); }; + auto setter = [](float value) { SnapshotAnimated::snapshotAnimatedDuration.set(value); }; + auto preference = new SpinnerPreference(SNAPSHOTS, "Animated Snapshot Duration", getter, setter); + preference->setMin(1); + preference->setMax(5); + preference->setStep(1); + preferences->addPreference(preference); + } + { auto getter = []()->bool { return !Menu::getInstance()->isOptionChecked(MenuOption::DisableActivityLogger); }; auto setter = [](bool value) { Menu::getInstance()->setIsOptionChecked(MenuOption::DisableActivityLogger, !value); }; From 0ca8545c203e91fc6669878a98148db2ffb82c1d Mon Sep 17 00:00:00 2001 From: SilverfishVR <53531160+SilverfishVR@users.noreply.github.com> Date: Thu, 1 Sep 2022 22:23:07 +0200 Subject: [PATCH 4/5] Update API docs to reflect changes --- .../src/scripting/WindowScriptingInterface.h | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 3b54112f6c..0167ec0035 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -334,9 +334,9 @@ public slots: * dimensions is adjusted in order to match the aspect ratio. * @param {string} [filename=""] - If a filename is not provided, the image is saved as "overte-snap-by-<user * name>-on-YYYY-MM-DD_HH-MM-SS". - * <p>Still images are saved in JPEG or PNG format according to the extension provided — <code>".jpg"</code>, - * <code>".jpeg"</code>, or <code>".png"</code> — or if not provided then in JPEG format with an extension of - * <code>".jpg"</code>. Animated images are saved in GIF format.</p> + * <p>Still images are saved in JPEG, PNG or WEBP format according to the extension provided — <code>".jpg"</code>, + * <code>".jpeg"</code>, <code>".png"</code>, or <code>".webp"</code> — or if not provided then in the format chosen in general settings, + * Default is PNG. Animated images are saved in GIF format.</p> * * @example <caption>Using the snapshot function and signals.</caption> * function onStillSnapshotTaken(path, notify) { @@ -371,11 +371,11 @@ public slots: * @function Window.takeSecondaryCameraSnapshot * @param {boolean} [notify=true] - This value is passed on through the {@link Window.stillSnapshotTaken|stillSnapshotTaken} * signal. - * @param {string} [filename=""] - If a filename is not provided, the image is saved as "overte-snap-by-<user + * @param {string} [filename=""] - If a filename is not provided, the image is saved as "overte-snap-by-<user * name>-on-YYYY-MM-DD_HH-MM-SS". - * <p>Images are saved in JPEG or PNG format according to the extension provided — <code>".jpg"</code>, - * <code>".jpeg"</code>, or <code>".png"</code> — or if not provided then in JPEG format with an extension of - * <code>".jpg"</code>.</p> + * <p>Still images are saved in JPEG, PNG or WEBP format according to the extension provided — <code>".jpg"</code>, + * <code>".jpeg"</code>, <code>".png"</code>, or <code>".webp"</code> — or if not provided then in the format chosen in general settings, + * Default is PNG. Animated images are saved in GIF format.</p> */ void takeSecondaryCameraSnapshot(const bool& notify = true, const QString& filename = QString()); @@ -390,11 +390,11 @@ public slots: * otherwise it is saved as an equirectangular image. * @param {boolean} [notify=true] - This value is passed on through the {@link Window.stillSnapshotTaken|stillSnapshotTaken} * signal. - * @param {string} [filename=""] - If a filename is not provided, the image is saved as "overte-snap-by-<user + * @param {string} [filename=""] - If a filename is not provided, the image is saved as "overte-snap-by-<user * name>-on-YYYY-MM-DD_HH-MM-SS". - * <p>Images are saved in JPEG or PNG format according to the extension provided — <code>".jpg"</code>, - * <code>".jpeg"</code>, or <code>".png"</code> — or if not provided then in JPEG format with an extension of - * <code>".jpg"</code>.</p> + * <p>Still images are saved in JPEG, PNG or WEBP format according to the extension provided — <code>".jpg"</code>, + * <code>".jpeg"</code>, <code>".png"</code>, or <code>".webp"</code> — or if not provided then in the format chosen in general settings, + * Default is PNG. Animated images are saved in GIF format.</p> */ void takeSecondaryCamera360Snapshot(const glm::vec3& cameraPosition, const bool& cubemapOutputFormat = false, const bool& notify = true, const QString& filename = QString()); From ad8da103b4055b6412d84a1071b88f78d79edf07 Mon Sep 17 00:00:00 2001 From: ksuprynowicz <ksuprynowicz@post.pl> Date: Sun, 11 Sep 2022 15:55:30 +0200 Subject: [PATCH 5/5] Fixed default preference selection bug for screenshot formats and added short descriptions --- interface/src/ui/PreferencesDialog.cpp | 16 ++++++++++++---- interface/src/ui/Snapshot.cpp | 8 ++++++++ interface/src/ui/Snapshot.h | 14 ++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 36df5c93f4..6d13f586d4 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -250,22 +250,30 @@ void setupPreferences() { } { - auto getter = []()->int { return DependencyManager::get<Snapshot>()->getAvailableSnapshotFormats().indexOf(DependencyManager::get<Snapshot>()->getSnapshotFormat()); }; + auto getter = []()->int { + if (!DependencyManager::get<Snapshot>()->_snapshotFormat.isSet()) { + DependencyManager::get<Snapshot>()->setSnapshotFormat(DependencyManager::get<Snapshot>()->getAvailableSnapshotFormats()[0]); + } + return DependencyManager::get<Snapshot>()->getAvailableSnapshotFormats().indexOf(DependencyManager::get<Snapshot>()->getSnapshotFormat()); }; auto setter = [](int value) { DependencyManager::get<Snapshot>()->setSnapshotFormat(DependencyManager::get<Snapshot>()->getAvailableSnapshotFormats()[value]); }; auto preference = new RadioButtonsPreference(SNAPSHOTS, "Snapshot format", getter, setter); QStringList items; - items << DependencyManager::get<Snapshot>()->getAvailableSnapshotFormats(); + items << DependencyManager::get<Snapshot>()->getAvailableSnapshotFormatsWithDescriptions(); preference->setHeading("Snapshot format"); preference->setItems(items); preferences->addPreference(preference); } { - auto getter = []()->int { return DependencyManager::get<Snapshot>()->getAvailableAnimatedSnapshotFormats().indexOf(DependencyManager::get<Snapshot>()->getAnimatedSnapshotFormat()); }; + auto getter = []()->int { + if (!DependencyManager::get<Snapshot>()->_animatedSnapshotFormat.isSet()) { + DependencyManager::get<Snapshot>()->setAnimatedSnapshotFormat(DependencyManager::get<Snapshot>()->getAvailableAnimatedSnapshotFormats()[0]); + } + return DependencyManager::get<Snapshot>()->getAvailableAnimatedSnapshotFormats().indexOf(DependencyManager::get<Snapshot>()->getAnimatedSnapshotFormat()); }; auto setter = [](int value) { DependencyManager::get<Snapshot>()->setAnimatedSnapshotFormat(DependencyManager::get<Snapshot>()->getAvailableAnimatedSnapshotFormats()[value]); }; auto preference = new RadioButtonsPreference(SNAPSHOTS, "Animated snapshot format", getter, setter); QStringList items; - items << DependencyManager::get<Snapshot>()->getAvailableAnimatedSnapshotFormats(); + items << DependencyManager::get<Snapshot>()->getAvailableAnimatedSnapshotFormatsWithDescriptions(); preference->setHeading("Animated snapshot format"); preference->setItems(items); preferences->addPreference(preference); diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index aaffbade3c..2884574767 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -552,6 +552,14 @@ QStringList Snapshot::getAvailableSnapshotFormats() { return QStringList({"png", "jpg", "webp"}); } +QStringList Snapshot::getAvailableSnapshotFormatsWithDescriptions() { + return QStringList({"PNG - lossless, large file size", "JPG - lossy, fast compression", "WEBP - lossy, higher quality and file size than JPG"}); +} + QStringList Snapshot::getAvailableAnimatedSnapshotFormats() { return QStringList({"gif"}); } + +QStringList Snapshot::getAvailableAnimatedSnapshotFormatsWithDescriptions() { + return QStringList({"GIF"}); +} diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index ad55186be4..61af735af7 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -135,12 +135,26 @@ public slots: */ Q_INVOKABLE QStringList getAvailableSnapshotFormats(); + /*@jsdoc + * Returns a list of supported snapshot formats with short descriptions. + * @function Snapshot.getAvailableSnapshotFormatsWithDescriptions + * @returns {Array.<string>} List of supported snapshot formats with short descriptions. + */ + Q_INVOKABLE QStringList getAvailableSnapshotFormatsWithDescriptions(); + /*@jsdoc * Returns a list of supported animated snapshot formats. * @function Snapshot.getAvailableAnimatedSnapshotFormats * @returns {Array.<string>} List of supported animated snapshot formats. */ Q_INVOKABLE QStringList getAvailableAnimatedSnapshotFormats(); + + /*@jsdoc + * Returns a list of supported animated snapshot formats with short descriptions. + * @function Snapshot.getAvailableAnimatedSnapshotFormatsWithDescriptions + * @returns {Array.<string>} List of supported animated snapshot formats with short descriptions. + */ + Q_INVOKABLE QStringList getAvailableAnimatedSnapshotFormatsWithDescriptions();