mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-09 21:42:13 +00:00
Specify the velocity-based animation speed multiplier when playing it
This commit is contained in:
parent
f296d13c20
commit
a932a89e02
@ -207,8 +207,13 @@ void CharacterController::refreshCurrentAnims(CharacterState idle, CharacterStat
|
||||
mAnimation->disable(mCurrentMovement);
|
||||
mCurrentMovement = movement;
|
||||
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,
|
||||
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)
|
||||
, mIdleState(CharState_Idle)
|
||||
, mMovementState(CharState_None)
|
||||
, mMovementSpeed(0.0f)
|
||||
, mDeathState(CharState_None)
|
||||
, mWeaponType(WeapType_None)
|
||||
, mSkipAnim(false)
|
||||
@ -281,7 +287,6 @@ void CharacterController::updatePtr(const MWWorld::Ptr &ptr)
|
||||
void CharacterController::update(float duration, Movement &movement)
|
||||
{
|
||||
const MWWorld::Class &cls = MWWorld::Class::get(mPtr);
|
||||
float speed = 0.0f;
|
||||
|
||||
if(!cls.isActor())
|
||||
{
|
||||
@ -308,7 +313,7 @@ void CharacterController::update(float duration, Movement &movement)
|
||||
bool sneak = cls.getStance(mPtr, MWWorld::Class::Sneak);
|
||||
Ogre::Vector3 vec = cls.getMovementVector(mPtr);
|
||||
Ogre::Vector3 rot = cls.getRotationVector(mPtr);
|
||||
speed = cls.getSpeed(mPtr);
|
||||
mMovementSpeed = cls.getSpeed(mPtr);
|
||||
|
||||
// advance athletics
|
||||
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;
|
||||
}
|
||||
|
||||
vec.x *= speed;
|
||||
vec.y *= speed;
|
||||
vec.x *= mMovementSpeed;
|
||||
vec.y *= mMovementSpeed;
|
||||
|
||||
CharacterState movestate = CharState_None;
|
||||
CharacterState idlestate = CharState_SpecialIdle;
|
||||
@ -541,11 +546,9 @@ void CharacterController::update(float duration, Movement &movement)
|
||||
|
||||
if(mAnimation && !mSkipAnim)
|
||||
{
|
||||
mAnimation->setSpeed(speed);
|
||||
|
||||
Ogre::Vector3 moved = mAnimation->runAnimation(duration);
|
||||
// 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) ||
|
||||
(movement.mPosition[0] > 0.0f && movement.mPosition[0] > moved.x*2.0f))
|
||||
|
@ -105,8 +105,10 @@ class CharacterController
|
||||
|
||||
CharacterState mIdleState;
|
||||
std::string mCurrentIdle;
|
||||
|
||||
CharacterState mMovementState;
|
||||
std::string mCurrentMovement;
|
||||
float mMovementSpeed;
|
||||
|
||||
CharacterState mDeathState;
|
||||
std::string mCurrentDeath;
|
||||
|
@ -52,8 +52,6 @@ Animation::Animation(const MWWorld::Ptr &ptr)
|
||||
, mNonAccumRoot(NULL)
|
||||
, mNonAccumCtrl(NULL)
|
||||
, mAccumulate(0.0f)
|
||||
, mAnimVelocity(0.0f)
|
||||
, mAnimSpeedMult(1.0f)
|
||||
{
|
||||
for(size_t i = 0;i < sNumGroups;i++)
|
||||
mAnimationValuePtr[i].bind(OGRE_NEW AnimationValue(this));
|
||||
@ -245,7 +243,6 @@ void Animation::clearAnimSources()
|
||||
mAnimationValuePtr[i]->setAnimName(std::string());
|
||||
|
||||
mNonAccumCtrl = NULL;
|
||||
mAnimVelocity = 0.0f;
|
||||
|
||||
mAccumRoot = NULL;
|
||||
mNonAccumRoot = NULL;
|
||||
@ -298,13 +295,6 @@ void Animation::setAccumulation(const Ogre::Vector3 &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)
|
||||
{
|
||||
@ -344,6 +334,61 @@ float Animation::calcAnimVelocity(const NifOgre::TextKeyMap &keys, NifOgre::Node
|
||||
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)
|
||||
{
|
||||
if(skelsrc->hasBone(bone->getName()))
|
||||
@ -599,9 +644,7 @@ void Animation::resetActiveGroups()
|
||||
mAnimationValuePtr[grp]->setAnimName((active == mStates.end()) ?
|
||||
std::string() : active->first);
|
||||
}
|
||||
|
||||
mNonAccumCtrl = NULL;
|
||||
mAnimVelocity = 0.0f;
|
||||
|
||||
if(!mNonAccumRoot || mAccumulate == Ogre::Vector3(0.0f))
|
||||
return;
|
||||
@ -619,35 +662,10 @@ void Animation::resetActiveGroups()
|
||||
dstval = static_cast<NifOgre::NodeTargetValue<Ogre::Real>*>(ctrls[i].getDestination().getPointer());
|
||||
if(dstval->getNode() == mNonAccumRoot)
|
||||
{
|
||||
mAnimVelocity = calcAnimVelocity(keys, dstval, mAccumulate, state->first);
|
||||
mNonAccumCtrl = dstval;
|
||||
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);
|
||||
|
||||
duration *= mAnimSpeedMult;
|
||||
AnimStateMap::iterator stateiter = mStates.begin();
|
||||
while(stateiter != mStates.end())
|
||||
{
|
||||
|
@ -101,9 +101,6 @@ protected:
|
||||
|
||||
ObjectAttachMap mAttachedObjects;
|
||||
|
||||
float mAnimVelocity;
|
||||
float mAnimSpeedMult;
|
||||
|
||||
/* Sets the appropriate animations on the bone groups based on priority.
|
||||
*/
|
||||
void resetActiveGroups();
|
||||
@ -174,8 +171,6 @@ public:
|
||||
// should be on the scale of 0 to 1.
|
||||
void setAccumulation(const Ogre::Vector3 &accum);
|
||||
|
||||
void setSpeed(float speed);
|
||||
|
||||
/** Plays an animation.
|
||||
* \param groupname Name of the animation group to play.
|
||||
* \param priority Priority of the animation. The animation will play on
|
||||
@ -215,6 +210,9 @@ public:
|
||||
*/
|
||||
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 void showWeapons(bool showWeapon);
|
||||
|
Loading…
Reference in New Issue
Block a user