From b953e6f0ff78c9e0fdf9cbd9a77f5d8ef19843fe Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 1 Aug 2016 18:12:30 -0700 Subject: [PATCH 1/9] when an avatar URL fails, switch to the default --- interface/src/avatar/Avatar.cpp | 10 ++++++++++ interface/src/avatar/Avatar.h | 4 +++- .../src/model-networking/ModelCache.cpp | 1 + .../src/model-networking/ModelCache.h | 3 +++ libraries/render-utils/src/Model.cpp | 11 +++++++++++ libraries/render-utils/src/Model.h | 8 ++++++++ 6 files changed, 36 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 4d9481f002..f09eb5bdec 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -98,6 +98,7 @@ Avatar::Avatar(RigPointer rig) : _headData = static_cast(new Head(this)); _skeletonModel = std::make_shared(this, nullptr, rig); + connect(_skeletonModel.get(), &Model::setURLFinished, this, &Avatar::setModelURLFinished); } Avatar::~Avatar() { @@ -916,6 +917,15 @@ void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { } } +void Avatar::setModelURLFinished(bool success) { + if (!success && _skeletonModelURL != AvatarData::defaultFullAvatarModelUrl()) { + qDebug() << "Using default after failing to load Avatar model: " << _skeletonModelURL; + QMetaObject::invokeMethod(this, "setSkeletonModelURL", + Qt::QueuedConnection, Q_ARG(QUrl, AvatarData::defaultFullAvatarModelUrl())); + } +} + + // create new model, can return an instance of a SoftAttachmentModel rather then Model static std::shared_ptr allocateAttachmentModel(bool isSoft, RigPointer rigOverride) { if (isSoft) { diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index b9f44613c7..f646fe57f4 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -115,7 +115,7 @@ public: virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) override { return false; } virtual bool setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) override { return false; } - virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override; + Q_INVOKABLE virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override; virtual void setAttachmentData(const QVector& attachmentData) override; void setShowDisplayName(bool showDisplayName); @@ -184,6 +184,8 @@ public slots: glm::vec3 getRightPalmPosition() const; glm::quat getRightPalmRotation() const; + void setModelURLFinished(bool success); + protected: friend class AvatarManager; diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 26798070a6..3b7092ce8d 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -404,6 +404,7 @@ void GeometryResourceWatcher::resourceFinished(bool success) { if (success) { _geometryRef = std::make_shared(*_resource); } + emit finished(success); } void GeometryResourceWatcher::resourceRefreshed() { diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index 4a0a921a04..962a919d6c 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -111,6 +111,9 @@ public: QUrl getURL() const { return (bool)_resource ? _resource->getURL() : QUrl(); } +signals: + void finished(bool success); + private: void startWatching(); void stopWatching(); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index b04a1d8023..de0d69930b 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -109,6 +109,9 @@ Model::Model(RigPointer rig, QObject* parent) : } setSnapModelToRegistrationPoint(true, glm::vec3(0.5f)); + + connect(&_renderWatcher, &GeometryResourceWatcher::finished, this, &Model::loadURLFinished); + connect(&_collisionWatcher, &GeometryResourceWatcher::finished, this, &Model::loadURLFinished); } Model::~Model() { @@ -825,6 +828,10 @@ void Model::setURL(const QUrl& url) { onInvalidate(); } +void Model::loadURLFinished(bool success) { + emit setURLFinished(success); +} + void Model::setCollisionModelURL(const QUrl& url) { if (_collisionUrl == url && _collisionWatcher.getURL() == url) { return; @@ -833,6 +840,10 @@ void Model::setCollisionModelURL(const QUrl& url) { _collisionWatcher.setResource(DependencyManager::get()->getGeometryResource(url)); } +void Model::loadCollisionModelURLFinished(bool success) { + emit setCollisionModelURLFinished(success); +} + bool Model::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const { return _rig->getJointPositionInWorldFrame(jointIndex, position, _translation, _rotation); } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 98e50c66f4..076913a883 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -236,6 +236,14 @@ public: // returns 'true' if needs fullUpdate after geometry change bool updateGeometry(); +public slots: + void loadURLFinished(bool success); + void loadCollisionModelURLFinished(bool success); + +signals: + void setURLFinished(bool success); + void setCollisionModelURLFinished(bool success); + protected: void setPupilDilation(float dilation) { _pupilDilation = dilation; } From ed4b0b3589d700b532eb546cca007900826cd7a8 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 2 Aug 2016 09:57:17 -0700 Subject: [PATCH 2/9] call _skeletonModel.setURL, but leave our copy of _skeletonModelURL alone. This is so that we don't redo this every time we receive an identity packet from the avatar with the bad url. --- interface/src/avatar/Avatar.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index f09eb5bdec..001dfea10b 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -920,7 +920,9 @@ void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { void Avatar::setModelURLFinished(bool success) { if (!success && _skeletonModelURL != AvatarData::defaultFullAvatarModelUrl()) { qDebug() << "Using default after failing to load Avatar model: " << _skeletonModelURL; - QMetaObject::invokeMethod(this, "setSkeletonModelURL", + // call _skeletonModel.setURL, but leave our copy of _skeletonModelURL alone. This is so that + // we don't redo this every time we receive an identity packet from the avatar with the bad url. + QMetaObject::invokeMethod(_skeletonModel.get(), "setURL", Qt::QueuedConnection, Q_ARG(QUrl, AvatarData::defaultFullAvatarModelUrl())); } } From 229b8d3b5ebd795087729bd336a5cdaa4d25a778 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 2 Aug 2016 10:46:11 -0700 Subject: [PATCH 3/9] testing a more explicit fix of the audio failure --- interface/src/avatar/Avatar.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 001dfea10b..ab9c4b2f79 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -299,7 +299,9 @@ void Avatar::simulate(float deltaTime) { { PerformanceTimer perfTimer("head"); glm::vec3 headPosition = getPosition(); - _skeletonModel->getHeadPosition(headPosition); + if (!_skeletonModel->getHeadPosition(headPosition)) { + headPosition = getPosition(); + } Head* head = getHead(); head->setPosition(headPosition); head->setScale(getUniformScale()); @@ -922,8 +924,8 @@ void Avatar::setModelURLFinished(bool success) { qDebug() << "Using default after failing to load Avatar model: " << _skeletonModelURL; // call _skeletonModel.setURL, but leave our copy of _skeletonModelURL alone. This is so that // we don't redo this every time we receive an identity packet from the avatar with the bad url. - QMetaObject::invokeMethod(_skeletonModel.get(), "setURL", - Qt::QueuedConnection, Q_ARG(QUrl, AvatarData::defaultFullAvatarModelUrl())); + // QMetaObject::invokeMethod(_skeletonModel.get(), "setURL", + // Qt::QueuedConnection, Q_ARG(QUrl, AvatarData::defaultFullAvatarModelUrl())); } } From 56af36ae64f27eeddf390b1d642341e401228dca Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 2 Aug 2016 11:29:43 -0700 Subject: [PATCH 4/9] set head position of other avatars even if they can't be drawn --- interface/src/avatar/Avatar.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index ab9c4b2f79..45cdba9ace 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -309,6 +309,7 @@ void Avatar::simulate(float deltaTime) { } } else { // a non-full update is still required so that the position, rotation, scale and bounds of the skeletonModel are updated. + getHead()->setPosition(getPosition()); _skeletonModel->simulate(deltaTime, false); } From 75f9626c2d046773c9e5ff527569db55749fe86f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 2 Aug 2016 11:50:53 -0700 Subject: [PATCH 5/9] if MyAvatar simulation is cut short (due to no skeleton), still update the head position --- interface/src/avatar/MyAvatar.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index eef176338f..de5455fc14 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -430,6 +430,7 @@ void MyAvatar::simulate(float deltaTime) { if (!_skeletonModel->hasSkeleton()) { // All the simulation that can be done has been done + getHead()->setPosition(getPosition()); // so audio-position isn't 0,0,0 return; } From f91df4997d7a2f8179cc394c3e673ddb010b1304 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 2 Aug 2016 11:55:11 -0700 Subject: [PATCH 6/9] re-enable falling-back to default avatar if an avatar's url is bad --- interface/src/avatar/Avatar.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 45cdba9ace..b1b30a1acd 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -925,8 +925,8 @@ void Avatar::setModelURLFinished(bool success) { qDebug() << "Using default after failing to load Avatar model: " << _skeletonModelURL; // call _skeletonModel.setURL, but leave our copy of _skeletonModelURL alone. This is so that // we don't redo this every time we receive an identity packet from the avatar with the bad url. - // QMetaObject::invokeMethod(_skeletonModel.get(), "setURL", - // Qt::QueuedConnection, Q_ARG(QUrl, AvatarData::defaultFullAvatarModelUrl())); + QMetaObject::invokeMethod(_skeletonModel.get(), "setURL", + Qt::QueuedConnection, Q_ARG(QUrl, AvatarData::defaultFullAvatarModelUrl())); } } From 79121133dfc6e7528d8de0c91fe42ed20ccc4991 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 2 Aug 2016 12:00:45 -0700 Subject: [PATCH 7/9] remove unneeded change --- interface/src/avatar/Avatar.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index f646fe57f4..910f2cc1e6 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -115,7 +115,7 @@ public: virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) override { return false; } virtual bool setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) override { return false; } - Q_INVOKABLE virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override; + virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override; virtual void setAttachmentData(const QVector& attachmentData) override; void setShowDisplayName(bool showDisplayName); From 363915b836e3a327231ffed1ae859fa8a5fa6234 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 2 Aug 2016 19:37:38 -0700 Subject: [PATCH 8/9] switch audio script to use a valid but invisible avatar url --- .../audioExamples/acAudioSearching/ACAudioSearchAndInject.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script-archive/audioExamples/acAudioSearching/ACAudioSearchAndInject.js b/script-archive/audioExamples/acAudioSearching/ACAudioSearchAndInject.js index 30567b4fc7..daef1d5db3 100644 --- a/script-archive/audioExamples/acAudioSearching/ACAudioSearchAndInject.js +++ b/script-archive/audioExamples/acAudioSearching/ACAudioSearchAndInject.js @@ -40,7 +40,7 @@ var DEFAULT_SOUND_DATA = { Script.include("../../libraries/utils.js"); Agent.isAvatar = true; // This puts a robot at 0,0,0, but is currently necessary in order to use AvatarList. -Avatar.skeletonModelURL = "http://invalid-url"; +Avatar.skeletonModelURL = "http://hifi-content.s3.amazonaws.com/ozan/dev/avatars/invisible_avatar/invisible_avatar.fst"; function ignore() {} function debug() { // Display the arguments not just [Object object]. //print.apply(null, [].map.call(arguments, JSON.stringify)); From c743cf379ee23367924adaabf01f2e5c93b9965d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 3 Aug 2016 11:31:51 -0700 Subject: [PATCH 9/9] use loadCollisionModelURLFinished when collisions model is finished --- libraries/render-utils/src/Model.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index bedd158f2a..d755dc3aca 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -112,7 +112,7 @@ Model::Model(RigPointer rig, QObject* parent) : setSnapModelToRegistrationPoint(true, glm::vec3(0.5f)); connect(&_renderWatcher, &GeometryResourceWatcher::finished, this, &Model::loadURLFinished); - connect(&_collisionWatcher, &GeometryResourceWatcher::finished, this, &Model::loadURLFinished); + connect(&_collisionWatcher, &GeometryResourceWatcher::finished, this, &Model::loadCollisionModelURLFinished); } Model::~Model() {