From cb907c189168c0c38e40baf090829d34cb29345e Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 10 Sep 2014 13:57:38 +0200 Subject: [PATCH 1/9] GlobalServicesScriptingInterface added, functions and properties functional --- interface/src/Application.cpp | 7 +- .../GlobalServicesScriptingInterface.cpp | 67 +++++++++++++++++++ .../GlobalServicesScriptingInterface.h | 53 +++++++++++++++ 3 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 interface/src/scripting/GlobalServicesScriptingInterface.cpp create mode 100644 interface/src/scripting/GlobalServicesScriptingInterface.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7c7c455d1d..6facabb3e2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -80,6 +80,7 @@ #include "scripting/AccountScriptingInterface.h" #include "scripting/AudioDeviceScriptingInterface.h" #include "scripting/ClipboardScriptingInterface.h" +#include "scripting/GlobalServicesScriptingInterface.h" #include "scripting/MenuScriptingInterface.h" #include "scripting/SettingsScriptingInterface.h" #include "scripting/WindowScriptingInterface.h" @@ -3778,9 +3779,11 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser scriptEngine->registerGlobalObject("AudioReflector", &_audioReflector); scriptEngine->registerGlobalObject("Account", AccountScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("Metavoxels", &_metavoxels); - + + scriptEngine->registerGlobalObject("GlobalServices", GlobalServicesScriptingInterface::getInstance()); + scriptEngine->registerGlobalObject("AvatarManager", &_avatarManager); - + #ifdef HAVE_RTMIDI scriptEngine->registerGlobalObject("MIDI", &MIDIManager::getInstance()); #endif diff --git a/interface/src/scripting/GlobalServicesScriptingInterface.cpp b/interface/src/scripting/GlobalServicesScriptingInterface.cpp new file mode 100644 index 0000000000..d28e96fa45 --- /dev/null +++ b/interface/src/scripting/GlobalServicesScriptingInterface.cpp @@ -0,0 +1,67 @@ +// +// GlobalServicesScriptingInterface.cpp +// interface/src/scripting +// +// Created by Thijs Wenker on 9/10/14. +// 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 "AccountManager.h" +#include "XmppClient.h" + +#include "GlobalServicesScriptingInterface.h" + +GlobalServicesScriptingInterface::GlobalServicesScriptingInterface() { + AccountManager& accountManager = AccountManager::getInstance(); + connect(&accountManager, &AccountManager::usernameChanged, this, + &GlobalServicesScriptingInterface::myUsernameChanged); + +} + +GlobalServicesScriptingInterface* GlobalServicesScriptingInterface::getInstance() { + static GlobalServicesScriptingInterface sharedInstance; + return &sharedInstance; +} + +bool GlobalServicesScriptingInterface::isConnected() { +#ifdef HAVE_QXMPP + return XmppClient::getInstance().getXMPPClient().isConnected(); +#else + return false; +#endif // HAVE_QXMPP +} + +QScriptValue GlobalServicesScriptingInterface::chat(const QString& message) { +#ifdef HAVE_QXMPP + if (XmppClient::getInstance().getXMPPClient().isConnected()) { + const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); + QXmppMessage messageObject; + messageObject.setTo(publicChatRoom->jid()); + messageObject.setType(QXmppMessage::GroupChat); + messageObject.setBody(message); + return XmppClient::getInstance().getXMPPClient().sendPacket(messageObject); + } +#endif // HAVE_QXMPP + return false; +} + +QString GlobalServicesScriptingInterface::getMyUsername() { + return AccountManager::getInstance().getAccountInfo().getUsername(); +} + +QStringList GlobalServicesScriptingInterface::getOnlineUsers() { +#ifdef HAVE_QXMPP + if (XmppClient::getInstance().getXMPPClient().isConnected()) { + QStringList usernames; + const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); + foreach(const QString& participant, XmppClient::getInstance().getPublicChatRoom()->participants()) { + usernames.append(participant.right(participant.count() - 1 - publicChatRoom->jid().count())); + } + return usernames; + } +#endif // HAVE_QXMPP + return QStringList(); +} \ No newline at end of file diff --git a/interface/src/scripting/GlobalServicesScriptingInterface.h b/interface/src/scripting/GlobalServicesScriptingInterface.h new file mode 100644 index 0000000000..9ab8a26923 --- /dev/null +++ b/interface/src/scripting/GlobalServicesScriptingInterface.h @@ -0,0 +1,53 @@ +// +// GlobalServicesScriptingInterface.h +// interface/src/scripting +// +// Created by Thijs Wenker on 9/10/14. +// 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_GlobalServicesScriptingInterface_h +#define hifi_GlobalServicesScriptingInterface_h + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_QXMPP + +#include +#include + +#endif + +class GlobalServicesScriptingInterface : public QObject { + Q_OBJECT + Q_PROPERTY(bool isConnected READ isConnected) + Q_PROPERTY(QString myUsername READ getMyUsername) + Q_PROPERTY(QStringList onlineUsers READ getOnlineUsers) + GlobalServicesScriptingInterface(); +public: + static GlobalServicesScriptingInterface* getInstance(); + + bool isConnected(); + QString getMyUsername(); + QStringList getOnlineUsers(); + +public slots: + QScriptValue chat(const QString& message); + +signals: + void connected(); + void disconnected(const QString& reason); + void incomingMessage(const QString& username, const QString& message); + void onlineUsersChanged(const QStringList& usernames); + void myUsernameChanged(const QString& username); +}; + +#endif // hifi_GlobalServicesScriptingInterface_h From 753dedce225d7fac005834debc59c092aa33575e Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Fri, 12 Sep 2014 02:16:23 +0200 Subject: [PATCH 2/9] combobox support in the Window.form javascript function example: Window.form('combobox', {label: "yourcombobox", ["opt #1.", "opt #2.", "opt #3."]}); --- .../src/scripting/WindowScriptingInterface.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 7a85fc7117..10d29cc3e2 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -165,6 +165,7 @@ QScriptValue WindowScriptingInterface::showForm(const QString& title, QScriptVal area->setWidget(container); QVector edits; + QVector combos; QVector directories; for (int i = 0; i < form.property("length").toInt32(); ++i) { QScriptValue item = form.property(i); @@ -201,7 +202,15 @@ QScriptValue WindowScriptingInterface::showForm(const QString& title, QScriptVal formLayout->addRow(new QLabel(item.property("label").toString()), directory); connect(directory, SIGNAL(clicked(bool)), SLOT(chooseDirectory())); - + } else if (item.property("options").isArray()) { + QComboBox* combo = new QComboBox(); + combo->setMinimumWidth(200); + QStringList options = item.property("options").toVariant().toStringList(); + for (QStringList::const_iterator it = options.begin(); it != options.end(); it += 1) { + combo->addItem(*it); + } + combos.push_back(combo); + formLayout->addRow(new QLabel(item.property("label").toString()), combo); } else { QLineEdit* edit = new QLineEdit(item.property("value").toString()); edit->setMinimumWidth(200); @@ -222,6 +231,7 @@ QScriptValue WindowScriptingInterface::showForm(const QString& title, QScriptVal if (result == QDialog::Accepted) { int e = -1; int d = -1; + int c = -1; for (int i = 0; i < form.property("length").toInt32(); ++i) { QScriptValue item = form.property(i); QScriptValue value = item.property("value"); @@ -233,6 +243,10 @@ QScriptValue WindowScriptingInterface::showForm(const QString& title, QScriptVal value = directories.at(d)->property("path").toString(); item.setProperty("directory", value); form.setProperty(i, item); + } else if (item.property("options").isArray()) { + c += 1; + item.setProperty("value", combos.at(c)->currentText()); + form.setProperty(i, item); } else { e += 1; bool ok = true; From 807173ae0a776cd0952d2d24f9c78289eca4cd34 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Fri, 12 Sep 2014 02:17:36 +0200 Subject: [PATCH 3/9] the GlobalServices Events are functional now --- .../GlobalServicesScriptingInterface.cpp | 50 ++++++++++++++++++- .../GlobalServicesScriptingInterface.h | 7 +++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/interface/src/scripting/GlobalServicesScriptingInterface.cpp b/interface/src/scripting/GlobalServicesScriptingInterface.cpp index d28e96fa45..8c117a4a11 100644 --- a/interface/src/scripting/GlobalServicesScriptingInterface.cpp +++ b/interface/src/scripting/GlobalServicesScriptingInterface.cpp @@ -16,9 +16,43 @@ GlobalServicesScriptingInterface::GlobalServicesScriptingInterface() { AccountManager& accountManager = AccountManager::getInstance(); - connect(&accountManager, &AccountManager::usernameChanged, this, - &GlobalServicesScriptingInterface::myUsernameChanged); + connect(&accountManager, &AccountManager::usernameChanged, this, &GlobalServicesScriptingInterface::myUsernameChanged); + connect(&accountManager, &AccountManager::logoutComplete, this, &GlobalServicesScriptingInterface::loggedOut); +#ifdef HAVE_QXMPP + const XmppClient& xmppClient = XmppClient::getInstance(); + connect(&xmppClient, &XmppClient::joinedPublicChatRoom, this, &GlobalServicesScriptingInterface::connected); + connect(&xmppClient, &XmppClient::joinedPublicChatRoom, this, &GlobalServicesScriptingInterface::onConnected); + const QXmppClient& qxmppClient = XmppClient::getInstance().getXMPPClient(); + connect(&qxmppClient, &QXmppClient::messageReceived, this, &GlobalServicesScriptingInterface::messageReceived); +#endif // HAVE_QXMPP +} +GlobalServicesScriptingInterface::~GlobalServicesScriptingInterface() { + AccountManager& accountManager = AccountManager::getInstance(); + disconnect(&accountManager, &AccountManager::usernameChanged, this, &GlobalServicesScriptingInterface::myUsernameChanged); + disconnect(&accountManager, &AccountManager::logoutComplete, this, &GlobalServicesScriptingInterface::loggedOut); +#ifdef HAVE_QXMPP + const XmppClient& xmppClient = XmppClient::getInstance(); + disconnect(&xmppClient, &XmppClient::joinedPublicChatRoom, this, &GlobalServicesScriptingInterface::connected); + disconnect(&xmppClient, &XmppClient::joinedPublicChatRoom, this, &GlobalServicesScriptingInterface::onConnected); + const QXmppClient& qxmppClient = XmppClient::getInstance().getXMPPClient(); + disconnect(&qxmppClient, &QXmppClient::messageReceived, this, &GlobalServicesScriptingInterface::messageReceived); + const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); + disconnect(publicChatRoom, &QXmppMucRoom::participantsChanged, this, &GlobalServicesScriptingInterface::participantsChanged); +#endif // HAVE_QXMPP +} + +void GlobalServicesScriptingInterface::onConnected() { +#ifdef HAVE_QXMPP + const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); + connect(publicChatRoom, &QXmppMucRoom::participantsChanged, this, &GlobalServicesScriptingInterface::participantsChanged, Qt::UniqueConnection); +#endif // HAVE_QXMPP +} + +void GlobalServicesScriptingInterface::participantsChanged() { +#ifdef HAVE_QXMPP + emit GlobalServicesScriptingInterface::onlineUsersChanged(this->getOnlineUsers()); +#endif // HAVE_QXMPP } GlobalServicesScriptingInterface* GlobalServicesScriptingInterface::getInstance() { @@ -64,4 +98,16 @@ QStringList GlobalServicesScriptingInterface::getOnlineUsers() { } #endif // HAVE_QXMPP return QStringList(); +} + +void GlobalServicesScriptingInterface::loggedOut() { + emit GlobalServicesScriptingInterface::disconnected(QString("logout")); +} + +void GlobalServicesScriptingInterface::messageReceived(const QXmppMessage& message) { + if (message.type() != QXmppMessage::GroupChat) { + return; + } + const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); + emit GlobalServicesScriptingInterface::incomingMessage(message.from().right(message.from().count() - 1 - publicChatRoom->jid().count()), message.body()); } \ No newline at end of file diff --git a/interface/src/scripting/GlobalServicesScriptingInterface.h b/interface/src/scripting/GlobalServicesScriptingInterface.h index 9ab8a26923..370ba1ade9 100644 --- a/interface/src/scripting/GlobalServicesScriptingInterface.h +++ b/interface/src/scripting/GlobalServicesScriptingInterface.h @@ -32,6 +32,7 @@ class GlobalServicesScriptingInterface : public QObject { Q_PROPERTY(QString myUsername READ getMyUsername) Q_PROPERTY(QStringList onlineUsers READ getOnlineUsers) GlobalServicesScriptingInterface(); + ~GlobalServicesScriptingInterface(); public: static GlobalServicesScriptingInterface* getInstance(); @@ -42,6 +43,12 @@ public: public slots: QScriptValue chat(const QString& message); +private slots: + void loggedOut(); + void onConnected(); + void participantsChanged(); + void messageReceived(const QXmppMessage& message); + signals: void connected(); void disconnected(const QString& reason); From e62380a1719db8212d37a9143fd136cbb1ee4658 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Fri, 12 Sep 2014 02:23:25 +0200 Subject: [PATCH 4/9] globalServicesExample.js --- examples/globalServicesExample.js | 57 +++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 examples/globalServicesExample.js diff --git a/examples/globalServicesExample.js b/examples/globalServicesExample.js new file mode 100644 index 0000000000..3d29b9510e --- /dev/null +++ b/examples/globalServicesExample.js @@ -0,0 +1,57 @@ +// +// globalServicesExample.js +// examples +// +// Created by Thijs Wenker on 9/12/14. +// Copyright 2014 High Fidelity, Inc. +// +// Example usage of the GlobalServices object. You could use it to make your own chatbox. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +function onConnected() { + if (GlobalServices.onlineUsers.length > 0) { + sendMessageForm() + return; + } + Script.setTimeout(function() { sendMessageForm(); }, 5000); +} + +function onDisconnected(reason) { + switch(reason) { + case "logout": + Window.alert("logged out!"); + break; + + } +} + +function onOnlineUsersChanged(users) { + print(users); +} + +function onIncommingMessage(user, message) { + print(user + ": " + message); + if (message === "hello") { + GlobalServices.chat("hello, @" + user + "!"); + } +} + +function sendMessageForm() { + var form = + [ + { label: "To:", options: ["(noone)"].concat(GlobalServices.onlineUsers) }, + { label: "Message:", value: "Enter message here" } + ]; + if (Window.form("Send message on public chat", form)) { + GlobalServices.chat(form[0].value == "(noone)" ? form[1].value : "@" + form[0].value + ", " + form[1].value); + + } +} + +GlobalServices.connected.connect(onConnected); +GlobalServices.disconnected.connect(onDisconnected); +GlobalServices.onlineUsersChanged.connect(onOnlineUsersChanged); +GlobalServices.incomingMessage.connect(onIncommingMessage); \ No newline at end of file From 63e68391426f895330576da6b90d43e9208ef204 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Fri, 12 Sep 2014 22:24:35 +0200 Subject: [PATCH 5/9] combo boxes ported to new form code --- .../scripting/WindowScriptingInterface.cpp | 19 +++++++++++++++++++ .../src/scripting/WindowScriptingInterface.h | 1 + 2 files changed, 20 insertions(+) diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 031899689c..6b339c49fd 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -220,6 +220,7 @@ QScriptValue WindowScriptingInterface::doGetNonBlockingFormResult(QScriptValue a if (_formResult == QDialog::Accepted) { int e = -1; int d = -1; + int c = -1; for (int i = 0; i < _form.property("length").toInt32(); ++i) { QScriptValue item = _form.property(i); QScriptValue value = item.property("value"); @@ -235,6 +236,10 @@ QScriptValue WindowScriptingInterface::doGetNonBlockingFormResult(QScriptValue a value = _directories.at(d)->property("path").toString(); item.setProperty("directory", value); _form.setProperty(i, item); + } else if (item.property("options").isArray()) { + c += 1; + item.setProperty("value", _combos.at(c)->currentText()); + _form.setProperty(i, item); } else { e += 1; bool ok = true; @@ -288,6 +293,7 @@ QScriptValue WindowScriptingInterface::showForm(const QString& title, QScriptVal if (result == QDialog::Accepted) { int e = -1; int d = -1; + int c = -1; for (int i = 0; i < form.property("length").toInt32(); ++i) { QScriptValue item = form.property(i); QScriptValue value = item.property("value"); @@ -303,6 +309,10 @@ QScriptValue WindowScriptingInterface::showForm(const QString& title, QScriptVal value = _directories.at(d)->property("path").toString(); item.setProperty("directory", value); form.setProperty(i, item); + } else if (item.property("options").isArray()) { + c += 1; + item.setProperty("value", _combos.at(c)->currentText()); + _form.setProperty(i, item); } else { e += 1; bool ok = true; @@ -405,6 +415,15 @@ QDialog* WindowScriptingInterface::createForm(const QString& title, QScriptValue } else if (item.property("type").toString() == "header") { formLayout->addRow(new QLabel(item.property("label").toString())); + } else if (item.property("options").isArray()) { + QComboBox* combo = new QComboBox(); + combo->setMinimumWidth(200); + QStringList options = item.property("options").toVariant().toStringList(); + for (QStringList::const_iterator it = options.begin(); it != options.end(); it += 1) { + combo->addItem(*it); + } + _combos.push_back(combo); + formLayout->addRow(new QLabel(item.property("label").toString()), combo); } else { QLineEdit* edit = new QLineEdit(item.property("value").toString()); edit->setMinimumWidth(200); diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 84f6da287c..3324cd2ab6 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -71,6 +71,7 @@ private: QScriptValue _form; bool _nonBlockingFormActive; int _formResult; + QVector _combos; QVector _edits; QVector _directories; }; From 1838272d73a2b12d974f1751078b8a610b204c6c Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Fri, 12 Sep 2014 22:53:53 +0200 Subject: [PATCH 6/9] moved back butterflies.js , did I do it right? --- ...titiesButterflyFlock.js => butterflies.js} | 33 ++++++++----------- 1 file changed, 13 insertions(+), 20 deletions(-) rename examples/{entitiesButterflyFlock.js => butterflies.js} (94%) diff --git a/examples/entitiesButterflyFlock.js b/examples/butterflies.js similarity index 94% rename from examples/entitiesButterflyFlock.js rename to examples/butterflies.js index b86528bda1..1f612ed4bf 100644 --- a/examples/entitiesButterflyFlock.js +++ b/examples/butterflies.js @@ -1,5 +1,5 @@ // -// butterflyFlockTest1.js +// butterflies.js // // // Created by Adrian McCarlie on August 2, 2014 @@ -23,9 +23,6 @@ function vScalarMult(v, s) { return rval; } -function printVector(v) { - print(v.x + ", " + v.y + ", " + v.z + "\n"); -} // Create a random vector with individual lengths between a,b function randVector(a, b) { var rval = { x: a + Math.random() * (b - a), y: a + Math.random() * (b - a), z: a + Math.random() * (b - a) }; @@ -40,7 +37,7 @@ function vInterpolate(a, b, fraction) { var startTimeInSeconds = new Date().getTime() / 1000; -var lifeTime = 60; // lifetime of the butterflies in seconds! +var lifeTime = 600; // lifetime of the butterflies in seconds var range = 1.0; // Over what distance in meters do you want the flock to fly around var frame = 0; @@ -49,7 +46,7 @@ var BUTTERFLY_GRAVITY = 0;//-0.06; var BUTTERFLY_FLAP_SPEED = 1.0; var BUTTERFLY_VELOCITY = 0.55; var DISTANCE_IN_FRONT_OF_ME = 1.5; -var DISTANCE_ABOVE_ME = 1.5; +var DISTANCE_ABOVE_ME = 1.0; var flockPosition = Vec3.sum(MyAvatar.position,Vec3.sum( Vec3.multiply(Quat.getFront(MyAvatar.orientation), DISTANCE_ABOVE_ME), Vec3.multiply(Quat.getFront(MyAvatar.orientation), DISTANCE_IN_FRONT_OF_ME))); @@ -81,18 +78,7 @@ function addButterfly() { var color = { red: 100, green: 100, blue: 100 }; var size = 0; - var which = Math.random(); - if (which < 0.2) { - size = 0.08; - } else if (which < 0.4) { - size = 0.09; - } else if (which < 0.6) { - size = 0.8; - } else if (which < 0.8) { - size = 0.8; - } else { - size = 0.8; - } + size = 0.06 + Math.random() * 0.2; flockPosition = Vec3.sum(MyAvatar.position,Vec3.sum( Vec3.multiply(Quat.getFront(MyAvatar.orientation), DISTANCE_ABOVE_ME), @@ -212,7 +198,7 @@ function updateButterflies(deltaTime) { var desiredVelocity = Vec3.subtract(butterflies[i].targetPosition, properties.position); desiredVelocity = vScalarMult(Vec3.normalize(desiredVelocity), BUTTERFLY_VELOCITY); - properties.velocity = vInterpolate(properties.velocity, desiredVelocity, 0.2); + properties.velocity = vInterpolate(properties.velocity, desiredVelocity, 0.5); properties.velocity.y = holding ; @@ -238,4 +224,11 @@ function updateButterflies(deltaTime) { } // register the call back so it fires before each data send -Script.update.connect(updateButterflies); \ No newline at end of file +Script.update.connect(updateButterflies); + +// Delete our little friends if script is stopped +Script.scriptEnding.connect(function() { + for (var i = 0; i < numButterflies; i++) { + Entities.deleteEntity(butterflies[i].entityID); + } +}); \ No newline at end of file From 29dae39ad78d0e81851ab67853bd581e7debcba4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 12 Sep 2014 15:01:08 -0700 Subject: [PATCH 7/9] handle location lookup for offline user or not found --- interface/src/Application.cpp | 12 +++++++----- interface/src/Menu.cpp | 17 ++++++++++++++++- interface/src/Menu.h | 2 ++ libraries/networking/src/AddressManager.cpp | 20 ++++++++++++-------- libraries/networking/src/AddressManager.h | 1 + 5 files changed, 38 insertions(+), 14 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4a328562c7..1e8be6dca2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3947,11 +3947,13 @@ void Application::uploadAttachment() { } 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); + if (!url.isEmpty()) { + if (url.scheme() == HIFI_URL_SCHEME) { + AddressManager::getInstance().handleLookupString(url.toString()); + } else { + // address manager did not handle - ask QDesktopServices to handle + QDesktopServices::openUrl(url); + } } } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index c39e9abd3d..87290a3e64 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -142,9 +142,14 @@ Menu::Menu() : // call our toggle login function now so the menu option is setup properly toggleLoginMenuItem(); - // connect to the appropriate slots of the AccountManager so that we can change the Login/Logout menu item + // connect to the appropriate signal of the AccountManager so that we can change the Login/Logout menu item connect(&accountManager, &AccountManager::profileChanged, this, &Menu::toggleLoginMenuItem); connect(&accountManager, &AccountManager::logoutComplete, this, &Menu::toggleLoginMenuItem); + + // connect to signal of account manager so we can tell user when the user/place they looked at is offline + AddressManager& addressManager = AddressManager::getInstance(); + connect(&addressManager, &AddressManager::lookupResultIsOffline, this, &Menu::displayAddressOfflineMessage); + connect(&addressManager, &AddressManager::lookupResultIsNotFound, this, &Menu::displayAddressNotFoundMessage); addDisabledActionAndSeparator(fileMenu, "Scripts"); addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScript, Qt::CTRL | Qt::Key_O, appInstance, SLOT(loadDialog())); @@ -1158,6 +1163,16 @@ void Menu::toggleAddressBar() { sendFakeEnterEvent(); } +void Menu::displayAddressOfflineMessage() { + QMessageBox::information(Application::getInstance()->getWindow(), "Address offline", + "That user or place is currently offline."); +} + +void Menu::displayAddressNotFoundMessage() { + QMessageBox::information(Application::getInstance()->getWindow(), "Address not found", + "There is no address information for that user or place."); +} + void Menu::muteEnvironment() { int headerSize = numBytesForPacketHeaderGivenPacketType(PacketTypeMuteEnvironment); int packetSize = headerSize + sizeof(glm::vec3) + sizeof(float); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 307b011f74..b43e7cb75e 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -219,6 +219,8 @@ private slots: void toggleChat(); void audioMuteToggled(); void displayNameLocationResponse(const QString& errorString); + void displayAddressOfflineMessage(); + void displayAddressNotFoundMessage(); void muteEnvironment(); private: diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index f2e9ce64ab..8d35216558 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -59,8 +59,6 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl) { // 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()); @@ -86,12 +84,14 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl) { } 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)); + if (!lookupString.isEmpty()) { + // make this a valid hifi URL and handle it off to handleUrl + 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) { @@ -141,6 +141,10 @@ void AddressManager::handleAPIResponse(const QJsonObject &jsonObject) { void AddressManager::handleAPIError(QNetworkReply& errorReply) { qDebug() << "AddressManager API error -" << errorReply.error() << "-" << errorReply.errorString(); + + if (errorReply.error() == QNetworkReply::ContentNotFoundError) { + emit lookupResultIsNotFound(); + } } const QString GET_PLACE = "/api/v1/places/%1"; diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index f27fb475c2..e77fed67dc 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -38,6 +38,7 @@ public slots: void goToUser(const QString& username); signals: void lookupResultIsOffline(); + void lookupResultIsNotFound(); void possibleDomainChangeRequired(const QString& newHostname); void locationChangeRequired(const glm::vec3& newPosition, bool hasOrientationChange, const glm::vec3& newOrientation); private: From 3b21348a6319d82328d5edab721b67d0742ed36f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 12 Sep 2014 15:22:51 -0700 Subject: [PATCH 8/9] make sure AddressManager signal is connected to before file event --- interface/src/Application.cpp | 19 ++++++++++--------- libraries/networking/src/AddressManager.cpp | 2 ++ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1e8be6dca2..3664df53ab 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -290,6 +290,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // once the event loop has started, check and signal for an access token QMetaObject::invokeMethod(&accountManager, "checkAndSignalForAccessToken", Qt::QueuedConnection); + + AddressManager& addressManager = AddressManager::getInstance(); + + // connect to the domainChangeRequired signal on AddressManager + connect(&addressManager, &AddressManager::possibleDomainChangeRequired, + this, &Application::changeDomainHostname); + + // when -url in command line, teleport to location + addressManager.handleLookupString(getCmdOption(argc, constArgv, "-url")); _settings = new QSettings(this); _numChangedSettings = 0; @@ -403,15 +412,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : connect(_window, &MainWindow::windowGeometryChanged, _runningScriptsWidget, &RunningScriptsWidget::setBoundary); - - AddressManager& addressManager = AddressManager::getInstance(); - - // connect to the domainChangeRequired signal on AddressManager - connect(&addressManager, &AddressManager::possibleDomainChangeRequired, - this, &Application::changeDomainHostname); - - // when -url in command line, teleport to location - addressManager.handleLookupString(getCmdOption(argc, constArgv, "-url")); // call the OAuthWebviewHandler static getter so that its instance lives in our thread OAuthWebViewHandler::getInstance(); @@ -810,6 +810,7 @@ bool Application::event(QEvent* event) { // handle custom URL if (event->type() == QEvent::FileOpen) { + QFileOpenEvent* fileEvent = static_cast(event); if (!fileEvent->url().isEmpty()) { diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 8d35216558..13af32bc83 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -52,6 +52,8 @@ const JSONCallbackParameters& AddressManager::apiCallbackParameters() { bool AddressManager::handleUrl(const QUrl& lookupUrl) { if (lookupUrl.scheme() == HIFI_URL_SCHEME) { + qDebug() << "Trying to go to URL" << lookupUrl.toString(); + // there are 4 possible lookup strings // 1. global place name (name of domain or place) - example: sanfrancisco From 72a6254fa130bdff247b78e14af93817c67162fd Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 12 Sep 2014 15:24:38 -0700 Subject: [PATCH 9/9] Only allow one "blender" to run at a time for each model. --- interface/src/renderer/Model.cpp | 27 +++++++++++++++++++++++---- interface/src/renderer/Model.h | 3 +++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 280f5bd21a..0b16688056 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -61,7 +61,10 @@ Model::Model(QObject* parent) : _showTrueJointTransforms(true), _lodDistance(0.0f), _pupilDilation(0.0f), - _url("http://invalid.com") { + _url("http://invalid.com"), + _blenderPending(false), + _blendRequired(false) { + // we may have been created in the network thread, but we live in the main thread moveToThread(Application::getInstance()->thread()); } @@ -998,9 +1001,15 @@ void Model::simulateInternal(float deltaTime) { } } - // post the blender + // post the blender if we're not currently waiting for one to finish if (geometry.hasBlendedMeshes()) { - QThreadPool::globalInstance()->start(new Blender(this, _geometry, geometry.meshes, _blendshapeCoefficients)); + if (_blenderPending) { + _blendRequired = true; + } else { + _blendRequired = false; + _blenderPending = true; + QThreadPool::globalInstance()->start(new Blender(this, _geometry, geometry.meshes, _blendshapeCoefficients)); + } } } @@ -1264,10 +1273,20 @@ void Model::renderJointCollisionShapes(float alpha) { } void Model::setBlendedVertices(const QVector& vertices, const QVector& normals) { + _blenderPending = false; + + // start the next blender if required + const FBXGeometry& geometry = _geometry->getFBXGeometry(); + if (_blendRequired) { + _blendRequired = false; + if (geometry.hasBlendedMeshes()) { + _blenderPending = true; + QThreadPool::globalInstance()->start(new Blender(this, _geometry, geometry.meshes, _blendshapeCoefficients)); + } + } if (_blendedVertexBuffers.isEmpty()) { return; } - const FBXGeometry& geometry = _geometry->getFBXGeometry(); int index = 0; for (int i = 0; i < geometry.meshes.size(); i++) { const FBXMesh& mesh = geometry.meshes.at(i); diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 6c27970d8e..396a3e576c 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -284,6 +284,9 @@ private: glm::vec4 _localLightColors[MAX_LOCAL_LIGHTS]; glm::vec4 _localLightDirections[MAX_LOCAL_LIGHTS]; + bool _blenderPending; + bool _blendRequired; + static ProgramObject _program; static ProgramObject _normalMapProgram; static ProgramObject _specularMapProgram;