From 2429b82b5e92dc83f9f5e77e28e95e896917f80b Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Thu, 21 Jul 2016 17:17:08 -0700 Subject: [PATCH] Support for animGraphUrl override in FST file. --- interface/src/avatar/MyAvatar.cpp | 53 ++++++++++++++++--- interface/src/avatar/MyAvatar.h | 12 +++-- interface/src/ui/PreferencesDialog.cpp | 4 +- .../src/model-networking/ModelCache.cpp | 14 +++++ .../src/model-networking/ModelCache.h | 3 ++ 5 files changed, 72 insertions(+), 14 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6a69ee9a9a..24c80cc2fd 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -687,7 +687,9 @@ void MyAvatar::saveData() { _fullAvatarURLFromPreferences.toString()); settings.setValue("fullAvatarModelName", _fullAvatarModelName); - settings.setValue("animGraphURL", _animGraphUrl); + + QUrl animGraphUrl = _prefOverrideAnimGraphUrl.get(); + settings.setValue("animGraphURL", animGraphUrl); settings.beginWriteArray("attachmentData"); for (int i = 0; i < _attachmentData.size(); i++) { @@ -800,7 +802,7 @@ void MyAvatar::loadData() { _targetScale = loadSetting(settings, "scale", 1.0f); setScale(glm::vec3(_targetScale)); - _animGraphUrl = settings.value("animGraphURL", "").toString(); + _prefOverrideAnimGraphUrl.set(QUrl(settings.value("animGraphURL", "").toString())); _fullAvatarURLFromPreferences = settings.value("fullAvatarURL", AvatarData::defaultFullAvatarModelUrl()).toUrl(); _fullAvatarModelName = settings.value("fullAvatarModelName", DEFAULT_FULL_AVATAR_MODEL_NAME).toString(); @@ -1379,21 +1381,55 @@ void MyAvatar::initHeadBones() { } } +QUrl MyAvatar::getAnimGraphOverrideUrl() const { + return _prefOverrideAnimGraphUrl.get(); +} + +void MyAvatar::setAnimGraphOverrideUrl(QUrl value) { + _prefOverrideAnimGraphUrl.set(value); + if (!value.isEmpty()) { + setAnimGraphUrl(value); + } else { + initAnimGraph(); + } +} + +QUrl MyAvatar::getAnimGraphUrl() const { + return _currentAnimGraphUrl.get(); +} + void MyAvatar::setAnimGraphUrl(const QUrl& url) { - if (_animGraphUrl == url) { + + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setAnimGraphUrl", Q_ARG(QUrl, url)); + return; + } + + if (_currentAnimGraphUrl.get() == url) { return; } destroyAnimGraph(); _skeletonModel->reset(); // Why is this necessary? Without this, we crash in the next render. - _animGraphUrl = url; - initAnimGraph(); + + _currentAnimGraphUrl.set(url); + _rig->initAnimGraph(url); + + _bodySensorMatrix = deriveBodyFromHMDSensor(); // Based on current cached HMD position/rotation.. + updateSensorToWorldMatrix(); // Uses updated position/orientation and _bodySensorMatrix changes } void MyAvatar::initAnimGraph() { - auto graphUrl =_animGraphUrl.isEmpty() ? - QUrl::fromLocalFile(PathUtils::resourcesPath() + "avatar/avatar-animation.json") : - QUrl(_animGraphUrl); + QUrl graphUrl; + if (!_prefOverrideAnimGraphUrl.get().isEmpty()) { + graphUrl = _prefOverrideAnimGraphUrl.get(); + } else if (!_fstAnimGraphOverrideUrl.isEmpty()) { + graphUrl = _fstAnimGraphOverrideUrl; + } else { + graphUrl = QUrl::fromLocalFile(PathUtils::resourcesPath() + "avatar/avatar-animation.json"); + } + _rig->initAnimGraph(graphUrl); + _currentAnimGraphUrl.set(graphUrl); _bodySensorMatrix = deriveBodyFromHMDSensor(); // Based on current cached HMD position/rotation.. updateSensorToWorldMatrix(); // Uses updated position/orientation and _bodySensorMatrix changes @@ -1411,6 +1447,7 @@ void MyAvatar::postUpdate(float deltaTime) { if (_skeletonModel->initWhenReady(scene)) { initHeadBones(); _skeletonModel->setCauterizeBoneSet(_headBoneSet); + _fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl(); initAnimGraph(); } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index a21922f1b1..97cb2b35fa 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -288,8 +288,6 @@ public slots: Q_INVOKABLE void updateMotionBehaviorFromMenu(); - Q_INVOKABLE QUrl getAnimGraphUrl() const { return _animGraphUrl; } - void setEnableDebugDrawDefaultPose(bool isEnabled); void setEnableDebugDrawAnimPose(bool isEnabled); void setEnableDebugDrawPosition(bool isEnabled); @@ -299,7 +297,11 @@ public slots: void setEnableMeshVisible(bool isEnabled); void setUseAnimPreAndPostRotations(bool isEnabled); void setEnableInverseKinematics(bool isEnabled); - Q_INVOKABLE void setAnimGraphUrl(const QUrl& url); + + QUrl getAnimGraphOverrideUrl() const; // thread-safe + void setAnimGraphOverrideUrl(QUrl value); // thread-safe + QUrl getAnimGraphUrl() const; // thread-safe + void setAnimGraphUrl(const QUrl& url); // thread-safe glm::vec3 getPositionForAudio(); glm::quat getOrientationForAudio(); @@ -403,7 +405,9 @@ private: // Avatar Preferences QUrl _fullAvatarURLFromPreferences; QString _fullAvatarModelName; - QUrl _animGraphUrl {""}; + ThreadSafeValueCache _currentAnimGraphUrl; + ThreadSafeValueCache _prefOverrideAnimGraphUrl; + QUrl _fstAnimGraphOverrideUrl; bool _useSnapTurn { true }; bool _clearOverlayWhenMoving { true }; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 4007c940c3..7fdafc9bda 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -161,8 +161,8 @@ void setupPreferences() { preferences->addPreference(preference); } { - auto getter = [=]()->QString { return myAvatar->getAnimGraphUrl().toString(); }; - auto setter = [=](const QString& value) { myAvatar->setAnimGraphUrl(value); }; + auto getter = [=]()->QString { return myAvatar->getAnimGraphOverrideUrl().toString(); }; + auto setter = [=](const QString& value) { myAvatar->setAnimGraphOverrideUrl(QUrl(value)); }; auto preference = new EditPreference(AVATAR_TUNING, "Avatar animation JSON", getter, setter); preference->setPlaceholderText("default"); preferences->addPreference(preference); diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 4885186e47..26798070a6 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -67,6 +67,18 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) { _textureBaseUrl = resolveTextureBaseUrl(url, _url.resolved(texdir)); } + auto animGraphVariant = mapping.value("animGraphUrl"); + if (animGraphVariant.isValid()) { + QUrl fstUrl(animGraphVariant.toString()); + if (fstUrl.isValid()) { + _animGraphOverrideUrl = _url.resolved(fstUrl); + } else { + _animGraphOverrideUrl = QUrl(); + } + } else { + _animGraphOverrideUrl = QUrl(); + } + auto modelCache = DependencyManager::get(); GeometryExtra extra{ mapping, _textureBaseUrl }; @@ -284,6 +296,8 @@ Geometry::Geometry(const Geometry& geometry) { for (const auto& material : geometry._materials) { _materials.push_back(std::make_shared(*material)); } + + _animGraphOverrideUrl = geometry._animGraphOverrideUrl; } void Geometry::setTextures(const QVariantMap& textureMap) { diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index aa3ea78db3..4a0a921a04 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -52,6 +52,7 @@ public: void setTextures(const QVariantMap& textureMap); virtual bool areTexturesLoaded() const; + const QUrl& getAnimGraphOverrideUrl() const { return _animGraphOverrideUrl; } protected: friend class GeometryMappingResource; @@ -64,6 +65,8 @@ protected: // Copied to each geometry, mutable throughout lifetime via setTextures NetworkMaterials _materials; + QUrl _animGraphOverrideUrl; + private: mutable bool _areTexturesLoaded { false }; };