From 7fc66392cce00da8f70fd6a1c2048e5275392a08 Mon Sep 17 00:00:00 2001 From: stojce Date: Sat, 8 Feb 2014 12:04:55 +0100 Subject: [PATCH 1/4] Interface OS X hifi URL scheme --- cmake/modules/MacOSXBundleInfo.plist.in | 47 +++++++++++++++++++++++++ interface/CMakeLists.txt | 4 +++ 2 files changed, 51 insertions(+) create mode 100644 cmake/modules/MacOSXBundleInfo.plist.in diff --git a/cmake/modules/MacOSXBundleInfo.plist.in b/cmake/modules/MacOSXBundleInfo.plist.in new file mode 100644 index 0000000000..1682b6c022 --- /dev/null +++ b/cmake/modules/MacOSXBundleInfo.plist.in @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + CFBundleGetInfoString + ${MACOSX_BUNDLE_INFO_STRING} + CFBundleIconFile + ${MACOSX_BUNDLE_ICON_FILE} + CFBundleIdentifier + ${MACOSX_BUNDLE_GUI_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleLongVersionString + ${MACOSX_BUNDLE_LONG_VERSION_STRING} + CFBundleName + ${MACOSX_BUNDLE_BUNDLE_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + ${MACOSX_BUNDLE_SHORT_VERSION_STRING} + CFBundleSignature + ???? + CFBundleVersion + ${MACOSX_BUNDLE_BUNDLE_VERSION} + CSResourcesFileMapped + + LSRequiresCarbon + + NSHumanReadableCopyright + ${MACOSX_BUNDLE_COPYRIGHT} + CFBundleURLTypes + + + CFBundleURLName + ${MACOSX_BUNDLE_BUNDLE_NAME} URL + CFBundleURLSchemes + + hifi + + + + + diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 6af6ed478d..846df5e493 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -90,6 +90,10 @@ qt5_wrap_ui(QT_UI_HEADERS ${QT_UI_FILES}) set(INTERFACE_SRCS ${INTERFACE_SRCS} ${QT_UI_HEADERS}) if (APPLE) + + # configure CMake to use a custom Info.plist + SET_TARGET_PROPERTIES( ${this_target} PROPERTIES MACOSX_BUNDLE_INFO_PLIST MacOSXBundleInfo.plist.in ) + set(MACOSX_BUNDLE_BUNDLE_NAME Interface) # set how the icon shows up in the Info.plist file SET(MACOSX_BUNDLE_ICON_FILE interface.icns) From b05967a5149ccff2a723a46581214861fcb54e8a Mon Sep 17 00:00:00 2001 From: stojce Date: Sun, 9 Feb 2014 17:47:46 +0100 Subject: [PATCH 2/4] Custom URL handler --- interface/src/Application.cpp | 17 +++++++ interface/src/Application.h | 4 +- interface/src/Menu.cpp | 84 +++++++++++++++-------------------- interface/src/Menu.h | 1 + 4 files changed, 57 insertions(+), 49 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3f32c6be09..9ba7699714 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -101,6 +101,8 @@ const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::D const int STATS_PELS_PER_LINE = 20; +const QString CUSTOM_URL_SCHEME = "hifi:"; + void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { if (message.size() > 0) { QString messageWithNewLine = message + "\n"; @@ -680,6 +682,21 @@ void Application::controlledBroadcastToNodes(const QByteArray& packet, const Nod } } +bool Application::event(QEvent* event) { + + // handle custom URL + if (event->type() == QEvent::FileOpen) { + QFileOpenEvent* fileEvent = static_cast(event); + if (!fileEvent->url().isEmpty() && fileEvent->url().toLocalFile().startsWith(CUSTOM_URL_SCHEME)) { + QString destination = fileEvent->url().toLocalFile().remove(QRegExp(CUSTOM_URL_SCHEME + "|/")); + Menu::getInstance()->goToDestination(destination); + } + + return false; + } + return QApplication::event(event); +} + void Application::keyPressEvent(QKeyEvent* event) { _controllerScriptingInterface.emitKeyPressEvent(event); // send events to any registered scripts diff --git a/interface/src/Application.h b/interface/src/Application.h index 94b5601797..c4550e2f0b 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -127,7 +127,9 @@ public: void touchUpdateEvent(QTouchEvent* event); void wheelEvent(QWheelEvent* event); - + + bool event(QEvent* event); + void makeVoxel(glm::vec3 position, float scale, unsigned char red, diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6640df3468..a447c6703a 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -913,6 +913,39 @@ void Menu::goToDomain() { sendFakeEnterEvent(); } +bool Menu::goToDestination(QString destination) { + + QStringList coordinateItems = destination.split(QRegExp("_|,"), QString::SkipEmptyParts); + + const int NUMBER_OF_COORDINATE_ITEMS = 3; + const int X_ITEM = 0; + const int Y_ITEM = 1; + const int Z_ITEM = 2; + if (coordinateItems.size() == NUMBER_OF_COORDINATE_ITEMS) { + + double x = replaceLastOccurrence('-', '.', coordinateItems[X_ITEM].trimmed()).toDouble(); + double y = replaceLastOccurrence('-', '.', coordinateItems[Y_ITEM].trimmed()).toDouble(); + double z = replaceLastOccurrence('-', '.', coordinateItems[Z_ITEM].trimmed()).toDouble(); + + glm::vec3 newAvatarPos(x, y, z); + + MyAvatar* myAvatar = Application::getInstance()->getAvatar(); + glm::vec3 avatarPos = myAvatar->getPosition(); + if (newAvatarPos != avatarPos) { + // send a node kill request, indicating to other clients that they should play the "disappeared" effect + MyAvatar::sendKillAvatar(); + + qDebug("Going To Location: %f, %f, %f...", x, y, z); + myAvatar->setPosition(newAvatarPos); + } + + return true; + } + + // no coordinates were parsed + return false; +} + void Menu::goTo() { QInputDialog gotoDialog(Application::getInstance()->getWindow()); @@ -928,31 +961,8 @@ void Menu::goTo() { destination = gotoDialog.textValue(); - QStringList coordinateItems = destination.split(QRegExp("_|,"), QString::SkipEmptyParts); - - const int NUMBER_OF_COORDINATE_ITEMS = 3; - const int X_ITEM = 0; - const int Y_ITEM = 1; - const int Z_ITEM = 2; - if (coordinateItems.size() == NUMBER_OF_COORDINATE_ITEMS) { - - double x = replaceLastOccurrence('-', '.', coordinateItems[X_ITEM].trimmed()).toDouble(); - double y = replaceLastOccurrence('-', '.', coordinateItems[Y_ITEM].trimmed()).toDouble(); - double z = replaceLastOccurrence('-', '.', coordinateItems[Z_ITEM].trimmed()).toDouble(); - - glm::vec3 newAvatarPos(x, y, z); - - MyAvatar* myAvatar = Application::getInstance()->getAvatar(); - glm::vec3 avatarPos = myAvatar->getPosition(); - if (newAvatarPos != avatarPos) { - // send a node kill request, indicating to other clients that they should play the "disappeared" effect - MyAvatar::sendKillAvatar(); - - qDebug("Going To Location: %f, %f, %f...", x, y, z); - myAvatar->setPosition(newAvatarPos); - } - - } else { + // go to coordinate destination or to Username + if (!goToDestination(destination)) { // there's a username entered by the user, make a request to the data-server DataServerClient::getValuesForKeysAndUserString( QStringList() @@ -983,29 +993,7 @@ void Menu::goToLocation() { int dialogReturn = coordinateDialog.exec(); if (dialogReturn == QDialog::Accepted && !coordinateDialog.textValue().isEmpty()) { - QByteArray newCoordinates; - - QString delimiterPattern(","); - QStringList coordinateItems = coordinateDialog.textValue().split(delimiterPattern); - - const int NUMBER_OF_COORDINATE_ITEMS = 3; - const int X_ITEM = 0; - const int Y_ITEM = 1; - const int Z_ITEM = 2; - if (coordinateItems.size() == NUMBER_OF_COORDINATE_ITEMS) { - double x = coordinateItems[X_ITEM].toDouble(); - double y = coordinateItems[Y_ITEM].toDouble(); - double z = coordinateItems[Z_ITEM].toDouble(); - glm::vec3 newAvatarPos(x, y, z); - - if (newAvatarPos != avatarPos) { - // send a node kill request, indicating to other clients that they should play the "disappeared" effect - MyAvatar::sendKillAvatar(); - - qDebug("Going To Location: %f, %f, %f...", x, y, z); - myAvatar->setPosition(newAvatarPos); - } - } + goToDestination(coordinateDialog.textValue()); } sendFakeEnterEvent(); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index fcd2d74940..4e835146e6 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -84,6 +84,7 @@ public: const char* member = NULL, QAction::MenuRole role = QAction::NoRole); virtual void removeAction(QMenu* menu, const QString& actionName); + bool goToDestination(QString destination); public slots: void bandwidthDetails(); From 6e31f1692437095894dd4edc301cb158e467e01c Mon Sep 17 00:00:00 2001 From: stojce Date: Tue, 11 Feb 2014 19:25:03 +0100 Subject: [PATCH 3/4] fix for Firefox --- interface/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 846df5e493..8e96006828 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -95,6 +95,8 @@ if (APPLE) SET_TARGET_PROPERTIES( ${this_target} PROPERTIES MACOSX_BUNDLE_INFO_PLIST MacOSXBundleInfo.plist.in ) set(MACOSX_BUNDLE_BUNDLE_NAME Interface) + set(MACOSX_BUNDLE_GUI_IDENTIFIER io.highfidelity.Interface) + # set how the icon shows up in the Info.plist file SET(MACOSX_BUNDLE_ICON_FILE interface.icns) From ab4164a6dfeea9888ee8468aa6b008983188ef1c Mon Sep 17 00:00:00 2001 From: stojce Date: Thu, 13 Feb 2014 22:44:10 +0100 Subject: [PATCH 4/4] #19505 - Add domain & orientation parsing to hifi:// protocol handler --- interface/src/Application.cpp | 21 +++++++++++++-- interface/src/Menu.cpp | 50 ++++++++++++++++++++++++++++++----- interface/src/Menu.h | 2 ++ 3 files changed, 65 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index eeb9d4a73a..57f66e68b2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -687,8 +687,25 @@ bool Application::event(QEvent* event) { if (event->type() == QEvent::FileOpen) { QFileOpenEvent* fileEvent = static_cast(event); if (!fileEvent->url().isEmpty() && fileEvent->url().toLocalFile().startsWith(CUSTOM_URL_SCHEME)) { - QString destination = fileEvent->url().toLocalFile().remove(QRegExp(CUSTOM_URL_SCHEME + "|/")); - Menu::getInstance()->goToDestination(destination); + QString destination = fileEvent->url().toLocalFile().remove(CUSTOM_URL_SCHEME); + QStringList urlParts = destination.split('/', QString::SkipEmptyParts); + + if (urlParts.count() > 1) { + // if url has 2 or more parts, the first one is domain name + Menu::getInstance()->goToDomain(urlParts[0]); + + // location coordinates + Menu::getInstance()->goToDestination(urlParts[1]); + if (urlParts.count() > 2) { + + // location orientation + Menu::getInstance()->goToOrientation(urlParts[2]); + } + } else if (urlParts.count() == 1) { + + // location coordinates + Menu::getInstance()->goToDestination(urlParts[0]); + } } return false; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 9854a8b97f..e064c4bd20 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -889,6 +889,17 @@ void Menu::editPreferences() { sendFakeEnterEvent(); } +void Menu::goToDomain(const QString newDomain) { + if (NodeList::getInstance()->getDomainHostname() != newDomain) { + + // send a node kill request, indicating to other clients that they should play the "disappeared" effect + Application::getInstance()->getAvatar()->sendKillAvatar(); + + // give our nodeList the new domain-server hostname + NodeList::getInstance()->setDomainHostname(newDomain); + } +} + void Menu::goToDomain() { QString currentDomainHostname = NodeList::getInstance()->getDomainHostname(); @@ -913,17 +924,44 @@ void Menu::goToDomain() { // the user input a new hostname, use that newHostname = domainDialog.textValue(); } - - // send a node kill request, indicating to other clients that they should play the "disappeared" effect - Application::getInstance()->getAvatar()->sendKillAvatar(); - - // give our nodeList the new domain-server hostname - NodeList::getInstance()->setDomainHostname(domainDialog.textValue()); + + goToDomain(newHostname); } sendFakeEnterEvent(); } +void Menu::goToOrientation(QString orientation) { + + if (orientation.isEmpty()) { + return; + } + + QStringList orientationItems = orientation.split(QRegExp("_|,"), QString::SkipEmptyParts); + + const int NUMBER_OF_ORIENTATION_ITEMS = 4; + const int W_ITEM = 0; + const int X_ITEM = 1; + const int Y_ITEM = 2; + const int Z_ITEM = 3; + + if (orientationItems.size() == NUMBER_OF_ORIENTATION_ITEMS) { + + double w = replaceLastOccurrence('-', '.', orientationItems[W_ITEM].trimmed()).toDouble(); + double x = replaceLastOccurrence('-', '.', orientationItems[X_ITEM].trimmed()).toDouble(); + double y = replaceLastOccurrence('-', '.', orientationItems[Y_ITEM].trimmed()).toDouble(); + double z = replaceLastOccurrence('-', '.', orientationItems[Z_ITEM].trimmed()).toDouble(); + + glm::quat newAvatarOrientation(w, x, y, z); + + MyAvatar* myAvatar = Application::getInstance()->getAvatar(); + glm::quat avatarOrientation = myAvatar->getOrientation(); + if (newAvatarOrientation != avatarOrientation) { + myAvatar->setOrientation(newAvatarOrientation); + } + } +} + bool Menu::goToDestination(QString destination) { QStringList coordinateItems = destination.split(QRegExp("_|,"), QString::SkipEmptyParts); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 9ccc5466e8..378c022ae0 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -85,6 +85,8 @@ public: QAction::MenuRole role = QAction::NoRole); virtual void removeAction(QMenu* menu, const QString& actionName); bool goToDestination(QString destination); + void goToOrientation(QString orientation); + void goToDomain(const QString newDomain); public slots: void bandwidthDetails();