1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-06-24 07:11:34 +00:00

Reset the idle animation after a movement animation ends

Fix non-biped actor idle reset
This commit is contained in:
Alexei Kotov 2022-06-13 23:40:17 +03:00
parent 1a646374b0
commit 5dfce6205a
2 changed files with 14 additions and 27 deletions

View file

@ -558,15 +558,17 @@ std::string CharacterController::fallbackShortWeaponGroup(const std::string& bas
return groupName; return groupName;
} }
void CharacterController::refreshMovementAnims(CharacterState movement, CharacterState& idle, bool force) void CharacterController::refreshMovementAnims(CharacterState movement, bool force)
{ {
if (movement == mMovementState && idle == mIdleState && !force) if (movement == mMovementState && !force)
return; return;
std::string movementAnimName = movementStateToAnimGroup(movement); std::string movementAnimName = movementStateToAnimGroup(movement);
if (movementAnimName.empty()) if (movementAnimName.empty())
{ {
if (!mCurrentMovement.empty())
resetCurrentIdleState();
resetCurrentMovementState(); resetCurrentMovementState();
return; return;
} }
@ -594,20 +596,11 @@ void CharacterController::refreshMovementAnims(CharacterState movement, Characte
weapMovementAnimName = movementAnimName + weapShortGroup; weapMovementAnimName = movementAnimName + weapShortGroup;
if (!mAnimation->hasAnimation(weapMovementAnimName)) if (!mAnimation->hasAnimation(weapMovementAnimName))
{
weapMovementAnimName = fallbackShortWeaponGroup(movementAnimName, &movemask); weapMovementAnimName = fallbackShortWeaponGroup(movementAnimName, &movemask);
// If we apply movement only for lower body, do not reset idle animations.
// For upper body there will be idle animation.
if (movemask == MWRender::Animation::BlendMask_LowerBody && idle == CharState_None)
idle = CharState_Idle;
}
movementAnimName = weapMovementAnimName; movementAnimName = weapMovementAnimName;
} }
if (!force && movement == mMovementState)
return;
if (!mAnimation->hasAnimation(movementAnimName)) if (!mAnimation->hasAnimation(movementAnimName))
{ {
std::string::size_type runpos = movementAnimName.find("run"); std::string::size_type runpos = movementAnimName.find("run");
@ -616,6 +609,8 @@ void CharacterController::refreshMovementAnims(CharacterState movement, Characte
if (!mAnimation->hasAnimation(movementAnimName)) if (!mAnimation->hasAnimation(movementAnimName))
{ {
if (!mCurrentMovement.empty())
resetCurrentIdleState();
resetCurrentMovementState(); resetCurrentMovementState();
return; return;
} }
@ -633,15 +628,6 @@ void CharacterController::refreshMovementAnims(CharacterState movement, Characte
clearStateAnimation(mCurrentMovement); clearStateAnimation(mCurrentMovement);
mCurrentMovement = movementAnimName; mCurrentMovement = movementAnimName;
// Reset idle if we actually play movement animations excepts of these cases:
// 1. When we play turning animations
// 2. When we use a fallback animation for lower body since movement animation for given weapon is missing (e.g. for crossbows and spellcasting)
if (!isTurning() && movemask == MWRender::Animation::BlendMask_All)
{
resetCurrentIdleState();
idle = CharState_None;
}
// For non-flying creatures, MW uses the Walk animation to calculate the animation velocity // For non-flying creatures, MW uses the Walk animation to calculate the animation velocity
// even if we are running. This must be replicated, otherwise the observed speed would differ drastically. // even if we are running. This must be replicated, otherwise the observed speed would differ drastically.
mAdjustMovementAnimSpeed = true; mAdjustMovementAnimSpeed = true;
@ -686,10 +672,11 @@ void CharacterController::refreshIdleAnims(CharacterState idle, bool force)
// FIXME: if one of the below states is close to their last animation frame (i.e. will be disabled in the coming update), // FIXME: if one of the below states is close to their last animation frame (i.e. will be disabled in the coming update),
// the idle animation should be displayed // the idle animation should be displayed
if (((mUpperBodyState != UpperCharState_Nothing && mUpperBodyState != UpperCharState_WeapEquiped) if (((mUpperBodyState != UpperCharState_Nothing && mUpperBodyState != UpperCharState_WeapEquiped)
|| (mMovementState != CharState_None && !isTurning()) || mMovementState != CharState_None || mHitState != CharState_None) && !mPtr.getClass().isBipedal(mPtr))
|| mHitState != CharState_None) {
&& !mPtr.getClass().isBipedal(mPtr)) resetCurrentIdleState();
idle = CharState_None; return;
}
if (!force && idle == mIdleState && (mAnimation->isPlaying(mCurrentIdle) || !mAnimQueue.empty())) if (!force && idle == mIdleState && (mAnimation->isPlaying(mCurrentIdle) || !mAnimQueue.empty()))
return; return;
@ -754,7 +741,7 @@ void CharacterController::refreshCurrentAnims(CharacterState idle, CharacterStat
refreshHitRecoilAnims(); refreshHitRecoilAnims();
refreshJumpAnims(jump, force); refreshJumpAnims(jump, force);
refreshMovementAnims(movement, idle, force); refreshMovementAnims(movement, force);
// idle handled last as it can depend on the other states // idle handled last as it can depend on the other states
refreshIdleAnims(idle, force); refreshIdleAnims(idle, force);
@ -2220,7 +2207,7 @@ void CharacterController::update(float duration)
} }
} }
if(movestate != CharState_None && !isTurning()) if (movestate != CharState_None)
clearAnimQueue(); clearAnimQueue();
if(mAnimQueue.empty() || inwater || (sneak && mIdleState != CharState_SpecialIdle)) if(mAnimQueue.empty() || inwater || (sneak && mIdleState != CharState_SpecialIdle))

View file

@ -206,7 +206,7 @@ class CharacterController : public MWRender::Animation::TextKeyListener
void refreshCurrentAnims(CharacterState idle, CharacterState movement, JumpingState jump, bool force=false); void refreshCurrentAnims(CharacterState idle, CharacterState movement, JumpingState jump, bool force=false);
void refreshHitRecoilAnims(); void refreshHitRecoilAnims();
void refreshJumpAnims(JumpingState jump, bool force=false); void refreshJumpAnims(JumpingState jump, bool force=false);
void refreshMovementAnims(CharacterState movement, CharacterState& idle, bool force=false); void refreshMovementAnims(CharacterState movement, bool force=false);
void refreshIdleAnims(CharacterState idle, bool force=false); void refreshIdleAnims(CharacterState idle, bool force=false);
void clearAnimQueue(bool clearPersistAnims = false); void clearAnimQueue(bool clearPersistAnims = false);