From 713330351bf1d8fa0867860266fce2de374e48d5 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sun, 23 Sep 2018 00:08:16 +0300 Subject: [PATCH 1/4] Experimental animation regression fixes Don't unnecessarily start movement and jump animations from loop start Don't play movement animation until jumping animation finishes --- apps/openmw/mwmechanics/character.cpp | 104 +++++++++++++------------- apps/openmw/mwmechanics/character.hpp | 2 +- 2 files changed, 55 insertions(+), 51 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 749f908d28..8f14e0331b 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -351,64 +351,69 @@ void CharacterController::refreshHitRecoilAnims(CharacterState& idle) idle = CharState_None; } -void CharacterController::refreshJumpAnims(const WeaponInfo* weap, JumpingState jump, CharacterState& idle, bool force) +void CharacterController::refreshJumpAnims(const WeaponInfo* weap, JumpingState jump, CharacterState& idle, CharacterState& movement, bool force) { - if(force || jump != mJumpState) + if (!force && jump == mJumpState && movement == CharState_None) + return; + + if (jump != JumpState_None) { - if (jump != JumpState_None) - idle = CharState_None; + idle = CharState_None; + movement = CharState_None; + } - bool startAtLoop = (jump == mJumpState); - mJumpState = jump; - - std::string jumpAnimName; - MWRender::Animation::BlendMask jumpmask = MWRender::Animation::BlendMask_All; - if(mJumpState != JumpState_None) + std::string jumpAnimName; + MWRender::Animation::BlendMask jumpmask = MWRender::Animation::BlendMask_All; + if (jump != JumpState_None) + { + jumpAnimName = "jump"; + if(weap != sWeaponTypeListEnd) { - jumpAnimName = "jump"; - if(weap != sWeaponTypeListEnd) + jumpAnimName += weap->shortgroup; + if(!mAnimation->hasAnimation(jumpAnimName)) { - jumpAnimName += weap->shortgroup; - if(!mAnimation->hasAnimation(jumpAnimName)) - { - jumpmask = MWRender::Animation::BlendMask_LowerBody; - jumpAnimName = "jump"; + jumpmask = MWRender::Animation::BlendMask_LowerBody; + jumpAnimName = "jump"; - // Since we apply movement only for lower body, do not reset idle animations. - // For upper body there will be idle animation. - if (idle == CharState_None) - idle = CharState_Idle; + // Since we apply movement only for lower body, do not reset idle animations. + // For upper body there will be idle animation. + if (idle == CharState_None) + idle = CharState_Idle; - // For crossbow animations use 1h ones as fallback - if (mWeaponType == WeapType_Crossbow) - jumpAnimName += "1h"; - } + // For crossbow animations use 1h ones as fallback + if (mWeaponType == WeapType_Crossbow) + jumpAnimName += "1h"; } } + } - if (!mCurrentJump.empty()) - { - mAnimation->disable(mCurrentJump); - mCurrentJump.clear(); - } + if (!force && jump == mJumpState) + return; - if(mJumpState == JumpState_InAir) + mJumpState = jump; + + if (!mCurrentJump.empty()) + { + mAnimation->disable(mCurrentJump); + mCurrentJump.clear(); + } + + if(mJumpState == JumpState_InAir) + { + if (mAnimation->hasAnimation(jumpAnimName)) { - if (mAnimation->hasAnimation(jumpAnimName)) - { - mAnimation->play(jumpAnimName, Priority_Jump, jumpmask, false, - 1.0f, (startAtLoop?"loop start":"start"), "stop", 0.0f, ~0ul); - mCurrentJump = jumpAnimName; - } + mAnimation->play(jumpAnimName, Priority_Jump, jumpmask, false, + 1.0f, "start", "stop", 0.f, ~0ul); + mCurrentJump = jumpAnimName; } - else if (mJumpState == JumpState_Landing) + } + else if (mJumpState == JumpState_Landing) + { + if (mAnimation->hasAnimation(jumpAnimName)) { - if (mAnimation->hasAnimation(jumpAnimName)) - { - mAnimation->play(jumpAnimName, Priority_Jump, jumpmask, true, - 1.0f, "loop stop", "stop", 0.0f, 0); - mCurrentJump = jumpAnimName; - } + mAnimation->play(jumpAnimName, Priority_Jump, jumpmask, true, + 1.0f, "loop stop", "stop", 0.0f, 0); + mCurrentJump = jumpAnimName; } } } @@ -494,10 +499,9 @@ void CharacterController::refreshMovementAnims(const WeaponInfo* weap, Character } // If we're playing the same animation, start it from the point it ended - bool sameAnim = (movementAnimName == mCurrentMovement); - float startPoint = 0.f; - if (sameAnim) - mAnimation->getInfo(mCurrentMovement, &startPoint); + float startpoint = 0.f; + if (!mCurrentMovement.empty() && movementAnimName == mCurrentMovement) + mAnimation->getInfo(mCurrentMovement, &startpoint); mMovementAnimationControlled = true; @@ -546,7 +550,7 @@ void CharacterController::refreshMovementAnims(const WeaponInfo* weap, Character } mAnimation->play(mCurrentMovement, Priority_Movement, movemask, false, - 1.f, (!sameAnim ? "start" : "loop start"), "stop", startPoint, ~0ul, true); + 1.f, "start", "stop", startpoint, ~0ul, true); } } } @@ -626,7 +630,7 @@ void CharacterController::refreshCurrentAnims(CharacterState idle, CharacterStat if (!mPtr.getClass().hasInventoryStore(mPtr)) weap = sWeaponTypeListEnd; - refreshJumpAnims(weap, jump, idle, force); + refreshJumpAnims(weap, jump, idle, movement, force); refreshMovementAnims(weap, movement, idle, force); // idle handled last as it can depend on the other states diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 8b3c68048d..1db497828e 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -214,7 +214,7 @@ class CharacterController : public MWRender::Animation::TextKeyListener void refreshCurrentAnims(CharacterState idle, CharacterState movement, JumpingState jump, bool force=false); void refreshHitRecoilAnims(CharacterState& idle); - void refreshJumpAnims(const WeaponInfo* weap, JumpingState jump, CharacterState& idle, bool force=false); + void refreshJumpAnims(const WeaponInfo* weap, JumpingState jump, CharacterState& idle, CharacterState& movement, bool force=false); void refreshMovementAnims(const WeaponInfo* weap, CharacterState movement, CharacterState& idle, bool force=false); void refreshIdleAnims(const WeaponInfo* weap, CharacterState idle, bool force=false); From 56ef11b023299b64e6177c31a3af832b3b274d8c Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sun, 23 Sep 2018 13:55:49 +0300 Subject: [PATCH 2/4] Reset sneak and swim idle animations when moving --- apps/openmw/mwmechanics/character.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 8f14e0331b..c437a21d51 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -2168,12 +2168,12 @@ void CharacterController::update(float duration) if(mAnimQueue.empty() || inwater || sneak) { // Note: turning animations should not interrupt idle ones - if (inwater) + if (movestate != CharState_None && !isTurning()) + idlestate = CharState_None; + else if (inwater) idlestate = CharState_IdleSwim; else if (sneak && !inJump) idlestate = CharState_IdleSneak; - else if (movestate != CharState_None && !isTurning()) - idlestate = CharState_None; else idlestate = CharState_Idle; } From 77fb4d6dd2d8ea589e8befe55a5075fdfbad2b0c Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sun, 23 Sep 2018 14:06:04 +0300 Subject: [PATCH 3/4] Make sure the idle animations are reset while jumping --- apps/openmw/mwmechanics/character.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index c437a21d51..27170d6a89 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -353,7 +353,7 @@ void CharacterController::refreshHitRecoilAnims(CharacterState& idle) void CharacterController::refreshJumpAnims(const WeaponInfo* weap, JumpingState jump, CharacterState& idle, CharacterState& movement, bool force) { - if (!force && jump == mJumpState && movement == CharState_None) + if (!force && jump == mJumpState && idle == CharState_None && movement == CharState_None) return; if (jump != JumpState_None) From d2cad229f897cfb1657095ac362708360e6bc688 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Tue, 25 Sep 2018 17:09:54 +0300 Subject: [PATCH 4/4] Ugly hack: don't reset player idle and movement animations in first person view --- apps/openmw/mwmechanics/character.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 27170d6a89..90f90e9e2a 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -356,7 +356,7 @@ void CharacterController::refreshJumpAnims(const WeaponInfo* weap, JumpingState if (!force && jump == mJumpState && idle == CharState_None && movement == CharState_None) return; - if (jump != JumpState_None) + if (jump != JumpState_None && !(mPtr == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->isFirstPerson())) // FIXME { idle = CharState_None; movement = CharState_None;