1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-04-15 23:42:20 +00:00

rename "persisted" animations to "scripted", because that is what they actually are. And begin teaching the animation system to distinguish between a scripted and an unscripted animation.

This commit is contained in:
Mads Buvik Sandvei 2023-10-25 19:53:34 +02:00
parent 24890a729b
commit 92a5e52407
10 changed files with 60 additions and 42 deletions

View File

@ -1998,12 +1998,12 @@ namespace MWMechanics
} }
bool Actors::playAnimationGroup( bool Actors::playAnimationGroup(
const MWWorld::Ptr& ptr, std::string_view groupName, int mode, int number, bool persist) const const MWWorld::Ptr& ptr, std::string_view groupName, int mode, int number, bool scripted) const
{ {
const auto iter = mIndex.find(ptr.mRef); const auto iter = mIndex.find(ptr.mRef);
if (iter != mIndex.end()) if (iter != mIndex.end())
{ {
return iter->second->getCharacterController().playGroup(groupName, mode, number, persist); return iter->second->getCharacterController().playGroup(groupName, mode, number, scripted);
} }
else else
{ {

View File

@ -113,7 +113,7 @@ namespace MWMechanics
void forceStateUpdate(const MWWorld::Ptr& ptr) const; void forceStateUpdate(const MWWorld::Ptr& ptr) const;
bool playAnimationGroup( bool playAnimationGroup(
const MWWorld::Ptr& ptr, std::string_view groupName, int mode, int number, bool persist = false) const; const MWWorld::Ptr& ptr, std::string_view groupName, int mode, int number, bool scripted = false) const;
void skipAnimation(const MWWorld::Ptr& ptr) const; void skipAnimation(const MWWorld::Ptr& ptr) const;
bool checkAnimationPlaying(const MWWorld::Ptr& ptr, const std::string& groupName) const; bool checkAnimationPlaying(const MWWorld::Ptr& ptr, const std::string& groupName) const;
void persistAnimationStates() const; void persistAnimationStates() const;

View File

@ -538,7 +538,7 @@ namespace MWMechanics
if (mAnimation->isPlaying("containerclose")) if (mAnimation->isPlaying("containerclose"))
return false; return false;
mAnimation->play("containeropen", Priority_Persistent, MWRender::Animation::BlendMask_All, false, 1.0f, mAnimation->play("containeropen", Priority_Scripted, MWRender::Animation::BlendMask_All, false, 1.0f,
"start", "stop", 0.f, 0); "start", "stop", 0.f, 0);
if (mAnimation->isPlaying("containeropen")) if (mAnimation->isPlaying("containeropen"))
return false; return false;
@ -559,7 +559,7 @@ namespace MWMechanics
if (animPlaying) if (animPlaying)
startPoint = 1.f - complete; startPoint = 1.f - complete;
mAnimation->play("containerclose", Priority_Persistent, MWRender::Animation::BlendMask_All, false, 1.0f, mAnimation->play("containerclose", Priority_Scripted, MWRender::Animation::BlendMask_All, false, 1.0f,
"start", "stop", startPoint, 0); "start", "stop", startPoint, 0);
} }
} }
@ -828,7 +828,7 @@ namespace MWMechanics
CharacterState idle, CharacterState movement, JumpingState jump, bool force) CharacterState idle, CharacterState movement, JumpingState jump, bool force)
{ {
// If the current animation is persistent, do not touch it // If the current animation is persistent, do not touch it
if (isPersistentAnimPlaying()) if (isScriptedAnimPlaying())
return; return;
refreshHitRecoilAnims(); refreshHitRecoilAnims();
@ -882,7 +882,7 @@ namespace MWMechanics
mDeathState = chooseRandomDeathState(); mDeathState = chooseRandomDeathState();
// Do not interrupt scripted animation by death // Do not interrupt scripted animation by death
if (isPersistentAnimPlaying()) if (isScriptedAnimPlaying())
return; return;
playDeath(startpoint, mDeathState); playDeath(startpoint, mDeathState);
@ -1482,7 +1482,7 @@ namespace MWMechanics
} }
// Combat for actors with persistent animations obviously will be buggy // Combat for actors with persistent animations obviously will be buggy
if (isPersistentAnimPlaying()) if (isScriptedAnimPlaying())
return forcestateupdate; return forcestateupdate;
float complete = 0.f; float complete = 0.f;
@ -1855,10 +1855,18 @@ namespace MWMechanics
if (mAnimQueue.empty()) if (mAnimQueue.empty())
return; return;
if (mAnimation->isPlaying(mAnimQueue.front().mGroup) == false) bool isFrontAnimPlaying = false;
if (mAnimQueue.front().mScripted)
isFrontAnimPlaying = mAnimation->isPlayingScripted(mAnimQueue.front().mGroup);
else
isFrontAnimPlaying = mAnimation->isPlaying(mAnimQueue.front().mGroup);
if (!isFrontAnimPlaying)
{ {
if (mAnimQueue.size() > 1) if (mAnimQueue.size() > 1)
{ {
// Curren animation finished, move to the next in queue
mAnimation->disable(mAnimQueue.front().mGroup); mAnimation->disable(mAnimQueue.front().mGroup);
mAnimQueue.pop_front(); mAnimQueue.pop_front();
@ -1866,14 +1874,13 @@ namespace MWMechanics
mAnimation->play(mAnimQueue.front().mGroup, Priority_Default, MWRender::Animation::BlendMask_All, false, mAnimation->play(mAnimQueue.front().mGroup, Priority_Default, MWRender::Animation::BlendMask_All, false,
1.0f, "start", "stop", 0.0f, mAnimQueue.front().mLoopCount, loopfallback); 1.0f, "start", "stop", 0.0f, mAnimQueue.front().mLoopCount, loopfallback);
} }
else if (mAnimQueue.front().mLoopCount > 1 && mAnimQueue.front().mPersist) else if (mAnimQueue.front().mLoopCount > 1 && mAnimQueue.front().mScripted)
{ {
// The last animation stopped playing when it shouldn't have. // A scripted animation stopped playing before time.
// This is caused by a rebuild of the animation object, so we should restart the animation here // This happens when the animation object is rebuilt, so we should restart the animation here.
// Subtract 1 from mLoopCount to consider the current loop done.
bool loopfallback = mAnimQueue.front().mGroup.starts_with("idle"); bool loopfallback = mAnimQueue.front().mGroup.starts_with("idle");
mAnimation->play(mAnimQueue.front().mGroup, Priority_Persistent, MWRender::Animation::BlendMask_All, mAnimation->play(mAnimQueue.front().mGroup, Priority_Scripted, MWRender::Animation::BlendMask_All,
false, 1.0f, "start", "stop", 0.0f, mAnimQueue.front().mLoopCount - 1, loopfallback); false, 1.0f, "start", "stop", 0.0f, mAnimQueue.front().mLoopCount, loopfallback);
} }
else else
{ {
@ -2393,7 +2400,7 @@ namespace MWMechanics
} }
} }
bool isPersist = isPersistentAnimPlaying(); bool isPersist = isScriptedAnimPlaying();
osg::Vec3f moved = mAnimation->runAnimation(mSkipAnim && !isPersist ? 0.f : duration); osg::Vec3f moved = mAnimation->runAnimation(mSkipAnim && !isPersist ? 0.f : duration);
if (duration > 0.0f) if (duration > 0.0f)
moved /= duration; moved /= duration;
@ -2450,7 +2457,7 @@ namespace MWMechanics
state.mScriptedAnims.clear(); state.mScriptedAnims.clear();
for (AnimationQueue::const_iterator iter = mAnimQueue.begin(); iter != mAnimQueue.end(); ++iter) for (AnimationQueue::const_iterator iter = mAnimQueue.begin(); iter != mAnimQueue.end(); ++iter)
{ {
if (!iter->mPersist) if (!iter->mScripted)
continue; continue;
ESM::AnimationState::ScriptedAnimation anim; ESM::AnimationState::ScriptedAnimation anim;
@ -2486,7 +2493,7 @@ namespace MWMechanics
AnimationQueueEntry entry; AnimationQueueEntry entry;
entry.mGroup = iter->mGroup; entry.mGroup = iter->mGroup;
entry.mLoopCount = iter->mLoopCount; entry.mLoopCount = iter->mLoopCount;
entry.mPersist = true; entry.mScripted = true;
mAnimQueue.push_back(entry); mAnimQueue.push_back(entry);
} }
@ -2505,18 +2512,18 @@ namespace MWMechanics
mIdleState = CharState_SpecialIdle; mIdleState = CharState_SpecialIdle;
bool loopfallback = mAnimQueue.front().mGroup.starts_with("idle"); bool loopfallback = mAnimQueue.front().mGroup.starts_with("idle");
mAnimation->play(anim.mGroup, Priority_Persistent, MWRender::Animation::BlendMask_All, false, 1.0f, "start", mAnimation->play(anim.mGroup, Priority_Scripted, MWRender::Animation::BlendMask_All, false, 1.0f, "start",
"stop", complete, anim.mLoopCount, loopfallback); "stop", complete, anim.mLoopCount, loopfallback);
} }
} }
bool CharacterController::playGroup(std::string_view groupname, int mode, int count, bool persist) bool CharacterController::playGroup(std::string_view groupname, int mode, int count, bool scripted)
{ {
if (!mAnimation || !mAnimation->hasAnimation(groupname)) if (!mAnimation || !mAnimation->hasAnimation(groupname))
return false; return false;
// We should not interrupt persistent animations by non-persistent ones // We should not interrupt persistent animations by non-persistent ones
if (isPersistentAnimPlaying() && !persist) if (isScriptedAnimPlaying() && !scripted)
return true; return true;
// If this animation is a looped animation (has a "loop start" key) that is already playing // If this animation is a looped animation (has a "loop start" key) that is already playing
@ -2545,17 +2552,17 @@ namespace MWMechanics
AnimationQueueEntry entry; AnimationQueueEntry entry;
entry.mGroup = groupname; entry.mGroup = groupname;
entry.mLoopCount = count - 1; entry.mLoopCount = count - 1;
entry.mPersist = persist; entry.mScripted = scripted;
if (mode != 0 || mAnimQueue.empty() || !isAnimPlaying(mAnimQueue.front().mGroup)) if (mode != 0 || mAnimQueue.empty() || !isAnimPlaying(mAnimQueue.front().mGroup))
{ {
clearAnimQueue(persist); clearAnimQueue(scripted);
clearStateAnimation(mCurrentIdle); clearStateAnimation(mCurrentIdle);
mIdleState = CharState_SpecialIdle; mIdleState = CharState_SpecialIdle;
bool loopfallback = entry.mGroup.starts_with("idle"); bool loopfallback = entry.mGroup.starts_with("idle");
mAnimation->play(groupname, persist && groupname != "idle" ? Priority_Persistent : Priority_Default, mAnimation->play(groupname, scripted && groupname != "idle" ? Priority_Scripted : Priority_Default,
MWRender::Animation::BlendMask_All, false, 1.0f, ((mode == 2) ? "loop start" : "start"), "stop", 0.0f, MWRender::Animation::BlendMask_All, false, 1.0f, ((mode == 2) ? "loop start" : "start"), "stop", 0.0f,
count - 1, loopfallback); count - 1, loopfallback);
} }
@ -2566,7 +2573,7 @@ namespace MWMechanics
// "PlayGroup idle" is a special case, used to remove to stop scripted animations playing // "PlayGroup idle" is a special case, used to remove to stop scripted animations playing
if (groupname == "idle") if (groupname == "idle")
entry.mPersist = false; entry.mScripted = false;
mAnimQueue.push_back(entry); mAnimQueue.push_back(entry);
@ -2578,12 +2585,12 @@ namespace MWMechanics
mSkipAnim = true; mSkipAnim = true;
} }
bool CharacterController::isPersistentAnimPlaying() const bool CharacterController::isScriptedAnimPlaying() const
{ {
if (!mAnimQueue.empty()) if (!mAnimQueue.empty())
{ {
const AnimationQueueEntry& first = mAnimQueue.front(); const AnimationQueueEntry& first = mAnimQueue.front();
return first.mPersist && isAnimPlaying(first.mGroup); return first.mScripted && isAnimPlaying(first.mGroup);
} }
return false; return false;
@ -2609,7 +2616,7 @@ namespace MWMechanics
void CharacterController::clearAnimQueue(bool clearPersistAnims) void CharacterController::clearAnimQueue(bool clearPersistAnims)
{ {
// Do not interrupt scripted animations, if we want to keep them // Do not interrupt scripted animations, if we want to keep them
if ((!isPersistentAnimPlaying() || clearPersistAnims) && !mAnimQueue.empty()) if ((!isScriptedAnimPlaying() || clearPersistAnims) && !mAnimQueue.empty())
mAnimation->disable(mAnimQueue.front().mGroup); mAnimation->disable(mAnimQueue.front().mGroup);
if (clearPersistAnims) if (clearPersistAnims)
@ -2620,7 +2627,7 @@ namespace MWMechanics
for (AnimationQueue::iterator it = mAnimQueue.begin(); it != mAnimQueue.end();) for (AnimationQueue::iterator it = mAnimQueue.begin(); it != mAnimQueue.end();)
{ {
if (!it->mPersist) if (!it->mScripted)
it = mAnimQueue.erase(it); it = mAnimQueue.erase(it);
else else
++it; ++it;

View File

@ -40,7 +40,7 @@ namespace MWMechanics
Priority_Torch, Priority_Torch,
Priority_Storm, Priority_Storm,
Priority_Death, Priority_Death,
Priority_Persistent, Priority_Scripted,
Num_Priorities Num_Priorities
}; };
@ -135,7 +135,7 @@ namespace MWMechanics
{ {
std::string mGroup; std::string mGroup;
size_t mLoopCount; size_t mLoopCount;
bool mPersist; bool mScripted;
}; };
typedef std::deque<AnimationQueueEntry> AnimationQueue; typedef std::deque<AnimationQueueEntry> AnimationQueue;
AnimationQueue mAnimQueue; AnimationQueue mAnimQueue;
@ -215,7 +215,7 @@ namespace MWMechanics
std::string chooseRandomAttackAnimation() const; std::string chooseRandomAttackAnimation() const;
static bool isRandomAttackAnimation(std::string_view group); static bool isRandomAttackAnimation(std::string_view group);
bool isPersistentAnimPlaying() const; bool isScriptedAnimPlaying() const;
bool isMovementAnimationControlled() const; bool isMovementAnimationControlled() const;
void updateAnimQueue(); void updateAnimQueue();
@ -270,7 +270,7 @@ namespace MWMechanics
void persistAnimationState() const; void persistAnimationState() const;
void unpersistAnimationState(); void unpersistAnimationState();
bool playGroup(std::string_view groupname, int mode, int count, bool persist = false); bool playGroup(std::string_view groupname, int mode, int count, bool scripted = false);
void skipAnim(); void skipAnim();
bool isAnimPlaying(std::string_view groupName) const; bool isAnimPlaying(std::string_view groupName) const;

View File

@ -760,12 +760,12 @@ namespace MWMechanics
} }
bool MechanicsManager::playAnimationGroup( bool MechanicsManager::playAnimationGroup(
const MWWorld::Ptr& ptr, std::string_view groupName, int mode, int number, bool persist) const MWWorld::Ptr& ptr, std::string_view groupName, int mode, int number, bool scripted)
{ {
if (ptr.getClass().isActor()) if (ptr.getClass().isActor())
return mActors.playAnimationGroup(ptr, groupName, mode, number, persist); return mActors.playAnimationGroup(ptr, groupName, mode, number, scripted);
else else
return mObjects.playAnimationGroup(ptr, groupName, mode, number, persist); return mObjects.playAnimationGroup(ptr, groupName, mode, number, scripted);
} }
void MechanicsManager::skipAnimation(const MWWorld::Ptr& ptr) void MechanicsManager::skipAnimation(const MWWorld::Ptr& ptr)
{ {

View File

@ -142,7 +142,7 @@ namespace MWMechanics
/// Attempt to play an animation group /// Attempt to play an animation group
/// @return Success or error /// @return Success or error
bool playAnimationGroup( bool playAnimationGroup(
const MWWorld::Ptr& ptr, std::string_view groupName, int mode, int number, bool persist = false) override; const MWWorld::Ptr& ptr, std::string_view groupName, int mode, int number, bool scripted = false) override;
void skipAnimation(const MWWorld::Ptr& ptr) override; void skipAnimation(const MWWorld::Ptr& ptr) override;
bool checkAnimationPlaying(const MWWorld::Ptr& ptr, const std::string& groupName) override; bool checkAnimationPlaying(const MWWorld::Ptr& ptr, const std::string& groupName) override;
void persistAnimationStates() override; void persistAnimationStates() override;

View File

@ -99,12 +99,12 @@ namespace MWMechanics
} }
bool Objects::playAnimationGroup( bool Objects::playAnimationGroup(
const MWWorld::Ptr& ptr, std::string_view groupName, int mode, int number, bool persist) const MWWorld::Ptr& ptr, std::string_view groupName, int mode, int number, bool scripted)
{ {
const auto iter = mIndex.find(ptr.mRef); const auto iter = mIndex.find(ptr.mRef);
if (iter != mIndex.end()) if (iter != mIndex.end())
{ {
return iter->second->playGroup(groupName, mode, number, persist); return iter->second->playGroup(groupName, mode, number, scripted);
} }
else else
{ {

View File

@ -46,7 +46,7 @@ namespace MWMechanics
void onClose(const MWWorld::Ptr& ptr); void onClose(const MWWorld::Ptr& ptr);
bool playAnimationGroup( bool playAnimationGroup(
const MWWorld::Ptr& ptr, std::string_view groupName, int mode, int number, bool persist = false); const MWWorld::Ptr& ptr, std::string_view groupName, int mode, int number, bool scripted = false);
void skipAnimation(const MWWorld::Ptr& ptr); void skipAnimation(const MWWorld::Ptr& ptr);
void persistAnimationStates(); void persistAnimationStates();

View File

@ -1020,6 +1020,14 @@ namespace MWRender
return false; return false;
} }
bool Animation::isPlayingScripted(std::string_view groupname) const
{
AnimStateMap::const_iterator state(mStates.find(groupname));
if (state != mStates.end())
return state->second.mPlaying && state->second.mPriority.contains(MWMechanics::Priority::Priority_Scripted);
return false;
}
bool Animation::getInfo(std::string_view groupname, float* complete, float* speedmult) const bool Animation::getInfo(std::string_view groupname, float* complete, float* speedmult) const
{ {
AnimStateMap::const_iterator iter = mStates.find(groupname); AnimStateMap::const_iterator iter = mStates.find(groupname);
@ -1145,7 +1153,7 @@ namespace MWRender
bool hasScriptedAnims = false; bool hasScriptedAnims = false;
for (AnimStateMap::iterator stateiter = mStates.begin(); stateiter != mStates.end(); stateiter++) for (AnimStateMap::iterator stateiter = mStates.begin(); stateiter != mStates.end(); stateiter++)
{ {
if (stateiter->second.mPriority.contains(int(MWMechanics::Priority_Persistent)) if (stateiter->second.mPriority.contains(int(MWMechanics::Priority_Scripted))
&& stateiter->second.mPlaying) && stateiter->second.mPlaying)
{ {
hasScriptedAnims = true; hasScriptedAnims = true;
@ -1158,7 +1166,7 @@ namespace MWRender
while (stateiter != mStates.end()) while (stateiter != mStates.end())
{ {
AnimState& state = stateiter->second; AnimState& state = stateiter->second;
if (hasScriptedAnims && !state.mPriority.contains(int(MWMechanics::Priority_Persistent))) if (hasScriptedAnims && !state.mPriority.contains(int(MWMechanics::Priority_Scripted)))
{ {
++stateiter; ++stateiter;
continue; continue;

View File

@ -432,6 +432,9 @@ namespace MWRender
/** Returns true if the named animation group is playing. */ /** Returns true if the named animation group is playing. */
bool isPlaying(std::string_view groupname) const; bool isPlaying(std::string_view groupname) const;
/** Returns true if the named, scripted animation group is playing. */
bool isPlayingScripted(std::string_view groupname) const;
/// Returns true if no important animations are currently playing on the upper body. /// Returns true if no important animations are currently playing on the upper body.
bool upperBodyReady() const; bool upperBodyReady() const;