From 71f2c0b542d088a3034b49dc4822f07dccf8c3a1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 11 Sep 2014 10:14:00 -0700 Subject: [PATCH] initial addition of the AddressManager with location switch hooked up --- interface/src/Application.cpp | 13 +- interface/src/Menu.cpp | 126 ++----------------- interface/src/Menu.h | 12 +- interface/src/avatar/MyAvatar.cpp | 56 ++++----- interface/src/avatar/MyAvatar.h | 3 +- interface/src/location/LocationManager.cpp | 86 ++++++++----- interface/src/location/LocationManager.h | 7 +- interface/src/ui/ChatMessageArea.cpp | 4 +- interface/src/ui/ChatWindow.cpp | 2 +- interface/src/ui/UserLocationsDialog.cpp | 2 +- libraries/networking/src/AddressManager.cpp | 108 ++++++++++++++++ libraries/networking/src/AddressManager.h | 33 +++++ libraries/networking/src/LimitedNodeList.cpp | 2 +- 13 files changed, 249 insertions(+), 205 deletions(-) create mode 100644 libraries/networking/src/AddressManager.cpp create mode 100644 libraries/networking/src/AddressManager.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 05a195c904..5b1110fbad 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -51,6 +51,7 @@ #include #include +#include #include #include #include @@ -421,6 +422,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : MIDIManager& midiManagerInstance = MIDIManager::getInstance(); midiManagerInstance.openDefaultPort(); #endif + + AddressManager::getInstance().handleLookupString("1.5,2.5,0.0/0.0,-161.98,0.02"); } Application::~Application() { @@ -809,7 +812,7 @@ bool Application::event(QEvent* event) { QFileOpenEvent* fileEvent = static_cast(event); bool isHifiSchemeURL = !fileEvent->url().isEmpty() && fileEvent->url().toLocalFile().startsWith(CUSTOM_URL_SCHEME); if (isHifiSchemeURL) { - Menu::getInstance()->goToURL(fileEvent->url().toLocalFile()); +// Menu::getInstance()->goToURL(fileEvent->url().toLocalFile()); } return false; } @@ -1059,7 +1062,7 @@ void Application::keyPressEvent(QKeyEvent* event) { break; case Qt::Key_At: - Menu::getInstance()->goTo(); +// Menu::getInstance()->goTo(); break; default: event->ignore(); @@ -3360,7 +3363,7 @@ void Application::updateWindowTitle(){ #ifndef WIN32 // crashes with vs2013/win32 qDebug("Application title set to: %s", title.toStdString().c_str()); -#endif !WIN32 +#endif _window->setWindowTitle(title); } @@ -4114,11 +4117,11 @@ void Application::urlGoTo(int argc, const char * constArgv[]) { // goto either @user, #place, or x-xx,y-yy,z-zz // style co-ordinate. - Menu::goTo(destination); +// Menu::goTo(destination); if (!orientation.isEmpty()) { // location orientation - Menu::goToOrientation(orientation); +// Menu::goToOrientation(orientation); } } } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index d7679968ae..48908b12a1 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -183,8 +183,6 @@ Menu::Menu() : Qt::Key_At, this, SLOT(goTo())); - connect(&LocationManager::getInstance(), &LocationManager::multipleDestinationsFound, - this, &Menu::multipleDestinationsDecision); addDisabledActionAndSeparator(fileMenu, "Upload Avatar Model"); addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadHead, 0, Application::getInstance(), SLOT(uploadHead())); @@ -1191,107 +1189,25 @@ void Menu::goToDomainDialog() { sendFakeEnterEvent(); } -void Menu::goToOrientation(QString orientation) { - LocationManager::getInstance().goToOrientation(orientation); -} +void Menu::addressBarDialog() { -bool Menu::goToDestination(QString destination) { - return LocationManager::getInstance().goToDestination(destination); -} - -void Menu::goTo(QString destination) { - LocationManager::getInstance().goTo(destination); -} - -void Menu::goTo() { - - QInputDialog gotoDialog(Application::getInstance()->getWindow()); - gotoDialog.setWindowTitle("Go to"); - gotoDialog.setLabelText("Destination or URL:\n @user, #place, hifi://domain/location/orientation"); + QInputDialog addressBarDialog(Application::getInstance()->getWindow()); + addressBarDialog.setWindowTitle("Address Bar"); + addressBarDialog.setLabelText("place, @user, hifi://domain/path, position/orientation"); QString destination = QString(); - gotoDialog.setTextValue(destination); - gotoDialog.resize(gotoDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, gotoDialog.size().height()); + addressBarDialog.setTextValue(destination); + addressBarDialog.resize(addressBarDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, + addressBarDialog.size().height()); - int dialogReturn = gotoDialog.exec(); - if (dialogReturn == QDialog::Accepted && !gotoDialog.textValue().isEmpty()) { - QString desiredDestination = gotoDialog.textValue(); - if (!goToURL(desiredDestination)) {; - goTo(desiredDestination); - } + int dialogReturn = addressBarDialog.exec(); + if (dialogReturn == QDialog::Accepted && !addressBarDialog.textValue().isEmpty()) { + // let the location manager parse this out and decide what to do with it +// LocationManager::getInstance().handleAddressBarEntry(addressBarDialog.textValue()); } sendFakeEnterEvent(); } -bool Menu::goToURL(QString location) { - if (location.startsWith(CUSTOM_URL_SCHEME + "/")) { - QStringList urlParts = location.remove(0, CUSTOM_URL_SCHEME.length()).split('/', QString::SkipEmptyParts); - - if (urlParts.count() > 1) { - // if url has 2 or more parts, the first one is domain name - QString domain = urlParts[0]; - - // second part is either a destination coordinate or - // a place name - QString destination = urlParts[1]; - - // any third part is an avatar orientation. - QString orientation = urlParts.count() > 2 ? urlParts[2] : QString(); - - goToDomain(domain); - - // goto either @user, #place, or x-xx,y-yy,z-zz - // style co-ordinate. - goTo(destination); - - if (!orientation.isEmpty()) { - // location orientation - goToOrientation(orientation); - } - } else if (urlParts.count() == 1) { - QString destination = urlParts[0]; - - // If this starts with # or @, treat it as a user/location, otherwise treat it as a domain - if (destination[0] == '#' || destination[0] == '@') { - goTo(destination); - } else { - goToDomain(destination); - } - } - return true; - } - return false; -} - -void Menu::goToUser(const QString& user) { - LocationManager::getInstance().goTo(user); -} - -/// Open a url, shortcutting any "hifi" scheme URLs to the local application. -void Menu::openUrl(const QUrl& url) { - if (url.scheme() == "hifi") { - goToURL(url.toString()); - } else { - QDesktopServices::openUrl(url); - } -} - -void Menu::multipleDestinationsDecision(const QJsonObject& userData, const QJsonObject& placeData) { - QMessageBox msgBox; - msgBox.setText("Both user and location exists with same name"); - msgBox.setInformativeText("Where you wanna go?"); - msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Open); - msgBox.button(QMessageBox::Ok)->setText("User"); - msgBox.button(QMessageBox::Open)->setText("Place"); - int userResponse = msgBox.exec(); - - if (userResponse == QMessageBox::Ok) { - Application::getInstance()->getAvatar()->goToLocationFromAddress(userData["address"].toObject()); - } else if (userResponse == QMessageBox::Open) { - Application::getInstance()->getAvatar()->goToLocationFromAddress(placeData["address"].toObject()); - } -} - void Menu::muteEnvironment() { int headerSize = numBytesForPacketHeaderGivenPacketType(PacketTypeMuteEnvironment); int packetSize = headerSize + sizeof(glm::vec3) + sizeof(float); @@ -1316,26 +1232,6 @@ void Menu::muteEnvironment() { free(packet); } -void Menu::goToLocation() { - MyAvatar* myAvatar = Application::getInstance()->getAvatar(); - glm::vec3 avatarPos = myAvatar->getPosition(); - QString currentLocation = QString("%1, %2, %3").arg(QString::number(avatarPos.x), - QString::number(avatarPos.y), QString::number(avatarPos.z)); - - QInputDialog coordinateDialog(Application::getInstance()->getWindow()); - coordinateDialog.setWindowTitle("Go to Location"); - coordinateDialog.setLabelText("Coordinate as x,y,z:"); - coordinateDialog.setTextValue(currentLocation); - coordinateDialog.resize(coordinateDialog.parentWidget()->size().width() * 0.30, coordinateDialog.size().height()); - - int dialogReturn = coordinateDialog.exec(); - if (dialogReturn == QDialog::Accepted && !coordinateDialog.textValue().isEmpty()) { - goToDestination(coordinateDialog.textValue()); - } - - sendFakeEnterEvent(); -} - void Menu::namedLocationCreated(LocationManager::NamedLocationCreateResponse response) { if (response == LocationManager::Created) { diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 3b263add36..a9068c4b60 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -162,11 +162,8 @@ public: int menuItemLocation = UNSPECIFIED_POSITION); void removeAction(QMenu* menu, const QString& actionName); - - bool static goToDestination(QString destination); - void static goToOrientation(QString orientation); + void static goToDomain(const QString newDomain); - void static goTo(QString destination); const QByteArray& getWalletPrivateKey() const { return _walletPrivateKey; } @@ -185,11 +182,8 @@ public slots: void saveSettings(QSettings* settings = NULL); void importSettings(); void exportSettings(); - void goTo(); - bool goToURL(QString location); - void goToUser(const QString& user); + void addressBarDialog(); void pasteToVoxel(); - void openUrl(const QUrl& url); void toggleLoginMenuItem(); @@ -212,7 +206,6 @@ private slots: void editAnimations(); void changePrivateKey(); void goToDomainDialog(); - void goToLocation(); void nameLocation(); void toggleLocationList(); void bandwidthDetailsClosed(); @@ -227,7 +220,6 @@ private slots: void toggleChat(); void audioMuteToggled(); void namedLocationCreated(LocationManager::NamedLocationCreateResponse response); - void multipleDestinationsDecision(const QJsonObject& userData, const QJsonObject& placeData); void muteEnvironment(); private: diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6472ba2efa..14120a7e2c 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -91,6 +92,9 @@ MyAvatar::MyAvatar() : Ragdoll* ragdoll = _skeletonModel.buildRagdoll(); _physicsSimulation.setRagdoll(ragdoll); _physicsSimulation.addEntity(&_voxelShapeManager); + + // connect to AddressManager signal for location jumps + connect(&AddressManager::getInstance(), &AddressManager::locationChangeRequired, this, &MyAvatar::goToLocation); } MyAvatar::~MyAvatar() { @@ -1798,45 +1802,29 @@ void MyAvatar::resetSize() { qDebug("Reseted scale to %f", _targetScale); } -void MyAvatar::goToLocationFromResponse(const QJsonObject& jsonObject) { - QJsonObject locationObject = jsonObject["data"].toObject()["address"].toObject(); - bool isOnline = jsonObject["data"].toObject()["online"].toBool(); - if (isOnline ) { - goToLocationFromAddress(locationObject); - } else { - QMessageBox::warning(Application::getInstance()->getWindow(), "", "The user is not online."); - } -} - -void MyAvatar::goToLocationFromAddress(const QJsonObject& locationObject) { +void MyAvatar::goToLocation(const glm::vec3& newPosition, bool hasOrientation, const glm::vec3& newOrientation) { // send a node kill request, indicating to other clients that they should play the "disappeared" effect sendKillAvatar(); - - QString positionString = locationObject["position"].toString(); - QString orientationString = locationObject["orientation"].toString(); - QString domainHostnameString = locationObject["domain"].toString(); - - qDebug() << "Changing domain to" << domainHostnameString << - ", position to" << positionString << - ", and orientation to" << orientationString; - - QStringList coordinateItems = positionString.split(','); - QStringList orientationItems = orientationString.split(','); - - NodeList::getInstance()->getDomainHandler().setHostname(domainHostnameString); - - // orient the user to face the target - glm::quat newOrientation = glm::quat(glm::radians(glm::vec3(orientationItems[0].toFloat(), - orientationItems[1].toFloat(), - orientationItems[2].toFloat()))) - * glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)); - setOrientation(newOrientation); + + glm::quat quatOrientation = getOrientation(); + + qDebug().nospace() << "MyAvatar goToLocation - moving to " << newPosition.x << ", " + << newPosition.y << ", " << newPosition.z; + + if (hasOrientation) { + qDebug().nospace() << "MyAvatar goToLocation - new orientation is " + << newOrientation.x << ", " << newOrientation.y << ", " << newOrientation.z; + + // orient the user to face the target + glm::quat quatOrientation = glm::quat(glm::radians(newOrientation)) + * glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)); + setOrientation(quatOrientation); + } // move the user a couple units away const float DISTANCE_TO_USER = 2.0f; - glm::vec3 newPosition = glm::vec3(coordinateItems[0].toFloat(), coordinateItems[1].toFloat(), - coordinateItems[2].toFloat()) - newOrientation * IDENTITY_FRONT * DISTANCE_TO_USER; - slamPosition(newPosition); + glm::vec3 shiftedPosition = newPosition - quatOrientation * IDENTITY_FRONT * DISTANCE_TO_USER; + slamPosition(shiftedPosition); emit transformChanged(); } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index be828e0c91..86c10fdbb4 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -155,8 +155,7 @@ public slots: void decreaseSize(); void resetSize(); - void goToLocationFromResponse(const QJsonObject& jsonObject); - void goToLocationFromAddress(const QJsonObject& jsonObject); + void goToLocation(const glm::vec3& newPosition, bool hasOrientation, const glm::vec3& newOrientation); // Set/Get update the thrust that will move the avatar around void addThrust(glm::vec3 newThrust) { _thrust += newThrust; }; diff --git a/interface/src/location/LocationManager.cpp b/interface/src/location/LocationManager.cpp index 67e1b899ee..4484c50ebf 100644 --- a/interface/src/location/LocationManager.cpp +++ b/interface/src/location/LocationManager.cpp @@ -16,15 +16,9 @@ #include const QString GET_USER_ADDRESS = "/api/v1/users/%1/address"; -const QString GET_PLACE_ADDRESS = "/api/v1/places/%1"; -const QString GET_ADDRESSES = "/api/v1/addresses/%1"; +const QString GET_PLACE_ADDRESS = "/api/v1/metaverse/search/%1"; const QString POST_PLACE_CREATE = "/api/v1/places/"; - -LocationManager::LocationManager() { - -}; - LocationManager& LocationManager::getInstance() { static LocationManager sharedInstance; return sharedInstance; @@ -63,7 +57,7 @@ void LocationManager::createNamedLocation(NamedLocation* namedLocation) { void LocationManager::goTo(QString destination) { const QString USER_DESTINATION_TYPE = "user"; const QString PLACE_DESTINATION_TYPE = "place"; - const QString OTHER_DESTINATION_TYPE = "coordinate_or_username"; + const QString COORDINATE_DESTINATION_TYPE = "coordinate"; if (destination.startsWith("@")) { // remove '@' and go to user @@ -73,45 +67,37 @@ void LocationManager::goTo(QString destination) { return; } - if (destination.startsWith("#")) { - // remove '#' and go to named place - QString destinationPlace = destination.remove(0, 1); - UserActivityLogger::getInstance().wentTo(PLACE_DESTINATION_TYPE, destinationPlace); - goToPlace(destinationPlace); - return; - } - // go to coordinate destination or to Username if (!goToDestination(destination)) { destination = QString(QUrl::toPercentEncoding(destination)); - UserActivityLogger::getInstance().wentTo(OTHER_DESTINATION_TYPE, destination); + UserActivityLogger::getInstance().wentTo(PLACE_DESTINATION_TYPE, destination); JSONCallbackParameters callbackParams; callbackParams.jsonCallbackReceiver = this; - callbackParams.jsonCallbackMethod = "goToAddressFromResponse"; + callbackParams.jsonCallbackMethod = "goToPlaceFromResponse"; callbackParams.errorCallbackReceiver = this; callbackParams.errorCallbackMethod = "handleAddressLookupError"; - AccountManager::getInstance().authenticatedRequest(GET_ADDRESSES.arg(destination), + AccountManager::getInstance().authenticatedRequest(GET_PLACE_ADDRESS.arg(destination), QNetworkAccessManager::GetOperation, callbackParams); + } else { + UserActivityLogger::getInstance().wentTo(COORDINATE_DESTINATION_TYPE, destination); } } -void LocationManager::goToAddressFromResponse(const QJsonObject& responseData) { +void LocationManager::goToPlaceFromResponse(const QJsonObject& responseData) { QJsonValue status = responseData["status"]; - const QJsonObject& data = responseData["data"].toObject(); - const QJsonValue& userObject = data["user"]; - const QJsonValue& placeObject = data["place"]; + QJsonObject data = responseData["data"].toObject(); + QJsonObject domainObject = data["domain"].toObject(); - if (!placeObject.isUndefined() && !userObject.isUndefined()) { - emit multipleDestinationsFound(userObject.toObject(), placeObject.toObject()); - } else if (placeObject.isUndefined()) { - Application::getInstance()->getAvatar()->goToLocationFromAddress(userObject.toObject()["address"].toObject()); - } else { - Application::getInstance()->getAvatar()->goToLocationFromAddress(placeObject.toObject()["address"].toObject()); - } + const QString DOMAIN_NETWORK_ADDRESS_KEY = "network_address"; + + // get the network address for the domain we need to switch to + NodeList::getInstance()->getDomainHandler().setHostname(domainObject[DOMAIN_NETWORK_ADDRESS_KEY].toString()); + + // check if there is a path inside the domain we need to jump to } void LocationManager::goToUser(QString userName) { @@ -140,6 +126,46 @@ void LocationManager::goToPlace(QString placeName) { callbackParams); } +void LocationManager::goToUrl(const QUrl& url) { +// if (location.startsWith(CUSTOM_URL_SCHEME + "/")) { +// QStringList urlParts = location.remove(0, CUSTOM_URL_SCHEME.length()).split('/', QString::SkipEmptyParts); +// +// if (urlParts.count() > 1) { +// // if url has 2 or more parts, the first one is domain name +// QString domain = urlParts[0]; +// +// // second part is either a destination coordinate or +// // a place name +// QString destination = urlParts[1]; +// +// // any third part is an avatar orientation. +// QString orientation = urlParts.count() > 2 ? urlParts[2] : QString(); +// +// goToDomain(domain); +// +// // goto either @user, #place, or x-xx,y-yy,z-zz +// // style co-ordinate. +// goTo(destination); +// +// if (!orientation.isEmpty()) { +// // location orientation +// goToOrientation(orientation); +// } +// } else if (urlParts.count() == 1) { +// QString destination = urlParts[0]; +// +// // If this starts with # or @, treat it as a user/location, otherwise treat it as a domain +// if (destination[0] == '#' || destination[0] == '@') { +// goTo(destination); +// } else { +// goToDomain(destination); +// } +// } +// return true; +// } +// return false; +} + void LocationManager::goToOrientation(QString orientation) { if (orientation.isEmpty()) { return; diff --git a/interface/src/location/LocationManager.h b/interface/src/location/LocationManager.h index 30b4447ded..bf1c0e67e2 100644 --- a/interface/src/location/LocationManager.h +++ b/interface/src/location/LocationManager.h @@ -29,12 +29,12 @@ public: SystemError }; - LocationManager(); void createNamedLocation(NamedLocation* namedLocation); - + void goTo(QString destination); void goToUser(QString userName); void goToPlace(QString placeName); + void goToUrl(const QUrl& url); void goToOrientation(QString orientation); bool goToDestination(QString destination); @@ -46,12 +46,11 @@ private: signals: void creationCompleted(LocationManager::NamedLocationCreateResponse response); - void multipleDestinationsFound(const QJsonObject& userData, const QJsonObject& placeData); private slots: void namedLocationDataReceived(const QJsonObject& data); void errorDataReceived(QNetworkReply::NetworkError error, const QString& message); - void goToAddressFromResponse(const QJsonObject& jsonObject); + void goToPlaceFromResponse(const QJsonObject& jsonObject); }; diff --git a/interface/src/ui/ChatMessageArea.cpp b/interface/src/ui/ChatMessageArea.cpp index 1e16a8a2db..ab93c7abe9 100644 --- a/interface/src/ui/ChatMessageArea.cpp +++ b/interface/src/ui/ChatMessageArea.cpp @@ -19,8 +19,8 @@ ChatMessageArea::ChatMessageArea(bool useFixedHeight) : QTextBrowser(), _useFixe connect(document()->documentLayout(), &QAbstractTextDocumentLayout::documentSizeChanged, this, &ChatMessageArea::updateLayout); - connect(this, &QTextBrowser::anchorClicked, - Menu::getInstance(), &Menu::openUrl); +// connect(this, &QTextBrowser::anchorClicked, +// Menu::getInstance(), &Menu::openUrl); } void ChatMessageArea::setHtml(const QString& html) { diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index b9b5ed8e19..9961a84e79 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -169,7 +169,7 @@ bool ChatWindow::eventFilter(QObject* sender, QEvent* event) { } else if (event->type() == QEvent::MouseButtonRelease) { QVariant userVar = sender->property("user"); if (userVar.isValid()) { - Menu::getInstance()->goToUser("@" + userVar.toString()); +// Menu::getInstance()->goToUser("@" + userVar.toString()); return true; } } diff --git a/interface/src/ui/UserLocationsDialog.cpp b/interface/src/ui/UserLocationsDialog.cpp index f72e66ce77..ca1a9b5ad6 100644 --- a/interface/src/ui/UserLocationsDialog.cpp +++ b/interface/src/ui/UserLocationsDialog.cpp @@ -52,7 +52,7 @@ void UserLocationsDialog::updateEnabled() { void UserLocationsDialog::goToModelIndex(const QModelIndex& index) { QVariant location = _proxyModel.data(index.sibling(index.row(), UserLocationsModel::LocationColumn)); - Menu::getInstance()->goToURL(location.toString()); +// Menu::getInstance()->goToURL(location.toString()); } void UserLocationsDialog::deleteSelection() { diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp new file mode 100644 index 0000000000..6413fe6580 --- /dev/null +++ b/libraries/networking/src/AddressManager.cpp @@ -0,0 +1,108 @@ +// +// AddressManager.cpp +// libraries/networking/src +// +// Created by Stephen Birarda on 2014-09-10. +// 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 +// + +#include +#include +#include + +#include "AddressManager.h" + +AddressManager& AddressManager::getInstance() { + static AddressManager sharedInstance; + return sharedInstance; +} + +void AddressManager::handleLookupString(const QString& lookupString) { + // there are 4 possible lookup strings + + // 1. global place name (name of domain or place) - example: sanfrancisco + // 2. user name (prepended with @) - example: @philip + // 3. location string (posX,posY,posZ/eulerX,eulerY,eulerZ) + // 4. domain network address (IP or dns resolvable hostname) + + // use our regex'ed helpers to figure out what we're supposed to do with this + if (!lookupHandledAsUsername(lookupString) && + !lookupHandledAsNetworkAddress(lookupString) && + !lookupHandledAsLocationString(lookupString)) { + + } + + + +} + +bool AddressManager::lookupHandledAsNetworkAddress(const QString& lookupString) { + const QString IP_ADDRESS_REGEX_STRING = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}" + "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"; + const QString HOSTNAME_REGEX_STRING = "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*" + "([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$"; + + + + return false; +} + +bool AddressManager::lookupHandledAsLocationString(const QString& lookupString) { + const QString FLOAT_REGEX_STRING = "([-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?)"; + const QString TRIPLE_FLOAT_REGEX_STRING = FLOAT_REGEX_STRING + "\\s*,\\s*" + + FLOAT_REGEX_STRING + "\\s*,\\s*" + FLOAT_REGEX_STRING + "\\s*(?:$|\\/)"; + + QRegExp tripleFloatRegex(TRIPLE_FLOAT_REGEX_STRING); + + if (tripleFloatRegex.indexIn(lookupString) != -1) { + // we have at least a position, so emit our signal to say we need to change position + glm::vec3 newPosition(tripleFloatRegex.cap(1).toFloat(), + tripleFloatRegex.cap(2).toFloat(), + tripleFloatRegex.cap(3).toFloat()); + + if (newPosition.x != NAN && newPosition.y != NAN && newPosition.z != NAN) { + glm::vec3 newOrientation; + // we may also have an orientation + if (lookupString[tripleFloatRegex.matchedLength() - 1] == QChar('/') + && tripleFloatRegex.indexIn(lookupString, tripleFloatRegex.matchedLength() - 1) != -1) { + + glm::vec3 newOrientation(tripleFloatRegex.cap(1).toFloat(), + tripleFloatRegex.cap(2).toFloat(), + tripleFloatRegex.cap(3).toFloat()); + + if (newOrientation.x != NAN && newOrientation.y != NAN && newOrientation.z != NAN) { + emit locationChangeRequired(newPosition, true, newOrientation); + return true; + } else { + qDebug() << "Orientation parsed from lookup string is invalid. Will not use for location change."; + } + } + + emit locationChangeRequired(newPosition, false, newOrientation); + + } else { + qDebug() << "Could not jump to position from lookup string because it has an invalid value."; + } + + return true; + } + + return false; +} + +bool AddressManager::lookupHandledAsUsername(const QString& lookupString) { + const QString USERNAME_REGEX_STRING = "^@(\\S+)$"; + + QRegExp usernameRegex(USERNAME_REGEX_STRING); + + if (usernameRegex.indexIn(lookupString) != -1) { + // this is a username - pull the captured name and lookup that user's address + + return true; + } + + return false; +} diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h new file mode 100644 index 0000000000..5c1a5c2e89 --- /dev/null +++ b/libraries/networking/src/AddressManager.h @@ -0,0 +1,33 @@ +// +// AddressManager.h +// libraries/networking/src +// +// Created by Stephen Birarda on 2014-09-10. +// 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 +// + +#ifndef hifi_AddressManager_h +#define hifi_AddressManager_h + +#include + +#include + +class AddressManager : public QObject { + Q_OBJECT +public: + static AddressManager& getInstance(); + + void handleLookupString(const QString& lookupString); +signals: + void locationChangeRequired(const glm::vec3& newPosition, bool hasOrientationChange, const glm::vec3& newOrientation); +private: + bool lookupHandledAsNetworkAddress(const QString& lookupString); + bool lookupHandledAsLocationString(const QString& lookupString); + bool lookupHandledAsUsername(const QString& lookupString); +}; + +#endif // hifi_AddressManager_h \ No newline at end of file diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index f50f7493fb..604f8c7434 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -33,7 +33,7 @@ const char SOLO_NODE_TYPES[2] = { NodeType::AudioMixer }; -const QUrl DEFAULT_NODE_AUTH_URL = QUrl("https://data.highfidelity.io"); +const QUrl DEFAULT_NODE_AUTH_URL = QUrl("http://localhost:3000"); LimitedNodeList* LimitedNodeList::_sharedInstance = NULL;