From bc5d9a46a2d5e8966b1931b4a7d18ab5f92774b6 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Tue, 11 Sep 2018 13:12:46 -0700 Subject: [PATCH] Avatar loading orb now indicates status white - no url has been received yet for this avatar purple - a url has been received for this avatar but it's content is still downloading/loading blue - (only visible breifly) content has succesfully loaded red - (only visible briefly) content has failed to download. --- interface/src/avatar/OtherAvatar.cpp | 27 ++++++++++++++++++- interface/src/avatar/OtherAvatar.h | 1 + .../src/avatars-renderer/Avatar.cpp | 17 +++++++++--- .../src/avatars-renderer/Avatar.h | 10 +++++++ 4 files changed, 50 insertions(+), 5 deletions(-) diff --git a/interface/src/avatar/OtherAvatar.cpp b/interface/src/avatar/OtherAvatar.cpp index a0fa496c4c..cf15d4abdf 100644 --- a/interface/src/avatar/OtherAvatar.cpp +++ b/interface/src/avatar/OtherAvatar.cpp @@ -11,6 +11,24 @@ #include "AvatarMotionState.h" +static xColor getLoadingOrbColor(Avatar::LoadingStatus loadingStatus) { + + const xColor NO_MODEL_COLOR(0xe3, 0xe3, 0xe3); + const xColor LOAD_MODEL_COLOR(0xef, 0x93, 0xd1); + const xColor LOAD_SUCCESS_COLOR(0x1f, 0xc6, 0xa6); + const xColor LOAD_FAILURE_COLOR(0xc6, 0x21, 0x47); + switch (loadingStatus) { + case Avatar::LoadingStatus::NoModel: + return NO_MODEL_COLOR; + case Avatar::LoadingStatus::LoadModel: + return LOAD_MODEL_COLOR; + case Avatar::LoadingStatus::LoadSuccess: + return LOAD_SUCCESS_COLOR; + case Avatar::LoadingStatus::LoadFailure: + return LOAD_FAILURE_COLOR; + } +} + OtherAvatar::OtherAvatar(QThread* thread) : Avatar(thread) { // give the pointer to our head to inherited _headData variable from AvatarData _headData = new Head(this); @@ -48,7 +66,7 @@ void OtherAvatar::createOrb() { if (_otherAvatarOrbMeshPlaceholderID.isNull()) { _otherAvatarOrbMeshPlaceholder = std::make_shared(); _otherAvatarOrbMeshPlaceholder->setAlpha(1.0f); - _otherAvatarOrbMeshPlaceholder->setColor({ 0xFF, 0x00, 0xFF }); + _otherAvatarOrbMeshPlaceholder->setColor(getLoadingOrbColor(_loadingStatus)); _otherAvatarOrbMeshPlaceholder->setIsSolid(false); _otherAvatarOrbMeshPlaceholder->setPulseMin(0.5); _otherAvatarOrbMeshPlaceholder->setPulseMax(1.0); @@ -64,6 +82,13 @@ void OtherAvatar::createOrb() { } } +void OtherAvatar::indicateLoadingStatus(LoadingStatus loadingStatus) { + Avatar::indicateLoadingStatus(loadingStatus); + if (_otherAvatarOrbMeshPlaceholder) { + _otherAvatarOrbMeshPlaceholder->setColor(getLoadingOrbColor(_loadingStatus)); + } +} + void OtherAvatar::setSpaceIndex(int32_t index) { assert(_spaceIndex == -1); _spaceIndex = index; diff --git a/interface/src/avatar/OtherAvatar.h b/interface/src/avatar/OtherAvatar.h index ccfe42dbed..94b98f2747 100644 --- a/interface/src/avatar/OtherAvatar.h +++ b/interface/src/avatar/OtherAvatar.h @@ -28,6 +28,7 @@ public: virtual void instantiableAvatar() override { }; virtual void createOrb() override; + virtual void indicateLoadingStatus(LoadingStatus loadingStatus) override; void updateOrbPosition(); void removeOrb(); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 4ffccefe61..ac25f65576 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -126,6 +126,8 @@ Avatar::Avatar(QThread* thread) : _leftPointerGeometryID = geometryCache->allocateID(); _rightPointerGeometryID = geometryCache->allocateID(); _lastRenderUpdateTime = usecTimestampNow(); + + indicateLoadingStatus(LoadingStatus::NoModel); } Avatar::~Avatar() { @@ -1370,12 +1372,15 @@ void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const { } void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { - if (!isMyAvatar()) { - createOrb(); - } AvatarData::setSkeletonModelURL(skeletonModelURL); if (QThread::currentThread() == thread()) { + + if (!isMyAvatar()) { + createOrb(); + } + _skeletonModel->setURL(_skeletonModelURL); + indicateLoadingStatus(LoadingStatus::LoadModel); } else { QMetaObject::invokeMethod(_skeletonModel.get(), "setURL", Qt::QueuedConnection, Q_ARG(QUrl, _skeletonModelURL)); } @@ -1388,11 +1393,12 @@ void Avatar::setModelURLFinished(bool success) { _reconstructSoftEntitiesJointMap = true; if (!success && _skeletonModelURL != AvatarData::defaultFullAvatarModelUrl()) { + indicateLoadingStatus(LoadingStatus::LoadFailure); const int MAX_SKELETON_DOWNLOAD_ATTEMPTS = 4; // NOTE: we don't want to be as generous as ResourceCache is, we only want 4 attempts if (_skeletonModel->getResourceDownloadAttemptsRemaining() <= 0 || _skeletonModel->getResourceDownloadAttempts() > MAX_SKELETON_DOWNLOAD_ATTEMPTS) { qCWarning(avatars_renderer) << "Using default after failing to load Avatar model: " << _skeletonModelURL - << "after" << _skeletonModel->getResourceDownloadAttempts() << "attempts."; + << "after" << _skeletonModel->getResourceDownloadAttempts() << "attempts."; // 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", @@ -1403,6 +1409,9 @@ void Avatar::setModelURLFinished(bool success) { << "out of:" << MAX_SKELETON_DOWNLOAD_ATTEMPTS; } } + if (success) { + indicateLoadingStatus(LoadingStatus::LoadSuccess); + } } // rig is ready diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 37c3d08c6c..3482c3c193 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -107,6 +107,14 @@ public: virtual bool isMyAvatar() const override { return false; } virtual void createOrb() { } + enum class LoadingStatus { + NoModel, + LoadModel, + LoadSuccess, + LoadFailure + }; + virtual void indicateLoadingStatus(LoadingStatus loadingStatus) { _loadingStatus = loadingStatus; } + virtual QVector getJointRotations() const override; using AvatarData::getJointRotation; virtual glm::quat getJointRotation(int index) const override; @@ -540,6 +548,8 @@ protected: static const float MYAVATAR_LOADING_PRIORITY; static const float OTHERAVATAR_LOADING_PRIORITY; static const float ATTACHMENT_LOADING_PRIORITY; + + LoadingStatus _loadingStatus { LoadingStatus::NoModel }; }; #endif // hifi_Avatar_h