mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-21 13:23:52 +00:00
Keep track of whether an animation supplies movement
Also handle it when it doesn't.
This commit is contained in:
parent
0817d59f23
commit
24f1eba902
5 changed files with 37 additions and 16 deletions
|
@ -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…
Reference in a new issue