From 218b26b5213cd1bc8af041064b4d5e82644e7334 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 1 Jul 2016 10:58:55 -0700 Subject: [PATCH 1/7] removed snapshot share dialog, ctrl s shouldn't leave you moving --- .../qml/hifi/dialogs/SnapshotShareDialog.qml | 117 ------------------ interface/src/Application.cpp | 12 +- interface/src/ui/Snapshot.cpp | 115 ----------------- interface/src/ui/Snapshot.h | 8 -- interface/src/ui/SnapshotShareDialog.cpp | 47 ------- .../src/input-plugins/KeyboardMouseDevice.cpp | 8 +- 6 files changed, 6 insertions(+), 301 deletions(-) delete mode 100644 interface/resources/qml/hifi/dialogs/SnapshotShareDialog.qml delete mode 100644 interface/src/ui/SnapshotShareDialog.cpp diff --git a/interface/resources/qml/hifi/dialogs/SnapshotShareDialog.qml b/interface/resources/qml/hifi/dialogs/SnapshotShareDialog.qml deleted file mode 100644 index f99b770a78..0000000000 --- a/interface/resources/qml/hifi/dialogs/SnapshotShareDialog.qml +++ /dev/null @@ -1,117 +0,0 @@ -import QtQuick 2.5 -import QtQuick.Controls 1.4 -import QtQuick.Controls.Styles 1.4 -import QtQuick.XmlListModel 2.0 - -import "../../windows" -import "../../js/Utils.js" as Utils -import "../models" - -Window { - id: root - resizable: true - width: 516 - height: 616 - minSize: Qt.vector2d(500, 600); - maxSize: Qt.vector2d(1000, 800); - - property alias source: image.source - - Rectangle { - anchors.fill: parent - color: "white" - - Item { - anchors { fill: parent; margins: 8 } - - Image { - id: image - anchors { top: parent.top; left: parent.left; right: parent.right; bottom: notesLabel.top; bottomMargin: 8 } - fillMode: Image.PreserveAspectFit - } - - Text { - id: notesLabel - anchors { left: parent.left; bottom: notes.top; bottomMargin: 8; } - text: "Notes about this image" - font.pointSize: 14 - font.bold: true - color: "#666" - } - - TextArea { - id: notes - anchors { left: parent.left; bottom: parent.bottom; right: shareButton.left; rightMargin: 8 } - height: 60 - } - - Button { - id: shareButton - anchors { verticalCenter: notes.verticalCenter; right: parent.right; } - width: 120; height: 50 - text: "Share" - - style: ButtonStyle { - background: Rectangle { - implicitWidth: 120 - implicitHeight: 50 - border.width: control.activeFocus ? 2 : 1 - color: "#333" - radius: 9 - } - label: Text { - color: shareButton.enabled ? "white" : "gray" - font.pixelSize: 18 - font.bold: true - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - anchors.fill: parent - text: shareButton.text - } - } - - onClicked: { - enabled = false; - uploadTimer.start(); - } - - Timer { - id: uploadTimer - running: false - interval: 5 - repeat: false - onTriggered: { - var uploaded = SnapshotUploader.uploadSnapshot(root.source.toString()) - console.log("Uploaded result " + uploaded) - if (!uploaded) { - console.log("Upload failed "); - } - } - } - } - } - - Action { - id: shareAction - text: qsTr("OK") - enabled: root.result ? true : false - shortcut: Qt.Key_Return - onTriggered: { - root.destroy(); - } - } - - Action { - id: cancelAction - text: qsTr("Cancel") - shortcut: Qt.Key_Escape - onTriggered: { - root.destroy(); - } - } - } -} - - - - diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1c9ec94dc4..9d177d724d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1517,7 +1517,6 @@ void Application::initializeUi() { // For some reason there is already an "Application" object in the QML context, // though I can't find it. Hence, "ApplicationInterface" - rootContext->setContextProperty("SnapshotUploader", new SnapshotUploader()); rootContext->setContextProperty("ApplicationInterface", this); rootContext->setContextProperty("Audio", &AudioScriptingInterface::getInstance()); rootContext->setContextProperty("Controller", DependencyManager::get().data()); @@ -4989,16 +4988,7 @@ void Application::takeSnapshot() { player->setMedia(QUrl::fromLocalFile(inf.absoluteFilePath())); player->play(); - QString fileName = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot()); - - auto accountManager = DependencyManager::get(); - if (!accountManager->isLoggedIn()) { - return; - } - - DependencyManager::get()->load("hifi/dialogs/SnapshotShareDialog.qml", [=](QQmlContext*, QObject* dialog) { - dialog->setProperty("source", QUrl::fromLocalFile(fileName)); - }); + Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot()); } float Application::getRenderResolutionScale() const { diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index b8be2bb8c4..a3af742f92 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -133,118 +133,3 @@ QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary) { return imageTempFile; } } - -const QString FORUM_URL = "https://alphas.highfidelity.io"; -const QString FORUM_UPLOADS_URL = FORUM_URL + "/uploads"; -const QString FORUM_POST_URL = FORUM_URL + "/posts"; -const QString FORUM_REPLY_TO_TOPIC = "244"; -const QString FORUM_POST_TEMPLATE = "

%2

"; -const QString SHARE_DEFAULT_ERROR = "The server isn't responding. Please try again in a few minutes."; -const QString SUCCESS_LABEL_TEMPLATE = "Success!!! Go check out your image ...
%1"; - - -QString SnapshotUploader::uploadSnapshot(const QUrl& fileUrl) { - auto accountManager = DependencyManager::get(); - if (accountManager->getAccountInfo().getDiscourseApiKey().isEmpty()) { - OffscreenUi::warning(nullptr, "", "Your Discourse API key is missing, you cannot share snapshots. Please try to relog."); - return QString(); - } - - QHttpPart apiKeyPart; - apiKeyPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"api_key\"")); - apiKeyPart.setBody(accountManager->getAccountInfo().getDiscourseApiKey().toLatin1()); - - QString filename = fileUrl.toLocalFile(); - qDebug() << filename; - QFile* file = new QFile(filename); - Q_ASSERT(file->exists()); - file->open(QIODevice::ReadOnly); - - QHttpPart imagePart; - imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); - imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, - QVariant("form-data; name=\"file\"; filename=\"" + file->fileName() + "\"")); - imagePart.setBodyDevice(file); - - QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); - file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart - multiPart->append(apiKeyPart); - multiPart->append(imagePart); - - QUrl url(FORUM_UPLOADS_URL); - QNetworkRequest request(url); - request.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); - - QString result; - QEventLoop loop; - - QSharedPointer reply(NetworkAccessManager::getInstance().post(request, multiPart)); - QObject::connect(reply.data(), &QNetworkReply::finished, [&] { - loop.quit(); - - qDebug() << reply->errorString(); - for (const auto& header : reply->rawHeaderList()) { - qDebug() << "Header " << QString(header); - } - auto replyResult = reply->readAll(); - qDebug() << QString(replyResult); - QJsonDocument jsonResponse = QJsonDocument::fromJson(replyResult); - const QJsonObject& responseObject = jsonResponse.object(); - if (!responseObject.contains("url")) { - OffscreenUi::warning(this, "", SHARE_DEFAULT_ERROR); - return; - } - result = responseObject["url"].toString(); - }); - loop.exec(); - return result; -} - -QString SnapshotUploader::sendForumPost(const QString& snapshotPath, const QString& notes) { - // post to Discourse forum - QNetworkRequest request; - request.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); - QUrl forumUrl(FORUM_POST_URL); - - QUrlQuery query; - query.addQueryItem("api_key", DependencyManager::get()->getAccountInfo().getDiscourseApiKey()); - query.addQueryItem("topic_id", FORUM_REPLY_TO_TOPIC); - query.addQueryItem("raw", FORUM_POST_TEMPLATE.arg(snapshotPath, notes)); - forumUrl.setQuery(query); - - QByteArray postData = forumUrl.toEncoded(QUrl::RemoveFragment); - request.setUrl(forumUrl); - request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); - - QNetworkReply* requestReply = NetworkAccessManager::getInstance().post(request, postData); - - QEventLoop loop; - QString result; - connect(requestReply, &QNetworkReply::finished, [&] { - loop.quit(); - QJsonDocument jsonResponse = QJsonDocument::fromJson(requestReply->readAll()); - requestReply->deleteLater(); - const QJsonObject& responseObject = jsonResponse.object(); - - if (!responseObject.contains("id")) { - QString errorMessage(SHARE_DEFAULT_ERROR); - if (responseObject.contains("errors")) { - QJsonArray errorArray = responseObject["errors"].toArray(); - if (!errorArray.first().toString().isEmpty()) { - errorMessage = errorArray.first().toString(); - } - } - OffscreenUi::warning(this, "", errorMessage); - return; - } - - const QString urlTemplate = "%1/t/%2/%3/%4"; - result = urlTemplate.arg(FORUM_URL, - responseObject["topic_slug"].toString(), - QString::number(responseObject["topic_id"].toDouble()), - QString::number(responseObject["post_number"].toDouble())); - }); - loop.exec(); - return result; -} - diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index d87a70255f..5856743141 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -43,12 +43,4 @@ private: static QFile* savedFileForSnapshot(QImage & image, bool isTemporary); }; -class SnapshotUploader : public QObject{ - Q_OBJECT -public: - SnapshotUploader(QObject* parent = nullptr) : QObject(parent) {} - Q_INVOKABLE QString uploadSnapshot(const QUrl& fileUrl); - Q_INVOKABLE QString sendForumPost(const QString& snapshotPath, const QString& notes); -}; - #endif // hifi_Snapshot_h diff --git a/interface/src/ui/SnapshotShareDialog.cpp b/interface/src/ui/SnapshotShareDialog.cpp deleted file mode 100644 index 94f89641e2..0000000000 --- a/interface/src/ui/SnapshotShareDialog.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// -// SnapshotShareDialog.cpp -// interface/src/ui -// -// Created by Stojce Slavkovski on 2/16/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#if 0 - - -#include - -const int NARROW_SNAPSHOT_DIALOG_SIZE = 500; -const int WIDE_SNAPSHOT_DIALOG_WIDTH = 650; -const int SUCCESS_LABEL_HEIGHT = 140; - -const QString SHARE_BUTTON_STYLE = "border-width:0;border-radius:9px;border-radius:9px;font-family:Arial;font-size:18px;" - "font-weight:100;color:#FFFFFF;width: 120px;height: 50px;"; -const QString SHARE_BUTTON_ENABLED_STYLE = "background-color: #333;"; -const QString SHARE_BUTTON_DISABLED_STYLE = "background-color: #999;"; - -Q_DECLARE_METATYPE(QNetworkAccessManager::Operation) - -SnapshotShareDialog::SnapshotShareDialog(QString fileName, QWidget* parent) : - QDialog(parent), - _fileName(fileName) -{ - - - _ui.snapshotWidget->setPixmap(snaphsotPixmap); - _ui.snapshotWidget->adjustSize(); -} - -void SnapshotShareDialog::accept() { - // prevent multiple clicks on share button - _ui.shareButton->setEnabled(false); - // gray out share button - _ui.shareButton->setStyleSheet(SHARE_BUTTON_STYLE + SHARE_BUTTON_DISABLED_STYLE); - uploadSnapshot(); -} - - -#endif diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index 915ec1db87..ebe80f12cf 100644 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -49,9 +49,11 @@ void KeyboardMouseDevice::InputDevice::focusOutEvent() { void KeyboardMouseDevice::keyPressEvent(QKeyEvent* event) { auto input = _inputDevice->makeInput((Qt::Key) event->key()); - auto result = _inputDevice->_buttonPressedMap.insert(input.getChannel()); - if (!result.second) { - // key pressed again ? without catching the release event ? + if (!(event->modifiers() & Qt::KeyboardModifier::ControlModifier)) { + auto result = _inputDevice->_buttonPressedMap.insert(input.getChannel()); + if (result.second) { + // key pressed again ? without catching the release event ? + } } } From 04184ee1fba636a42e6844334d6b7e11980c5cc4 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 5 Jul 2016 17:21:57 -0700 Subject: [PATCH 2/7] added snapshot notification in desktop mode --- interface/src/Application.cpp | 4 +- .../src/scripting/WindowScriptingInterface.h | 1 + scripts/system/notifications.js | 83 +++++++++++-------- 3 files changed, 53 insertions(+), 35 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9d177d724d..d00c966da1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4988,7 +4988,9 @@ void Application::takeSnapshot() { player->setMedia(QUrl::fromLocalFile(inf.absoluteFilePath())); player->play(); - Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot()); + QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot()); + + emit DependencyManager::get()->snapshotTaken(path); } float Application::getRenderResolutionScale() const { diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index b92114c1bf..4f26ccd057 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -46,6 +46,7 @@ signals: void domainChanged(const QString& domainHostname); void svoImportRequested(const QString& url); void domainConnectionRefused(const QString& reasonMessage, int reasonCode); + void snapshotTaken(const QString& path); private slots: WebWindowClass* doCreateWebWindow(const QString& title, const QString& url, int width, int height); diff --git a/scripts/system/notifications.js b/scripts/system/notifications.js index 7d97470b8a..667d87271d 100644 --- a/scripts/system/notifications.js +++ b/scripts/system/notifications.js @@ -49,10 +49,10 @@ // 2. Declare a text string. // 3. Call createNotifications(text, NotificationType) parsing the text. // example: -// if (key.text === "s") { +// if (key.text === "o") { // if (ctrlIsPressed === true) { -// noteString = "Snapshot taken."; -// createNotification(noteString, NotificationType.SNAPSHOT); +// noteString = "Open script"; +// createNotification(noteString, NotificationType.OPEN_SCRIPT); // } // } @@ -233,8 +233,9 @@ function calculate3DOverlayPositions(noticeWidth, noticeHeight, y) { // Pushes data to each array and sets up data for 2nd dimension array // to handle auxiliary data not carried by the overlay class // specifically notification "heights", "times" of creation, and . -function notify(notice, button, height) { - var noticeWidth, +function notify(notice, button, height, imageProperties, image) { + var notificationText, + noticeWidth, noticeHeight, positions, last; @@ -269,9 +270,13 @@ function notify(notice, button, height) { height: noticeHeight }); } else { - var notificationText = Overlays.addOverlay("text", notice); - notifications.push((notificationText)); - buttons.push((Overlays.addOverlay("image", button))); + if (!image) { + notificationText = Overlays.addOverlay("text", notice); + notifications.push((notificationText)); + } else { + notifications.push(Overlays.addOverlay("image", notice)); + } + buttons.push(Overlays.addOverlay("image", button)); } height = height + 1.0; @@ -281,11 +286,24 @@ function notify(notice, button, height) { last = notifications.length - 1; createArrays(notifications[last], buttons[last], times[last], heights[last], myAlpha[last]); fadeIn(notifications[last], buttons[last]); + + if (imageProperties && !image) { + var imageHeight = notice.width / imageProperties.aspectRatio; + notice = { + x: notice.x, + y: notice.y + height, + width: notice.width, + height: imageHeight, + imageURL: imageProperties.path + }; + notify(notice, button, imageHeight, imageProperties, true); + } + return notificationText; } // This function creates and sizes the overlays -function createNotification(text, notificationType) { +function createNotification(text, notificationType, imageProperties) { var count = (text.match(/\n/g) || []).length, breakPoint = 43.0, // length when new line is added extraLine = 0, @@ -308,6 +326,11 @@ function createNotification(text, notificationType) { level = (stack + 20.0); height = height + extraLine; + + if (imageProperties && imageProperties.path) { + imageProperties.path = Script.resolvePath(imageProperties.path); + } + noticeProperties = { x: overlayLocationX, y: level, @@ -336,12 +359,11 @@ function createNotification(text, notificationType) { }; if (Menu.isOptionChecked(PLAY_NOTIFICATION_SOUNDS_MENU_ITEM) && - Menu.isOptionChecked(NotificationType.getMenuString(notificationType))) - { + Menu.isOptionChecked(NotificationType.getMenuString(notificationType))) { randomSounds.playRandom(); } - return notify(noticeProperties, buttonProperties, height); + return notify(noticeProperties, buttonProperties, height, imageProperties); } function deleteNotification(index) { @@ -362,21 +384,12 @@ function deleteNotification(index) { // wraps whole word to newline function stringDivider(str, slotWidth, spaceReplacer) { - var p, - left, - right; + var left, right; - if (str.length > slotWidth) { - p = slotWidth; - while (p > 0 && str[p] !== ' ') { - p -= 1; - } - - if (p > 0) { - left = str.substring(0, p); - right = str.substring(p + 1); - return left + spaceReplacer + stringDivider(right, slotWidth, spaceReplacer); - } + if (str.length > slotWidth && slotWidth > 0) { + left = str.substring(0, slotWidth); + right = str.substring(slotWidth + 1); + return left + spaceReplacer + stringDivider(right, slotWidth, spaceReplacer); } return str; } @@ -504,7 +517,15 @@ function onMuteStateChanged() { } function onDomainConnectionRefused(reason) { - createNotification("Connection refused: " + reason, NotificationType.CONNECTION_REFUSED ); + createNotification("Connection refused: " + reason, NotificationType.CONNECTION_REFUSED); +} + +function onSnapshotTaken(path) { + var imageProperties = { + path: path, + aspectRatio: Window.innerWidth / Window.innerHeight + } + createNotification(wordWrap("Snapshot saved to " + path), NotificationType.SNAPSHOT, imageProperties); } // handles mouse clicks on buttons @@ -541,13 +562,6 @@ function keyPressEvent(key) { if (key.key === 16777249) { ctrlIsPressed = true; } - - if (key.text === "s") { - if (ctrlIsPressed === true) { - noteString = "Snapshot taken."; - createNotification(noteString, NotificationType.SNAPSHOT); - } - } } function setup() { @@ -615,5 +629,6 @@ Script.update.connect(update); Script.scriptEnding.connect(scriptEnding); Menu.menuItemEvent.connect(menuItemEvent); Window.domainConnectionRefused.connect(onDomainConnectionRefused); +Window.snapshotTaken.connect(onSnapshotTaken); setup(); From 4eb94f8ccbd48d6b86f2ca23945c34fea2122d8e Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 5 Jul 2016 17:40:33 -0700 Subject: [PATCH 3/7] added support for snapshot notification in HMD, although 3d image overlays seem to be broken in master --- scripts/system/notifications.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/scripts/system/notifications.js b/scripts/system/notifications.js index 667d87271d..988d2998d7 100644 --- a/scripts/system/notifications.js +++ b/scripts/system/notifications.js @@ -251,16 +251,23 @@ function notify(notice, button, height, imageProperties, image) { notice.leftMargin = 2 * notice.leftMargin * NOTIFICATION_3D_SCALE; notice.bottomMargin = 0; notice.rightMargin = 0; - notice.lineHeight = 10.0 * (fontSize / 12.0) * NOTIFICATION_3D_SCALE; - notice.isFacingAvatar = false; + + positions = calculate3DOverlayPositions(noticeWidth, noticeHeight, notice.y); + + if (!image) { + notice.lineHeight = 10.0 * (fontSize / 12.0) * NOTIFICATION_3D_SCALE; + notice.isFacingAvatar = false; + + notificationText = Overlays.addOverlay("text3d", notice); + notifications.push(notificationText); + } else { + notifications.push(Overlays.addOverlay("image3d", notice)); + } button.url = button.imageURL; button.scale = button.width * NOTIFICATION_3D_SCALE; button.isFacingAvatar = false; - positions = calculate3DOverlayPositions(noticeWidth, noticeHeight, notice.y); - - notifications.push((Overlays.addOverlay("text3d", notice))); buttons.push((Overlays.addOverlay("image3d", button))); overlay3DDetails.push({ notificationOrientation: positions.notificationOrientation, @@ -294,6 +301,8 @@ function notify(notice, button, height, imageProperties, image) { y: notice.y + height, width: notice.width, height: imageHeight, + topMargin: 0, + leftMargin: 0, imageURL: imageProperties.path }; notify(notice, button, imageHeight, imageProperties, true); From b3513b543c50899edc63c9fda74bd386e4916e27 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 5 Jul 2016 18:23:59 -0700 Subject: [PATCH 4/7] fixed snapshot path setting --- .../hifi/dialogs/AvatarPreferencesDialog.qml | 2 +- interface/src/ui/PreferencesDialog.cpp | 28 +++++++++++-------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/AvatarPreferencesDialog.qml b/interface/resources/qml/hifi/dialogs/AvatarPreferencesDialog.qml index 86f195612c..45414cfaf8 100644 --- a/interface/resources/qml/hifi/dialogs/AvatarPreferencesDialog.qml +++ b/interface/resources/qml/hifi/dialogs/AvatarPreferencesDialog.qml @@ -7,7 +7,7 @@ PreferencesDialog { id: root objectName: "AvatarPreferencesDialog" title: "Avatar Settings" - showCategories: [ "Avatar Basics", "Avatar Tuning", "Avatar Camera" ] + showCategories: [ "Avatar Basics", "Snapshots", "Avatar Tuning", "Avatar Camera" ] property var settings: Settings { category: root.objectName property alias x: root.x diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index c1705da206..146df549dd 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -35,7 +35,7 @@ void setupPreferences() { MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); static const QString AVATAR_BASICS { "Avatar Basics" }; { - auto getter = [=]()->QString {return myAvatar->getDisplayName(); }; + auto getter = [=]()->QString { return myAvatar->getDisplayName(); }; auto setter = [=](const QString& value) { myAvatar->setDisplayName(value); }; auto preference = new EditPreference(AVATAR_BASICS, "Avatar display name (optional)", getter, setter); preference->setPlaceholderText("Not showing a name"); @@ -43,7 +43,7 @@ void setupPreferences() { } { - auto getter = [=]()->QString {return myAvatar->getCollisionSoundURL(); }; + auto getter = [=]()->QString { return myAvatar->getCollisionSoundURL(); }; auto setter = [=](const QString& value) { myAvatar->setCollisionSoundURL(value); }; auto preference = new EditPreference(AVATAR_BASICS, "Avatar collision sound URL (optional)", getter, setter); preference->setPlaceholderText("Enter the URL of a sound to play when you bump into something"); @@ -56,20 +56,24 @@ void setupPreferences() { auto preference = new AvatarPreference(AVATAR_BASICS, "Appearance", getter, setter); preferences->addPreference(preference); } + { - auto getter = [=]()->bool {return myAvatar->getSnapTurn(); }; + auto getter = [=]()->bool { return myAvatar->getSnapTurn(); }; auto setter = [=](bool value) { myAvatar->setSnapTurn(value); }; preferences->addPreference(new CheckPreference(AVATAR_BASICS, "Snap turn when in HMD", getter, setter)); } { - auto getter = [=]()->bool {return myAvatar->getClearOverlayWhenMoving(); }; + auto getter = [=]()->bool { return myAvatar->getClearOverlayWhenMoving(); }; auto setter = [=](bool value) { myAvatar->setClearOverlayWhenMoving(value); }; preferences->addPreference(new CheckPreference(AVATAR_BASICS, "Clear overlays when moving", getter, setter)); } + + // Snapshots + static const QString SNAPSHOTS { "Snapshots" }; { - auto getter = []()->QString { return Snapshot::snapshotsLocation.get(); }; - auto setter = [](const QString& value) { Snapshot::snapshotsLocation.set(value); }; - auto preference = new BrowsePreference("Snapshots", "Put my snapshots here", getter, setter); + auto getter = [=]()->QString { return Snapshot::snapshotsLocation.get(); }; + auto setter = [=](const QString& value) { Snapshot::snapshotsLocation.set(value); }; + auto preference = new BrowsePreference(SNAPSHOTS, "Put my snapshots here", getter, setter); preferences->addPreference(preference); } @@ -85,7 +89,7 @@ void setupPreferences() { })); { - auto getter = []()->bool {return !Menu::getInstance()->isOptionChecked(MenuOption::DisableActivityLogger); }; + auto getter = []()->bool { return !Menu::getInstance()->isOptionChecked(MenuOption::DisableActivityLogger); }; auto setter = [](bool value) { Menu::getInstance()->setIsOptionChecked(MenuOption::DisableActivityLogger, !value); }; preferences->addPreference(new CheckPreference("Privacy", "Send data", getter, setter)); } @@ -184,7 +188,7 @@ void setupPreferences() { static const QString AUDIO("Audio"); { - auto getter = []()->bool {return DependencyManager::get()->getReceivedAudioStream().getDynamicJitterBuffers(); }; + auto getter = []()->bool { return DependencyManager::get()->getReceivedAudioStream().getDynamicJitterBuffers(); }; auto setter = [](bool value) { DependencyManager::get()->getReceivedAudioStream().setDynamicJitterBuffers(value); }; preferences->addPreference(new CheckPreference(AUDIO, "Enable dynamic jitter buffers", getter, setter)); } @@ -207,7 +211,7 @@ void setupPreferences() { preferences->addPreference(preference); } { - auto getter = []()->bool {return DependencyManager::get()->getReceivedAudioStream().getUseStDevForJitterCalc(); }; + auto getter = []()->bool { return DependencyManager::get()->getReceivedAudioStream().getUseStDevForJitterCalc(); }; auto setter = [](bool value) { DependencyManager::get()->getReceivedAudioStream().setUseStDevForJitterCalc(value); }; preferences->addPreference(new CheckPreference(AUDIO, "Use standard deviation for dynamic jitter calc", getter, setter)); } @@ -236,7 +240,7 @@ void setupPreferences() { preferences->addPreference(preference); } { - auto getter = []()->bool {return DependencyManager::get()->getReceivedAudioStream().getRepetitionWithFade(); }; + auto getter = []()->bool { return DependencyManager::get()->getReceivedAudioStream().getRepetitionWithFade(); }; auto setter = [](bool value) { DependencyManager::get()->getReceivedAudioStream().setRepetitionWithFade(value); }; preferences->addPreference(new CheckPreference(AUDIO, "Repetition with fade", getter, setter)); } @@ -250,7 +254,7 @@ void setupPreferences() { preferences->addPreference(preference); } { - auto getter = []()->bool {return DependencyManager::get()->getOutputStarveDetectionEnabled(); }; + auto getter = []()->bool { return DependencyManager::get()->getOutputStarveDetectionEnabled(); }; auto setter = [](bool value) { DependencyManager::get()->setOutputStarveDetectionEnabled(value); }; auto preference = new CheckPreference(AUDIO, "Output starve detection (automatic buffer size increase)", getter, setter); preferences->addPreference(preference); From 79864df08ea91abf042bbf20ffc02068d91c9693 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 5 Jul 2016 18:53:39 -0700 Subject: [PATCH 5/7] didn't mean to do that --- interface/src/ui/PreferencesDialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 146df549dd..4007c940c3 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -71,8 +71,8 @@ void setupPreferences() { // Snapshots static const QString SNAPSHOTS { "Snapshots" }; { - auto getter = [=]()->QString { return Snapshot::snapshotsLocation.get(); }; - auto setter = [=](const QString& value) { Snapshot::snapshotsLocation.set(value); }; + auto getter = []()->QString { return Snapshot::snapshotsLocation.get(); }; + auto setter = [](const QString& value) { Snapshot::snapshotsLocation.set(value); }; auto preference = new BrowsePreference(SNAPSHOTS, "Put my snapshots here", getter, setter); preferences->addPreference(preference); } From 6a44ea76e541b22bd9bfdaec392f4a5e193bdf95 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 6 Jul 2016 11:57:29 -0700 Subject: [PATCH 6/7] fixed snapshot preview on windows --- scripts/system/notifications.js | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/scripts/system/notifications.js b/scripts/system/notifications.js index 988d2998d7..98a31d708c 100644 --- a/scripts/system/notifications.js +++ b/scripts/system/notifications.js @@ -247,14 +247,14 @@ function notify(notice, button, height, imageProperties, image) { noticeHeight = notice.height * NOTIFICATION_3D_SCALE; notice.size = { x: noticeWidth, y: noticeHeight }; - notice.topMargin = 0.75 * notice.topMargin * NOTIFICATION_3D_SCALE; - notice.leftMargin = 2 * notice.leftMargin * NOTIFICATION_3D_SCALE; - notice.bottomMargin = 0; - notice.rightMargin = 0; positions = calculate3DOverlayPositions(noticeWidth, noticeHeight, notice.y); if (!image) { + notice.topMargin = 0.75 * notice.topMargin * NOTIFICATION_3D_SCALE; + notice.leftMargin = 2 * notice.leftMargin * NOTIFICATION_3D_SCALE; + notice.bottomMargin = 0; + notice.rightMargin = 0; notice.lineHeight = 10.0 * (fontSize / 12.0) * NOTIFICATION_3D_SCALE; notice.isFacingAvatar = false; @@ -289,8 +289,8 @@ function notify(notice, button, height, imageProperties, image) { height = height + 1.0; heights.push(height); times.push(new Date().getTime() / 1000); - myAlpha.push(0); last = notifications.length - 1; + myAlpha.push(notifications[last].alpha); createArrays(notifications[last], buttons[last], times[last], heights[last], myAlpha[last]); fadeIn(notifications[last], buttons[last]); @@ -301,9 +301,11 @@ function notify(notice, button, height, imageProperties, image) { y: notice.y + height, width: notice.width, height: imageHeight, - topMargin: 0, - leftMargin: 0, - imageURL: imageProperties.path + subImage: { x: 0, y: 0 }, + color: { red: 255, green: 255, blue: 255}, + visible: true, + imageURL: imageProperties.path, + alpha: backgroundAlpha }; notify(notice, button, imageHeight, imageProperties, true); } @@ -336,10 +338,6 @@ function createNotification(text, notificationType, imageProperties) { level = (stack + 20.0); height = height + extraLine; - if (imageProperties && imageProperties.path) { - imageProperties.path = Script.resolvePath(imageProperties.path); - } - noticeProperties = { x: overlayLocationX, y: level, @@ -397,7 +395,7 @@ function stringDivider(str, slotWidth, spaceReplacer) { if (str.length > slotWidth && slotWidth > 0) { left = str.substring(0, slotWidth); - right = str.substring(slotWidth + 1); + right = str.substring(slotWidth); return left + spaceReplacer + stringDivider(right, slotWidth, spaceReplacer); } return str; @@ -531,7 +529,7 @@ function onDomainConnectionRefused(reason) { function onSnapshotTaken(path) { var imageProperties = { - path: path, + path: Script.resolvePath("file:///" + path), aspectRatio: Window.innerWidth / Window.innerHeight } createNotification(wordWrap("Snapshot saved to " + path), NotificationType.SNAPSHOT, imageProperties); From 890b22426c44b5773257c483d17e00e86809aab9 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 6 Jul 2016 12:15:34 -0700 Subject: [PATCH 7/7] added folder selection dialog on first snapshot --- interface/src/ui/Snapshot.cpp | 10 +++++++++- interface/src/ui/Snapshot.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index a3af742f92..aaf11d14a4 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -44,6 +44,7 @@ const QString URL = "highfidelity_url"; Setting::Handle Snapshot::snapshotsLocation("snapshotsLocation", QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); +Setting::Handle Snapshot::hasSetSnapshotsLocation("hasSetSnapshotsLocation", false); SnapshotMetaData* Snapshot::parseSnapshotData(QString snapshotPath) { @@ -103,7 +104,14 @@ QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary) { const int IMAGE_QUALITY = 100; if (!isTemporary) { - QString snapshotFullPath = snapshotsLocation.get(); + QString snapshotFullPath; + if (!hasSetSnapshotsLocation.get()) { + snapshotFullPath = QFileDialog::getExistingDirectory(nullptr, "Choose Snapshots Directory", snapshotsLocation.get()); + hasSetSnapshotsLocation.set(true); + snapshotsLocation.set(snapshotFullPath); + } else { + snapshotFullPath = snapshotsLocation.get(); + } if (!snapshotFullPath.endsWith(QDir::separator())) { snapshotFullPath.append(QDir::separator()); diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index 5856743141..2e7986a5c0 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -39,6 +39,7 @@ public: static SnapshotMetaData* parseSnapshotData(QString snapshotPath); static Setting::Handle snapshotsLocation; + static Setting::Handle hasSetSnapshotsLocation; private: static QFile* savedFileForSnapshot(QImage & image, bool isTemporary); };