diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 07c1b4e38d..ec4b2c6b8e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1,4 +1,4 @@ -// + // // Application.cpp // interface/src // @@ -2481,17 +2481,41 @@ void Application::init() { connect(tree, &EntityTree::newCollisionSoundURL, DependencyManager::get().data(), &SoundCache::getSound); connect(_myAvatar, &MyAvatar::newCollisionSoundURL, DependencyManager::get().data(), &SoundCache::getSound); - setAvatarUpdateThreading(Menu::getInstance()->isOptionChecked(MenuOption::EnableAvatarUpdateThreading)); + setAvatarUpdateThreading(); } -void Application::setAvatarUpdateThreading(bool isThreaded) { +void Application::setAvatarUpdateThreading() { + setAvatarUpdateThreading(Menu::getInstance()->isOptionChecked(MenuOption::EnableAvatarUpdateThreading)); +} +void Application::setRawAvatarUpdateThreading() { + setRawAvatarUpdateThreading(Menu::getInstance()->isOptionChecked(MenuOption::EnableAvatarUpdateThreading)); +} +void Application::setRawAvatarUpdateThreading(bool isThreaded) { if (_avatarUpdate) { - getMyAvatar()->destroyAnimGraph(); + if (_avatarUpdate->isThreaded() == isThreaded) { + return; + } _avatarUpdate->terminate(); } _avatarUpdate = new AvatarUpdate(); _avatarUpdate->initialize(isThreaded); } +void Application::setAvatarUpdateThreading(bool isThreaded) { + if (_avatarUpdate && (_avatarUpdate->isThreaded() == isThreaded)) { + return; + } + bool isRigEnabled = getMyAvatar()->getEnableRigAnimations(); + bool isGraphEnabled = getMyAvatar()->getEnableAnimGraph(); + if (_avatarUpdate) { + _avatarUpdate->terminate(); // Must be before we shutdown anim graph. + } + getMyAvatar()->setEnableRigAnimations(false); + getMyAvatar()->setEnableAnimGraph(false); + _avatarUpdate = new AvatarUpdate(); + _avatarUpdate->initialize(isThreaded); + getMyAvatar()->setEnableRigAnimations(isRigEnabled); + getMyAvatar()->setEnableAnimGraph(isGraphEnabled); +} void Application::closeMirrorView() { diff --git a/interface/src/Application.h b/interface/src/Application.h index 6056323aa9..e1acc7c7c3 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -412,7 +412,10 @@ public slots: void openUrl(const QUrl& url); void updateMyAvatarTransform(); + void setAvatarUpdateThreading(); void setAvatarUpdateThreading(bool isThreaded); + void setRawAvatarUpdateThreading(); + void setRawAvatarUpdateThreading(bool isThreaded); void domainSettingsReceived(const QJsonObject& domainSettingsObject); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index bafca2844d..27b69554db 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -710,7 +710,6 @@ float loadSetting(QSettings& settings, const char* name, float defaultValue) { // If we demand the animation from the update thread while we're locked, we'll deadlock. // Until we untangle this, code puts the updates back on the main thread temporarilly and starts all the loading. void MyAvatar::safelyLoadAnimations() { - qApp->setAvatarUpdateThreading(false); _rig->addAnimationByRole("idle"); _rig->addAnimationByRole("walk"); _rig->addAnimationByRole("backup"); @@ -721,30 +720,40 @@ void MyAvatar::safelyLoadAnimations() { } void MyAvatar::setEnableRigAnimations(bool isEnabled) { - if (isEnabled) { - safelyLoadAnimations(); + if (_rig->getEnableRig() == isEnabled) { + return; } - _rig->setEnableRig(isEnabled); - if (!isEnabled) { + if (isEnabled) { + qApp->setRawAvatarUpdateThreading(false); + setEnableAnimGraph(false); + Menu::getInstance()->setIsOptionChecked(MenuOption::EnableAnimGraph, false); + safelyLoadAnimations(); + qApp->setRawAvatarUpdateThreading(); + _rig->setEnableRig(true); + } else { + _rig->setEnableRig(false); _rig->deleteAnimations(); - } else if (Menu::getInstance()->isOptionChecked(MenuOption::EnableAvatarUpdateThreading)) { - qApp->setAvatarUpdateThreading(true); } } void MyAvatar::setEnableAnimGraph(bool isEnabled) { - if (isEnabled) { - safelyLoadAnimations(); + if (_rig->getEnableAnimGraph() == isEnabled) { + return; } - _rig->setEnableAnimGraph(isEnabled); if (isEnabled) { + qApp->setRawAvatarUpdateThreading(false); + setEnableRigAnimations(false); + Menu::getInstance()->setIsOptionChecked(MenuOption::EnableRigAnimations, false); + safelyLoadAnimations(); if (_skeletonModel.readyToAddToScene()) { - initAnimGraph(); - } - if (Menu::getInstance()->isOptionChecked(MenuOption::EnableAvatarUpdateThreading)) { - qApp->setAvatarUpdateThreading(true); - } + _rig->setEnableAnimGraph(true); + initAnimGraph(); // must be enabled for the init to happen + _rig->setEnableAnimGraph(false); // must be disable to safely reset threading + } + qApp->setRawAvatarUpdateThreading(); + _rig->setEnableAnimGraph(true); } else { + _rig->setEnableAnimGraph(false); destroyAnimGraph(); } } @@ -1098,7 +1107,17 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN const QString& urlString = fullAvatarURL.toString(); if (urlString.isEmpty() || (fullAvatarURL != getSkeletonModelURL())) { + bool isRigEnabled = getEnableRigAnimations(); + bool isGraphEnabled = getEnableAnimGraph(); + qApp->setRawAvatarUpdateThreading(false); + setEnableRigAnimations(false); + setEnableAnimGraph(false); + setSkeletonModelURL(fullAvatarURL); + + setEnableRigAnimations(isRigEnabled); + setEnableAnimGraph(isGraphEnabled); + qApp->setRawAvatarUpdateThreading(); UserActivityLogger::getInstance().changedModel("skeleton", urlString); } sendIdentityPacket(); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index bb3c6385f9..6989ea3969 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -192,7 +192,9 @@ public slots: virtual void rebuildSkeletonBody(); + bool getEnableRigAnimations() const { return _rig->getEnableRig(); } void setEnableRigAnimations(bool isEnabled); + bool getEnableAnimGraph() const { return _rig->getEnableAnimGraph(); } void setEnableAnimGraph(bool isEnabled); void setEnableDebugDrawBindPose(bool isEnabled); void setEnableDebugDrawAnimPose(bool isEnabled); diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 71401b6c60..b6d2be11f2 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -29,7 +29,7 @@ void AnimInverseKinematics::loadDefaultPoses(const AnimPoseVec& poses) { } void AnimInverseKinematics::loadPoses(const AnimPoseVec& poses) { - assert(_skeleton && _skeleton->getNumJoints() == (int)poses.size()); + assert(_skeleton && (!poses.size() || (_skeleton->getNumJoints() == (int)poses.size()))); if (_skeleton->getNumJoints() == (int)poses.size()) { _relativePoses = poses; } else { diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 0a3ebad5d2..861f095b9c 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -159,6 +159,7 @@ public: virtual void updateJointState(int index, glm::mat4 rootTransform) = 0; void setEnableRig(bool isEnabled) { _enableRig = isEnabled; } + bool getEnableRig() const { return _enableRig; } void setEnableAnimGraph(bool isEnabled) { _enableAnimGraph = isEnabled; } bool getEnableAnimGraph() const { return _enableAnimGraph; }