Allow specifying where to start in an animation

This commit is contained in:
Chris Robinson 2013-04-24 19:09:36 -07:00
parent 333354fe62
commit 0817d59f23
4 changed files with 38 additions and 16 deletions

View file

@ -121,7 +121,7 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim
mAnimation->setAccumulation(Ogre::Vector3(0.0f)); mAnimation->setAccumulation(Ogre::Vector3(0.0f));
} }
if(mAnimation->hasAnimation(mCurrentGroup)) 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() CharacterController::~CharacterController()
@ -204,15 +204,15 @@ void CharacterController::update(float duration, Movement &movement)
} }
else if(getState() != CharState_SpecialIdle || !mAnimation->isPlaying(0)) 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; mCurrentGroup = mAnimQueue.front().first;
size_t count = mAnimQueue.front().second; size_t count = mAnimQueue.front().second;
mAnimQueue.pop_front(); 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; movement.mRotation[0] += rot.x * duration;
@ -244,7 +244,7 @@ void CharacterController::playGroup(const std::string &groupname, int mode, int
mAnimQueue.clear(); mAnimQueue.clear();
mCurrentGroup = groupname; mCurrentGroup = groupname;
mState = CharState_SpecialIdle; 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) else if(mode == 0)
{ {
@ -275,7 +275,7 @@ void CharacterController::setState(CharacterState state, bool loop)
if(mAnimation->hasAnimation(anim)) if(mAnimation->hasAnimation(anim))
{ {
mCurrentGroup = 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);
} }
} }

View file

@ -402,7 +402,7 @@ void Animation::updatePosition(Ogre::Vector3 &position)
mAccumRoot->setPosition(-mLastPosition); mAccumRoot->setPosition(-mLastPosition);
} }
bool Animation::reset(size_t layeridx, const NifOgre::TextKeyMap &keys, NifOgre::NodeTargetValue<Ogre::Real> *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<Ogre::Real> *nonaccumctrl, const std::string &groupname, const std::string &start, const std::string &stop, float startpoint)
{ {
std::string tag = groupname+": "+start; std::string tag = groupname+": "+start;
NifOgre::TextKeyMap::const_iterator startkey(keys.begin()); 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].mLoopStartKey = startkey;
mLayer[layeridx].mStopKey = stopkey; mLayer[layeridx].mStopKey = stopkey;
mLayer[layeridx].mNextKey = startkey; 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) if(layeridx == 0 && nonaccumctrl)
mLastPosition = nonaccumctrl->getTranslation(mLayer[layeridx].mTime) * mAccumulate; 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 // TODO: parameterize this
size_t layeridx = 0; size_t layeridx = 0;
@ -554,7 +562,7 @@ void Animation::play(const std::string &groupname, const std::string &start, con
if(!foundanim) if(!foundanim)
{ {
if(!reset(layeridx, keys, nonaccumctrl, groupname, start, stop)) if(!reset(layeridx, keys, nonaccumctrl, groupname, start, stop, startpoint))
continue; continue;
mLayer[layeridx].mGroupName = groupname; mLayer[layeridx].mGroupName = groupname;
mLayer[layeridx].mTextKeys = &keys; mLayer[layeridx].mTextKeys = &keys;

View file

@ -95,7 +95,10 @@ protected:
* the marker is not found, or if the markers are the same, it returns * the marker is not found, or if the markers are the same, it returns
* false. * false.
*/ */
bool reset(size_t layeridx, const NifOgre::TextKeyMap &keys, NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl, const std::string &groupname, const std::string &start, const std::string &stop); bool reset(size_t layeridx, const NifOgre::TextKeyMap &keys,
NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl,
const std::string &groupname, const std::string &start, const std::string &stop,
float startpoint);
bool doLoop(size_t layeridx); bool doLoop(size_t layeridx);
@ -123,7 +126,18 @@ public:
void setSpeed(float speed); 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); virtual Ogre::Vector3 runAnimation(float timepassed);
bool isPlaying(size_t layeridx) const bool isPlaying(size_t layeridx) const

View file

@ -155,7 +155,7 @@ namespace MWRender
if (!mSelectionBuffer) if (!mSelectionBuffer)
mSelectionBuffer = new OEngine::Render::SelectionBuffer(mCamera, 512, 1024, 0); 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 () void RaceSelectionPreview::onSetup ()
{ {
mAnimation->play("idle", "start", "stop", 0); mAnimation->play("idle", "start", "stop", 0.0f, 0);
updateCamera(); updateCamera();
} }