mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 14:03:55 +02:00
Merge pull request #3404 from birarda/data-web-domain-lookup
initial transition to new metaverse API
This commit is contained in:
commit
b209b70094
31 changed files with 599 additions and 612 deletions
|
@ -189,6 +189,12 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) {
|
|||
populateDefaultStaticAssignmentsExcludingTypes(parsedTypes);
|
||||
|
||||
LimitedNodeList* nodeList = LimitedNodeList::createInstance(domainServerPort, domainServerDTLSPort);
|
||||
|
||||
const QString DOMAIN_CONFIG_ID_KEY = "id";
|
||||
|
||||
// set our LimitedNodeList UUID to match the UUID from our config
|
||||
// nodes will currently use this to add resources to data-web that relate to our domain
|
||||
nodeList->setSessionUUID(_argumentVariantMap.value(DOMAIN_CONFIG_ID_KEY).toString());
|
||||
|
||||
connect(nodeList, &LimitedNodeList::nodeAdded, this, &DomainServer::nodeAdded);
|
||||
connect(nodeList, &LimitedNodeList::nodeKilled, this, &DomainServer::nodeKilled);
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include <QMimeData>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <AddressManager.h>
|
||||
#include <AccountManager.h>
|
||||
#include <AudioInjector.h>
|
||||
#include <EntityScriptingInterface.h>
|
||||
|
@ -80,10 +81,10 @@
|
|||
#include "scripting/AccountScriptingInterface.h"
|
||||
#include "scripting/AudioDeviceScriptingInterface.h"
|
||||
#include "scripting/ClipboardScriptingInterface.h"
|
||||
#include "scripting/LocationScriptingInterface.h"
|
||||
#include "scripting/MenuScriptingInterface.h"
|
||||
#include "scripting/SettingsScriptingInterface.h"
|
||||
#include "scripting/WindowScriptingInterface.h"
|
||||
#include "scripting/LocationScriptingInterface.h"
|
||||
|
||||
#include "ui/InfoView.h"
|
||||
#include "ui/OAuthWebViewHandler.h"
|
||||
|
@ -358,9 +359,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
Particle::setVoxelEditPacketSender(&_voxelEditSender);
|
||||
Particle::setParticleEditPacketSender(&_particleEditSender);
|
||||
|
||||
// when -url in command line, teleport to location
|
||||
urlGoTo(argc, constArgv);
|
||||
|
||||
// For now we're going to set the PPS for outbound packets to be super high, this is
|
||||
// probably not the right long term solution. But for now, we're going to do this to
|
||||
// allow you to move a particle around in your hand
|
||||
|
@ -405,9 +403,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
|
||||
connect(_window, &MainWindow::windowGeometryChanged,
|
||||
_runningScriptsWidget, &RunningScriptsWidget::setBoundary);
|
||||
|
||||
AddressManager& addressManager = AddressManager::getInstance();
|
||||
|
||||
//When -url in command line, teleport to location
|
||||
urlGoTo(argc, constArgv);
|
||||
// connect to the domainChangeRequired signal on AddressManager
|
||||
connect(&addressManager, &AddressManager::possibleDomainChangeRequired,
|
||||
this, &Application::changeDomainHostname);
|
||||
|
||||
// when -url in command line, teleport to location
|
||||
addressManager.handleLookupString(getCmdOption(argc, constArgv, "-url"));
|
||||
|
||||
// call the OAuthWebviewHandler static getter so that its instance lives in our thread
|
||||
OAuthWebViewHandler::getInstance();
|
||||
|
@ -807,12 +811,14 @@ bool Application::event(QEvent* event) {
|
|||
// handle custom URL
|
||||
if (event->type() == QEvent::FileOpen) {
|
||||
QFileOpenEvent* fileEvent = static_cast<QFileOpenEvent*>(event);
|
||||
bool isHifiSchemeURL = !fileEvent->url().isEmpty() && fileEvent->url().toLocalFile().startsWith(CUSTOM_URL_SCHEME);
|
||||
if (isHifiSchemeURL) {
|
||||
Menu::getInstance()->goToURL(fileEvent->url().toLocalFile());
|
||||
|
||||
if (!fileEvent->url().isEmpty()) {
|
||||
AddressManager::getInstance().handleLookupString(fileEvent->url().toLocalFile());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return QApplication::event(event);
|
||||
}
|
||||
|
||||
|
@ -912,7 +918,12 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
|
||||
case Qt::Key_Return:
|
||||
case Qt::Key_Enter:
|
||||
Menu::getInstance()->triggerOption(MenuOption::Chat);
|
||||
if (isMeta) {
|
||||
Menu::getInstance()->triggerOption(MenuOption::AddressBar);
|
||||
} else {
|
||||
Menu::getInstance()->triggerOption(MenuOption::Chat);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Qt::Key_Up:
|
||||
|
@ -1059,10 +1070,6 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
case Qt::Key_Equal:
|
||||
_myAvatar->resetSize();
|
||||
break;
|
||||
|
||||
case Qt::Key_At:
|
||||
Menu::getInstance()->goTo();
|
||||
break;
|
||||
default:
|
||||
event->ignore();
|
||||
break;
|
||||
|
@ -1321,7 +1328,7 @@ void Application::dropEvent(QDropEvent *event) {
|
|||
SnapshotMetaData* snapshotData = Snapshot::parseSnapshotData(snapshotPath);
|
||||
if (snapshotData) {
|
||||
if (!snapshotData->getDomain().isEmpty()) {
|
||||
Menu::getInstance()->goToDomain(snapshotData->getDomain());
|
||||
changeDomainHostname(snapshotData->getDomain());
|
||||
}
|
||||
|
||||
_myAvatar->setPosition(snapshotData->getLocation());
|
||||
|
@ -3377,31 +3384,53 @@ 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);
|
||||
}
|
||||
|
||||
void Application::updateLocationInServer() {
|
||||
|
||||
AccountManager& accountManager = AccountManager::getInstance();
|
||||
|
||||
if (accountManager.isLoggedIn()) {
|
||||
const QUuid& domainUUID = NodeList::getInstance()->getDomainHandler().getUUID();
|
||||
|
||||
if (accountManager.isLoggedIn() && !domainUUID.isNull()) {
|
||||
|
||||
// construct a QJsonObject given the user's current address information
|
||||
QJsonObject updatedLocationObject;
|
||||
QJsonObject rootObject;
|
||||
|
||||
QJsonObject addressObject;
|
||||
addressObject.insert("position", QString(createByteArray(_myAvatar->getPosition())));
|
||||
addressObject.insert("orientation", QString(createByteArray(glm::degrees(safeEulerAngles(_myAvatar->getOrientation())))));
|
||||
addressObject.insert("domain", NodeList::getInstance()->getDomainHandler().getHostname());
|
||||
QJsonObject locationObject;
|
||||
|
||||
QString pathString = AddressManager::pathForPositionAndOrientation(_myAvatar->getPosition(),
|
||||
true,
|
||||
_myAvatar->getOrientation());
|
||||
|
||||
const QString LOCATION_KEY_IN_ROOT = "location";
|
||||
const QString PATH_KEY_IN_LOCATION = "path";
|
||||
const QString DOMAIN_ID_KEY_IN_LOCATION = "domain_id";
|
||||
|
||||
locationObject.insert(PATH_KEY_IN_LOCATION, pathString);
|
||||
locationObject.insert(DOMAIN_ID_KEY_IN_LOCATION, domainUUID.toString());
|
||||
|
||||
updatedLocationObject.insert("address", addressObject);
|
||||
rootObject.insert(LOCATION_KEY_IN_ROOT, locationObject);
|
||||
|
||||
accountManager.authenticatedRequest("/api/v1/users/address", QNetworkAccessManager::PutOperation,
|
||||
JSONCallbackParameters(), QJsonDocument(updatedLocationObject).toJson());
|
||||
accountManager.authenticatedRequest("/api/v1/users/location", QNetworkAccessManager::PutOperation,
|
||||
JSONCallbackParameters(), QJsonDocument(rootObject).toJson());
|
||||
}
|
||||
}
|
||||
|
||||
void Application::changeDomainHostname(const QString &newDomainHostname) {
|
||||
NodeList* nodeList = NodeList::getInstance();
|
||||
|
||||
if (!nodeList->getDomainHandler().isCurrentHostname(newDomainHostname)) {
|
||||
// tell the MyAvatar object to send a kill packet so that it dissapears from its old avatar mixer immediately
|
||||
_myAvatar->sendKillAvatar();
|
||||
|
||||
// call the domain hostname change as a queued connection on the nodelist
|
||||
QMetaObject::invokeMethod(&NodeList::getInstance()->getDomainHandler(), "setHostname",
|
||||
Q_ARG(const QString&, newDomainHostname));
|
||||
}
|
||||
}
|
||||
|
||||
void Application::domainChanged(const QString& domainHostname) {
|
||||
updateWindowTitle();
|
||||
|
||||
|
@ -3785,12 +3814,11 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser
|
|||
|
||||
QScriptValue windowValue = scriptEngine->registerGlobalObject("Window", WindowScriptingInterface::getInstance());
|
||||
scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter,
|
||||
LocationScriptingInterface::locationSetter, windowValue);
|
||||
|
||||
LocationScriptingInterface::locationSetter, windowValue);
|
||||
// register `location` on the global object.
|
||||
scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter,
|
||||
LocationScriptingInterface::locationSetter);
|
||||
|
||||
LocationScriptingInterface::locationSetter);
|
||||
|
||||
scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance());
|
||||
scriptEngine->registerGlobalObject("Settings", SettingsScriptingInterface::getInstance());
|
||||
scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance());
|
||||
|
@ -3918,6 +3946,15 @@ void Application::uploadAttachment() {
|
|||
uploadModel(ATTACHMENT_MODEL);
|
||||
}
|
||||
|
||||
void Application::openUrl(const QUrl& url) {
|
||||
if (url.scheme() == HIFI_URL_SCHEME) {
|
||||
AddressManager::getInstance().handleLookupString(url.toString());
|
||||
} else {
|
||||
// address manager did not handle - ask QDesktopServices to handle
|
||||
QDesktopServices::openUrl(url);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::domainSettingsReceived(const QJsonObject& domainSettingsObject) {
|
||||
|
||||
// from the domain-handler, figure out the satoshi cost per voxel and per meter cubed
|
||||
|
@ -4114,37 +4151,3 @@ void Application::takeSnapshot() {
|
|||
}
|
||||
_snapshotShareDialog->show();
|
||||
}
|
||||
|
||||
void Application::urlGoTo(int argc, const char * constArgv[]) {
|
||||
//Gets the url (hifi://domain/destination/orientation)
|
||||
QString customUrl = getCmdOption(argc, constArgv, "-url");
|
||||
if(customUrl.startsWith(CUSTOM_URL_SCHEME + "//")) {
|
||||
QStringList urlParts = customUrl.remove(0, CUSTOM_URL_SCHEME.length() + 2).split('/', QString::SkipEmptyParts);
|
||||
if (urlParts.count() == 1) {
|
||||
// location coordinates or place name
|
||||
QString domain = urlParts[0];
|
||||
Menu::goToDomain(domain);
|
||||
} else 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();
|
||||
|
||||
Menu::goToDomain(domain);
|
||||
|
||||
// goto either @user, #place, or x-xx,y-yy,z-zz
|
||||
// style co-ordinate.
|
||||
Menu::goTo(destination);
|
||||
|
||||
if (!orientation.isEmpty()) {
|
||||
// location orientation
|
||||
Menu::goToOrientation(orientation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,7 +114,6 @@ static const float NODE_KILLED_GREEN = 0.0f;
|
|||
static const float NODE_KILLED_BLUE = 0.0f;
|
||||
|
||||
static const QString SNAPSHOT_EXTENSION = ".jpg";
|
||||
static const QString CUSTOM_URL_SCHEME = "hifi:";
|
||||
|
||||
static const float BILLBOARD_FIELD_OF_VIEW = 30.0f; // degrees
|
||||
static const float BILLBOARD_DISTANCE = 5.0f; // meters
|
||||
|
@ -153,7 +152,6 @@ public:
|
|||
void initializeGL();
|
||||
void paintGL();
|
||||
void resizeGL(int width, int height);
|
||||
void urlGoTo(int argc, const char * constArgv[]);
|
||||
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
void keyReleaseEvent(QKeyEvent* event);
|
||||
|
@ -316,6 +314,7 @@ signals:
|
|||
void importDone();
|
||||
|
||||
public slots:
|
||||
void changeDomainHostname(const QString& newDomainHostname);
|
||||
void domainChanged(const QString& domainHostname);
|
||||
void updateWindowTitle();
|
||||
void updateLocationInServer();
|
||||
|
@ -355,6 +354,8 @@ public slots:
|
|||
void uploadHead();
|
||||
void uploadSkeleton();
|
||||
void uploadAttachment();
|
||||
|
||||
void openUrl(const QUrl& url);
|
||||
|
||||
void bumpSettings() { ++_numChangedSettings; }
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <QDesktopServices>
|
||||
|
||||
#include <AccountManager.h>
|
||||
#include <AddressManager.h>
|
||||
#include <XmppClient.h>
|
||||
#include <UUID.h>
|
||||
#include <UserActivityLogger.h>
|
||||
|
@ -155,21 +156,6 @@ Menu::Menu() :
|
|||
appInstance, SLOT(toggleRunningScriptsWidget()));
|
||||
|
||||
addDisabledActionAndSeparator(fileMenu, "Go");
|
||||
addActionToQMenuAndActionHash(fileMenu,
|
||||
MenuOption::GoHome,
|
||||
Qt::CTRL | Qt::Key_G,
|
||||
appInstance->getAvatar(),
|
||||
SLOT(goHome()));
|
||||
addActionToQMenuAndActionHash(fileMenu,
|
||||
MenuOption::GoToDomain,
|
||||
Qt::CTRL | Qt::Key_D,
|
||||
this,
|
||||
SLOT(goToDomainDialog()));
|
||||
addActionToQMenuAndActionHash(fileMenu,
|
||||
MenuOption::GoToLocation,
|
||||
Qt::CTRL | Qt::SHIFT | Qt::Key_L,
|
||||
this,
|
||||
SLOT(goToLocation()));
|
||||
addActionToQMenuAndActionHash(fileMenu,
|
||||
MenuOption::NameLocation,
|
||||
Qt::CTRL | Qt::Key_N,
|
||||
|
@ -181,12 +167,10 @@ Menu::Menu() :
|
|||
this,
|
||||
SLOT(toggleLocationList()));
|
||||
addActionToQMenuAndActionHash(fileMenu,
|
||||
MenuOption::GoTo,
|
||||
Qt::Key_At,
|
||||
MenuOption::AddressBar,
|
||||
Qt::CTRL | Qt::Key_Enter,
|
||||
this,
|
||||
SLOT(goTo()));
|
||||
connect(&LocationManager::getInstance(), &LocationManager::multipleDestinationsFound,
|
||||
this, &Menu::multipleDestinationsDecision);
|
||||
SLOT(toggleAddressBar()));
|
||||
|
||||
addDisabledActionAndSeparator(fileMenu, "Upload Avatar Model");
|
||||
addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadHead, 0, Application::getInstance(), SLOT(uploadHead()));
|
||||
|
@ -1155,147 +1139,25 @@ void Menu::changePrivateKey() {
|
|||
sendFakeEnterEvent();
|
||||
}
|
||||
|
||||
void Menu::goToDomain(const QString newDomain) {
|
||||
if (NodeList::getInstance()->getDomainHandler().getHostname() != newDomain) {
|
||||
// send a node kill request, indicating to other clients that they should play the "disappeared" effect
|
||||
Application::getInstance()->getAvatar()->sendKillAvatar();
|
||||
void Menu::toggleAddressBar() {
|
||||
|
||||
// give our nodeList the new domain-server hostname
|
||||
NodeList::getInstance()->getDomainHandler().setHostname(newDomain);
|
||||
QInputDialog addressBarDialog(Application::getInstance()->getWindow());
|
||||
addressBarDialog.setWindowTitle("Address Bar");
|
||||
addressBarDialog.setWindowFlags(Qt::Sheet);
|
||||
addressBarDialog.setLabelText("place, domain, @user, example.com, /position/orientation");
|
||||
|
||||
addressBarDialog.resize(addressBarDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW,
|
||||
addressBarDialog.size().height());
|
||||
|
||||
int dialogReturn = addressBarDialog.exec();
|
||||
if (dialogReturn == QDialog::Accepted && !addressBarDialog.textValue().isEmpty()) {
|
||||
// let the AddressManger figure out what to do with this
|
||||
AddressManager::getInstance().handleLookupString(addressBarDialog.textValue());
|
||||
}
|
||||
}
|
||||
|
||||
void Menu::goToDomainDialog() {
|
||||
|
||||
QString currentDomainHostname = NodeList::getInstance()->getDomainHandler().getHostname();
|
||||
|
||||
if (NodeList::getInstance()->getDomainHandler().getPort() != DEFAULT_DOMAIN_SERVER_PORT) {
|
||||
// add the port to the currentDomainHostname string if it is custom
|
||||
currentDomainHostname.append(QString(":%1").arg(NodeList::getInstance()->getDomainHandler().getPort()));
|
||||
}
|
||||
|
||||
QInputDialog domainDialog(Application::getInstance()->getWindow());
|
||||
domainDialog.setWindowTitle("Go to Domain");
|
||||
domainDialog.setLabelText("Domain server:");
|
||||
domainDialog.setTextValue(currentDomainHostname);
|
||||
domainDialog.resize(domainDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, domainDialog.size().height());
|
||||
|
||||
int dialogReturn = domainDialog.exec();
|
||||
if (dialogReturn == QDialog::Accepted) {
|
||||
QString newHostname(DEFAULT_DOMAIN_HOSTNAME);
|
||||
|
||||
if (domainDialog.textValue().size() > 0) {
|
||||
// the user input a new hostname, use that
|
||||
newHostname = domainDialog.textValue();
|
||||
}
|
||||
|
||||
goToDomain(newHostname);
|
||||
}
|
||||
|
||||
|
||||
sendFakeEnterEvent();
|
||||
}
|
||||
|
||||
void Menu::goToOrientation(QString orientation) {
|
||||
LocationManager::getInstance().goToOrientation(orientation);
|
||||
}
|
||||
|
||||
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");
|
||||
QString destination = QString();
|
||||
|
||||
gotoDialog.setTextValue(destination);
|
||||
gotoDialog.resize(gotoDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, gotoDialog.size().height());
|
||||
|
||||
int dialogReturn = gotoDialog.exec();
|
||||
if (dialogReturn == QDialog::Accepted && !gotoDialog.textValue().isEmpty()) {
|
||||
QString desiredDestination = gotoDialog.textValue();
|
||||
if (!goToURL(desiredDestination)) {;
|
||||
goTo(desiredDestination);
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
@ -1320,43 +1182,13 @@ 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));
|
||||
void Menu::displayNameLocationResponse(const QString& errorString) {
|
||||
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
|
||||
QMessageBox msgBox;
|
||||
switch (response) {
|
||||
case LocationManager::AlreadyExists:
|
||||
msgBox.setText("That name has been already claimed, try something else.");
|
||||
break;
|
||||
default:
|
||||
msgBox.setText("An unexpected error has occurred, please try again later.");
|
||||
break;
|
||||
}
|
||||
|
||||
msgBox.exec();
|
||||
if (!errorString.isEmpty()) {
|
||||
QMessageBox msgBox;
|
||||
msgBox.setText(errorString);
|
||||
msgBox.exec();
|
||||
}
|
||||
}
|
||||
|
||||
void Menu::toggleLocationList() {
|
||||
|
@ -1374,23 +1206,34 @@ void Menu::nameLocation() {
|
|||
// check if user is logged in or show login dialog if not
|
||||
|
||||
AccountManager& accountManager = AccountManager::getInstance();
|
||||
|
||||
if (!accountManager.isLoggedIn()) {
|
||||
QMessageBox msgBox;
|
||||
msgBox.setText("We need to tie this location to your username.");
|
||||
msgBox.setInformativeText("Please login first, then try naming the location again.");
|
||||
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
|
||||
msgBox.button(QMessageBox::Ok)->setText("Login");
|
||||
|
||||
if (msgBox.exec() == QMessageBox::Ok) {
|
||||
loginForCurrentDomain();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
DomainHandler& domainHandler = NodeList::getInstance()->getDomainHandler();
|
||||
if (domainHandler.getUUID().isNull()) {
|
||||
const QString UNREGISTERED_DOMAIN_MESSAGE = "This domain is not registered with High Fidelity."
|
||||
"\n\nYou cannot create a global location in an unregistered domain.";
|
||||
QMessageBox::critical(this, "Unregistered Domain", UNREGISTERED_DOMAIN_MESSAGE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
QInputDialog nameDialog(Application::getInstance()->getWindow());
|
||||
nameDialog.setWindowTitle("Name this location");
|
||||
nameDialog.setLabelText("Name this location, then share that name with others.\n"
|
||||
"When they come here, they'll be in the same location and orientation\n"
|
||||
"When they come here, they'll have the same viewpoint\n"
|
||||
"(wherever you are standing and looking now) as you.\n\n"
|
||||
"Location name:");
|
||||
|
||||
|
@ -1405,10 +1248,10 @@ void Menu::nameLocation() {
|
|||
|
||||
MyAvatar* myAvatar = Application::getInstance()->getAvatar();
|
||||
LocationManager* manager = new LocationManager();
|
||||
connect(manager, &LocationManager::creationCompleted, this, &Menu::namedLocationCreated);
|
||||
connect(manager, &LocationManager::creationCompleted, this, &Menu::displayNameLocationResponse);
|
||||
NamedLocation* location = new NamedLocation(locationName,
|
||||
myAvatar->getPosition(), myAvatar->getOrientation(),
|
||||
NodeList::getInstance()->getDomainHandler().getHostname());
|
||||
domainHandler.getUUID());
|
||||
manager->createNamedLocation(location);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -164,11 +164,6 @@ 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; }
|
||||
|
||||
|
@ -187,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 toggleAddressBar();
|
||||
void pasteToVoxel();
|
||||
void openUrl(const QUrl& url);
|
||||
|
||||
void toggleLoginMenuItem();
|
||||
|
||||
|
@ -213,8 +205,6 @@ private slots:
|
|||
void editAttachments();
|
||||
void editAnimations();
|
||||
void changePrivateKey();
|
||||
void goToDomainDialog();
|
||||
void goToLocation();
|
||||
void nameLocation();
|
||||
void toggleLocationList();
|
||||
void bandwidthDetailsClosed();
|
||||
|
@ -228,8 +218,7 @@ private slots:
|
|||
void toggleConsole();
|
||||
void toggleChat();
|
||||
void audioMuteToggled();
|
||||
void namedLocationCreated(LocationManager::NamedLocationCreateResponse response);
|
||||
void multipleDestinationsDecision(const QJsonObject& userData, const QJsonObject& placeData);
|
||||
void displayNameLocationResponse(const QString& errorString);
|
||||
void muteEnvironment();
|
||||
|
||||
private:
|
||||
|
@ -318,6 +307,7 @@ private:
|
|||
|
||||
namespace MenuOption {
|
||||
const QString AboutApp = "About Interface";
|
||||
const QString AddressBar = "Show Address Bar";
|
||||
const QString AlignForearmsWithWrists = "Align Forearms with Wrists";
|
||||
const QString AlternateIK = "Alternate IK";
|
||||
const QString AmbientOcclusion = "Ambient Occlusion";
|
||||
|
@ -403,10 +393,7 @@ namespace MenuOption {
|
|||
const QString FullscreenMirror = "Fullscreen Mirror";
|
||||
const QString GlowMode = "Cycle Glow Mode";
|
||||
const QString GlowWhenSpeaking = "Glow When Speaking";
|
||||
const QString GoHome = "Go Home";
|
||||
const QString GoToDomain = "Go To Domain...";
|
||||
const QString GoTo = "Go To...";
|
||||
const QString GoToLocation = "Go To Location...";
|
||||
const QString GoToUser = "Go To User";
|
||||
const QString HeadMouse = "Head Mouse";
|
||||
const QString IncreaseAvatarSize = "Increase Avatar Size";
|
||||
const QString IncreaseVoxelSize = "Increase Voxel Size";
|
||||
|
|
|
@ -421,11 +421,11 @@ void ModelUploader::uploadSuccess(const QJsonObject& jsonResponse) {
|
|||
checkS3();
|
||||
}
|
||||
|
||||
void ModelUploader::uploadFailed(QNetworkReply::NetworkError errorCode, const QString& errorString) {
|
||||
void ModelUploader::uploadFailed(QNetworkReply& errorReply) {
|
||||
if (_progressDialog) {
|
||||
_progressDialog->reject();
|
||||
}
|
||||
qDebug() << "Model upload failed (" << errorCode << "): " << errorString;
|
||||
qDebug() << "Model upload failed (" << errorReply.error() << "): " << errorReply.errorString();
|
||||
QMessageBox::warning(NULL,
|
||||
QString("ModelUploader::uploadFailed()"),
|
||||
QString("There was a problem with your upload, please try again later."),
|
||||
|
|
|
@ -43,7 +43,7 @@ private slots:
|
|||
void checkJSON(const QJsonObject& jsonResponse);
|
||||
void uploadUpdate(qint64 bytesSent, qint64 bytesTotal);
|
||||
void uploadSuccess(const QJsonObject& jsonResponse);
|
||||
void uploadFailed(QNetworkReply::NetworkError errorCode, const QString& errorString);
|
||||
void uploadFailed(QNetworkReply& errorReply);
|
||||
void checkS3();
|
||||
void processCheck();
|
||||
|
||||
|
|
|
@ -18,14 +18,13 @@
|
|||
#include "Application.h"
|
||||
#include "UserLocationsModel.h"
|
||||
|
||||
static const QString PLACES_GET = "/api/v1/places";
|
||||
static const QString PLACES_UPDATE = "/api/v1/places/%1";
|
||||
static const QString PLACES_DELETE= "/api/v1/places/%1";
|
||||
static const QString LOCATIONS_GET = "/api/v1/locations";
|
||||
static const QString LOCATION_UPDATE_OR_DELETE = "/api/v1/locations/%1";
|
||||
|
||||
UserLocation::UserLocation(QString id, QString name, QString location) :
|
||||
UserLocation::UserLocation(const QString& id, const QString& name, const QString& address) :
|
||||
_id(id),
|
||||
_name(name),
|
||||
_location(location),
|
||||
_address(address),
|
||||
_previousName(name),
|
||||
_updating(false) {
|
||||
}
|
||||
|
@ -35,10 +34,15 @@ void UserLocation::requestRename(const QString& newName) {
|
|||
_updating = true;
|
||||
|
||||
JSONCallbackParameters callbackParams(this, "handleRenameResponse", this, "handleRenameError");
|
||||
|
||||
QJsonObject jsonNameObject;
|
||||
jsonNameObject.insert("name", QJsonValue(newName));
|
||||
jsonNameObject.insert("name", newName);
|
||||
|
||||
QJsonObject locationObject;
|
||||
locationObject.insert("location", jsonNameObject);
|
||||
|
||||
QJsonDocument jsonDocument(jsonNameObject);
|
||||
AccountManager::getInstance().authenticatedRequest(PLACES_UPDATE.arg(_id),
|
||||
AccountManager::getInstance().authenticatedRequest(LOCATION_UPDATE_OR_DELETE.arg(_id),
|
||||
QNetworkAccessManager::PutOperation,
|
||||
callbackParams,
|
||||
jsonDocument.toJson());
|
||||
|
@ -54,7 +58,9 @@ void UserLocation::handleRenameResponse(const QJsonObject& responseData) {
|
|||
|
||||
QJsonValue status = responseData["status"];
|
||||
if (!status.isUndefined() && status.toString() == "success") {
|
||||
QString updatedName = responseData["data"].toObject()["name"].toString();
|
||||
qDebug() << responseData;
|
||||
QString updatedName = responseData["data"].toObject()["location"].toObject()["name"].toString();
|
||||
qDebug() << "The updated name is" << updatedName;
|
||||
_name = updatedName;
|
||||
} else {
|
||||
_name = _previousName;
|
||||
|
@ -75,10 +81,10 @@ void UserLocation::handleRenameResponse(const QJsonObject& responseData) {
|
|||
emit updated(_name);
|
||||
}
|
||||
|
||||
void UserLocation::handleRenameError(QNetworkReply::NetworkError error, const QString& errorString) {
|
||||
void UserLocation::handleRenameError(QNetworkReply& errorReply) {
|
||||
_updating = false;
|
||||
|
||||
QString msg = "There was an error renaming location '" + _name + "': " + errorString;
|
||||
QString msg = "There was an error renaming location '" + _name + "': " + errorReply.errorString();
|
||||
qDebug() << msg;
|
||||
QMessageBox::warning(Application::getInstance()->getWindow(), "Error", msg);
|
||||
|
||||
|
@ -90,7 +96,7 @@ void UserLocation::requestDelete() {
|
|||
_updating = true;
|
||||
|
||||
JSONCallbackParameters callbackParams(this, "handleDeleteResponse", this, "handleDeleteError");
|
||||
AccountManager::getInstance().authenticatedRequest(PLACES_DELETE.arg(_id),
|
||||
AccountManager::getInstance().authenticatedRequest(LOCATION_UPDATE_OR_DELETE.arg(_id),
|
||||
QNetworkAccessManager::DeleteOperation,
|
||||
callbackParams);
|
||||
}
|
||||
|
@ -109,10 +115,10 @@ void UserLocation::handleDeleteResponse(const QJsonObject& responseData) {
|
|||
}
|
||||
}
|
||||
|
||||
void UserLocation::handleDeleteError(QNetworkReply::NetworkError error, const QString& errorString) {
|
||||
void UserLocation::handleDeleteError(QNetworkReply& errorReply) {
|
||||
_updating = false;
|
||||
|
||||
QString msg = "There was an error deleting location '" + _name + "': " + errorString;
|
||||
QString msg = "There was an error deleting location '" + _name + "': " + errorReply.errorString();
|
||||
qDebug() << msg;
|
||||
QMessageBox::warning(Application::getInstance()->getWindow(), "Error", msg);
|
||||
}
|
||||
|
@ -153,7 +159,7 @@ void UserLocationsModel::refresh() {
|
|||
endResetModel();
|
||||
|
||||
JSONCallbackParameters callbackParams(this, "handleLocationsResponse");
|
||||
AccountManager::getInstance().authenticatedRequest(PLACES_GET,
|
||||
AccountManager::getInstance().authenticatedRequest(LOCATIONS_GET,
|
||||
QNetworkAccessManager::GetOperation,
|
||||
callbackParams);
|
||||
}
|
||||
|
@ -165,14 +171,13 @@ void UserLocationsModel::handleLocationsResponse(const QJsonObject& responseData
|
|||
QJsonValue status = responseData["status"];
|
||||
if (!status.isUndefined() && status.toString() == "success") {
|
||||
beginResetModel();
|
||||
QJsonArray locations = responseData["data"].toObject()["places"].toArray();
|
||||
QJsonArray locations = responseData["data"].toObject()["locations"].toArray();
|
||||
for (QJsonArray::const_iterator it = locations.constBegin(); it != locations.constEnd(); it++) {
|
||||
QJsonObject location = (*it).toObject();
|
||||
QJsonObject address = location["address"].toObject();
|
||||
QString locationAddress = "hifi://" + location["domain"].toObject()["name"].toString()
|
||||
+ location["path"].toString();
|
||||
UserLocation* userLocation = new UserLocation(location["id"].toString(), location["name"].toString(),
|
||||
"hifi://" + address["domain"].toString()
|
||||
+ "/" + address["position"].toString()
|
||||
+ "/" + address["orientation"].toString());
|
||||
locationAddress);
|
||||
_locations.append(userLocation);
|
||||
connect(userLocation, &UserLocation::deleted, this, &UserLocationsModel::removeLocation);
|
||||
connect(userLocation, &UserLocation::updated, this, &UserLocationsModel::update);
|
||||
|
@ -214,8 +219,8 @@ QVariant UserLocationsModel::data(const QModelIndex& index, int role) const {
|
|||
return QVariant();
|
||||
} else if (index.column() == NameColumn) {
|
||||
return _locations[index.row()]->name();
|
||||
} else if (index.column() == LocationColumn) {
|
||||
return QVariant(_locations[index.row()]->location());
|
||||
} else if (index.column() == AddressColumn) {
|
||||
return QVariant(_locations[index.row()]->address());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,7 +231,7 @@ QVariant UserLocationsModel::headerData(int section, Qt::Orientation orientation
|
|||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
||||
switch (section) {
|
||||
case NameColumn: return "Name";
|
||||
case LocationColumn: return "Location";
|
||||
case AddressColumn: return "Address";
|
||||
default: return QVariant();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,20 +20,20 @@
|
|||
class UserLocation : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
UserLocation(QString id, QString name, QString location);
|
||||
UserLocation(const QString& id, const QString& name, const QString& address);
|
||||
bool isUpdating() { return _updating; }
|
||||
void requestRename(const QString& newName);
|
||||
void requestDelete();
|
||||
|
||||
QString id() { return _id; }
|
||||
QString name() { return _name; }
|
||||
QString location() { return _location; }
|
||||
const QString& id() { return _id; }
|
||||
const QString& name() { return _name; }
|
||||
const QString& address() { return _address; }
|
||||
|
||||
public slots:
|
||||
void handleRenameResponse(const QJsonObject& responseData);
|
||||
void handleRenameError(QNetworkReply::NetworkError error, const QString& errorString);
|
||||
void handleRenameError(QNetworkReply& errorReply);
|
||||
void handleDeleteResponse(const QJsonObject& responseData);
|
||||
void handleDeleteError(QNetworkReply::NetworkError error, const QString& errorString);
|
||||
void handleDeleteError(QNetworkReply& errorReply);
|
||||
|
||||
signals:
|
||||
void updated(const QString& name);
|
||||
|
@ -42,7 +42,7 @@ signals:
|
|||
private:
|
||||
QString _id;
|
||||
QString _name;
|
||||
QString _location;
|
||||
QString _address;
|
||||
QString _previousName;
|
||||
bool _updating;
|
||||
|
||||
|
@ -65,7 +65,7 @@ public:
|
|||
|
||||
enum Columns {
|
||||
NameColumn = 0,
|
||||
LocationColumn
|
||||
AddressColumn
|
||||
};
|
||||
|
||||
public slots:
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <QtCore/QTimer>
|
||||
|
||||
#include <AccountManager.h>
|
||||
#include <AddressManager.h>
|
||||
#include <GeometryUtil.h>
|
||||
#include <NodeList.h>
|
||||
#include <PacketHeaders.h>
|
||||
|
@ -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() {
|
||||
|
@ -1763,11 +1767,6 @@ void MyAvatar::maybeUpdateBillboard() {
|
|||
sendBillboardPacket();
|
||||
}
|
||||
|
||||
void MyAvatar::goHome() {
|
||||
qDebug("Going Home!");
|
||||
slamPosition(START_LOCATION);
|
||||
}
|
||||
|
||||
void MyAvatar::increaseSize() {
|
||||
if ((1.0f + SCALING_RATIO) * _targetScale < MAX_AVATAR_SCALE) {
|
||||
_targetScale *= (1.0f + SCALING_RATIO);
|
||||
|
@ -1787,45 +1786,26 @@ 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::goToLocation(const glm::vec3& newPosition, bool hasOrientation, const glm::vec3& 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);
|
||||
}
|
||||
}
|
||||
|
||||
void MyAvatar::goToLocationFromAddress(const QJsonObject& locationObject) {
|
||||
// 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);
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
|
|
|
@ -150,13 +150,11 @@ public:
|
|||
const PlayerPointer getPlayer() const { return _player; }
|
||||
|
||||
public slots:
|
||||
void goHome();
|
||||
void increaseSize();
|
||||
void decreaseSize();
|
||||
void resetSize();
|
||||
|
||||
void goToLocationFromResponse(const QJsonObject& jsonObject);
|
||||
void goToLocationFromAddress(const QJsonObject& jsonObject);
|
||||
void goToLocation(const glm::vec3& newPosition, bool hasOrientation = false, const glm::vec3& newOrientation = glm::vec3());
|
||||
|
||||
// Set/Get update the thrust that will move the avatar around
|
||||
void addThrust(glm::vec3 newThrust) { _thrust += newThrust; };
|
||||
|
|
|
@ -9,43 +9,33 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <qjsonobject.h>
|
||||
|
||||
#include <AccountManager.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "LocationManager.h"
|
||||
#include <UserActivityLogger.h>
|
||||
|
||||
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 POST_PLACE_CREATE = "/api/v1/places/";
|
||||
|
||||
|
||||
LocationManager::LocationManager() {
|
||||
|
||||
};
|
||||
const QString POST_LOCATION_CREATE = "/api/v1/locations/";
|
||||
|
||||
LocationManager& LocationManager::getInstance() {
|
||||
static LocationManager sharedInstance;
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
const QString UNKNOWN_ERROR_MESSAGE = "Unknown error creating named location. Please try again!";
|
||||
|
||||
void LocationManager::namedLocationDataReceived(const QJsonObject& data) {
|
||||
if (data.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.contains("status") && data["status"].toString() == "success") {
|
||||
emit creationCompleted(LocationManager::Created);
|
||||
emit creationCompleted(QString());
|
||||
} else {
|
||||
emit creationCompleted(LocationManager::AlreadyExists);
|
||||
emit creationCompleted(UNKNOWN_ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
void LocationManager::errorDataReceived(QNetworkReply::NetworkError error, const QString& message) {
|
||||
emit creationCompleted(LocationManager::SystemError);
|
||||
}
|
||||
|
||||
void LocationManager::createNamedLocation(NamedLocation* namedLocation) {
|
||||
AccountManager& accountManager = AccountManager::getInstance();
|
||||
if (accountManager.isLoggedIn()) {
|
||||
|
@ -55,185 +45,45 @@ void LocationManager::createNamedLocation(NamedLocation* namedLocation) {
|
|||
callbackParams.errorCallbackReceiver = this;
|
||||
callbackParams.errorCallbackMethod = "errorDataReceived";
|
||||
|
||||
accountManager.authenticatedRequest(POST_PLACE_CREATE, QNetworkAccessManager::PostOperation,
|
||||
accountManager.authenticatedRequest(POST_LOCATION_CREATE, QNetworkAccessManager::PostOperation,
|
||||
callbackParams, namedLocation->toJsonString().toUtf8());
|
||||
}
|
||||
}
|
||||
|
||||
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";
|
||||
void LocationManager::errorDataReceived(QNetworkReply& errorReply) {
|
||||
|
||||
if (destination.startsWith("@")) {
|
||||
// remove '@' and go to user
|
||||
QString destinationUser = destination.remove(0, 1);
|
||||
UserActivityLogger::getInstance().wentTo(USER_DESTINATION_TYPE, destinationUser);
|
||||
goToUser(destinationUser);
|
||||
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);
|
||||
if (errorReply.header(QNetworkRequest::ContentTypeHeader).toString().startsWith("application/json")) {
|
||||
// we have some JSON error data we can parse for our error message
|
||||
QJsonDocument responseJson = QJsonDocument::fromJson(errorReply.readAll());
|
||||
|
||||
JSONCallbackParameters callbackParams;
|
||||
callbackParams.jsonCallbackReceiver = this;
|
||||
callbackParams.jsonCallbackMethod = "goToAddressFromResponse";
|
||||
callbackParams.errorCallbackReceiver = this;
|
||||
callbackParams.errorCallbackMethod = "handleAddressLookupError";
|
||||
QJsonObject dataObject = responseJson.object()["data"].toObject();
|
||||
|
||||
AccountManager::getInstance().authenticatedRequest(GET_ADDRESSES.arg(destination),
|
||||
QNetworkAccessManager::GetOperation,
|
||||
callbackParams);
|
||||
}
|
||||
}
|
||||
|
||||
void LocationManager::goToAddressFromResponse(const QJsonObject& responseData) {
|
||||
QJsonValue status = responseData["status"];
|
||||
|
||||
const QJsonObject& data = responseData["data"].toObject();
|
||||
const QJsonValue& userObject = data["user"];
|
||||
const QJsonValue& placeObject = data["place"];
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
void LocationManager::goToUser(QString userName) {
|
||||
JSONCallbackParameters callbackParams;
|
||||
callbackParams.jsonCallbackReceiver = Application::getInstance()->getAvatar();
|
||||
callbackParams.jsonCallbackMethod = "goToLocationFromResponse";
|
||||
callbackParams.errorCallbackReceiver = this;
|
||||
callbackParams.errorCallbackMethod = "handleAddressLookupError";
|
||||
|
||||
userName = QString(QUrl::toPercentEncoding(userName));
|
||||
AccountManager::getInstance().authenticatedRequest(GET_USER_ADDRESS.arg(userName),
|
||||
QNetworkAccessManager::GetOperation,
|
||||
callbackParams);
|
||||
}
|
||||
|
||||
void LocationManager::goToPlace(QString placeName) {
|
||||
JSONCallbackParameters callbackParams;
|
||||
callbackParams.jsonCallbackReceiver = Application::getInstance()->getAvatar();
|
||||
callbackParams.jsonCallbackMethod = "goToLocationFromResponse";
|
||||
callbackParams.errorCallbackReceiver = this;
|
||||
callbackParams.errorCallbackMethod = "handleAddressLookupError";
|
||||
|
||||
placeName = QString(QUrl::toPercentEncoding(placeName));
|
||||
AccountManager::getInstance().authenticatedRequest(GET_PLACE_ADDRESS.arg(placeName),
|
||||
QNetworkAccessManager::GetOperation,
|
||||
callbackParams);
|
||||
}
|
||||
|
||||
void LocationManager::goToOrientation(QString orientation) {
|
||||
if (orientation.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList orientationItems = orientation.remove(' ').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) {
|
||||
|
||||
// replace last occurrence of '_' with decimal point
|
||||
replaceLastOccurrence('-', '.', orientationItems[W_ITEM]);
|
||||
replaceLastOccurrence('-', '.', orientationItems[X_ITEM]);
|
||||
replaceLastOccurrence('-', '.', orientationItems[Y_ITEM]);
|
||||
replaceLastOccurrence('-', '.', orientationItems[Z_ITEM]);
|
||||
|
||||
double w = orientationItems[W_ITEM].toDouble();
|
||||
double x = orientationItems[X_ITEM].toDouble();
|
||||
double y = orientationItems[Y_ITEM].toDouble();
|
||||
double z = orientationItems[Z_ITEM].toDouble();
|
||||
|
||||
glm::quat newAvatarOrientation(w, x, y, z);
|
||||
|
||||
MyAvatar* myAvatar = Application::getInstance()->getAvatar();
|
||||
glm::quat avatarOrientation = myAvatar->getOrientation();
|
||||
if (newAvatarOrientation != avatarOrientation) {
|
||||
myAvatar->setOrientation(newAvatarOrientation);
|
||||
emit myAvatar->transformChanged();
|
||||
qDebug() << dataObject;
|
||||
|
||||
QString errorString = "There was a problem creating that location.\n";
|
||||
|
||||
// construct the error string from the returned attribute errors
|
||||
foreach(const QString& key, dataObject.keys()) {
|
||||
errorString += "\n\u2022 " + key + " - ";
|
||||
|
||||
QJsonValue keyedErrorValue = dataObject[key];
|
||||
|
||||
if (keyedErrorValue.isArray()) {
|
||||
foreach(const QJsonValue& attributeErrorValue, keyedErrorValue.toArray()) {
|
||||
errorString += attributeErrorValue.toString() + ", ";
|
||||
}
|
||||
|
||||
// remove the trailing comma at end of error list
|
||||
errorString.remove(errorString.length() - 2, 2);
|
||||
} else if (keyedErrorValue.isString()) {
|
||||
errorString += keyedErrorValue.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LocationManager::goToDestination(QString destination) {
|
||||
|
||||
QStringList coordinateItems = destination.remove(' ').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) {
|
||||
|
||||
// replace last occurrence of '_' with decimal point
|
||||
replaceLastOccurrence('-', '.', coordinateItems[X_ITEM]);
|
||||
replaceLastOccurrence('-', '.', coordinateItems[Y_ITEM]);
|
||||
replaceLastOccurrence('-', '.', coordinateItems[Z_ITEM]);
|
||||
|
||||
double x = coordinateItems[X_ITEM].toDouble();
|
||||
double y = coordinateItems[Y_ITEM].toDouble();
|
||||
double z = coordinateItems[Z_ITEM].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->slamPosition(newAvatarPos);
|
||||
emit myAvatar->transformChanged();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// no coordinates were parsed
|
||||
return false;
|
||||
}
|
||||
|
||||
void LocationManager::handleAddressLookupError(QNetworkReply::NetworkError networkError,
|
||||
const QString& errorString) {
|
||||
QString messageBoxString;
|
||||
|
||||
if (networkError == QNetworkReply::ContentNotFoundError) {
|
||||
messageBoxString = "That address could not be found.";
|
||||
|
||||
// emit our creationCompleted signal with the error
|
||||
emit creationCompleted(errorString);
|
||||
|
||||
} else {
|
||||
messageBoxString = errorString;
|
||||
}
|
||||
|
||||
QMessageBox::warning(Application::getInstance()->getWindow(), "", messageBoxString);
|
||||
}
|
||||
|
||||
void LocationManager::replaceLastOccurrence(const QChar search, const QChar replace, QString& string) {
|
||||
int lastIndex;
|
||||
lastIndex = string.lastIndexOf(search);
|
||||
if (lastIndex > 0) {
|
||||
lastIndex = string.lastIndexOf(search);
|
||||
string.replace(lastIndex, 1, replace);
|
||||
creationCompleted(UNKNOWN_ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
#define hifi_LocationManager_h
|
||||
|
||||
#include <QtCore>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
|
||||
#include "AccountManager.h"
|
||||
#include "NamedLocation.h"
|
||||
|
||||
class LocationManager : public QObject {
|
||||
|
@ -29,29 +29,14 @@ public:
|
|||
SystemError
|
||||
};
|
||||
|
||||
LocationManager();
|
||||
void createNamedLocation(NamedLocation* namedLocation);
|
||||
|
||||
void goTo(QString destination);
|
||||
void goToUser(QString userName);
|
||||
void goToPlace(QString placeName);
|
||||
void goToOrientation(QString orientation);
|
||||
bool goToDestination(QString destination);
|
||||
|
||||
public slots:
|
||||
void handleAddressLookupError(QNetworkReply::NetworkError networkError, const QString& errorString);
|
||||
|
||||
private:
|
||||
void replaceLastOccurrence(const QChar search, const QChar replace, QString& string);
|
||||
|
||||
signals:
|
||||
void creationCompleted(LocationManager::NamedLocationCreateResponse response);
|
||||
void multipleDestinationsFound(const QJsonObject& userData, const QJsonObject& placeData);
|
||||
void creationCompleted(const QString& errorMessage);
|
||||
|
||||
private slots:
|
||||
void namedLocationDataReceived(const QJsonObject& data);
|
||||
void errorDataReceived(QNetworkReply::NetworkError error, const QString& message);
|
||||
void goToAddressFromResponse(const QJsonObject& jsonObject);
|
||||
void errorDataReceived(QNetworkReply& errorReply);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -9,19 +9,25 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <AddressManager.h>
|
||||
#include <UUID.h>
|
||||
|
||||
#include "NamedLocation.h"
|
||||
|
||||
const QString JSON_FORMAT = "{\"address\":{\"position\":\"%1,%2,%3\","
|
||||
"\"orientation\":\"%4,%5,%6,%7\",\"domain\":\"%8\"},\"name\":\"%9\"}";
|
||||
NamedLocation::NamedLocation(const QString& name,
|
||||
const glm::vec3& position, const glm::quat& orientation,
|
||||
const QUuid& domainID) :
|
||||
_name(name),
|
||||
_position(position),
|
||||
_orientation(orientation),
|
||||
_domainID(domainID)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const QString JSON_FORMAT = "{\"location\":{\"path\":\"%1\",\"domain_id\":\"%2\",\"name\":\"%3\"}}";
|
||||
|
||||
QString NamedLocation::toJsonString() {
|
||||
return JSON_FORMAT.arg(QString::number(_location.x),
|
||||
QString::number(_location.y),
|
||||
QString::number(_location.z),
|
||||
QString::number(_orientation.w),
|
||||
QString::number(_orientation.x),
|
||||
QString::number(_orientation.y),
|
||||
QString::number(_orientation.z),
|
||||
_domain,
|
||||
_locationName);
|
||||
return JSON_FORMAT.arg(AddressManager::pathForPositionAndOrientation(_position, true, _orientation),
|
||||
uuidStringWithoutCurlyBraces(_domainID), _name);
|
||||
}
|
||||
|
|
|
@ -22,39 +22,33 @@ class NamedLocation : public QObject {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NamedLocation(QString locationName, glm::vec3 location, glm::quat orientation, QString domain) {
|
||||
_locationName = locationName;
|
||||
_location = location;
|
||||
_orientation = orientation;
|
||||
_domain = domain;
|
||||
}
|
||||
NamedLocation(const QString& name, const glm::vec3& position, const glm::quat& orientation, const QUuid& domainID);
|
||||
|
||||
QString toJsonString();
|
||||
|
||||
bool isEmpty() { return _locationName.isNull() || _locationName.isEmpty(); }
|
||||
bool isEmpty() { return _name.isNull() || _name.isEmpty(); }
|
||||
|
||||
void setLocationName(QString locationName) { _locationName = locationName; }
|
||||
QString locationName() { return _locationName; }
|
||||
void setName(QString name) { _name = name; }
|
||||
const QString& getName() const { return _name; }
|
||||
|
||||
void setLocation(glm::vec3 location) { _location = location; }
|
||||
glm::vec3 location() { return _location; }
|
||||
void setLocation(glm::vec3 position) { _position = position; }
|
||||
const glm::vec3& getPosition() const { return _position; }
|
||||
|
||||
void setOrientation(glm::quat orentation) { _orientation = orentation; }
|
||||
glm::quat orientation() { return _orientation; }
|
||||
void setOrientation(const glm::quat& orentation) { _orientation = orentation; }
|
||||
const glm::quat& getOrientation() const { return _orientation; }
|
||||
|
||||
void setDomain(QString domain) { _domain = domain; }
|
||||
QString domain() { return _domain; }
|
||||
void setDomainID(const QUuid& domainID) { _domainID = domainID; }
|
||||
const QUuid& getDomainID() const { return _domainID; }
|
||||
|
||||
signals:
|
||||
void dataReceived(bool locationExists);
|
||||
|
||||
private:
|
||||
|
||||
QString _locationName;
|
||||
QString _name;
|
||||
QString _createdBy;
|
||||
glm::vec3 _location;
|
||||
glm::vec3 _position;
|
||||
glm::quat _orientation;
|
||||
QString _domain;
|
||||
QUuid _domainID;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -29,10 +29,9 @@ QString LocationScriptingInterface::getHref() {
|
|||
}
|
||||
|
||||
QString LocationScriptingInterface::getPathname() {
|
||||
const glm::vec3& position = Application::getInstance()->getAvatar()->getPosition();
|
||||
QString path;
|
||||
path.sprintf("/%.4f,%.4f,%.4f", position.x, position.y, position.z);
|
||||
return path;
|
||||
MyAvatar* applicationAvatar = Application::getInstance()->getAvatar();
|
||||
return AddressManager::pathForPositionAndOrientation(applicationAvatar->getPosition(),
|
||||
true, applicationAvatar->getOrientation());
|
||||
}
|
||||
|
||||
QString LocationScriptingInterface::getHostname() {
|
||||
|
@ -40,7 +39,7 @@ QString LocationScriptingInterface::getHostname() {
|
|||
}
|
||||
|
||||
void LocationScriptingInterface::assign(const QString& url) {
|
||||
QMetaObject::invokeMethod(Menu::getInstance(), "goToURL", Q_ARG(const QString&, url));
|
||||
QMetaObject::invokeMethod(&AddressManager::getInstance(), "handleLookupString", Q_ARG(const QString&, url));
|
||||
}
|
||||
|
||||
QScriptValue LocationScriptingInterface::locationGetter(QScriptContext* context, QScriptEngine* engine) {
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include <QScriptValue>
|
||||
#include <QString>
|
||||
|
||||
#include <AddressManager.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
class LocationScriptingInterface : public QObject {
|
||||
|
@ -33,7 +35,7 @@ public:
|
|||
|
||||
bool isConnected();
|
||||
QString getHref();
|
||||
QString getProtocol() { return CUSTOM_URL_SCHEME; };
|
||||
QString getProtocol() { return HIFI_URL_SCHEME; };
|
||||
QString getPathname();
|
||||
QString getHostname();
|
||||
|
||||
|
|
|
@ -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, Application::getInstance(), &Application::openUrl);
|
||||
}
|
||||
|
||||
void ChatMessageArea::setHtml(const QString& html) {
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
#include <QSizePolicy>
|
||||
#include <QTimer>
|
||||
|
||||
#include <AddressManager.h>
|
||||
#include <AccountManager.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "ChatMessageArea.h"
|
||||
#include "FlowLayout.h"
|
||||
|
@ -28,7 +31,6 @@
|
|||
#include "ChatWindow.h"
|
||||
|
||||
|
||||
|
||||
const int NUM_MESSAGES_TO_TIME_STAMP = 20;
|
||||
|
||||
const QRegularExpression regexLinks("((?:(?:ftp)|(?:https?)|(?:hifi))://\\S+)");
|
||||
|
@ -169,7 +171,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());
|
||||
AddressManager::getInstance().goToUser(userVar.toString());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include <QtWebKitWidgets/QWebView>
|
||||
|
||||
#include <AccountManager.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
#include "OAuthWebViewHandler.h"
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include <QTimer>
|
||||
#include <QWidget>
|
||||
|
||||
#include <NetworkAccessManager.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "ScriptHighlighting.h"
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#include <QInputDialog>
|
||||
#include <QPushButton>
|
||||
|
||||
#include <AddressManager.h>
|
||||
|
||||
#include "Menu.h"
|
||||
#include "UserLocationsDialog.h"
|
||||
|
||||
|
@ -51,8 +53,8 @@ void UserLocationsDialog::updateEnabled() {
|
|||
}
|
||||
|
||||
void UserLocationsDialog::goToModelIndex(const QModelIndex& index) {
|
||||
QVariant location = _proxyModel.data(index.sibling(index.row(), UserLocationsModel::LocationColumn));
|
||||
Menu::getInstance()->goToURL(location.toString());
|
||||
QVariant address = _proxyModel.data(index.sibling(index.row(), UserLocationsModel::AddressColumn));
|
||||
AddressManager::getInstance().handleLookupString(address.toString());
|
||||
}
|
||||
|
||||
void UserLocationsDialog::deleteSelection() {
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "../../Application.h"
|
||||
#include <NetworkAccessManager.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
#include "BillboardOverlay.h"
|
||||
|
||||
|
|
|
@ -292,8 +292,7 @@ void AccountManager::passErrorToCallback(QNetworkReply* requestReply) {
|
|||
if (callbackParams.errorCallbackReceiver) {
|
||||
// invoke the right method on the callback receiver
|
||||
QMetaObject::invokeMethod(callbackParams.errorCallbackReceiver, qPrintable(callbackParams.errorCallbackMethod),
|
||||
Q_ARG(QNetworkReply::NetworkError, requestReply->error()),
|
||||
Q_ARG(const QString&, requestReply->errorString()));
|
||||
Q_ARG(QNetworkReply&, *requestReply));
|
||||
|
||||
// remove the related reply-callback group from the map
|
||||
_pendingCallbackMap.remove(requestReply);
|
||||
|
|
244
libraries/networking/src/AddressManager.cpp
Normal file
244
libraries/networking/src/AddressManager.cpp
Normal file
|
@ -0,0 +1,244 @@
|
|||
//
|
||||
// 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 <qdebug.h>
|
||||
#include <qregexp.h>
|
||||
#include <qstringlist.h>
|
||||
|
||||
#include <GLMHelpers.h>
|
||||
|
||||
#include "AddressManager.h"
|
||||
|
||||
AddressManager& AddressManager::getInstance() {
|
||||
static AddressManager sharedInstance;
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
QString AddressManager::pathForPositionAndOrientation(const glm::vec3& position, bool hasOrientation,
|
||||
const glm::quat& orientation) {
|
||||
|
||||
QString pathString = "/" + createByteArray(position);
|
||||
|
||||
if (hasOrientation) {
|
||||
QString orientationString = createByteArray(glm::degrees(safeEulerAngles(orientation)));
|
||||
pathString += "/" + orientationString;
|
||||
}
|
||||
|
||||
return pathString;
|
||||
}
|
||||
|
||||
const JSONCallbackParameters& AddressManager::apiCallbackParameters() {
|
||||
static bool hasSetupParameters = false;
|
||||
static JSONCallbackParameters callbackParams;
|
||||
|
||||
if (!hasSetupParameters) {
|
||||
callbackParams.jsonCallbackReceiver = this;
|
||||
callbackParams.jsonCallbackMethod = "handleAPIResponse";
|
||||
callbackParams.errorCallbackReceiver = this;
|
||||
callbackParams.errorCallbackMethod = "handleAPIError";
|
||||
}
|
||||
|
||||
return callbackParams;
|
||||
}
|
||||
|
||||
bool AddressManager::handleUrl(const QUrl& lookupUrl) {
|
||||
if (lookupUrl.scheme() == HIFI_URL_SCHEME) {
|
||||
|
||||
// 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)
|
||||
|
||||
qDebug() << lookupUrl;
|
||||
|
||||
if (lookupUrl.isRelative()) {
|
||||
// if this is a relative path then handle it as a relative viewpoint
|
||||
handleRelativeViewpoint(lookupUrl.path());
|
||||
} else {
|
||||
// use our regex'ed helpers to figure out what we're supposed to do with this
|
||||
if (!handleUsername(lookupUrl.authority())) {
|
||||
// we're assuming this is either a network address or global place name
|
||||
// check if it is a network address first
|
||||
if (!handleNetworkAddress(lookupUrl.host())) {
|
||||
// wasn't an address - lookup the place name
|
||||
attemptPlaceNameLookup(lookupUrl.host());
|
||||
}
|
||||
|
||||
// we may have a path that defines a relative viewpoint - if so we should jump to that now
|
||||
handleRelativeViewpoint(lookupUrl.path());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void AddressManager::handleLookupString(const QString& lookupString) {
|
||||
// we've verified that this is a valid hifi URL - hand it off to handleLookupString
|
||||
QString sanitizedString = lookupString;
|
||||
const QRegExp HIFI_SCHEME_REGEX = QRegExp(HIFI_URL_SCHEME + ":\\/{1,2}", Qt::CaseInsensitive);
|
||||
sanitizedString = sanitizedString.remove(HIFI_SCHEME_REGEX);
|
||||
|
||||
handleUrl(QUrl(HIFI_URL_SCHEME + "://" + sanitizedString));
|
||||
}
|
||||
|
||||
void AddressManager::handleAPIResponse(const QJsonObject &jsonObject) {
|
||||
QJsonObject dataObject = jsonObject["data"].toObject();
|
||||
|
||||
const QString ADDRESS_API_DOMAIN_KEY = "domain";
|
||||
const QString ADDRESS_API_ONLINE_KEY = "online";
|
||||
|
||||
if (!dataObject.contains(ADDRESS_API_ONLINE_KEY)
|
||||
|| dataObject[ADDRESS_API_ONLINE_KEY].toBool()) {
|
||||
|
||||
if (dataObject.contains(ADDRESS_API_DOMAIN_KEY)) {
|
||||
QJsonObject domainObject = dataObject[ADDRESS_API_DOMAIN_KEY].toObject();
|
||||
|
||||
const QString DOMAIN_NETWORK_ADDRESS_KEY = "network_address";
|
||||
QString domainHostname = domainObject[DOMAIN_NETWORK_ADDRESS_KEY].toString();
|
||||
|
||||
emit possibleDomainChangeRequired(domainHostname);
|
||||
|
||||
// take the path that came back
|
||||
const QString LOCATION_KEY = "location";
|
||||
const QString LOCATION_PATH_KEY = "path";
|
||||
QString returnedPath;
|
||||
|
||||
if (domainObject.contains(LOCATION_PATH_KEY)) {
|
||||
returnedPath = domainObject[LOCATION_PATH_KEY].toString();
|
||||
} else if (domainObject.contains(LOCATION_KEY)) {
|
||||
returnedPath = domainObject[LOCATION_KEY].toObject()[LOCATION_PATH_KEY].toString();
|
||||
}
|
||||
|
||||
if (!returnedPath.isEmpty()) {
|
||||
// try to parse this returned path as a viewpoint, that's the only thing it could be for now
|
||||
if (!handleRelativeViewpoint(returnedPath)) {
|
||||
qDebug() << "Received a location path that was could not be handled as a viewpoint -" << returnedPath;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
qDebug() << "Received an address manager API response with no domain key. Cannot parse.";
|
||||
qDebug() << jsonObject;
|
||||
}
|
||||
} else {
|
||||
// we've been told that this result exists but is offline, emit our signal so the application can handle
|
||||
emit lookupResultIsOffline();
|
||||
}
|
||||
}
|
||||
|
||||
void AddressManager::handleAPIError(QNetworkReply& errorReply) {
|
||||
qDebug() << "AddressManager API error -" << errorReply.error() << "-" << errorReply.errorString();
|
||||
}
|
||||
|
||||
const QString GET_PLACE = "/api/v1/places/%1";
|
||||
|
||||
void AddressManager::attemptPlaceNameLookup(const QString& lookupString) {
|
||||
// assume this is a place name and see if we can get any info on it
|
||||
QString placeName = QUrl::toPercentEncoding(lookupString);
|
||||
AccountManager::getInstance().authenticatedRequest(GET_PLACE.arg(placeName),
|
||||
QNetworkAccessManager::GetOperation,
|
||||
apiCallbackParameters());
|
||||
}
|
||||
|
||||
bool AddressManager::handleNetworkAddress(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])(:\\d{1,5})?$";
|
||||
|
||||
const QString HOSTNAME_REGEX_STRING = "^((?:[A-Z0-9]|[A-Z0-9][A-Z0-9\\-]{0,61}[A-Z0-9])"
|
||||
"(?:\\.(?:[A-Z0-9]|[A-Z0-9][A-Z0-9\\-]{0,61}[A-Z0-9]))+|localhost)(:{1}\\d{1,5})?$";
|
||||
|
||||
QRegExp hostnameRegex(HOSTNAME_REGEX_STRING, Qt::CaseInsensitive);
|
||||
|
||||
if (hostnameRegex.indexIn(lookupString) != -1) {
|
||||
emit possibleDomainChangeRequired(hostnameRegex.cap(0));
|
||||
return true;
|
||||
}
|
||||
|
||||
QRegExp ipAddressRegex(IP_ADDRESS_REGEX_STRING);
|
||||
|
||||
if (ipAddressRegex.indexIn(lookupString) != -1) {
|
||||
emit possibleDomainChangeRequired(ipAddressRegex.cap(0));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AddressManager::handleRelativeViewpoint(const QString& lookupString) {
|
||||
const QString FLOAT_REGEX_STRING = "([-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?)";
|
||||
const QString TRIPLE_FLOAT_REGEX_STRING = QString("\\/") + 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 (!isNaN(newPosition.x) && !isNaN(newPosition.y) && !isNaN(newPosition.z)) {
|
||||
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 (!isNaN(newOrientation.x) && !isNaN(newOrientation.y) && !isNaN(newOrientation.z)) {
|
||||
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;
|
||||
}
|
||||
|
||||
const QString GET_USER_LOCATION = "/api/v1/users/%1/location";
|
||||
|
||||
bool AddressManager::handleUsername(const QString& lookupString) {
|
||||
const QString USERNAME_REGEX_STRING = "^@(\\S+)";
|
||||
|
||||
QRegExp usernameRegex(USERNAME_REGEX_STRING);
|
||||
|
||||
if (usernameRegex.indexIn(lookupString) != -1) {
|
||||
goToUser(usernameRegex.cap(1));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void AddressManager::goToUser(const QString& username) {
|
||||
QString formattedUsername = QUrl::toPercentEncoding(username);
|
||||
// this is a username - pull the captured name and lookup that user's location
|
||||
AccountManager::getInstance().authenticatedRequest(GET_USER_LOCATION.arg(formattedUsername),
|
||||
QNetworkAccessManager::GetOperation,
|
||||
apiCallbackParameters());
|
||||
}
|
53
libraries/networking/src/AddressManager.h
Normal file
53
libraries/networking/src/AddressManager.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
//
|
||||
// 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 <qobject.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
#include "AccountManager.h"
|
||||
|
||||
static const QString HIFI_URL_SCHEME = "hifi";
|
||||
|
||||
class AddressManager : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static AddressManager& getInstance();
|
||||
|
||||
static QString pathForPositionAndOrientation(const glm::vec3& position, bool hasOrientation = false,
|
||||
const glm::quat& orientation = glm::quat());
|
||||
|
||||
void attemptPlaceNameLookup(const QString& lookupString);
|
||||
public slots:
|
||||
void handleLookupString(const QString& lookupString);
|
||||
|
||||
void handleAPIResponse(const QJsonObject& jsonObject);
|
||||
void handleAPIError(QNetworkReply& errorReply);
|
||||
void goToUser(const QString& username);
|
||||
signals:
|
||||
void lookupResultIsOffline();
|
||||
void possibleDomainChangeRequired(const QString& newHostname);
|
||||
void locationChangeRequired(const glm::vec3& newPosition, bool hasOrientationChange, const glm::vec3& newOrientation);
|
||||
private:
|
||||
const JSONCallbackParameters& apiCallbackParameters();
|
||||
|
||||
bool handleUrl(const QUrl& lookupUrl);
|
||||
|
||||
bool handleNetworkAddress(const QString& lookupString);
|
||||
bool handleRelativeViewpoint(const QString& pathSubsection);
|
||||
bool handleUsername(const QString& lookupString);
|
||||
};
|
||||
|
||||
#endif // hifi_AddressManager_h
|
|
@ -73,6 +73,22 @@ void DomainHandler::setSockAddr(const HifiSockAddr& sockAddr, const QString& hos
|
|||
_hostname = hostname;
|
||||
}
|
||||
|
||||
void DomainHandler::setUUID(const QUuid& uuid) {
|
||||
if (uuid != _uuid) {
|
||||
_uuid = uuid;
|
||||
qDebug() << "Domain uuid changed to" << uuidStringWithoutCurlyBraces(_uuid);
|
||||
}
|
||||
}
|
||||
|
||||
QString DomainHandler::hostnameWithoutPort(const QString& hostname) {
|
||||
int colonIndex = hostname.indexOf(':');
|
||||
return colonIndex > 0 ? hostname.left(colonIndex) : hostname;
|
||||
}
|
||||
|
||||
bool DomainHandler::isCurrentHostname(const QString& hostname) {
|
||||
return hostnameWithoutPort(hostname) == _hostname;
|
||||
}
|
||||
|
||||
void DomainHandler::setHostname(const QString& hostname) {
|
||||
|
||||
if (hostname != _hostname) {
|
||||
|
|
|
@ -37,10 +37,11 @@ public:
|
|||
void clearSettings();
|
||||
|
||||
const QUuid& getUUID() const { return _uuid; }
|
||||
void setUUID(const QUuid& uuid) { _uuid = uuid; }
|
||||
void setUUID(const QUuid& uuid);
|
||||
|
||||
static QString hostnameWithoutPort(const QString& hostname);
|
||||
bool isCurrentHostname(const QString& hostname);
|
||||
const QString& getHostname() const { return _hostname; }
|
||||
void setHostname(const QString& hostname);
|
||||
|
||||
const QHostAddress& getIP() const { return _sockAddr.getAddress(); }
|
||||
void setIPToLocalhost() { _sockAddr.setAddress(QHostAddress(QHostAddress::LocalHost)); }
|
||||
|
@ -63,6 +64,8 @@ public:
|
|||
void parseDTLSRequirementPacket(const QByteArray& dtlsRequirementPacket);
|
||||
|
||||
void softReset();
|
||||
public slots:
|
||||
void setHostname(const QString& hostname);
|
||||
|
||||
private slots:
|
||||
void completedHostnameLookup(const QHostInfo& hostInfo);
|
||||
|
|
|
@ -397,7 +397,10 @@ int NodeList::processDomainServerList(const QByteArray& packet) {
|
|||
_numNoReplyDomainCheckIns = 0;
|
||||
|
||||
// if this was the first domain-server list from this domain, we've now connected
|
||||
_domainHandler.setIsConnected(true);
|
||||
if (!_domainHandler.isConnected()) {
|
||||
_domainHandler.setUUID(uuidFromPacketHeader(packet));
|
||||
_domainHandler.setIsConnected(true);
|
||||
}
|
||||
|
||||
int readNodes = 0;
|
||||
|
||||
|
|
|
@ -73,8 +73,8 @@ void UserActivityLogger::requestFinished(const QJsonObject& object) {
|
|||
// qDebug() << object;
|
||||
}
|
||||
|
||||
void UserActivityLogger::requestError(QNetworkReply::NetworkError error,const QString& string) {
|
||||
qDebug() << error << ": " << string;
|
||||
void UserActivityLogger::requestError(QNetworkReply& errorReply) {
|
||||
qDebug() << errorReply.error() << "-" << errorReply.errorString();
|
||||
}
|
||||
|
||||
void UserActivityLogger::launch(QString applicationVersion) {
|
||||
|
|
|
@ -40,7 +40,7 @@ public slots:
|
|||
|
||||
private slots:
|
||||
void requestFinished(const QJsonObject& object);
|
||||
void requestError(QNetworkReply::NetworkError error,const QString& string);
|
||||
void requestError(QNetworkReply& errorReply);
|
||||
|
||||
private:
|
||||
UserActivityLogger();
|
||||
|
|
Loading…
Reference in a new issue