Keep track of whether an animation supplies movement

Also handle it when it doesn't.
actorid
Chris Robinson 12 years ago
parent 0817d59f23
commit 24f1eba902

@ -103,7 +103,7 @@ static void getStateInfo(CharacterState state, std::string *group)
CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim, CharacterState state, bool loop)
: mPtr(ptr), mAnimation(anim), mState(state), mSkipAnim(false)
: mPtr(ptr), mAnimation(anim), mState(state), mSkipAnim(false), mMovingAnim(false)
{
if(!mAnimation)
return;
@ -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", 1.0f, loop ? (~(size_t)0) : 0);
mMovingAnim = mAnimation->play(mCurrentGroup, "start", "stop", 1.0f, loop ? (~(size_t)0) : 0);
}
CharacterController::~CharacterController()
@ -180,6 +180,9 @@ void CharacterController::update(float duration, Movement &movement)
setState(inwater ? (isrunning ? CharState_SwimRunLeft : CharState_SwimWalkLeft)
: (sneak ? CharState_SneakLeft : (isrunning ? CharState_RunLeft : CharState_WalkLeft)), true);
// If this animation isn't moving us sideways, do it manually
if(!mMovingAnim)
movement.mPosition[0] += vec.x * (speed*duration);
// Apply any forward/backward movement manually
movement.mPosition[1] += vec.y * (speed*duration);
}
@ -194,6 +197,9 @@ void CharacterController::update(float duration, Movement &movement)
// Apply any sideways movement manually
movement.mPosition[0] += vec.x * (speed*duration);
// If this animation isn't moving us forward/backward, do it manually
if(!mMovingAnim)
movement.mPosition[1] += vec.y * (speed*duration);
}
else if(rot.z != 0.0f && !inwater && !sneak)
{
@ -211,7 +217,7 @@ void CharacterController::update(float duration, Movement &movement)
mCurrentGroup = mAnimQueue.front().first;
size_t count = mAnimQueue.front().second;
mAnimQueue.pop_front();
mAnimation->play(mCurrentGroup, "start", "stop", 0.0f, count);
mMovingAnim = mAnimation->play(mCurrentGroup, "start", "stop", 0.0f, count);
}
}
@ -244,7 +250,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", 0.0f, count-1);
mMovingAnim = mAnimation->play(mCurrentGroup, ((mode==2) ? "loop start" : "start"), "stop", 0.0f, count-1);
}
else if(mode == 0)
{
@ -272,10 +278,10 @@ void CharacterController::setState(CharacterState state, bool loop)
std::string anim;
getStateInfo(mState, &anim);
if(mAnimation->hasAnimation(anim))
if((mMovingAnim=mAnimation->hasAnimation(anim)) != false)
{
mCurrentGroup = anim;
mAnimation->play(mCurrentGroup, "start", "stop", 0.0f, loop ? (~(size_t)0) : 0);
mMovingAnim = mAnimation->play(mCurrentGroup, "start", "stop", 0.0f, loop ? (~(size_t)0) : 0);
}
}

@ -79,6 +79,8 @@ class CharacterController
CharacterState mState;
bool mSkipAnim;
bool mMovingAnim;
public:
CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim, CharacterState state, bool loop);
virtual ~CharacterController();

@ -317,7 +317,7 @@ void Animation::updatePtr(const MWWorld::Ptr &ptr)
}
float Animation::calcAnimVelocity(const NifOgre::TextKeyMap &keys, NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl, const std::string &groupname)
float Animation::calcAnimVelocity(const NifOgre::TextKeyMap &keys, NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl, const Ogre::Vector3 &accum, const std::string &groupname)
{
const std::string start = groupname+": start";
const std::string loopstart = groupname+": loop start";
@ -340,8 +340,8 @@ float Animation::calcAnimVelocity(const NifOgre::TextKeyMap &keys, NifOgre::Node
if(stoptime > starttime)
{
Ogre::Vector3 startpos = nonaccumctrl->getTranslation(starttime);
Ogre::Vector3 endpos = nonaccumctrl->getTranslation(stoptime);
Ogre::Vector3 startpos = nonaccumctrl->getTranslation(starttime) * accum;
Ogre::Vector3 endpos = nonaccumctrl->getTranslation(stoptime) * accum;
return startpos.distance(endpos) / (stoptime-starttime);
}
@ -515,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, float startpoint, size_t loops)
bool 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;
@ -523,6 +523,7 @@ void Animation::play(const std::string &groupname, const std::string &start, con
for(std::vector<ObjectInfo>::iterator iter(mObjects.begin());iter != mObjects.end();iter++)
iter->mActiveLayers &= ~(1<<layeridx);
bool movinganim = false;
bool foundanim = false;
if(groupname.empty())
{
@ -578,18 +579,27 @@ void Animation::play(const std::string &groupname, const std::string &start, con
iter->mActiveLayers |= (1<<layeridx);
foundanim = true;
if(mAccumulate == Ogre::Vector3(0.0f))
break;
}
if(!nonaccumctrl)
break;
mAnimVelocity = calcAnimVelocity(keys, nonaccumctrl, groupname);
if(mAnimVelocity > 0.0f) break;
mAnimVelocity = calcAnimVelocity(keys, nonaccumctrl, mAccumulate, groupname);
if(mAnimVelocity > 1.0f)
{
movinganim = (nonaccumctrl==mNonAccumCtrl);
break;
}
}
if(!foundanim)
std::cerr<< "Failed to find animation "<<groupname <<std::endl;
updateActiveControllers();
return movinganim;
}
Ogre::Vector3 Animation::runAnimation(float duration)

@ -78,6 +78,7 @@ protected:
static float calcAnimVelocity(const NifOgre::TextKeyMap &keys,
NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl,
const Ogre::Vector3 &accum,
const std::string &groupname);
/* Updates a skeleton instance so that all bones matching the source skeleton (based on
@ -135,8 +136,10 @@ public:
* \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".
* \return Boolean specifying whether the animation will return movement
* for the character at all.
*/
void play(const std::string &groupname, const std::string &start, const std::string &stop, float startpoint, size_t loops);
bool play(const std::string &groupname, const std::string &start, const std::string &stop, float startpoint, size_t loops);
virtual Ogre::Vector3 runAnimation(float timepassed);

@ -97,10 +97,10 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor
std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif");
addObjectList(node, smodel, true);
if(!mNpc->isMale() && !isBeast)
addObjectList(node, "meshes\\base_anim_female.nif", true);
else if(mBodyPrefix.find("argonian") != std::string::npos)
if(mBodyPrefix.find("argonian") != std::string::npos)
addObjectList(node, "meshes\\argonian_swimkna.nif", true);
else if(!mNpc->isMale() && !isBeast)
addObjectList(node, "meshes\\base_anim_female.nif", true);
if(mNpc->mModel.length() > 0)
addObjectList(node, "meshes\\"+mNpc->mModel, true);

Loading…
Cancel
Save