mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 04:37:48 +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);
|
populateDefaultStaticAssignmentsExcludingTypes(parsedTypes);
|
||||||
|
|
||||||
LimitedNodeList* nodeList = LimitedNodeList::createInstance(domainServerPort, domainServerDTLSPort);
|
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::nodeAdded, this, &DomainServer::nodeAdded);
|
||||||
connect(nodeList, &LimitedNodeList::nodeKilled, this, &DomainServer::nodeKilled);
|
connect(nodeList, &LimitedNodeList::nodeKilled, this, &DomainServer::nodeKilled);
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
#include <AddressManager.h>
|
||||||
#include <AccountManager.h>
|
#include <AccountManager.h>
|
||||||
#include <AudioInjector.h>
|
#include <AudioInjector.h>
|
||||||
#include <EntityScriptingInterface.h>
|
#include <EntityScriptingInterface.h>
|
||||||
|
@ -80,10 +81,10 @@
|
||||||
#include "scripting/AccountScriptingInterface.h"
|
#include "scripting/AccountScriptingInterface.h"
|
||||||
#include "scripting/AudioDeviceScriptingInterface.h"
|
#include "scripting/AudioDeviceScriptingInterface.h"
|
||||||
#include "scripting/ClipboardScriptingInterface.h"
|
#include "scripting/ClipboardScriptingInterface.h"
|
||||||
|
#include "scripting/LocationScriptingInterface.h"
|
||||||
#include "scripting/MenuScriptingInterface.h"
|
#include "scripting/MenuScriptingInterface.h"
|
||||||
#include "scripting/SettingsScriptingInterface.h"
|
#include "scripting/SettingsScriptingInterface.h"
|
||||||
#include "scripting/WindowScriptingInterface.h"
|
#include "scripting/WindowScriptingInterface.h"
|
||||||
#include "scripting/LocationScriptingInterface.h"
|
|
||||||
|
|
||||||
#include "ui/InfoView.h"
|
#include "ui/InfoView.h"
|
||||||
#include "ui/OAuthWebViewHandler.h"
|
#include "ui/OAuthWebViewHandler.h"
|
||||||
|
@ -358,9 +359,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
||||||
Particle::setVoxelEditPacketSender(&_voxelEditSender);
|
Particle::setVoxelEditPacketSender(&_voxelEditSender);
|
||||||
Particle::setParticleEditPacketSender(&_particleEditSender);
|
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
|
// 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
|
// 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
|
// 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,
|
connect(_window, &MainWindow::windowGeometryChanged,
|
||||||
_runningScriptsWidget, &RunningScriptsWidget::setBoundary);
|
_runningScriptsWidget, &RunningScriptsWidget::setBoundary);
|
||||||
|
|
||||||
|
AddressManager& addressManager = AddressManager::getInstance();
|
||||||
|
|
||||||
//When -url in command line, teleport to location
|
// connect to the domainChangeRequired signal on AddressManager
|
||||||
urlGoTo(argc, constArgv);
|
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
|
// call the OAuthWebviewHandler static getter so that its instance lives in our thread
|
||||||
OAuthWebViewHandler::getInstance();
|
OAuthWebViewHandler::getInstance();
|
||||||
|
@ -807,12 +811,14 @@ bool Application::event(QEvent* event) {
|
||||||
// handle custom URL
|
// handle custom URL
|
||||||
if (event->type() == QEvent::FileOpen) {
|
if (event->type() == QEvent::FileOpen) {
|
||||||
QFileOpenEvent* fileEvent = static_cast<QFileOpenEvent*>(event);
|
QFileOpenEvent* fileEvent = static_cast<QFileOpenEvent*>(event);
|
||||||
bool isHifiSchemeURL = !fileEvent->url().isEmpty() && fileEvent->url().toLocalFile().startsWith(CUSTOM_URL_SCHEME);
|
|
||||||
if (isHifiSchemeURL) {
|
if (!fileEvent->url().isEmpty()) {
|
||||||
Menu::getInstance()->goToURL(fileEvent->url().toLocalFile());
|
AddressManager::getInstance().handleLookupString(fileEvent->url().toLocalFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return QApplication::event(event);
|
return QApplication::event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -912,7 +918,12 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
||||||
|
|
||||||
case Qt::Key_Return:
|
case Qt::Key_Return:
|
||||||
case Qt::Key_Enter:
|
case Qt::Key_Enter:
|
||||||
Menu::getInstance()->triggerOption(MenuOption::Chat);
|
if (isMeta) {
|
||||||
|
Menu::getInstance()->triggerOption(MenuOption::AddressBar);
|
||||||
|
} else {
|
||||||
|
Menu::getInstance()->triggerOption(MenuOption::Chat);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Qt::Key_Up:
|
case Qt::Key_Up:
|
||||||
|
@ -1059,10 +1070,6 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
||||||
case Qt::Key_Equal:
|
case Qt::Key_Equal:
|
||||||
_myAvatar->resetSize();
|
_myAvatar->resetSize();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Qt::Key_At:
|
|
||||||
Menu::getInstance()->goTo();
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
event->ignore();
|
event->ignore();
|
||||||
break;
|
break;
|
||||||
|
@ -1321,7 +1328,7 @@ void Application::dropEvent(QDropEvent *event) {
|
||||||
SnapshotMetaData* snapshotData = Snapshot::parseSnapshotData(snapshotPath);
|
SnapshotMetaData* snapshotData = Snapshot::parseSnapshotData(snapshotPath);
|
||||||
if (snapshotData) {
|
if (snapshotData) {
|
||||||
if (!snapshotData->getDomain().isEmpty()) {
|
if (!snapshotData->getDomain().isEmpty()) {
|
||||||
Menu::getInstance()->goToDomain(snapshotData->getDomain());
|
changeDomainHostname(snapshotData->getDomain());
|
||||||
}
|
}
|
||||||
|
|
||||||
_myAvatar->setPosition(snapshotData->getLocation());
|
_myAvatar->setPosition(snapshotData->getLocation());
|
||||||
|
@ -3377,31 +3384,53 @@ void Application::updateWindowTitle(){
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
// crashes with vs2013/win32
|
// crashes with vs2013/win32
|
||||||
qDebug("Application title set to: %s", title.toStdString().c_str());
|
qDebug("Application title set to: %s", title.toStdString().c_str());
|
||||||
#endif //!WIN32
|
#endif
|
||||||
_window->setWindowTitle(title);
|
_window->setWindowTitle(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateLocationInServer() {
|
void Application::updateLocationInServer() {
|
||||||
|
|
||||||
AccountManager& accountManager = AccountManager::getInstance();
|
AccountManager& accountManager = AccountManager::getInstance();
|
||||||
|
const QUuid& domainUUID = NodeList::getInstance()->getDomainHandler().getUUID();
|
||||||
if (accountManager.isLoggedIn()) {
|
|
||||||
|
if (accountManager.isLoggedIn() && !domainUUID.isNull()) {
|
||||||
|
|
||||||
// construct a QJsonObject given the user's current address information
|
// construct a QJsonObject given the user's current address information
|
||||||
QJsonObject updatedLocationObject;
|
QJsonObject rootObject;
|
||||||
|
|
||||||
QJsonObject addressObject;
|
QJsonObject locationObject;
|
||||||
addressObject.insert("position", QString(createByteArray(_myAvatar->getPosition())));
|
|
||||||
addressObject.insert("orientation", QString(createByteArray(glm::degrees(safeEulerAngles(_myAvatar->getOrientation())))));
|
QString pathString = AddressManager::pathForPositionAndOrientation(_myAvatar->getPosition(),
|
||||||
addressObject.insert("domain", NodeList::getInstance()->getDomainHandler().getHostname());
|
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,
|
accountManager.authenticatedRequest("/api/v1/users/location", QNetworkAccessManager::PutOperation,
|
||||||
JSONCallbackParameters(), QJsonDocument(updatedLocationObject).toJson());
|
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) {
|
void Application::domainChanged(const QString& domainHostname) {
|
||||||
updateWindowTitle();
|
updateWindowTitle();
|
||||||
|
|
||||||
|
@ -3785,12 +3814,11 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser
|
||||||
|
|
||||||
QScriptValue windowValue = scriptEngine->registerGlobalObject("Window", WindowScriptingInterface::getInstance());
|
QScriptValue windowValue = scriptEngine->registerGlobalObject("Window", WindowScriptingInterface::getInstance());
|
||||||
scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter,
|
scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter,
|
||||||
LocationScriptingInterface::locationSetter, windowValue);
|
LocationScriptingInterface::locationSetter, windowValue);
|
||||||
|
|
||||||
// register `location` on the global object.
|
// register `location` on the global object.
|
||||||
scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter,
|
scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter,
|
||||||
LocationScriptingInterface::locationSetter);
|
LocationScriptingInterface::locationSetter);
|
||||||
|
|
||||||
scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance());
|
scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance());
|
||||||
scriptEngine->registerGlobalObject("Settings", SettingsScriptingInterface::getInstance());
|
scriptEngine->registerGlobalObject("Settings", SettingsScriptingInterface::getInstance());
|
||||||
scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance());
|
scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance());
|
||||||
|
@ -3918,6 +3946,15 @@ void Application::uploadAttachment() {
|
||||||
uploadModel(ATTACHMENT_MODEL);
|
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) {
|
void Application::domainSettingsReceived(const QJsonObject& domainSettingsObject) {
|
||||||
|
|
||||||
// from the domain-handler, figure out the satoshi cost per voxel and per meter cubed
|
// from the domain-handler, figure out the satoshi cost per voxel and per meter cubed
|
||||||
|
@ -4114,37 +4151,3 @@ void Application::takeSnapshot() {
|
||||||
}
|
}
|
||||||
_snapshotShareDialog->show();
|
_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 float NODE_KILLED_BLUE = 0.0f;
|
||||||
|
|
||||||
static const QString SNAPSHOT_EXTENSION = ".jpg";
|
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_FIELD_OF_VIEW = 30.0f; // degrees
|
||||||
static const float BILLBOARD_DISTANCE = 5.0f; // meters
|
static const float BILLBOARD_DISTANCE = 5.0f; // meters
|
||||||
|
@ -153,7 +152,6 @@ public:
|
||||||
void initializeGL();
|
void initializeGL();
|
||||||
void paintGL();
|
void paintGL();
|
||||||
void resizeGL(int width, int height);
|
void resizeGL(int width, int height);
|
||||||
void urlGoTo(int argc, const char * constArgv[]);
|
|
||||||
|
|
||||||
void keyPressEvent(QKeyEvent* event);
|
void keyPressEvent(QKeyEvent* event);
|
||||||
void keyReleaseEvent(QKeyEvent* event);
|
void keyReleaseEvent(QKeyEvent* event);
|
||||||
|
@ -316,6 +314,7 @@ signals:
|
||||||
void importDone();
|
void importDone();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
void changeDomainHostname(const QString& newDomainHostname);
|
||||||
void domainChanged(const QString& domainHostname);
|
void domainChanged(const QString& domainHostname);
|
||||||
void updateWindowTitle();
|
void updateWindowTitle();
|
||||||
void updateLocationInServer();
|
void updateLocationInServer();
|
||||||
|
@ -355,6 +354,8 @@ public slots:
|
||||||
void uploadHead();
|
void uploadHead();
|
||||||
void uploadSkeleton();
|
void uploadSkeleton();
|
||||||
void uploadAttachment();
|
void uploadAttachment();
|
||||||
|
|
||||||
|
void openUrl(const QUrl& url);
|
||||||
|
|
||||||
void bumpSettings() { ++_numChangedSettings; }
|
void bumpSettings() { ++_numChangedSettings; }
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
|
|
||||||
#include <AccountManager.h>
|
#include <AccountManager.h>
|
||||||
|
#include <AddressManager.h>
|
||||||
#include <XmppClient.h>
|
#include <XmppClient.h>
|
||||||
#include <UUID.h>
|
#include <UUID.h>
|
||||||
#include <UserActivityLogger.h>
|
#include <UserActivityLogger.h>
|
||||||
|
@ -155,21 +156,6 @@ Menu::Menu() :
|
||||||
appInstance, SLOT(toggleRunningScriptsWidget()));
|
appInstance, SLOT(toggleRunningScriptsWidget()));
|
||||||
|
|
||||||
addDisabledActionAndSeparator(fileMenu, "Go");
|
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,
|
addActionToQMenuAndActionHash(fileMenu,
|
||||||
MenuOption::NameLocation,
|
MenuOption::NameLocation,
|
||||||
Qt::CTRL | Qt::Key_N,
|
Qt::CTRL | Qt::Key_N,
|
||||||
|
@ -181,12 +167,10 @@ Menu::Menu() :
|
||||||
this,
|
this,
|
||||||
SLOT(toggleLocationList()));
|
SLOT(toggleLocationList()));
|
||||||
addActionToQMenuAndActionHash(fileMenu,
|
addActionToQMenuAndActionHash(fileMenu,
|
||||||
MenuOption::GoTo,
|
MenuOption::AddressBar,
|
||||||
Qt::Key_At,
|
Qt::CTRL | Qt::Key_Enter,
|
||||||
this,
|
this,
|
||||||
SLOT(goTo()));
|
SLOT(toggleAddressBar()));
|
||||||
connect(&LocationManager::getInstance(), &LocationManager::multipleDestinationsFound,
|
|
||||||
this, &Menu::multipleDestinationsDecision);
|
|
||||||
|
|
||||||
addDisabledActionAndSeparator(fileMenu, "Upload Avatar Model");
|
addDisabledActionAndSeparator(fileMenu, "Upload Avatar Model");
|
||||||
addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadHead, 0, Application::getInstance(), SLOT(uploadHead()));
|
addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadHead, 0, Application::getInstance(), SLOT(uploadHead()));
|
||||||
|
@ -1155,147 +1139,25 @@ void Menu::changePrivateKey() {
|
||||||
sendFakeEnterEvent();
|
sendFakeEnterEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::goToDomain(const QString newDomain) {
|
void Menu::toggleAddressBar() {
|
||||||
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();
|
|
||||||
|
|
||||||
// give our nodeList the new domain-server hostname
|
QInputDialog addressBarDialog(Application::getInstance()->getWindow());
|
||||||
NodeList::getInstance()->getDomainHandler().setHostname(newDomain);
|
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();
|
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() {
|
void Menu::muteEnvironment() {
|
||||||
int headerSize = numBytesForPacketHeaderGivenPacketType(PacketTypeMuteEnvironment);
|
int headerSize = numBytesForPacketHeaderGivenPacketType(PacketTypeMuteEnvironment);
|
||||||
int packetSize = headerSize + sizeof(glm::vec3) + sizeof(float);
|
int packetSize = headerSize + sizeof(glm::vec3) + sizeof(float);
|
||||||
|
@ -1320,43 +1182,13 @@ void Menu::muteEnvironment() {
|
||||||
free(packet);
|
free(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::goToLocation() {
|
void Menu::displayNameLocationResponse(const QString& errorString) {
|
||||||
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());
|
if (!errorString.isEmpty()) {
|
||||||
coordinateDialog.setWindowTitle("Go to Location");
|
QMessageBox msgBox;
|
||||||
coordinateDialog.setLabelText("Coordinate as x,y,z:");
|
msgBox.setText(errorString);
|
||||||
coordinateDialog.setTextValue(currentLocation);
|
msgBox.exec();
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::toggleLocationList() {
|
void Menu::toggleLocationList() {
|
||||||
|
@ -1374,23 +1206,34 @@ void Menu::nameLocation() {
|
||||||
// check if user is logged in or show login dialog if not
|
// check if user is logged in or show login dialog if not
|
||||||
|
|
||||||
AccountManager& accountManager = AccountManager::getInstance();
|
AccountManager& accountManager = AccountManager::getInstance();
|
||||||
|
|
||||||
if (!accountManager.isLoggedIn()) {
|
if (!accountManager.isLoggedIn()) {
|
||||||
QMessageBox msgBox;
|
QMessageBox msgBox;
|
||||||
msgBox.setText("We need to tie this location to your username.");
|
msgBox.setText("We need to tie this location to your username.");
|
||||||
msgBox.setInformativeText("Please login first, then try naming the location again.");
|
msgBox.setInformativeText("Please login first, then try naming the location again.");
|
||||||
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
|
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
|
||||||
msgBox.button(QMessageBox::Ok)->setText("Login");
|
msgBox.button(QMessageBox::Ok)->setText("Login");
|
||||||
|
|
||||||
if (msgBox.exec() == QMessageBox::Ok) {
|
if (msgBox.exec() == QMessageBox::Ok) {
|
||||||
loginForCurrentDomain();
|
loginForCurrentDomain();
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
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());
|
QInputDialog nameDialog(Application::getInstance()->getWindow());
|
||||||
nameDialog.setWindowTitle("Name this location");
|
nameDialog.setWindowTitle("Name this location");
|
||||||
nameDialog.setLabelText("Name this location, then share that name with others.\n"
|
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"
|
"(wherever you are standing and looking now) as you.\n\n"
|
||||||
"Location name:");
|
"Location name:");
|
||||||
|
|
||||||
|
@ -1405,10 +1248,10 @@ void Menu::nameLocation() {
|
||||||
|
|
||||||
MyAvatar* myAvatar = Application::getInstance()->getAvatar();
|
MyAvatar* myAvatar = Application::getInstance()->getAvatar();
|
||||||
LocationManager* manager = new LocationManager();
|
LocationManager* manager = new LocationManager();
|
||||||
connect(manager, &LocationManager::creationCompleted, this, &Menu::namedLocationCreated);
|
connect(manager, &LocationManager::creationCompleted, this, &Menu::displayNameLocationResponse);
|
||||||
NamedLocation* location = new NamedLocation(locationName,
|
NamedLocation* location = new NamedLocation(locationName,
|
||||||
myAvatar->getPosition(), myAvatar->getOrientation(),
|
myAvatar->getPosition(), myAvatar->getOrientation(),
|
||||||
NodeList::getInstance()->getDomainHandler().getHostname());
|
domainHandler.getUUID());
|
||||||
manager->createNamedLocation(location);
|
manager->createNamedLocation(location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,11 +164,6 @@ public:
|
||||||
int menuItemLocation = UNSPECIFIED_POSITION);
|
int menuItemLocation = UNSPECIFIED_POSITION);
|
||||||
|
|
||||||
void removeAction(QMenu* menu, const QString& actionName);
|
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; }
|
const QByteArray& getWalletPrivateKey() const { return _walletPrivateKey; }
|
||||||
|
|
||||||
|
@ -187,11 +182,8 @@ public slots:
|
||||||
void saveSettings(QSettings* settings = NULL);
|
void saveSettings(QSettings* settings = NULL);
|
||||||
void importSettings();
|
void importSettings();
|
||||||
void exportSettings();
|
void exportSettings();
|
||||||
void goTo();
|
void toggleAddressBar();
|
||||||
bool goToURL(QString location);
|
|
||||||
void goToUser(const QString& user);
|
|
||||||
void pasteToVoxel();
|
void pasteToVoxel();
|
||||||
void openUrl(const QUrl& url);
|
|
||||||
|
|
||||||
void toggleLoginMenuItem();
|
void toggleLoginMenuItem();
|
||||||
|
|
||||||
|
@ -213,8 +205,6 @@ private slots:
|
||||||
void editAttachments();
|
void editAttachments();
|
||||||
void editAnimations();
|
void editAnimations();
|
||||||
void changePrivateKey();
|
void changePrivateKey();
|
||||||
void goToDomainDialog();
|
|
||||||
void goToLocation();
|
|
||||||
void nameLocation();
|
void nameLocation();
|
||||||
void toggleLocationList();
|
void toggleLocationList();
|
||||||
void bandwidthDetailsClosed();
|
void bandwidthDetailsClosed();
|
||||||
|
@ -228,8 +218,7 @@ private slots:
|
||||||
void toggleConsole();
|
void toggleConsole();
|
||||||
void toggleChat();
|
void toggleChat();
|
||||||
void audioMuteToggled();
|
void audioMuteToggled();
|
||||||
void namedLocationCreated(LocationManager::NamedLocationCreateResponse response);
|
void displayNameLocationResponse(const QString& errorString);
|
||||||
void multipleDestinationsDecision(const QJsonObject& userData, const QJsonObject& placeData);
|
|
||||||
void muteEnvironment();
|
void muteEnvironment();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -318,6 +307,7 @@ private:
|
||||||
|
|
||||||
namespace MenuOption {
|
namespace MenuOption {
|
||||||
const QString AboutApp = "About Interface";
|
const QString AboutApp = "About Interface";
|
||||||
|
const QString AddressBar = "Show Address Bar";
|
||||||
const QString AlignForearmsWithWrists = "Align Forearms with Wrists";
|
const QString AlignForearmsWithWrists = "Align Forearms with Wrists";
|
||||||
const QString AlternateIK = "Alternate IK";
|
const QString AlternateIK = "Alternate IK";
|
||||||
const QString AmbientOcclusion = "Ambient Occlusion";
|
const QString AmbientOcclusion = "Ambient Occlusion";
|
||||||
|
@ -403,10 +393,7 @@ namespace MenuOption {
|
||||||
const QString FullscreenMirror = "Fullscreen Mirror";
|
const QString FullscreenMirror = "Fullscreen Mirror";
|
||||||
const QString GlowMode = "Cycle Glow Mode";
|
const QString GlowMode = "Cycle Glow Mode";
|
||||||
const QString GlowWhenSpeaking = "Glow When Speaking";
|
const QString GlowWhenSpeaking = "Glow When Speaking";
|
||||||
const QString GoHome = "Go Home";
|
const QString GoToUser = "Go To User";
|
||||||
const QString GoToDomain = "Go To Domain...";
|
|
||||||
const QString GoTo = "Go To...";
|
|
||||||
const QString GoToLocation = "Go To Location...";
|
|
||||||
const QString HeadMouse = "Head Mouse";
|
const QString HeadMouse = "Head Mouse";
|
||||||
const QString IncreaseAvatarSize = "Increase Avatar Size";
|
const QString IncreaseAvatarSize = "Increase Avatar Size";
|
||||||
const QString IncreaseVoxelSize = "Increase Voxel Size";
|
const QString IncreaseVoxelSize = "Increase Voxel Size";
|
||||||
|
|
|
@ -421,11 +421,11 @@ void ModelUploader::uploadSuccess(const QJsonObject& jsonResponse) {
|
||||||
checkS3();
|
checkS3();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelUploader::uploadFailed(QNetworkReply::NetworkError errorCode, const QString& errorString) {
|
void ModelUploader::uploadFailed(QNetworkReply& errorReply) {
|
||||||
if (_progressDialog) {
|
if (_progressDialog) {
|
||||||
_progressDialog->reject();
|
_progressDialog->reject();
|
||||||
}
|
}
|
||||||
qDebug() << "Model upload failed (" << errorCode << "): " << errorString;
|
qDebug() << "Model upload failed (" << errorReply.error() << "): " << errorReply.errorString();
|
||||||
QMessageBox::warning(NULL,
|
QMessageBox::warning(NULL,
|
||||||
QString("ModelUploader::uploadFailed()"),
|
QString("ModelUploader::uploadFailed()"),
|
||||||
QString("There was a problem with your upload, please try again later."),
|
QString("There was a problem with your upload, please try again later."),
|
||||||
|
|
|
@ -43,7 +43,7 @@ private slots:
|
||||||
void checkJSON(const QJsonObject& jsonResponse);
|
void checkJSON(const QJsonObject& jsonResponse);
|
||||||
void uploadUpdate(qint64 bytesSent, qint64 bytesTotal);
|
void uploadUpdate(qint64 bytesSent, qint64 bytesTotal);
|
||||||
void uploadSuccess(const QJsonObject& jsonResponse);
|
void uploadSuccess(const QJsonObject& jsonResponse);
|
||||||
void uploadFailed(QNetworkReply::NetworkError errorCode, const QString& errorString);
|
void uploadFailed(QNetworkReply& errorReply);
|
||||||
void checkS3();
|
void checkS3();
|
||||||
void processCheck();
|
void processCheck();
|
||||||
|
|
||||||
|
|
|
@ -18,14 +18,13 @@
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "UserLocationsModel.h"
|
#include "UserLocationsModel.h"
|
||||||
|
|
||||||
static const QString PLACES_GET = "/api/v1/places";
|
static const QString LOCATIONS_GET = "/api/v1/locations";
|
||||||
static const QString PLACES_UPDATE = "/api/v1/places/%1";
|
static const QString LOCATION_UPDATE_OR_DELETE = "/api/v1/locations/%1";
|
||||||
static const QString PLACES_DELETE= "/api/v1/places/%1";
|
|
||||||
|
|
||||||
UserLocation::UserLocation(QString id, QString name, QString location) :
|
UserLocation::UserLocation(const QString& id, const QString& name, const QString& address) :
|
||||||
_id(id),
|
_id(id),
|
||||||
_name(name),
|
_name(name),
|
||||||
_location(location),
|
_address(address),
|
||||||
_previousName(name),
|
_previousName(name),
|
||||||
_updating(false) {
|
_updating(false) {
|
||||||
}
|
}
|
||||||
|
@ -35,10 +34,15 @@ void UserLocation::requestRename(const QString& newName) {
|
||||||
_updating = true;
|
_updating = true;
|
||||||
|
|
||||||
JSONCallbackParameters callbackParams(this, "handleRenameResponse", this, "handleRenameError");
|
JSONCallbackParameters callbackParams(this, "handleRenameResponse", this, "handleRenameError");
|
||||||
|
|
||||||
QJsonObject jsonNameObject;
|
QJsonObject jsonNameObject;
|
||||||
jsonNameObject.insert("name", QJsonValue(newName));
|
jsonNameObject.insert("name", newName);
|
||||||
|
|
||||||
|
QJsonObject locationObject;
|
||||||
|
locationObject.insert("location", jsonNameObject);
|
||||||
|
|
||||||
QJsonDocument jsonDocument(jsonNameObject);
|
QJsonDocument jsonDocument(jsonNameObject);
|
||||||
AccountManager::getInstance().authenticatedRequest(PLACES_UPDATE.arg(_id),
|
AccountManager::getInstance().authenticatedRequest(LOCATION_UPDATE_OR_DELETE.arg(_id),
|
||||||
QNetworkAccessManager::PutOperation,
|
QNetworkAccessManager::PutOperation,
|
||||||
callbackParams,
|
callbackParams,
|
||||||
jsonDocument.toJson());
|
jsonDocument.toJson());
|
||||||
|
@ -54,7 +58,9 @@ void UserLocation::handleRenameResponse(const QJsonObject& responseData) {
|
||||||
|
|
||||||
QJsonValue status = responseData["status"];
|
QJsonValue status = responseData["status"];
|
||||||
if (!status.isUndefined() && status.toString() == "success") {
|
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;
|
_name = updatedName;
|
||||||
} else {
|
} else {
|
||||||
_name = _previousName;
|
_name = _previousName;
|
||||||
|
@ -75,10 +81,10 @@ void UserLocation::handleRenameResponse(const QJsonObject& responseData) {
|
||||||
emit updated(_name);
|
emit updated(_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserLocation::handleRenameError(QNetworkReply::NetworkError error, const QString& errorString) {
|
void UserLocation::handleRenameError(QNetworkReply& errorReply) {
|
||||||
_updating = false;
|
_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;
|
qDebug() << msg;
|
||||||
QMessageBox::warning(Application::getInstance()->getWindow(), "Error", msg);
|
QMessageBox::warning(Application::getInstance()->getWindow(), "Error", msg);
|
||||||
|
|
||||||
|
@ -90,7 +96,7 @@ void UserLocation::requestDelete() {
|
||||||
_updating = true;
|
_updating = true;
|
||||||
|
|
||||||
JSONCallbackParameters callbackParams(this, "handleDeleteResponse", this, "handleDeleteError");
|
JSONCallbackParameters callbackParams(this, "handleDeleteResponse", this, "handleDeleteError");
|
||||||
AccountManager::getInstance().authenticatedRequest(PLACES_DELETE.arg(_id),
|
AccountManager::getInstance().authenticatedRequest(LOCATION_UPDATE_OR_DELETE.arg(_id),
|
||||||
QNetworkAccessManager::DeleteOperation,
|
QNetworkAccessManager::DeleteOperation,
|
||||||
callbackParams);
|
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;
|
_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;
|
qDebug() << msg;
|
||||||
QMessageBox::warning(Application::getInstance()->getWindow(), "Error", msg);
|
QMessageBox::warning(Application::getInstance()->getWindow(), "Error", msg);
|
||||||
}
|
}
|
||||||
|
@ -153,7 +159,7 @@ void UserLocationsModel::refresh() {
|
||||||
endResetModel();
|
endResetModel();
|
||||||
|
|
||||||
JSONCallbackParameters callbackParams(this, "handleLocationsResponse");
|
JSONCallbackParameters callbackParams(this, "handleLocationsResponse");
|
||||||
AccountManager::getInstance().authenticatedRequest(PLACES_GET,
|
AccountManager::getInstance().authenticatedRequest(LOCATIONS_GET,
|
||||||
QNetworkAccessManager::GetOperation,
|
QNetworkAccessManager::GetOperation,
|
||||||
callbackParams);
|
callbackParams);
|
||||||
}
|
}
|
||||||
|
@ -165,14 +171,13 @@ void UserLocationsModel::handleLocationsResponse(const QJsonObject& responseData
|
||||||
QJsonValue status = responseData["status"];
|
QJsonValue status = responseData["status"];
|
||||||
if (!status.isUndefined() && status.toString() == "success") {
|
if (!status.isUndefined() && status.toString() == "success") {
|
||||||
beginResetModel();
|
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++) {
|
for (QJsonArray::const_iterator it = locations.constBegin(); it != locations.constEnd(); it++) {
|
||||||
QJsonObject location = (*it).toObject();
|
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(),
|
UserLocation* userLocation = new UserLocation(location["id"].toString(), location["name"].toString(),
|
||||||
"hifi://" + address["domain"].toString()
|
locationAddress);
|
||||||
+ "/" + address["position"].toString()
|
|
||||||
+ "/" + address["orientation"].toString());
|
|
||||||
_locations.append(userLocation);
|
_locations.append(userLocation);
|
||||||
connect(userLocation, &UserLocation::deleted, this, &UserLocationsModel::removeLocation);
|
connect(userLocation, &UserLocation::deleted, this, &UserLocationsModel::removeLocation);
|
||||||
connect(userLocation, &UserLocation::updated, this, &UserLocationsModel::update);
|
connect(userLocation, &UserLocation::updated, this, &UserLocationsModel::update);
|
||||||
|
@ -214,8 +219,8 @@ QVariant UserLocationsModel::data(const QModelIndex& index, int role) const {
|
||||||
return QVariant();
|
return QVariant();
|
||||||
} else if (index.column() == NameColumn) {
|
} else if (index.column() == NameColumn) {
|
||||||
return _locations[index.row()]->name();
|
return _locations[index.row()]->name();
|
||||||
} else if (index.column() == LocationColumn) {
|
} else if (index.column() == AddressColumn) {
|
||||||
return QVariant(_locations[index.row()]->location());
|
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) {
|
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
||||||
switch (section) {
|
switch (section) {
|
||||||
case NameColumn: return "Name";
|
case NameColumn: return "Name";
|
||||||
case LocationColumn: return "Location";
|
case AddressColumn: return "Address";
|
||||||
default: return QVariant();
|
default: return QVariant();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,20 +20,20 @@
|
||||||
class UserLocation : public QObject {
|
class UserLocation : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
UserLocation(QString id, QString name, QString location);
|
UserLocation(const QString& id, const QString& name, const QString& address);
|
||||||
bool isUpdating() { return _updating; }
|
bool isUpdating() { return _updating; }
|
||||||
void requestRename(const QString& newName);
|
void requestRename(const QString& newName);
|
||||||
void requestDelete();
|
void requestDelete();
|
||||||
|
|
||||||
QString id() { return _id; }
|
const QString& id() { return _id; }
|
||||||
QString name() { return _name; }
|
const QString& name() { return _name; }
|
||||||
QString location() { return _location; }
|
const QString& address() { return _address; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void handleRenameResponse(const QJsonObject& responseData);
|
void handleRenameResponse(const QJsonObject& responseData);
|
||||||
void handleRenameError(QNetworkReply::NetworkError error, const QString& errorString);
|
void handleRenameError(QNetworkReply& errorReply);
|
||||||
void handleDeleteResponse(const QJsonObject& responseData);
|
void handleDeleteResponse(const QJsonObject& responseData);
|
||||||
void handleDeleteError(QNetworkReply::NetworkError error, const QString& errorString);
|
void handleDeleteError(QNetworkReply& errorReply);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void updated(const QString& name);
|
void updated(const QString& name);
|
||||||
|
@ -42,7 +42,7 @@ signals:
|
||||||
private:
|
private:
|
||||||
QString _id;
|
QString _id;
|
||||||
QString _name;
|
QString _name;
|
||||||
QString _location;
|
QString _address;
|
||||||
QString _previousName;
|
QString _previousName;
|
||||||
bool _updating;
|
bool _updating;
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ public:
|
||||||
|
|
||||||
enum Columns {
|
enum Columns {
|
||||||
NameColumn = 0,
|
NameColumn = 0,
|
||||||
LocationColumn
|
AddressColumn
|
||||||
};
|
};
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
|
|
||||||
#include <AccountManager.h>
|
#include <AccountManager.h>
|
||||||
|
#include <AddressManager.h>
|
||||||
#include <GeometryUtil.h>
|
#include <GeometryUtil.h>
|
||||||
#include <NodeList.h>
|
#include <NodeList.h>
|
||||||
#include <PacketHeaders.h>
|
#include <PacketHeaders.h>
|
||||||
|
@ -91,6 +92,9 @@ MyAvatar::MyAvatar() :
|
||||||
Ragdoll* ragdoll = _skeletonModel.buildRagdoll();
|
Ragdoll* ragdoll = _skeletonModel.buildRagdoll();
|
||||||
_physicsSimulation.setRagdoll(ragdoll);
|
_physicsSimulation.setRagdoll(ragdoll);
|
||||||
_physicsSimulation.addEntity(&_voxelShapeManager);
|
_physicsSimulation.addEntity(&_voxelShapeManager);
|
||||||
|
|
||||||
|
// connect to AddressManager signal for location jumps
|
||||||
|
connect(&AddressManager::getInstance(), &AddressManager::locationChangeRequired, this, &MyAvatar::goToLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
MyAvatar::~MyAvatar() {
|
MyAvatar::~MyAvatar() {
|
||||||
|
@ -1763,11 +1767,6 @@ void MyAvatar::maybeUpdateBillboard() {
|
||||||
sendBillboardPacket();
|
sendBillboardPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::goHome() {
|
|
||||||
qDebug("Going Home!");
|
|
||||||
slamPosition(START_LOCATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyAvatar::increaseSize() {
|
void MyAvatar::increaseSize() {
|
||||||
if ((1.0f + SCALING_RATIO) * _targetScale < MAX_AVATAR_SCALE) {
|
if ((1.0f + SCALING_RATIO) * _targetScale < MAX_AVATAR_SCALE) {
|
||||||
_targetScale *= (1.0f + SCALING_RATIO);
|
_targetScale *= (1.0f + SCALING_RATIO);
|
||||||
|
@ -1787,45 +1786,26 @@ void MyAvatar::resetSize() {
|
||||||
qDebug("Reseted scale to %f", _targetScale);
|
qDebug("Reseted scale to %f", _targetScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::goToLocationFromResponse(const QJsonObject& jsonObject) {
|
void MyAvatar::goToLocation(const glm::vec3& newPosition, bool hasOrientation, const glm::vec3& newOrientation) {
|
||||||
QJsonObject locationObject = jsonObject["data"].toObject()["address"].toObject();
|
glm::quat quatOrientation = getOrientation();
|
||||||
bool isOnline = jsonObject["data"].toObject()["online"].toBool();
|
|
||||||
if (isOnline ) {
|
qDebug().nospace() << "MyAvatar goToLocation - moving to " << newPosition.x << ", "
|
||||||
goToLocationFromAddress(locationObject);
|
<< newPosition.y << ", " << newPosition.z;
|
||||||
} else {
|
|
||||||
QMessageBox::warning(Application::getInstance()->getWindow(), "", "The user is not online.");
|
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
|
// move the user a couple units away
|
||||||
const float DISTANCE_TO_USER = 2.0f;
|
const float DISTANCE_TO_USER = 2.0f;
|
||||||
glm::vec3 newPosition = glm::vec3(coordinateItems[0].toFloat(), coordinateItems[1].toFloat(),
|
glm::vec3 shiftedPosition = newPosition - quatOrientation * IDENTITY_FRONT * DISTANCE_TO_USER;
|
||||||
coordinateItems[2].toFloat()) - newOrientation * IDENTITY_FRONT * DISTANCE_TO_USER;
|
slamPosition(shiftedPosition);
|
||||||
slamPosition(newPosition);
|
|
||||||
emit transformChanged();
|
emit transformChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -150,13 +150,11 @@ public:
|
||||||
const PlayerPointer getPlayer() const { return _player; }
|
const PlayerPointer getPlayer() const { return _player; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void goHome();
|
|
||||||
void increaseSize();
|
void increaseSize();
|
||||||
void decreaseSize();
|
void decreaseSize();
|
||||||
void resetSize();
|
void resetSize();
|
||||||
|
|
||||||
void goToLocationFromResponse(const QJsonObject& jsonObject);
|
void goToLocation(const glm::vec3& newPosition, bool hasOrientation = false, const glm::vec3& newOrientation = glm::vec3());
|
||||||
void goToLocationFromAddress(const QJsonObject& jsonObject);
|
|
||||||
|
|
||||||
// Set/Get update the thrust that will move the avatar around
|
// Set/Get update the thrust that will move the avatar around
|
||||||
void addThrust(glm::vec3 newThrust) { _thrust += newThrust; };
|
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
|
// 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 "LocationManager.h"
|
||||||
#include <UserActivityLogger.h>
|
|
||||||
|
|
||||||
const QString GET_USER_ADDRESS = "/api/v1/users/%1/address";
|
const QString POST_LOCATION_CREATE = "/api/v1/locations/";
|
||||||
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() {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
LocationManager& LocationManager::getInstance() {
|
LocationManager& LocationManager::getInstance() {
|
||||||
static LocationManager sharedInstance;
|
static LocationManager sharedInstance;
|
||||||
return sharedInstance;
|
return sharedInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QString UNKNOWN_ERROR_MESSAGE = "Unknown error creating named location. Please try again!";
|
||||||
|
|
||||||
void LocationManager::namedLocationDataReceived(const QJsonObject& data) {
|
void LocationManager::namedLocationDataReceived(const QJsonObject& data) {
|
||||||
if (data.isEmpty()) {
|
if (data.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.contains("status") && data["status"].toString() == "success") {
|
if (data.contains("status") && data["status"].toString() == "success") {
|
||||||
emit creationCompleted(LocationManager::Created);
|
emit creationCompleted(QString());
|
||||||
} else {
|
} 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) {
|
void LocationManager::createNamedLocation(NamedLocation* namedLocation) {
|
||||||
AccountManager& accountManager = AccountManager::getInstance();
|
AccountManager& accountManager = AccountManager::getInstance();
|
||||||
if (accountManager.isLoggedIn()) {
|
if (accountManager.isLoggedIn()) {
|
||||||
|
@ -55,185 +45,45 @@ void LocationManager::createNamedLocation(NamedLocation* namedLocation) {
|
||||||
callbackParams.errorCallbackReceiver = this;
|
callbackParams.errorCallbackReceiver = this;
|
||||||
callbackParams.errorCallbackMethod = "errorDataReceived";
|
callbackParams.errorCallbackMethod = "errorDataReceived";
|
||||||
|
|
||||||
accountManager.authenticatedRequest(POST_PLACE_CREATE, QNetworkAccessManager::PostOperation,
|
accountManager.authenticatedRequest(POST_LOCATION_CREATE, QNetworkAccessManager::PostOperation,
|
||||||
callbackParams, namedLocation->toJsonString().toUtf8());
|
callbackParams, namedLocation->toJsonString().toUtf8());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocationManager::goTo(QString destination) {
|
void LocationManager::errorDataReceived(QNetworkReply& errorReply) {
|
||||||
const QString USER_DESTINATION_TYPE = "user";
|
|
||||||
const QString PLACE_DESTINATION_TYPE = "place";
|
|
||||||
const QString OTHER_DESTINATION_TYPE = "coordinate_or_username";
|
|
||||||
|
|
||||||
if (destination.startsWith("@")) {
|
if (errorReply.header(QNetworkRequest::ContentTypeHeader).toString().startsWith("application/json")) {
|
||||||
// remove '@' and go to user
|
// we have some JSON error data we can parse for our error message
|
||||||
QString destinationUser = destination.remove(0, 1);
|
QJsonDocument responseJson = QJsonDocument::fromJson(errorReply.readAll());
|
||||||
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);
|
|
||||||
|
|
||||||
JSONCallbackParameters callbackParams;
|
QJsonObject dataObject = responseJson.object()["data"].toObject();
|
||||||
callbackParams.jsonCallbackReceiver = this;
|
|
||||||
callbackParams.jsonCallbackMethod = "goToAddressFromResponse";
|
|
||||||
callbackParams.errorCallbackReceiver = this;
|
|
||||||
callbackParams.errorCallbackMethod = "handleAddressLookupError";
|
|
||||||
|
|
||||||
AccountManager::getInstance().authenticatedRequest(GET_ADDRESSES.arg(destination),
|
qDebug() << dataObject;
|
||||||
QNetworkAccessManager::GetOperation,
|
|
||||||
callbackParams);
|
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()) {
|
||||||
void LocationManager::goToAddressFromResponse(const QJsonObject& responseData) {
|
errorString += "\n\u2022 " + key + " - ";
|
||||||
QJsonValue status = responseData["status"];
|
|
||||||
|
QJsonValue keyedErrorValue = dataObject[key];
|
||||||
const QJsonObject& data = responseData["data"].toObject();
|
|
||||||
const QJsonValue& userObject = data["user"];
|
if (keyedErrorValue.isArray()) {
|
||||||
const QJsonValue& placeObject = data["place"];
|
foreach(const QJsonValue& attributeErrorValue, keyedErrorValue.toArray()) {
|
||||||
|
errorString += attributeErrorValue.toString() + ", ";
|
||||||
if (!placeObject.isUndefined() && !userObject.isUndefined()) {
|
}
|
||||||
emit multipleDestinationsFound(userObject.toObject(), placeObject.toObject());
|
|
||||||
} else if (placeObject.isUndefined()) {
|
// remove the trailing comma at end of error list
|
||||||
Application::getInstance()->getAvatar()->goToLocationFromAddress(userObject.toObject()["address"].toObject());
|
errorString.remove(errorString.length() - 2, 2);
|
||||||
} else {
|
} else if (keyedErrorValue.isString()) {
|
||||||
Application::getInstance()->getAvatar()->goToLocationFromAddress(placeObject.toObject()["address"].toObject());
|
errorString += keyedErrorValue.toString();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
// emit our creationCompleted signal with the error
|
||||||
|
emit creationCompleted(errorString);
|
||||||
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.";
|
|
||||||
} else {
|
} else {
|
||||||
messageBoxString = errorString;
|
creationCompleted(UNKNOWN_ERROR_MESSAGE);
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
#define hifi_LocationManager_h
|
#define hifi_LocationManager_h
|
||||||
|
|
||||||
#include <QtCore>
|
#include <QtCore>
|
||||||
|
#include <QtNetwork/QNetworkReply>
|
||||||
|
|
||||||
#include "AccountManager.h"
|
|
||||||
#include "NamedLocation.h"
|
#include "NamedLocation.h"
|
||||||
|
|
||||||
class LocationManager : public QObject {
|
class LocationManager : public QObject {
|
||||||
|
@ -29,29 +29,14 @@ public:
|
||||||
SystemError
|
SystemError
|
||||||
};
|
};
|
||||||
|
|
||||||
LocationManager();
|
|
||||||
void createNamedLocation(NamedLocation* namedLocation);
|
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:
|
signals:
|
||||||
void creationCompleted(LocationManager::NamedLocationCreateResponse response);
|
void creationCompleted(const QString& errorMessage);
|
||||||
void multipleDestinationsFound(const QJsonObject& userData, const QJsonObject& placeData);
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void namedLocationDataReceived(const QJsonObject& data);
|
void namedLocationDataReceived(const QJsonObject& data);
|
||||||
void errorDataReceived(QNetworkReply::NetworkError error, const QString& message);
|
void errorDataReceived(QNetworkReply& errorReply);
|
||||||
void goToAddressFromResponse(const QJsonObject& jsonObject);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,19 +9,25 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <AddressManager.h>
|
||||||
|
#include <UUID.h>
|
||||||
|
|
||||||
#include "NamedLocation.h"
|
#include "NamedLocation.h"
|
||||||
|
|
||||||
const QString JSON_FORMAT = "{\"address\":{\"position\":\"%1,%2,%3\","
|
NamedLocation::NamedLocation(const QString& name,
|
||||||
"\"orientation\":\"%4,%5,%6,%7\",\"domain\":\"%8\"},\"name\":\"%9\"}";
|
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() {
|
QString NamedLocation::toJsonString() {
|
||||||
return JSON_FORMAT.arg(QString::number(_location.x),
|
return JSON_FORMAT.arg(AddressManager::pathForPositionAndOrientation(_position, true, _orientation),
|
||||||
QString::number(_location.y),
|
uuidStringWithoutCurlyBraces(_domainID), _name);
|
||||||
QString::number(_location.z),
|
|
||||||
QString::number(_orientation.w),
|
|
||||||
QString::number(_orientation.x),
|
|
||||||
QString::number(_orientation.y),
|
|
||||||
QString::number(_orientation.z),
|
|
||||||
_domain,
|
|
||||||
_locationName);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,39 +22,33 @@ class NamedLocation : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NamedLocation(QString locationName, glm::vec3 location, glm::quat orientation, QString domain) {
|
NamedLocation(const QString& name, const glm::vec3& position, const glm::quat& orientation, const QUuid& domainID);
|
||||||
_locationName = locationName;
|
|
||||||
_location = location;
|
|
||||||
_orientation = orientation;
|
|
||||||
_domain = domain;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString toJsonString();
|
QString toJsonString();
|
||||||
|
|
||||||
bool isEmpty() { return _locationName.isNull() || _locationName.isEmpty(); }
|
bool isEmpty() { return _name.isNull() || _name.isEmpty(); }
|
||||||
|
|
||||||
void setLocationName(QString locationName) { _locationName = locationName; }
|
void setName(QString name) { _name = name; }
|
||||||
QString locationName() { return _locationName; }
|
const QString& getName() const { return _name; }
|
||||||
|
|
||||||
void setLocation(glm::vec3 location) { _location = location; }
|
void setLocation(glm::vec3 position) { _position = position; }
|
||||||
glm::vec3 location() { return _location; }
|
const glm::vec3& getPosition() const { return _position; }
|
||||||
|
|
||||||
void setOrientation(glm::quat orentation) { _orientation = orentation; }
|
void setOrientation(const glm::quat& orentation) { _orientation = orentation; }
|
||||||
glm::quat orientation() { return _orientation; }
|
const glm::quat& getOrientation() const { return _orientation; }
|
||||||
|
|
||||||
void setDomain(QString domain) { _domain = domain; }
|
void setDomainID(const QUuid& domainID) { _domainID = domainID; }
|
||||||
QString domain() { return _domain; }
|
const QUuid& getDomainID() const { return _domainID; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void dataReceived(bool locationExists);
|
void dataReceived(bool locationExists);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QString _name;
|
||||||
QString _locationName;
|
|
||||||
QString _createdBy;
|
QString _createdBy;
|
||||||
glm::vec3 _location;
|
glm::vec3 _position;
|
||||||
glm::quat _orientation;
|
glm::quat _orientation;
|
||||||
QString _domain;
|
QUuid _domainID;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -29,10 +29,9 @@ QString LocationScriptingInterface::getHref() {
|
||||||
}
|
}
|
||||||
|
|
||||||
QString LocationScriptingInterface::getPathname() {
|
QString LocationScriptingInterface::getPathname() {
|
||||||
const glm::vec3& position = Application::getInstance()->getAvatar()->getPosition();
|
MyAvatar* applicationAvatar = Application::getInstance()->getAvatar();
|
||||||
QString path;
|
return AddressManager::pathForPositionAndOrientation(applicationAvatar->getPosition(),
|
||||||
path.sprintf("/%.4f,%.4f,%.4f", position.x, position.y, position.z);
|
true, applicationAvatar->getOrientation());
|
||||||
return path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString LocationScriptingInterface::getHostname() {
|
QString LocationScriptingInterface::getHostname() {
|
||||||
|
@ -40,7 +39,7 @@ QString LocationScriptingInterface::getHostname() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocationScriptingInterface::assign(const QString& url) {
|
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) {
|
QScriptValue LocationScriptingInterface::locationGetter(QScriptContext* context, QScriptEngine* engine) {
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
#include <QScriptValue>
|
#include <QScriptValue>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
|
#include <AddressManager.h>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
|
||||||
class LocationScriptingInterface : public QObject {
|
class LocationScriptingInterface : public QObject {
|
||||||
|
@ -33,7 +35,7 @@ public:
|
||||||
|
|
||||||
bool isConnected();
|
bool isConnected();
|
||||||
QString getHref();
|
QString getHref();
|
||||||
QString getProtocol() { return CUSTOM_URL_SCHEME; };
|
QString getProtocol() { return HIFI_URL_SCHEME; };
|
||||||
QString getPathname();
|
QString getPathname();
|
||||||
QString getHostname();
|
QString getHostname();
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,8 @@ ChatMessageArea::ChatMessageArea(bool useFixedHeight) : QTextBrowser(), _useFixe
|
||||||
|
|
||||||
connect(document()->documentLayout(), &QAbstractTextDocumentLayout::documentSizeChanged,
|
connect(document()->documentLayout(), &QAbstractTextDocumentLayout::documentSizeChanged,
|
||||||
this, &ChatMessageArea::updateLayout);
|
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) {
|
void ChatMessageArea::setHtml(const QString& html) {
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
#include <QSizePolicy>
|
#include <QSizePolicy>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include <AddressManager.h>
|
||||||
|
#include <AccountManager.h>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "ChatMessageArea.h"
|
#include "ChatMessageArea.h"
|
||||||
#include "FlowLayout.h"
|
#include "FlowLayout.h"
|
||||||
|
@ -28,7 +31,6 @@
|
||||||
#include "ChatWindow.h"
|
#include "ChatWindow.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const int NUM_MESSAGES_TO_TIME_STAMP = 20;
|
const int NUM_MESSAGES_TO_TIME_STAMP = 20;
|
||||||
|
|
||||||
const QRegularExpression regexLinks("((?:(?:ftp)|(?:https?)|(?:hifi))://\\S+)");
|
const QRegularExpression regexLinks("((?:(?:ftp)|(?:https?)|(?:hifi))://\\S+)");
|
||||||
|
@ -169,7 +171,7 @@ bool ChatWindow::eventFilter(QObject* sender, QEvent* event) {
|
||||||
} else if (event->type() == QEvent::MouseButtonRelease) {
|
} else if (event->type() == QEvent::MouseButtonRelease) {
|
||||||
QVariant userVar = sender->property("user");
|
QVariant userVar = sender->property("user");
|
||||||
if (userVar.isValid()) {
|
if (userVar.isValid()) {
|
||||||
Menu::getInstance()->goToUser("@" + userVar.toString());
|
AddressManager::getInstance().goToUser(userVar.toString());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
#include <QtWebKitWidgets/QWebView>
|
#include <QtWebKitWidgets/QWebView>
|
||||||
|
|
||||||
|
#include <AccountManager.h>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
|
||||||
#include "OAuthWebViewHandler.h"
|
#include "OAuthWebViewHandler.h"
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include <NetworkAccessManager.h>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "ScriptHighlighting.h"
|
#include "ScriptHighlighting.h"
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
|
||||||
|
#include <AddressManager.h>
|
||||||
|
|
||||||
#include "Menu.h"
|
#include "Menu.h"
|
||||||
#include "UserLocationsDialog.h"
|
#include "UserLocationsDialog.h"
|
||||||
|
|
||||||
|
@ -51,8 +53,8 @@ void UserLocationsDialog::updateEnabled() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserLocationsDialog::goToModelIndex(const QModelIndex& index) {
|
void UserLocationsDialog::goToModelIndex(const QModelIndex& index) {
|
||||||
QVariant location = _proxyModel.data(index.sibling(index.row(), UserLocationsModel::LocationColumn));
|
QVariant address = _proxyModel.data(index.sibling(index.row(), UserLocationsModel::AddressColumn));
|
||||||
Menu::getInstance()->goToURL(location.toString());
|
AddressManager::getInstance().handleLookupString(address.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserLocationsDialog::deleteSelection() {
|
void UserLocationsDialog::deleteSelection() {
|
||||||
|
|
|
@ -9,7 +9,9 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// 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"
|
#include "BillboardOverlay.h"
|
||||||
|
|
||||||
|
|
|
@ -292,8 +292,7 @@ void AccountManager::passErrorToCallback(QNetworkReply* requestReply) {
|
||||||
if (callbackParams.errorCallbackReceiver) {
|
if (callbackParams.errorCallbackReceiver) {
|
||||||
// invoke the right method on the callback receiver
|
// invoke the right method on the callback receiver
|
||||||
QMetaObject::invokeMethod(callbackParams.errorCallbackReceiver, qPrintable(callbackParams.errorCallbackMethod),
|
QMetaObject::invokeMethod(callbackParams.errorCallbackReceiver, qPrintable(callbackParams.errorCallbackMethod),
|
||||||
Q_ARG(QNetworkReply::NetworkError, requestReply->error()),
|
Q_ARG(QNetworkReply&, *requestReply));
|
||||||
Q_ARG(const QString&, requestReply->errorString()));
|
|
||||||
|
|
||||||
// remove the related reply-callback group from the map
|
// remove the related reply-callback group from the map
|
||||||
_pendingCallbackMap.remove(requestReply);
|
_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;
|
_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) {
|
void DomainHandler::setHostname(const QString& hostname) {
|
||||||
|
|
||||||
if (hostname != _hostname) {
|
if (hostname != _hostname) {
|
||||||
|
|
|
@ -37,10 +37,11 @@ public:
|
||||||
void clearSettings();
|
void clearSettings();
|
||||||
|
|
||||||
const QUuid& getUUID() const { return _uuid; }
|
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; }
|
const QString& getHostname() const { return _hostname; }
|
||||||
void setHostname(const QString& hostname);
|
|
||||||
|
|
||||||
const QHostAddress& getIP() const { return _sockAddr.getAddress(); }
|
const QHostAddress& getIP() const { return _sockAddr.getAddress(); }
|
||||||
void setIPToLocalhost() { _sockAddr.setAddress(QHostAddress(QHostAddress::LocalHost)); }
|
void setIPToLocalhost() { _sockAddr.setAddress(QHostAddress(QHostAddress::LocalHost)); }
|
||||||
|
@ -63,6 +64,8 @@ public:
|
||||||
void parseDTLSRequirementPacket(const QByteArray& dtlsRequirementPacket);
|
void parseDTLSRequirementPacket(const QByteArray& dtlsRequirementPacket);
|
||||||
|
|
||||||
void softReset();
|
void softReset();
|
||||||
|
public slots:
|
||||||
|
void setHostname(const QString& hostname);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void completedHostnameLookup(const QHostInfo& hostInfo);
|
void completedHostnameLookup(const QHostInfo& hostInfo);
|
||||||
|
|
|
@ -397,7 +397,10 @@ int NodeList::processDomainServerList(const QByteArray& packet) {
|
||||||
_numNoReplyDomainCheckIns = 0;
|
_numNoReplyDomainCheckIns = 0;
|
||||||
|
|
||||||
// if this was the first domain-server list from this domain, we've now connected
|
// 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;
|
int readNodes = 0;
|
||||||
|
|
||||||
|
|
|
@ -73,8 +73,8 @@ void UserActivityLogger::requestFinished(const QJsonObject& object) {
|
||||||
// qDebug() << object;
|
// qDebug() << object;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserActivityLogger::requestError(QNetworkReply::NetworkError error,const QString& string) {
|
void UserActivityLogger::requestError(QNetworkReply& errorReply) {
|
||||||
qDebug() << error << ": " << string;
|
qDebug() << errorReply.error() << "-" << errorReply.errorString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserActivityLogger::launch(QString applicationVersion) {
|
void UserActivityLogger::launch(QString applicationVersion) {
|
||||||
|
|
|
@ -40,7 +40,7 @@ public slots:
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void requestFinished(const QJsonObject& object);
|
void requestFinished(const QJsonObject& object);
|
||||||
void requestError(QNetworkReply::NetworkError error,const QString& string);
|
void requestError(QNetworkReply& errorReply);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UserActivityLogger();
|
UserActivityLogger();
|
||||||
|
|
Loading…
Reference in a new issue