forked from teamnwah/openmw-tes3coop
Specify the velocity-based animation speed multiplier when playing it
This commit is contained in:
parent
f296d13c20
commit
a932a89e02
4 changed files with 71 additions and 51 deletions
|
@ -207,8 +207,13 @@ void CharacterController::refreshCurrentAnims(CharacterState idle, CharacterStat
|
||||||
mAnimation->disable(mCurrentMovement);
|
mAnimation->disable(mCurrentMovement);
|
||||||
mCurrentMovement = movement;
|
mCurrentMovement = movement;
|
||||||
if(!mCurrentMovement.empty())
|
if(!mCurrentMovement.empty())
|
||||||
|
{
|
||||||
|
float vel, speed = 0.0f;
|
||||||
|
if(mMovementSpeed > 0.0f && (vel=mAnimation->getVelocity(mCurrentMovement)) > 1.0f)
|
||||||
|
speed = mMovementSpeed / vel;
|
||||||
mAnimation->play(mCurrentMovement, Priority_Movement, movegroup, false,
|
mAnimation->play(mCurrentMovement, Priority_Movement, movegroup, false,
|
||||||
1.0f, "start", "stop", 0.0f, ~0ul);
|
speed, "start", "stop", 0.0f, ~0ul);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,6 +231,7 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim
|
||||||
, mAnimation(anim)
|
, mAnimation(anim)
|
||||||
, mIdleState(CharState_Idle)
|
, mIdleState(CharState_Idle)
|
||||||
, mMovementState(CharState_None)
|
, mMovementState(CharState_None)
|
||||||
|
, mMovementSpeed(0.0f)
|
||||||
, mDeathState(CharState_None)
|
, mDeathState(CharState_None)
|
||||||
, mWeaponType(WeapType_None)
|
, mWeaponType(WeapType_None)
|
||||||
, mSkipAnim(false)
|
, mSkipAnim(false)
|
||||||
|
@ -281,7 +287,6 @@ void CharacterController::updatePtr(const MWWorld::Ptr &ptr)
|
||||||
void CharacterController::update(float duration, Movement &movement)
|
void CharacterController::update(float duration, Movement &movement)
|
||||||
{
|
{
|
||||||
const MWWorld::Class &cls = MWWorld::Class::get(mPtr);
|
const MWWorld::Class &cls = MWWorld::Class::get(mPtr);
|
||||||
float speed = 0.0f;
|
|
||||||
|
|
||||||
if(!cls.isActor())
|
if(!cls.isActor())
|
||||||
{
|
{
|
||||||
|
@ -308,7 +313,7 @@ void CharacterController::update(float duration, Movement &movement)
|
||||||
bool sneak = cls.getStance(mPtr, MWWorld::Class::Sneak);
|
bool sneak = cls.getStance(mPtr, MWWorld::Class::Sneak);
|
||||||
Ogre::Vector3 vec = cls.getMovementVector(mPtr);
|
Ogre::Vector3 vec = cls.getMovementVector(mPtr);
|
||||||
Ogre::Vector3 rot = cls.getRotationVector(mPtr);
|
Ogre::Vector3 rot = cls.getRotationVector(mPtr);
|
||||||
speed = cls.getSpeed(mPtr);
|
mMovementSpeed = cls.getSpeed(mPtr);
|
||||||
|
|
||||||
// advance athletics
|
// advance athletics
|
||||||
if(vec.squaredLength() > 0 && mPtr.getRefData().getHandle() == "player")
|
if(vec.squaredLength() > 0 && mPtr.getRefData().getHandle() == "player")
|
||||||
|
@ -355,8 +360,8 @@ void CharacterController::update(float duration, Movement &movement)
|
||||||
//decrease fatigue by fFatigueJumpBase + (1 - normalizedEncumbrance) * fFatigueJumpMult;
|
//decrease fatigue by fFatigueJumpBase + (1 - normalizedEncumbrance) * fFatigueJumpMult;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec.x *= speed;
|
vec.x *= mMovementSpeed;
|
||||||
vec.y *= speed;
|
vec.y *= mMovementSpeed;
|
||||||
|
|
||||||
CharacterState movestate = CharState_None;
|
CharacterState movestate = CharState_None;
|
||||||
CharacterState idlestate = CharState_SpecialIdle;
|
CharacterState idlestate = CharState_SpecialIdle;
|
||||||
|
@ -541,11 +546,9 @@ void CharacterController::update(float duration, Movement &movement)
|
||||||
|
|
||||||
if(mAnimation && !mSkipAnim)
|
if(mAnimation && !mSkipAnim)
|
||||||
{
|
{
|
||||||
mAnimation->setSpeed(speed);
|
|
||||||
|
|
||||||
Ogre::Vector3 moved = mAnimation->runAnimation(duration);
|
Ogre::Vector3 moved = mAnimation->runAnimation(duration);
|
||||||
// Ensure we're moving in generally the right direction
|
// Ensure we're moving in generally the right direction
|
||||||
if (speed > 0.f)
|
if(mMovementSpeed > 0.f)
|
||||||
{
|
{
|
||||||
if((movement.mPosition[0] < 0.0f && movement.mPosition[0] < moved.x*2.0f) ||
|
if((movement.mPosition[0] < 0.0f && movement.mPosition[0] < moved.x*2.0f) ||
|
||||||
(movement.mPosition[0] > 0.0f && movement.mPosition[0] > moved.x*2.0f))
|
(movement.mPosition[0] > 0.0f && movement.mPosition[0] > moved.x*2.0f))
|
||||||
|
|
|
@ -105,8 +105,10 @@ class CharacterController
|
||||||
|
|
||||||
CharacterState mIdleState;
|
CharacterState mIdleState;
|
||||||
std::string mCurrentIdle;
|
std::string mCurrentIdle;
|
||||||
|
|
||||||
CharacterState mMovementState;
|
CharacterState mMovementState;
|
||||||
std::string mCurrentMovement;
|
std::string mCurrentMovement;
|
||||||
|
float mMovementSpeed;
|
||||||
|
|
||||||
CharacterState mDeathState;
|
CharacterState mDeathState;
|
||||||
std::string mCurrentDeath;
|
std::string mCurrentDeath;
|
||||||
|
|
|
@ -52,8 +52,6 @@ Animation::Animation(const MWWorld::Ptr &ptr)
|
||||||
, mNonAccumRoot(NULL)
|
, mNonAccumRoot(NULL)
|
||||||
, mNonAccumCtrl(NULL)
|
, mNonAccumCtrl(NULL)
|
||||||
, mAccumulate(0.0f)
|
, mAccumulate(0.0f)
|
||||||
, mAnimVelocity(0.0f)
|
|
||||||
, mAnimSpeedMult(1.0f)
|
|
||||||
{
|
{
|
||||||
for(size_t i = 0;i < sNumGroups;i++)
|
for(size_t i = 0;i < sNumGroups;i++)
|
||||||
mAnimationValuePtr[i].bind(OGRE_NEW AnimationValue(this));
|
mAnimationValuePtr[i].bind(OGRE_NEW AnimationValue(this));
|
||||||
|
@ -245,7 +243,6 @@ void Animation::clearAnimSources()
|
||||||
mAnimationValuePtr[i]->setAnimName(std::string());
|
mAnimationValuePtr[i]->setAnimName(std::string());
|
||||||
|
|
||||||
mNonAccumCtrl = NULL;
|
mNonAccumCtrl = NULL;
|
||||||
mAnimVelocity = 0.0f;
|
|
||||||
|
|
||||||
mAccumRoot = NULL;
|
mAccumRoot = NULL;
|
||||||
mNonAccumRoot = NULL;
|
mNonAccumRoot = NULL;
|
||||||
|
@ -298,13 +295,6 @@ void Animation::setAccumulation(const Ogre::Vector3 &accum)
|
||||||
mAccumulate = accum;
|
mAccumulate = accum;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::setSpeed(float speed)
|
|
||||||
{
|
|
||||||
mAnimSpeedMult = 1.0f;
|
|
||||||
if(speed > 0.0f && mAnimVelocity > 1.0f)
|
|
||||||
mAnimSpeedMult = speed / mAnimVelocity;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Animation::updatePtr(const MWWorld::Ptr &ptr)
|
void Animation::updatePtr(const MWWorld::Ptr &ptr)
|
||||||
{
|
{
|
||||||
|
@ -344,6 +334,61 @@ float Animation::calcAnimVelocity(const NifOgre::TextKeyMap &keys, NifOgre::Node
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Animation::getVelocity(const std::string &groupname) const
|
||||||
|
{
|
||||||
|
/* Look in reverse; last-inserted source has priority. */
|
||||||
|
AnimSourceList::const_reverse_iterator animsrc(mAnimSources.rbegin());
|
||||||
|
for(;animsrc != mAnimSources.rend();animsrc++)
|
||||||
|
{
|
||||||
|
const NifOgre::TextKeyMap &keys = (*animsrc)->mTextKeys;
|
||||||
|
if(findGroupStart(keys, groupname) != keys.end())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(animsrc == mAnimSources.rend())
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
float velocity = 0.0f;
|
||||||
|
const NifOgre::TextKeyMap &keys = (*animsrc)->mTextKeys;
|
||||||
|
const std::vector<Ogre::Controller<Ogre::Real> >&ctrls = (*animsrc)->mControllers[0];
|
||||||
|
for(size_t i = 0;i < ctrls.size();i++)
|
||||||
|
{
|
||||||
|
NifOgre::NodeTargetValue<Ogre::Real> *dstval;
|
||||||
|
dstval = static_cast<NifOgre::NodeTargetValue<Ogre::Real>*>(ctrls[i].getDestination().getPointer());
|
||||||
|
if(dstval->getNode() == mNonAccumRoot)
|
||||||
|
{
|
||||||
|
velocity = calcAnimVelocity(keys, dstval, mAccumulate, groupname);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's no velocity, keep looking
|
||||||
|
if(!(velocity > 1.0f))
|
||||||
|
{
|
||||||
|
AnimSourceList::const_reverse_iterator animiter = mAnimSources.rbegin();
|
||||||
|
while(*animiter != *animsrc)
|
||||||
|
++animiter;
|
||||||
|
|
||||||
|
while(!(velocity > 1.0f) && ++animiter != mAnimSources.rend())
|
||||||
|
{
|
||||||
|
const NifOgre::TextKeyMap &keys = (*animiter)->mTextKeys;
|
||||||
|
const std::vector<Ogre::Controller<Ogre::Real> >&ctrls = (*animiter)->mControllers[0];
|
||||||
|
for(size_t i = 0;i < ctrls.size();i++)
|
||||||
|
{
|
||||||
|
NifOgre::NodeTargetValue<Ogre::Real> *dstval;
|
||||||
|
dstval = static_cast<NifOgre::NodeTargetValue<Ogre::Real>*>(ctrls[i].getDestination().getPointer());
|
||||||
|
if(dstval->getNode() == mNonAccumRoot)
|
||||||
|
{
|
||||||
|
velocity = calcAnimVelocity(keys, dstval, mAccumulate, groupname);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void updateBoneTree(const Ogre::SkeletonInstance *skelsrc, Ogre::Bone *bone)
|
static void updateBoneTree(const Ogre::SkeletonInstance *skelsrc, Ogre::Bone *bone)
|
||||||
{
|
{
|
||||||
if(skelsrc->hasBone(bone->getName()))
|
if(skelsrc->hasBone(bone->getName()))
|
||||||
|
@ -599,9 +644,7 @@ void Animation::resetActiveGroups()
|
||||||
mAnimationValuePtr[grp]->setAnimName((active == mStates.end()) ?
|
mAnimationValuePtr[grp]->setAnimName((active == mStates.end()) ?
|
||||||
std::string() : active->first);
|
std::string() : active->first);
|
||||||
}
|
}
|
||||||
|
|
||||||
mNonAccumCtrl = NULL;
|
mNonAccumCtrl = NULL;
|
||||||
mAnimVelocity = 0.0f;
|
|
||||||
|
|
||||||
if(!mNonAccumRoot || mAccumulate == Ogre::Vector3(0.0f))
|
if(!mNonAccumRoot || mAccumulate == Ogre::Vector3(0.0f))
|
||||||
return;
|
return;
|
||||||
|
@ -619,35 +662,10 @@ void Animation::resetActiveGroups()
|
||||||
dstval = static_cast<NifOgre::NodeTargetValue<Ogre::Real>*>(ctrls[i].getDestination().getPointer());
|
dstval = static_cast<NifOgre::NodeTargetValue<Ogre::Real>*>(ctrls[i].getDestination().getPointer());
|
||||||
if(dstval->getNode() == mNonAccumRoot)
|
if(dstval->getNode() == mNonAccumRoot)
|
||||||
{
|
{
|
||||||
mAnimVelocity = calcAnimVelocity(keys, dstval, mAccumulate, state->first);
|
|
||||||
mNonAccumCtrl = dstval;
|
mNonAccumCtrl = dstval;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there's no velocity, keep looking
|
|
||||||
if(!(mAnimVelocity > 1.0f))
|
|
||||||
{
|
|
||||||
AnimSourceList::const_reverse_iterator animiter = mAnimSources.rbegin();
|
|
||||||
while(*animiter != animsrc)
|
|
||||||
++animiter;
|
|
||||||
|
|
||||||
while(!(mAnimVelocity > 1.0f) && ++animiter != mAnimSources.rend())
|
|
||||||
{
|
|
||||||
const NifOgre::TextKeyMap &keys = (*animiter)->mTextKeys;
|
|
||||||
const std::vector<Ogre::Controller<Ogre::Real> >&ctrls = (*animiter)->mControllers[0];
|
|
||||||
for(size_t i = 0;i < ctrls.size();i++)
|
|
||||||
{
|
|
||||||
NifOgre::NodeTargetValue<Ogre::Real> *dstval;
|
|
||||||
dstval = static_cast<NifOgre::NodeTargetValue<Ogre::Real>*>(ctrls[i].getDestination().getPointer());
|
|
||||||
if(dstval->getNode() == mNonAccumRoot)
|
|
||||||
{
|
|
||||||
mAnimVelocity = calcAnimVelocity(keys, dstval, mAccumulate, state->first);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -685,7 +703,6 @@ Ogre::Vector3 Animation::runAnimation(float duration)
|
||||||
{
|
{
|
||||||
Ogre::Vector3 movement(0.0f);
|
Ogre::Vector3 movement(0.0f);
|
||||||
|
|
||||||
duration *= mAnimSpeedMult;
|
|
||||||
AnimStateMap::iterator stateiter = mStates.begin();
|
AnimStateMap::iterator stateiter = mStates.begin();
|
||||||
while(stateiter != mStates.end())
|
while(stateiter != mStates.end())
|
||||||
{
|
{
|
||||||
|
|
|
@ -101,9 +101,6 @@ protected:
|
||||||
|
|
||||||
ObjectAttachMap mAttachedObjects;
|
ObjectAttachMap mAttachedObjects;
|
||||||
|
|
||||||
float mAnimVelocity;
|
|
||||||
float mAnimSpeedMult;
|
|
||||||
|
|
||||||
/* Sets the appropriate animations on the bone groups based on priority.
|
/* Sets the appropriate animations on the bone groups based on priority.
|
||||||
*/
|
*/
|
||||||
void resetActiveGroups();
|
void resetActiveGroups();
|
||||||
|
@ -174,8 +171,6 @@ public:
|
||||||
// should be on the scale of 0 to 1.
|
// should be on the scale of 0 to 1.
|
||||||
void setAccumulation(const Ogre::Vector3 &accum);
|
void setAccumulation(const Ogre::Vector3 &accum);
|
||||||
|
|
||||||
void setSpeed(float speed);
|
|
||||||
|
|
||||||
/** Plays an animation.
|
/** Plays an animation.
|
||||||
* \param groupname Name of the animation group to play.
|
* \param groupname Name of the animation group to play.
|
||||||
* \param priority Priority of the animation. The animation will play on
|
* \param priority Priority of the animation. The animation will play on
|
||||||
|
@ -215,6 +210,9 @@ public:
|
||||||
*/
|
*/
|
||||||
void disable(const std::string &groupname);
|
void disable(const std::string &groupname);
|
||||||
|
|
||||||
|
/** Retrieves the velocity (in units per second) that the animation will move. */
|
||||||
|
float getVelocity(const std::string &groupname) const;
|
||||||
|
|
||||||
virtual Ogre::Vector3 runAnimation(float duration);
|
virtual Ogre::Vector3 runAnimation(float duration);
|
||||||
|
|
||||||
virtual void showWeapons(bool showWeapon);
|
virtual void showWeapons(bool showWeapon);
|
||||||
|
|
Loading…
Reference in a new issue