From ce3d6d2fca0de3eaf6fef0e69ce3b84c66b0f9a0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 25 Feb 2014 13:07:39 -0800 Subject: [PATCH 1/5] reset nodelist if domain-server stops talking to you, closes #2092 --- interface/src/Application.cpp | 1 + libraries/shared/src/NodeList.cpp | 6 ++++++ libraries/shared/src/NodeList.h | 1 + 3 files changed, 8 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 035845eda4..03905a45c1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -227,6 +227,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), &_voxels, SLOT(nodeAdded(SharedNodePointer))); connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), &_voxels, SLOT(nodeKilled(SharedNodePointer))); connect(nodeList, &NodeList::uuidChanged, this, &Application::updateWindowTitle); + connect(nodeList, &NodeList::limitOfSilentDomainCheckInsReached, nodeList, &NodeList::reset); // connect to appropriate slots on AccountManager AccountManager& accountManager = AccountManager::getInstance(); diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 98387ce420..d8c6cd09f1 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -549,6 +549,12 @@ void NodeList::sendDomainServerCheckIn() { sendSTUNRequest(); } + if (_numNoReplyDomainCheckIns >= MAX_SILENT_DOMAIN_SERVER_CHECK_INS) { + // we haven't heard back from DS in MAX_SILENT_DOMAIN_SERVER_CHECK_INS + // so emit our signal that indicates that + emit limitOfSilentDomainCheckInsReached(); + } + // increment the count of un-replied check-ins _numNoReplyDomainCheckIns++; } else if (AccountManager::getInstance().hasValidAccessToken()) { diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index a66bcf3535..590a2ce83f 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -132,6 +132,7 @@ signals: void uuidChanged(const QUuid& ownerUUID); void nodeAdded(SharedNodePointer); void nodeKilled(SharedNodePointer); + void limitOfSilentDomainCheckInsReached(); private slots: void domainServerAuthReply(const QJsonObject& jsonObject); private: From 70c1f8290e62f56596a39555aca5588176a2d3e7 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 25 Feb 2014 13:21:02 -0800 Subject: [PATCH 2/5] assume RAW audio if not processed as WAV --- libraries/audio/src/Sound.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/libraries/audio/src/Sound.cpp b/libraries/audio/src/Sound.cpp index a403439ec6..07eec031b5 100644 --- a/libraries/audio/src/Sound.cpp +++ b/libraries/audio/src/Sound.cpp @@ -44,13 +44,8 @@ void Sound::replyFinished(QNetworkReply* reply) { QByteArray headerContentType = reply->rawHeader("Content-Type"); - // RAW audio file encountered - if (headerContentType == "application/octet-stream") { - downSample(rawAudioByteArray); - } - // WAV audio file encountered - else if (headerContentType == "audio/x-wav" + if (headerContentType == "audio/x-wav" || headerContentType == "audio/wav" || headerContentType == "audio/wave") { @@ -59,7 +54,8 @@ void Sound::replyFinished(QNetworkReply* reply) { interpretAsWav(rawAudioByteArray, outputAudioByteArray); downSample(outputAudioByteArray); } else { - qDebug() << "Unknown audio file 'Content-Type'."; + // Process as RAW file + downSample(rawAudioByteArray); } } else { qDebug() << "Network reply without 'Content-Type'."; From f2a70bf27549aade51f57aa90be96459d0f7de6b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 25 Feb 2014 13:38:20 -0800 Subject: [PATCH 3/5] add support for billboard setting from URL --- libraries/avatars/src/AvatarData.cpp | 27 +++++++++++++++++++++++++++ libraries/avatars/src/AvatarData.h | 13 ++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 2cb719c446..95e0cfe7d5 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -11,6 +11,9 @@ #include #include +#include +#include +#include #include #include @@ -24,6 +27,8 @@ using namespace std; static const float fingerVectorRadix = 4; // bits of precision when converting from float<->fixed +QNetworkAccessManager* AvatarData::networkAccessManager = NULL; + AvatarData::AvatarData() : NodeData(), _handPosition(0,0,0), @@ -338,6 +343,28 @@ void AvatarData::setBillboard(const QByteArray& billboard) { qDebug() << "Changing billboard for avatar."; } +void AvatarData::setBillboardFromURL(const QString &billboardURL) { + _billboardURL = billboardURL; + + if (AvatarData::networkAccessManager) { + qDebug() << "Changing billboard for avatar to PNG at" << qPrintable(billboardURL); + + QNetworkRequest billboardRequest; + billboardRequest.setUrl(QUrl(billboardURL)); + + QNetworkReply* networkReply = AvatarData::networkAccessManager->get(billboardRequest); + connect(networkReply, SIGNAL(finished()), this, SLOT(setBillboardFromNetworkReply())); + + } else { + qDebug() << "Billboard PNG download requested but no network access manager is available."; + } +} + +void AvatarData::setBillboardFromNetworkReply() { + QNetworkReply* networkReply = reinterpret_cast(sender()); + setBillboard(networkReply->readAll()); +} + void AvatarData::setClampedTargetScale(float targetScale) { targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index c5cd72c184..0ce2910398 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -68,6 +68,8 @@ enum KeyState { const glm::vec3 vec3Zero(0.0f); +class QNetworkAccessManager; + class AvatarData : public NodeData { Q_OBJECT @@ -88,6 +90,7 @@ class AvatarData : public NodeData { Q_PROPERTY(QString faceModelURL READ getFaceModelURLFromScript WRITE setFaceModelURLFromScript) Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript) + Q_PROPERTY(QString billboardURL READ getBillboardURL WRITE setBillboardFromURL) public: AvatarData(); ~AvatarData(); @@ -170,6 +173,9 @@ public: virtual void setBillboard(const QByteArray& billboard); const QByteArray& getBillboard() const { return _billboard; } + void setBillboardFromURL(const QString& billboardURL); + const QString& getBillboardURL() { return _billboardURL; } + QString getFaceModelURLFromScript() const { return _faceModelURL.toString(); } void setFaceModelURLFromScript(const QString& faceModelString) { setFaceModelURL(faceModelString); } @@ -177,11 +183,13 @@ public: void setSkeletonModelURLFromScript(const QString& skeletonModelString) { setSkeletonModelURL(QUrl(skeletonModelString)); } virtual float getBoundingRadius() const { return 1.f; } + + static void setNetworkAccessManager(QNetworkAccessManager* sharedAccessManager) { networkAccessManager = sharedAccessManager; } public slots: void sendIdentityPacket(); void sendBillboardPacket(); - + void setBillboardFromNetworkReply(); protected: glm::vec3 _position; glm::vec3 _handPosition; @@ -217,6 +225,9 @@ protected: float _displayNameAlpha; QByteArray _billboard; + QString _billboardURL; + + static QNetworkAccessManager* networkAccessManager; private: // privatize the copy constructor and assignment operator so they cannot be called From ee70c93a3e7a7c35a5a757e12c4a67f38dd2eba6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 25 Feb 2014 13:42:07 -0800 Subject: [PATCH 4/5] have scripted avatars send billboard, if they have one --- libraries/avatars/src/AvatarData.cpp | 13 ++++++++----- libraries/script-engine/src/ScriptEngine.cpp | 14 ++++++++++++-- libraries/script-engine/src/ScriptEngine.h | 2 ++ 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 95e0cfe7d5..482cd7564a 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -43,7 +43,8 @@ AvatarData::AvatarData() : _handData(NULL), _displayNameBoundingRect(), _displayNameTargetAlpha(0.0f), - _displayNameAlpha(0.0f) + _displayNameAlpha(0.0f), + _billboard() { } @@ -388,8 +389,10 @@ void AvatarData::sendIdentityPacket() { } void AvatarData::sendBillboardPacket() { - QByteArray billboardPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarBillboard); - billboardPacket.append(_billboard); - - NodeList::getInstance()->broadcastToNodes(billboardPacket, NodeSet() << NodeType::AvatarMixer); + if (!_billboard.isEmpty()) { + QByteArray billboardPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarBillboard); + billboardPacket.append(_billboard); + + NodeList::getInstance()->broadcastToNodes(billboardPacket, NodeSet() << NodeType::AvatarMixer); + } } diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 076f941222..c1b122b523 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -45,6 +45,7 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems, co AbstractControllerScriptingInterface* controllerScriptingInterface) : _isAvatar(false), _avatarIdentityTimer(NULL), + _avatarBillboardTimer(NULL), _avatarData(NULL) { _scriptContents = scriptContents; @@ -79,14 +80,17 @@ void ScriptEngine::setIsAvatar(bool isAvatar) { _isAvatar = isAvatar; if (_isAvatar && !_avatarIdentityTimer) { - // set up the avatar identity timer + // set up the avatar timers _avatarIdentityTimer = new QTimer(this); + _avatarBillboardTimer = new QTimer(this); // connect our slot connect(_avatarIdentityTimer, &QTimer::timeout, this, &ScriptEngine::sendAvatarIdentityPacket); + connect(_avatarBillboardTimer, &QTimer::timeout, this, &ScriptEngine::sendAvatarBillboardPacket); - // start the timer + // start the timers _avatarIdentityTimer->start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS); + _avatarBillboardTimer->start(AVATAR_BILLBOARD_PACKET_SEND_INTERVAL_MSECS); } } @@ -196,6 +200,12 @@ void ScriptEngine::sendAvatarIdentityPacket() { } } +void ScriptEngine::sendAvatarBillboardPacket() { + if (_isAvatar && _avatarData) { + _avatarData->sendBillboardPacket(); + } +} + void ScriptEngine::run() { if (!_isInitialized) { init(); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index cf5ad1a68b..72ac848bff 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -85,10 +85,12 @@ protected: QScriptEngine _engine; bool _isAvatar; QTimer* _avatarIdentityTimer; + QTimer* _avatarBillboardTimer; QHash _timerFunctionMap; private: void sendAvatarIdentityPacket(); + void sendAvatarBillboardPacket(); QObject* setupTimerWithInterval(const QScriptValue& function, int intervalMS, bool isSingleShot); void stopTimer(QTimer* timer); From 937768ae51615bd365981893cc782df11cc83de6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 25 Feb 2014 13:51:48 -0800 Subject: [PATCH 5/5] add option for fake billboard from URL, closes #2087 --- assignment-client/src/Agent.cpp | 3 +++ examples/bot.js | 1 + 2 files changed, 4 insertions(+) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index cdaa825ad8..104f65d7d9 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -92,6 +92,9 @@ void Agent::run() { loop.exec(); + // let the AvatarData class use our QNetworkAcessManager + AvatarData::setNetworkAccessManager(networkManager); + QString scriptContents(reply->readAll()); qDebug() << "Downloaded script:" << scriptContents; diff --git a/examples/bot.js b/examples/bot.js index 53f723381c..c8280e063d 100644 --- a/examples/bot.js +++ b/examples/bot.js @@ -50,5 +50,6 @@ if (botNumber <= 20) { // there is no need to change the body model - we're using the default Avatar.faceModelURL = "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/" + newFaceFilePrefix + ".fst"; Avatar.skeletonModelURL = "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/" + newBodyFilePrefix + ".fst"; +Avatar.billboardURL = "https://dl.dropboxusercontent.com/u/1864924/bot-billboard.png"; Agent.isAvatar = true; \ No newline at end of file