mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-29 22:45:34 +00:00
Merge pull request #1029 from Allofich/anim
Improvements for playgroup and loopgroup
This commit is contained in:
commit
346f5a19a3
4 changed files with 90 additions and 74 deletions
|
@ -1524,6 +1524,26 @@ bool CharacterController::updateWeaponState()
|
|||
return forcestateupdate;
|
||||
}
|
||||
|
||||
void CharacterController::updateAnimQueue()
|
||||
{
|
||||
if(mAnimQueue.size() > 1)
|
||||
{
|
||||
if(mAnimation->isPlaying(mAnimQueue.front().mGroup) == false)
|
||||
{
|
||||
mAnimation->disable(mAnimQueue.front().mGroup);
|
||||
mAnimQueue.pop_front();
|
||||
|
||||
bool loopfallback = (mAnimQueue.front().mGroup.compare(0,4,"idle") == 0);
|
||||
mAnimation->play(mAnimQueue.front().mGroup, Priority_Default,
|
||||
MWRender::Animation::BlendMask_All, false,
|
||||
1.0f, "start", "stop", 0.0f, mAnimQueue.front().mLoopCount, loopfallback);
|
||||
}
|
||||
}
|
||||
|
||||
if(!mAnimQueue.empty())
|
||||
mAnimation->setLoopingEnabled(mAnimQueue.front().mGroup, mAnimQueue.size() <= 1);
|
||||
}
|
||||
|
||||
void CharacterController::update(float duration)
|
||||
{
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
|
@ -1534,21 +1554,7 @@ void CharacterController::update(float duration)
|
|||
updateMagicEffects();
|
||||
|
||||
if(!cls.isActor())
|
||||
{
|
||||
if(mAnimQueue.size() > 1)
|
||||
{
|
||||
if(mAnimation->isPlaying(mAnimQueue.front().mGroup) == false)
|
||||
{
|
||||
mAnimation->disable(mAnimQueue.front().mGroup);
|
||||
mAnimQueue.pop_front();
|
||||
|
||||
bool loopfallback = (mAnimQueue.front().mGroup.compare(0,4,"idle") == 0);
|
||||
mAnimation->play(mAnimQueue.front().mGroup, Priority_Default,
|
||||
MWRender::Animation::BlendMask_All, false,
|
||||
1.0f, "start", "stop", 0.0f, mAnimQueue.front().mLoopCount, loopfallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
updateAnimQueue();
|
||||
else if(!cls.getCreatureStats(mPtr).isDead())
|
||||
{
|
||||
bool onground = world->isOnGround(mPtr);
|
||||
|
@ -1816,19 +1822,8 @@ void CharacterController::update(float duration)
|
|||
{
|
||||
idlestate = (inwater ? CharState_IdleSwim : (sneak && !inJump ? CharState_IdleSneak : CharState_Idle));
|
||||
}
|
||||
else if(mAnimQueue.size() > 1)
|
||||
{
|
||||
if(mAnimation->isPlaying(mAnimQueue.front().mGroup) == false)
|
||||
{
|
||||
mAnimation->disable(mAnimQueue.front().mGroup);
|
||||
mAnimQueue.pop_front();
|
||||
|
||||
bool loopfallback = (mAnimQueue.front().mGroup.compare(0,4,"idle") == 0);
|
||||
mAnimation->play(mAnimQueue.front().mGroup, Priority_Default,
|
||||
MWRender::Animation::BlendMask_All, false,
|
||||
1.0f, "start", "stop", 0.0f, mAnimQueue.front().mLoopCount, loopfallback);
|
||||
}
|
||||
}
|
||||
else
|
||||
updateAnimQueue();
|
||||
|
||||
if (!mSkipAnim)
|
||||
{
|
||||
|
@ -1994,9 +1989,10 @@ void CharacterController::unpersistAnimationState()
|
|||
mCurrentIdle.clear();
|
||||
mIdleState = CharState_SpecialIdle;
|
||||
|
||||
bool loopfallback = (mAnimQueue.front().mGroup.compare(0,4,"idle") == 0);
|
||||
mAnimation->play(anim.mGroup,
|
||||
Priority_Default, MWRender::Animation::BlendMask_All, false, 1.0f,
|
||||
"start", "stop", complete, anim.mLoopCount);
|
||||
"start", "stop", complete, anim.mLoopCount, loopfallback);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2009,6 +2005,27 @@ bool CharacterController::playGroup(const std::string &groupname, int mode, int
|
|||
}
|
||||
else
|
||||
{
|
||||
// If the given animation is a looped animation, is already playing
|
||||
// and has not yet reached its Loop Stop key, make it the only animation
|
||||
// in the queue, and retain the loop count from the animation that was
|
||||
// already playing. This emulates observed behavior from the original
|
||||
// engine and allows banners to animate correctly.
|
||||
if (!mAnimQueue.empty() && mAnimQueue.front().mGroup == groupname &&
|
||||
mAnimation->getTextKeyTime(mAnimQueue.front().mGroup+": loop start") >= 0)
|
||||
{
|
||||
float endOfLoop = mAnimation->getTextKeyTime(mAnimQueue.front().mGroup+": loop stop");
|
||||
|
||||
if (endOfLoop < 0) // if no Loop Stop key was found, use the Stop key
|
||||
endOfLoop = mAnimation->getTextKeyTime(mAnimQueue.front().mGroup+": stop");
|
||||
|
||||
if (endOfLoop > 0 && (mAnimation->getCurrentTime(mAnimQueue.front().mGroup) < endOfLoop))
|
||||
{
|
||||
mAnimation->setLoopingEnabled(mAnimQueue.front().mGroup, true);
|
||||
mAnimQueue.resize(1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
count = std::max(count, 1);
|
||||
|
||||
AnimationQueueEntry entry;
|
||||
|
@ -2032,8 +2049,6 @@ bool CharacterController::playGroup(const std::string &groupname, int mode, int
|
|||
}
|
||||
else if(mode == 0)
|
||||
{
|
||||
if (!mAnimQueue.empty())
|
||||
mAnimation->stopLooping(mAnimQueue.front().mGroup);
|
||||
mAnimQueue.resize(1);
|
||||
mAnimQueue.push_back(entry);
|
||||
}
|
||||
|
|
|
@ -212,6 +212,8 @@ class CharacterController : public MWRender::Animation::TextKeyListener
|
|||
bool updateCreatureState();
|
||||
void updateIdleStormState(bool inwater);
|
||||
|
||||
void updateAnimQueue();
|
||||
|
||||
void updateHeadTracking(float duration);
|
||||
|
||||
void updateMagicEffects();
|
||||
|
|
|
@ -873,16 +873,6 @@ namespace MWRender
|
|||
addControllers();
|
||||
}
|
||||
|
||||
void Animation::stopLooping(const std::string& groupname)
|
||||
{
|
||||
AnimStateMap::iterator stateiter = mStates.find(groupname);
|
||||
if(stateiter != mStates.end())
|
||||
{
|
||||
stateiter->second.mLoopCount = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Animation::adjustSpeedMult(const std::string &groupname, float speedmult)
|
||||
{
|
||||
AnimStateMap::iterator state(mStates.find(groupname));
|
||||
|
@ -1023,35 +1013,33 @@ namespace MWRender
|
|||
{
|
||||
float targetTime;
|
||||
|
||||
if(state.getTime() >= state.mLoopStopTime && state.mLoopCount > 0)
|
||||
goto handle_loop;
|
||||
|
||||
targetTime = state.getTime() + timepassed;
|
||||
if(textkey == textkeys.end() || textkey->first > targetTime)
|
||||
if (!state.shouldLoop())
|
||||
{
|
||||
if(mAccumCtrl && state.mTime == mAnimationTimePtr[0]->getTimePtr())
|
||||
updatePosition(state.getTime(), targetTime, movement);
|
||||
state.setTime(std::min(targetTime, state.mStopTime));
|
||||
targetTime = state.getTime() + timepassed;
|
||||
if(textkey == textkeys.end() || textkey->first > targetTime)
|
||||
{
|
||||
if(mAccumCtrl && state.mTime == mAnimationTimePtr[0]->getTimePtr())
|
||||
updatePosition(state.getTime(), targetTime, movement);
|
||||
state.setTime(std::min(targetTime, state.mStopTime));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(mAccumCtrl && state.mTime == mAnimationTimePtr[0]->getTimePtr())
|
||||
updatePosition(state.getTime(), textkey->first, movement);
|
||||
state.setTime(textkey->first);
|
||||
}
|
||||
|
||||
state.mPlaying = (state.getTime() < state.mStopTime);
|
||||
timepassed = targetTime - state.getTime();
|
||||
|
||||
while(textkey != textkeys.end() && textkey->first <= state.getTime())
|
||||
{
|
||||
handleTextKey(state, stateiter->first, textkey, textkeys);
|
||||
++textkey;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(state.shouldLoop())
|
||||
{
|
||||
if(mAccumCtrl && state.mTime == mAnimationTimePtr[0]->getTimePtr())
|
||||
updatePosition(state.getTime(), textkey->first, movement);
|
||||
state.setTime(textkey->first);
|
||||
}
|
||||
|
||||
state.mPlaying = (state.getTime() < state.mStopTime);
|
||||
timepassed = targetTime - state.getTime();
|
||||
|
||||
while(textkey != textkeys.end() && textkey->first <= state.getTime())
|
||||
{
|
||||
handleTextKey(state, stateiter->first, textkey, textkeys);
|
||||
++textkey;
|
||||
}
|
||||
|
||||
if(state.getTime() >= state.mLoopStopTime && state.mLoopCount > 0)
|
||||
{
|
||||
handle_loop:
|
||||
state.mLoopCount--;
|
||||
state.setTime(state.mLoopStartTime);
|
||||
state.mPlaying = true;
|
||||
|
@ -1065,7 +1053,7 @@ namespace MWRender
|
|||
|
||||
if(state.getTime() >= state.mLoopStopTime)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(timepassed <= 0.0f)
|
||||
break;
|
||||
|
@ -1095,6 +1083,13 @@ namespace MWRender
|
|||
return movement;
|
||||
}
|
||||
|
||||
void Animation::setLoopingEnabled(const std::string &groupname, bool enabled)
|
||||
{
|
||||
AnimStateMap::iterator state(mStates.find(groupname));
|
||||
if(state != mStates.end())
|
||||
state->second.mLoopingEnabled = enabled;
|
||||
}
|
||||
|
||||
void Animation::setObjectRoot(const std::string &model, bool forceskeleton, bool baseonly, bool isCreature)
|
||||
{
|
||||
osg::ref_ptr<osg::StateSet> previousStateset;
|
||||
|
|
|
@ -183,6 +183,7 @@ protected:
|
|||
float mSpeedMult;
|
||||
|
||||
bool mPlaying;
|
||||
bool mLoopingEnabled;
|
||||
size_t mLoopCount;
|
||||
|
||||
AnimPriority mPriority;
|
||||
|
@ -190,8 +191,8 @@ protected:
|
|||
bool mAutoDisable;
|
||||
|
||||
AnimState() : mStartTime(0.0f), mLoopStartTime(0.0f), mLoopStopTime(0.0f), mStopTime(0.0f),
|
||||
mTime(new float), mSpeedMult(1.0f), mPlaying(false), mLoopCount(0),
|
||||
mPriority(0), mBlendMask(0), mAutoDisable(true)
|
||||
mTime(new float), mSpeedMult(1.0f), mPlaying(false), mLoopingEnabled(true),
|
||||
mLoopCount(0), mPriority(0), mBlendMask(0), mAutoDisable(true)
|
||||
{
|
||||
}
|
||||
~AnimState();
|
||||
|
@ -204,6 +205,11 @@ protected:
|
|||
{
|
||||
*mTime = time;
|
||||
}
|
||||
|
||||
bool shouldLoop() const
|
||||
{
|
||||
return getTime() >= mLoopStopTime && mLoopingEnabled && mLoopCount > 0;
|
||||
}
|
||||
};
|
||||
typedef std::map<std::string,AnimState> AnimStateMap;
|
||||
AnimStateMap mStates;
|
||||
|
@ -389,10 +395,6 @@ public:
|
|||
float speedmult, const std::string &start, const std::string &stop,
|
||||
float startpoint, size_t loops, bool loopfallback=false);
|
||||
|
||||
/** If the given animation group is currently playing, set its remaining loop count to '0'.
|
||||
*/
|
||||
void stopLooping(const std::string& groupName);
|
||||
|
||||
/** Adjust the speed multiplier of an already playing animation.
|
||||
*/
|
||||
void adjustSpeedMult (const std::string& groupname, float speedmult);
|
||||
|
@ -432,6 +434,8 @@ public:
|
|||
|
||||
virtual osg::Vec3f runAnimation(float duration);
|
||||
|
||||
void setLoopingEnabled(const std::string &groupname, bool enabled);
|
||||
|
||||
/// This is typically called as part of runAnimation, but may be called manually if needed.
|
||||
void updateEffects(float duration);
|
||||
|
||||
|
|
Loading…
Reference in a new issue