From 0817d59f23d4b2f36711109696c87cf6c22ad672 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 24 Apr 2013 19:09:36 -0700 Subject: [PATCH] Allow specifying where to start in an animation --- apps/openmw/mwmechanics/character.cpp | 14 +++++++------- apps/openmw/mwrender/animation.cpp | 18 +++++++++++++----- apps/openmw/mwrender/animation.hpp | 18 ++++++++++++++++-- apps/openmw/mwrender/characterpreview.cpp | 4 ++-- 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 2a7ab8b09..9397b2e35 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -121,7 +121,7 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim mAnimation->setAccumulation(Ogre::Vector3(0.0f)); } if(mAnimation->hasAnimation(mCurrentGroup)) - mAnimation->play(mCurrentGroup, "start", "stop", loop ? (~(size_t)0) : 0); + mAnimation->play(mCurrentGroup, "start", "stop", 1.0f, loop ? (~(size_t)0) : 0); } CharacterController::~CharacterController() @@ -204,15 +204,15 @@ void CharacterController::update(float duration, Movement &movement) } else if(getState() != CharState_SpecialIdle || !mAnimation->isPlaying(0)) { - if(mAnimQueue.size() > 0) + if(mAnimQueue.size() == 0) + setState((inwater ? CharState_IdleSwim : (sneak ? CharState_IdleSneak : CharState_Idle)), true); + else { mCurrentGroup = mAnimQueue.front().first; size_t count = mAnimQueue.front().second; mAnimQueue.pop_front(); - mAnimation->play(mCurrentGroup, "start", "stop", count); + mAnimation->play(mCurrentGroup, "start", "stop", 0.0f, count); } - else - setState((inwater ? CharState_IdleSwim : (sneak ? CharState_IdleSneak : CharState_Idle)), true); } movement.mRotation[0] += rot.x * duration; @@ -244,7 +244,7 @@ void CharacterController::playGroup(const std::string &groupname, int mode, int mAnimQueue.clear(); mCurrentGroup = groupname; mState = CharState_SpecialIdle; - mAnimation->play(mCurrentGroup, ((mode==2) ? "loop start" : "start"), "stop", count-1); + mAnimation->play(mCurrentGroup, ((mode==2) ? "loop start" : "start"), "stop", 0.0f, count-1); } else if(mode == 0) { @@ -275,7 +275,7 @@ void CharacterController::setState(CharacterState state, bool loop) if(mAnimation->hasAnimation(anim)) { mCurrentGroup = anim; - mAnimation->play(mCurrentGroup, "start", "stop", loop ? (~(size_t)0) : 0); + mAnimation->play(mCurrentGroup, "start", "stop", 0.0f, loop ? (~(size_t)0) : 0); } } diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index c2f453516..0f509d276 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -402,7 +402,7 @@ void Animation::updatePosition(Ogre::Vector3 &position) mAccumRoot->setPosition(-mLastPosition); } -bool Animation::reset(size_t layeridx, const NifOgre::TextKeyMap &keys, NifOgre::NodeTargetValue *nonaccumctrl, const std::string &groupname, const std::string &start, const std::string &stop) +bool Animation::reset(size_t layeridx, const NifOgre::TextKeyMap &keys, NifOgre::NodeTargetValue *nonaccumctrl, const std::string &groupname, const std::string &start, const std::string &stop, float startpoint) { std::string tag = groupname+": "+start; NifOgre::TextKeyMap::const_iterator startkey(keys.begin()); @@ -432,9 +432,17 @@ bool Animation::reset(size_t layeridx, const NifOgre::TextKeyMap &keys, NifOgre: mLayer[layeridx].mLoopStartKey = startkey; mLayer[layeridx].mStopKey = stopkey; mLayer[layeridx].mNextKey = startkey; - mLayer[layeridx].mNextKey++; - mLayer[layeridx].mTime = mLayer[layeridx].mStartKey->first; + mLayer[layeridx].mTime = mLayer[layeridx].mStartKey->first + ((mLayer[layeridx].mStopKey->first- + mLayer[layeridx].mStartKey->first) * startpoint); + + tag = groupname+": loop start"; + while(mLayer[layeridx].mNextKey->first <= mLayer[layeridx].mTime && mLayer[layeridx].mNextKey != mLayer[layeridx].mStopKey) + { + if(mLayer[layeridx].mNextKey->second == tag) + mLayer[layeridx].mLoopStartKey = mLayer[layeridx].mNextKey; + mLayer[layeridx].mNextKey++; + } if(layeridx == 0 && nonaccumctrl) mLastPosition = nonaccumctrl->getTranslation(mLayer[layeridx].mTime) * mAccumulate; @@ -507,7 +515,7 @@ bool Animation::handleTextKey(size_t layeridx, const NifOgre::TextKeyMap::const_ } -void Animation::play(const std::string &groupname, const std::string &start, const std::string &stop, size_t loops) +void Animation::play(const std::string &groupname, const std::string &start, const std::string &stop, float startpoint, size_t loops) { // TODO: parameterize this size_t layeridx = 0; @@ -554,7 +562,7 @@ void Animation::play(const std::string &groupname, const std::string &start, con if(!foundanim) { - if(!reset(layeridx, keys, nonaccumctrl, groupname, start, stop)) + if(!reset(layeridx, keys, nonaccumctrl, groupname, start, stop, startpoint)) continue; mLayer[layeridx].mGroupName = groupname; mLayer[layeridx].mTextKeys = &keys; diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 526bca69a..d7f38545f 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -95,7 +95,10 @@ protected: * the marker is not found, or if the markers are the same, it returns * false. */ - bool reset(size_t layeridx, const NifOgre::TextKeyMap &keys, NifOgre::NodeTargetValue *nonaccumctrl, const std::string &groupname, const std::string &start, const std::string &stop); + bool reset(size_t layeridx, const NifOgre::TextKeyMap &keys, + NifOgre::NodeTargetValue *nonaccumctrl, + const std::string &groupname, const std::string &start, const std::string &stop, + float startpoint); bool doLoop(size_t layeridx); @@ -123,7 +126,18 @@ public: void setSpeed(float speed); - void play(const std::string &groupname, const std::string &start, const std::string &stop, size_t loops); + /** Plays an animation. + * \param groupname Name of the animation group to play. + * \param start Key marker from which to start. + * \param stop Key marker to stop at. + * \param startpoint How far in between the two markers to start. 0 starts + * at the start marker, 1 starts at the stop marker. + * \param loops How many times to loop the animation. This will use the + * "loop start" and "loop stop" markers if they exist, + * otherwise it will use "start" and "stop". + */ + void play(const std::string &groupname, const std::string &start, const std::string &stop, float startpoint, size_t loops); + virtual Ogre::Vector3 runAnimation(float timepassed); bool isPlaying(size_t layeridx) const diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index c22d8a4da..24b089db3 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -155,7 +155,7 @@ namespace MWRender if (!mSelectionBuffer) mSelectionBuffer = new OEngine::Render::SelectionBuffer(mCamera, 512, 1024, 0); - mAnimation->play("inventoryhandtohand", "start", "stop", 0); + mAnimation->play("inventoryhandtohand", "start", "stop", 0.0f, 0); } // -------------------------------------------------------------------------------------------------- @@ -189,7 +189,7 @@ namespace MWRender void RaceSelectionPreview::onSetup () { - mAnimation->play("idle", "start", "stop", 0); + mAnimation->play("idle", "start", "stop", 0.0f, 0); updateCamera(); }