diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 36fd8f9635..b316548ad4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -48,6 +48,8 @@ #include #include #include +#include +#include #include #include @@ -199,7 +201,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : connect(audioThread, SIGNAL(started()), &_audio, SLOT(start())); audioThread->start(); - + connect(nodeList, SIGNAL(domainChanged(const QString&)), SLOT(domainChanged(const QString&))); connect(nodeList, &NodeList::nodeAdded, this, &Application::nodeAdded); connect(nodeList, &NodeList::nodeKilled, this, &Application::nodeKilled); @@ -1415,6 +1417,32 @@ void Application::wheelEvent(QWheelEvent* event) { } } +void Application::dropEvent(QDropEvent *event) { + QString snapshotPath; + const QMimeData *mimeData = event->mimeData(); + foreach (QUrl url, mimeData->urls()) { + if (url.url().toLower().endsWith(SNAPSHOT_EXTENSION)) { + snapshotPath = url.url().remove("file://"); + break; + } + } + + SnapshotMetaData* snapshotData = Snapshot::parseSnapshotData(snapshotPath); + if (snapshotData != NULL) { + if (!snapshotData->getDomain().isEmpty()) { + Menu::getInstance()->goToDomain(snapshotData->getDomain()); + } + + _myAvatar->setPosition(snapshotData->getLocation()); + _myAvatar->setOrientation(snapshotData->getOrientation()); + } else { + QMessageBox msgBox; + msgBox.setText("No location details were found in this JPG, try dragging in an authentic Hifi snapshot."); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.exec(); + } +} + void Application::sendPingPackets() { QByteArray pingPacket = NodeList::getInstance()->constructPingPacket(); controlledBroadcastToNodes(pingPacket, NodeSet() << NodeType::VoxelServer @@ -3830,7 +3858,7 @@ void Application::updateWindowTitle(){ QString title = QString() + _profile.getUsername() + " " + nodeList->getSessionUUID().toString() + " @ " + nodeList->getDomainHostname() + buildVersion; - + qDebug("Application title set to: %s", title.toStdString().c_str()); _window->setWindowTitle(title); } @@ -4234,6 +4262,6 @@ void Application::takeSnapshot() { player->setMedia(QUrl::fromLocalFile(inf.absoluteFilePath())); player->play(); - Snapshot::saveSnapshot(_glWidget, _profile.getUsername(), _myAvatar->getPosition()); + Snapshot::saveSnapshot(_glWidget, &_profile, _myAvatar); } diff --git a/interface/src/Application.h b/interface/src/Application.h index a9c20ac00d..0b6907e0f5 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -93,6 +93,8 @@ static const float NODE_KILLED_RED = 1.0f; static const float NODE_KILLED_GREEN = 0.0f; static const float NODE_KILLED_BLUE = 0.0f; +static const QString SNAPSHOT_EXTENSION = ".jpg"; + class Application : public QApplication { Q_OBJECT @@ -127,6 +129,7 @@ public: void touchUpdateEvent(QTouchEvent* event); void wheelEvent(QWheelEvent* event); + void dropEvent(QDropEvent *event); bool event(QEvent* event); diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index cd6f49383e..7bc79e56d8 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -9,6 +9,8 @@ #include "Application.h" #include "GLCanvas.h" +#include +#include GLCanvas::GLCanvas() : QGLWidget(QGLFormat(QGL::NoDepthBuffer, QGL::NoStencilBuffer)) { } @@ -16,6 +18,7 @@ GLCanvas::GLCanvas() : QGLWidget(QGLFormat(QGL::NoDepthBuffer, QGL::NoStencilBuf void GLCanvas::initializeGL() { Application::getInstance()->initializeGL(); setAttribute(Qt::WA_AcceptTouchEvents); + setAcceptDrops(true); } void GLCanvas::paintGL() { @@ -67,4 +70,18 @@ bool GLCanvas::event(QEvent* event) { void GLCanvas::wheelEvent(QWheelEvent* event) { Application::getInstance()->wheelEvent(event); -} \ No newline at end of file +} + +void GLCanvas::dragEnterEvent(QDragEnterEvent* event) { + const QMimeData *mimeData = event->mimeData(); + foreach (QUrl url, mimeData->urls()) { + if (url.url().toLower().endsWith(SNAPSHOT_EXTENSION)) { + event->acceptProposedAction(); + break; + } + } +} + +void GLCanvas::dropEvent(QDropEvent* event) { + Application::getInstance()->dropEvent(event); +} diff --git a/interface/src/GLCanvas.h b/interface/src/GLCanvas.h index ad181f4456..0f0cb5c7d0 100644 --- a/interface/src/GLCanvas.h +++ b/interface/src/GLCanvas.h @@ -31,6 +31,9 @@ protected: virtual bool event(QEvent* event); virtual void wheelEvent(QWheelEvent* event); + + virtual void dragEnterEvent(QDragEnterEvent *event); + virtual void dropEvent(QDropEvent* event); }; #endif /* defined(__hifi__GLCanvas__) */ diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index c61b4cbdaf..b8dfb24c07 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -112,7 +112,7 @@ Menu::Menu() : MenuOption::GoToDomain, Qt::CTRL | Qt::Key_D, this, - SLOT(goToDomain())); + SLOT(goToDomainDialog())); addActionToQMenuAndActionHash(fileMenu, MenuOption::GoToLocation, Qt::CTRL | Qt::SHIFT | Qt::Key_L, @@ -897,7 +897,7 @@ void Menu::goToDomain(const QString newDomain) { } } -void Menu::goToDomain() { +void Menu::goToDomainDialog() { QString currentDomainHostname = NodeList::getInstance()->getDomainHostname(); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 986034002d..efe668b793 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -116,7 +116,7 @@ private slots: void aboutApp(); void login(); void editPreferences(); - void goToDomain(); + void goToDomainDialog(); void goToLocation(); void bandwidthDetailsClosed(); void voxelStatsDetailsClosed(); diff --git a/interface/src/devices/Transmitter.h b/interface/src/devices/Transmitter.h index 1fa392a280..12f2b302f7 100644 --- a/interface/src/devices/Transmitter.h +++ b/interface/src/devices/Transmitter.h @@ -45,5 +45,6 @@ private: TouchState _touchState; timeval* _lastReceivedPacket; -#endif /* defined(__hifi__Transmitter__) */ }; + +#endif /* defined(__hifi__Transmitter__) */ diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index f0fef33cee..e16b0c570d 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -12,7 +12,6 @@ #include #include -#include // filename format: hifi-snap-by-%username%-on-%date%_%time%_@-%location%.jpg // %1 <= username, %2 <= date and time, %3 <= current location @@ -21,18 +20,69 @@ const QString FILENAME_PATH_FORMAT = "hifi-snap-by-%1-on-%2@%3.jpg"; const QString DATETIME_FORMAT = "yyyy-MM-dd_hh-mm-ss"; const QString SNAPSHOTS_DIRECTORY = "Snapshots"; -void Snapshot::saveSnapshot(QGLWidget* widget, QString username, glm::vec3 location) { - QImage shot = widget->grabFrameBuffer(); +const QString LOCATION_X = "location-x"; +const QString LOCATION_Y = "location-y"; +const QString LOCATION_Z = "location-z"; +const QString ORIENTATION_X = "orientation-x"; +const QString ORIENTATION_Y = "orientation-y"; +const QString ORIENTATION_Z = "orientation-z"; +const QString ORIENTATION_W = "orientation-w"; + +const QString DOMAIN_KEY = "domain"; + + +SnapshotMetaData* Snapshot::parseSnapshotData(QString snapshotPath) { + + if (!QFile(snapshotPath).exists()) { + return NULL; + } + + QImage shot(snapshotPath); + + // no location data stored + if (shot.text(LOCATION_X).isEmpty() || shot.text(LOCATION_Y).isEmpty() || shot.text(LOCATION_Z).isEmpty()) { + return NULL; + } + + SnapshotMetaData* data = new SnapshotMetaData(); + data->setLocation(glm::vec3(shot.text(LOCATION_X).toFloat(), + shot.text(LOCATION_Y).toFloat(), + shot.text(LOCATION_Z).toFloat())); + + data->setOrientation(glm::quat(shot.text(ORIENTATION_W).toFloat(), + shot.text(ORIENTATION_X).toFloat(), + shot.text(ORIENTATION_Y).toFloat(), + shot.text(ORIENTATION_Z).toFloat())); + + data->setDomain(shot.text(DOMAIN_KEY)); + + return data; +} + +void Snapshot::saveSnapshot(QGLWidget* widget, Profile* profile, Avatar* avatar) { + QImage shot = widget->grabFrameBuffer(); + + glm::vec3 location = avatar->getPosition(); + glm::quat orientation = avatar->getHead().getOrientation(); + // add metadata - shot.setText("location-x", QString::number(location.x)); - shot.setText("location-y", QString::number(location.y)); - shot.setText("location-z", QString::number(location.z)); + shot.setText(LOCATION_X, QString::number(location.x)); + shot.setText(LOCATION_Y, QString::number(location.y)); + shot.setText(LOCATION_Z, QString::number(location.z)); + + shot.setText(ORIENTATION_X, QString::number(orientation.x)); + shot.setText(ORIENTATION_Y, QString::number(orientation.y)); + shot.setText(ORIENTATION_Z, QString::number(orientation.z)); + shot.setText(ORIENTATION_W, QString::number(orientation.w)); + + shot.setText(DOMAIN_KEY, profile->getLastDomain()); QString formattedLocation = QString("%1_%2_%3").arg(location.x).arg(location.y).arg(location.z); // replace decimal . with '-' formattedLocation.replace('.', '-'); + QString username = profile->getUsername(); // normalize username, replace all non alphanumeric with '-' username.replace(QRegExp("[^A-Za-z0-9_]"), "-"); diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index 26315678f9..13c6945349 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -9,19 +9,38 @@ #ifndef __hifi__Snapshot__ #define __hifi__Snapshot__ +#include "InterfaceConfig.h" + #include #include #include -#include +#include "avatar/Avatar.h" +#include "avatar/Profile.h" + +class SnapshotMetaData { +public: + + QString getDomain() { return _domain; } + void setDomain(QString domain) { _domain = domain; } + + glm::vec3 getLocation() { return _location; } + void setLocation(glm::vec3 location) { _location = location; } + + glm::quat getOrientation() { return _orientation; } + void setOrientation(glm::quat orientation) { _orientation = orientation; } + +private: + QString _domain; + glm::vec3 _location; + glm::quat _orientation;; +}; class Snapshot { public: - static void saveSnapshot(QGLWidget* widget, QString username, glm::vec3 location); - -private: - QString _username; + static void saveSnapshot(QGLWidget* widget, Profile* profile, Avatar* avatar); + static SnapshotMetaData* parseSnapshotData(QString snapshotPath); }; #endif /* defined(__hifi__Snapshot__) */ diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index c0bc7f0010..8dd3857198 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -807,7 +807,8 @@ void NodeList::loadData(QSettings *settings) { } else { _domainHostname = DEFAULT_DOMAIN_HOSTNAME; } - + + emit domainChanged(_domainHostname); settings->endGroup(); }