From a1bbb63ec42478b42ffbf2c8d77cb1ae6e47e333 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 12 Apr 2016 14:51:17 -0700 Subject: [PATCH] Rig: save and restore user animations across resets --- libraries/animation/src/Rig.cpp | 61 +++++++++++++++++++++------------ libraries/animation/src/Rig.h | 27 +++++++++++---- 2 files changed, 61 insertions(+), 27 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 6a8f190808..a57f0b01d2 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -48,36 +48,47 @@ const glm::vec3 DEFAULT_NECK_POS(0.0f, 0.70f, 0.0f); void Rig::overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame) { - // find an unused AnimClip clipNode - std::shared_ptr clip; - if (_userAnimState == UserAnimState::None || _userAnimState == UserAnimState::B) { - _userAnimState = UserAnimState::A; - clip = std::dynamic_pointer_cast(_animNode->findByName("userAnimA")); - } else if (_userAnimState == UserAnimState::A) { - _userAnimState = UserAnimState::B; - clip = std::dynamic_pointer_cast(_animNode->findByName("userAnimB")); + UserAnimState::ClipNodeEnum clipNodeEnum; + if (_userAnimState.clipNodeEnum == UserAnimState::None || _userAnimState.clipNodeEnum == UserAnimState::B) { + clipNodeEnum = UserAnimState::A; + } else { + clipNodeEnum = UserAnimState::B; } - // set parameters - clip->setLoopFlag(loop); - clip->setStartFrame(firstFrame); - clip->setEndFrame(lastFrame); - const float REFERENCE_FRAMES_PER_SECOND = 30.0f; - float timeScale = fps / REFERENCE_FRAMES_PER_SECOND; - clip->setTimeScale(timeScale); - clip->loadURL(url); + if (_animNode) { + // find an unused AnimClip clipNode + std::shared_ptr clip; + if (clipNodeEnum == UserAnimState::A) { + clip = std::dynamic_pointer_cast(_animNode->findByName("userAnimA")); + } else { + clip = std::dynamic_pointer_cast(_animNode->findByName("userAnimB")); + } - _currentUserAnimURL = url; + if (clip) { + // set parameters + clip->setLoopFlag(loop); + clip->setStartFrame(firstFrame); + clip->setEndFrame(lastFrame); + const float REFERENCE_FRAMES_PER_SECOND = 30.0f; + float timeScale = fps / REFERENCE_FRAMES_PER_SECOND; + clip->setTimeScale(timeScale); + clip->loadURL(url); + } + } + + // store current user anim state. + _userAnimState = { clipNodeEnum, url, fps, loop, firstFrame, lastFrame }; // notify the userAnimStateMachine the desired state. _animVars.set("userAnimNone", false); - _animVars.set("userAnimA", _userAnimState == UserAnimState::A); - _animVars.set("userAnimB", _userAnimState == UserAnimState::B); + _animVars.set("userAnimA", clipNodeEnum == UserAnimState::A); + _animVars.set("userAnimB", clipNodeEnum == UserAnimState::B); } void Rig::restoreAnimation() { - if (_currentUserAnimURL != "") { - _currentUserAnimURL = ""; + if (_userAnimState.clipNodeEnum != UserAnimState::None) { + _userAnimState.clipNodeEnum = UserAnimState::None; + // notify the userAnimStateMachine the desired state. _animVars.set("userAnimNone", true); _animVars.set("userAnimA", false); @@ -1129,6 +1140,14 @@ void Rig::initAnimGraph(const QUrl& url) { connect(_animLoader.get(), &AnimNodeLoader::success, [this](AnimNode::Pointer nodeIn) { _animNode = nodeIn; _animNode->setSkeleton(_animSkeleton); + + if (_userAnimState.clipNodeEnum != UserAnimState::None) { + // restore the user animation we had before reset. + UserAnimState origState = _userAnimState; + _userAnimState = { UserAnimState::None, "", 30.0f, false, 0.0f, 0.0f }; + overrideAnimation(origState.url, origState.fps, origState.loop, origState.firstFrame, origState.lastFrame); + } + }); connect(_animLoader.get(), &AnimNodeLoader::error, [url](int error, QString str) { qCCritical(animation) << "Error loading" << url.toDisplayString() << "code = " << error << "str =" << str; diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 3a27b9304b..cbf4696723 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -289,13 +289,28 @@ public: RigRole _state { RigRole::Idle }; RigRole _desiredState { RigRole::Idle }; float _desiredStateAge { 0.0f }; - enum class UserAnimState { - None = 0, - A, - B + + struct UserAnimState { + enum ClipNodeEnum { + None = 0, + A, + B + }; + + UserAnimState() : clipNodeEnum(UserAnimState::None) {} + UserAnimState(ClipNodeEnum clipNodeEnumIn, const QString& urlIn, float fpsIn, bool loopIn, float firstFrameIn, float lastFrameIn) : + clipNodeEnum(clipNodeEnumIn), url(urlIn), fps(fpsIn), loop(loopIn), firstFrame(firstFrameIn), lastFrame(lastFrameIn) {} + + ClipNodeEnum clipNodeEnum; + QString url; + float fps; + bool loop; + float firstFrame; + float lastFrame; }; - UserAnimState _userAnimState { UserAnimState::None }; - QString _currentUserAnimURL; + + UserAnimState _userAnimState; + float _leftHandOverlayAlpha { 0.0f }; float _rightHandOverlayAlpha { 0.0f };