1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-02-01 20:15:33 +00:00

Keep track of whether an animation supplies movement

Also handle it when it doesn't.
This commit is contained in:
Chris Robinson 2013-04-24 22:45:43 -07:00
parent 0817d59f23
commit 24f1eba902
5 changed files with 37 additions and 16 deletions

View file

@ -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) 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) if(!mAnimation)
return; return;
@ -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", 1.0f, loop ? (~(size_t)0) : 0); mMovingAnim = mAnimation->play(mCurrentGroup, "start", "stop", 1.0f, loop ? (~(size_t)0) : 0);
} }
CharacterController::~CharacterController() CharacterController::~CharacterController()
@ -180,6 +180,9 @@ void CharacterController::update(float duration, Movement &movement)
setState(inwater ? (isrunning ? CharState_SwimRunLeft : CharState_SwimWalkLeft) setState(inwater ? (isrunning ? CharState_SwimRunLeft : CharState_SwimWalkLeft)
: (sneak ? CharState_SneakLeft : (isrunning ? CharState_RunLeft : CharState_WalkLeft)), true); : (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 // Apply any forward/backward movement manually
movement.mPosition[1] += vec.y * (speed*duration); movement.mPosition[1] += vec.y * (speed*duration);
} }
@ -194,6 +197,9 @@ void CharacterController::update(float duration, Movement &movement)
// Apply any sideways movement manually // Apply any sideways movement manually
movement.mPosition[0] += vec.x * (speed*duration); 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) else if(rot.z != 0.0f && !inwater && !sneak)
{ {
@ -211,7 +217,7 @@ void CharacterController::update(float duration, Movement &movement)
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", 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(); mAnimQueue.clear();
mCurrentGroup = groupname; mCurrentGroup = groupname;
mState = CharState_SpecialIdle; 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) else if(mode == 0)
{ {
@ -272,10 +278,10 @@ void CharacterController::setState(CharacterState state, bool loop)
std::string anim; std::string anim;
getStateInfo(mState, &anim); getStateInfo(mState, &anim);
if(mAnimation->hasAnimation(anim)) if((mMovingAnim=mAnimation->hasAnimation(anim)) != false)
{ {
mCurrentGroup = anim; 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);
} }
} }

View file

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

View file

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

View file

@ -78,6 +78,7 @@ protected:
static float calcAnimVelocity(const NifOgre::TextKeyMap &keys, static float calcAnimVelocity(const NifOgre::TextKeyMap &keys,
NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl, NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl,
const Ogre::Vector3 &accum,
const std::string &groupname); const std::string &groupname);
/* Updates a skeleton instance so that all bones matching the source skeleton (based on /* 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 * \param loops How many times to loop the animation. This will use the
* "loop start" and "loop stop" markers if they exist, * "loop start" and "loop stop" markers if they exist,
* otherwise it will use "start" and "stop". * 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); virtual Ogre::Vector3 runAnimation(float timepassed);

View file

@ -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"); std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif");
addObjectList(node, smodel, true); addObjectList(node, smodel, true);
if(!mNpc->isMale() && !isBeast) if(mBodyPrefix.find("argonian") != std::string::npos)
addObjectList(node, "meshes\\base_anim_female.nif", true);
else if(mBodyPrefix.find("argonian") != std::string::npos)
addObjectList(node, "meshes\\argonian_swimkna.nif", true); 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) if(mNpc->mModel.length() > 0)
addObjectList(node, "meshes\\"+mNpc->mModel, true); addObjectList(node, "meshes\\"+mNpc->mModel, true);