mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-19 20:53:52 +00:00
Figure out which animations to play based on priority
Bone group will also be taken into account later.
This commit is contained in:
parent
921f534980
commit
7c3b014193
4 changed files with 106 additions and 63 deletions
|
@ -171,7 +171,7 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim
|
|||
|
||||
std::string group;
|
||||
getCurrentGroup(group);
|
||||
mMovingAnim = mAnimation->play(group, "start", "stop", 1.0f, loop ? (~(size_t)0) : 0);
|
||||
mMovingAnim = mAnimation->play(group, MWRender::Animation::Priority_Default, "start", "stop", 1.0f, loop ? (~(size_t)0) : 0);
|
||||
}
|
||||
|
||||
CharacterController::~CharacterController()
|
||||
|
@ -346,6 +346,7 @@ void CharacterController::update(float duration, Movement &movement)
|
|||
else
|
||||
{
|
||||
mMovingAnim = mAnimation->play(mAnimQueue.front().first,
|
||||
MWRender::Animation::Priority_Default,
|
||||
"start", "stop", 0.0f,
|
||||
mAnimQueue.front().second);
|
||||
mAnimQueue.pop_front();
|
||||
|
@ -381,7 +382,8 @@ void CharacterController::playGroup(const std::string &groupname, int mode, int
|
|||
mAnimQueue.clear();
|
||||
mCharState = CharState_SpecialIdle;
|
||||
mLooping = false;
|
||||
mMovingAnim = mAnimation->play(groupname, ((mode==2) ? "loop start" : "start"), "stop", 0.0f, count-1);
|
||||
mMovingAnim = mAnimation->play(groupname, MWRender::Animation::Priority_Default,
|
||||
((mode==2) ? "loop start" : "start"), "stop", 0.0f, count-1);
|
||||
}
|
||||
else if(mode == 0)
|
||||
{
|
||||
|
@ -424,7 +426,8 @@ void CharacterController::forceStateUpdate()
|
|||
|
||||
std::string group;
|
||||
getCurrentGroup(group);
|
||||
mMovingAnim = mAnimation->play(group, "start", "stop", 0.0f, mLooping ? (~(size_t)0) : 0);
|
||||
mMovingAnim = mAnimation->play(group, MWRender::Animation::Priority_Default,
|
||||
"start", "stop", 0.0f, mLooping ? (~(size_t)0) : 0);
|
||||
|
||||
mAnimation->showWeapons(mWeapState != WeapState_None && mWeapState != WeapState_HandToHand &&
|
||||
mWeapState != WeapState_Spell);
|
||||
|
|
|
@ -372,7 +372,7 @@ void Animation::updatePosition(float time, Ogre::Vector3 &position)
|
|||
mAccumRoot->setPosition(-mLastPosition);
|
||||
}
|
||||
|
||||
bool Animation::reset(AnimState &state, const NifOgre::TextKeyMap &keys, NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl, const std::string &groupname, const std::string &start, const std::string &stop, float startpoint)
|
||||
bool Animation::reset(AnimState &state, const NifOgre::TextKeyMap &keys, const std::string &groupname, const std::string &start, const std::string &stop, float startpoint)
|
||||
{
|
||||
std::string tag = groupname+": "+start;
|
||||
NifOgre::TextKeyMap::const_iterator startkey(keys.begin());
|
||||
|
@ -413,9 +413,6 @@ bool Animation::reset(AnimState &state, const NifOgre::TextKeyMap &keys, NifOgre
|
|||
state.mNextKey++;
|
||||
}
|
||||
|
||||
if(nonaccumctrl)
|
||||
mLastPosition = nonaccumctrl->getTranslation(state.mTime) * mAccumulate;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -429,8 +426,6 @@ bool Animation::doLoop(AnimState &state)
|
|||
state.mNextKey = state.mLoopStartKey;
|
||||
state.mNextKey++;
|
||||
state.mPlaying = true;
|
||||
if(mNonAccumCtrl)
|
||||
mLastPosition = mNonAccumCtrl->getTranslation(state.mTime) * mAccumulate;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -476,6 +471,11 @@ bool Animation::handleTextKey(AnimState &state, const std::string &groupname, co
|
|||
if(state.mTime >= time)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ugly
|
||||
if(mNonAccumCtrl && groupname == mAnimationValuePtr[0]->getAnimName())
|
||||
mLastPosition = mNonAccumCtrl->getTranslation(state.mTime) * mAccumulate;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -484,78 +484,101 @@ bool Animation::handleTextKey(AnimState &state, const std::string &groupname, co
|
|||
}
|
||||
|
||||
|
||||
bool Animation::play(const std::string &groupname, const std::string &start, const std::string &stop, float startpoint, size_t loops)
|
||||
bool Animation::play(const std::string &groupname, Priority priority, const std::string &start, const std::string &stop, float startpoint, size_t loops)
|
||||
{
|
||||
if(!mSkelBase || groupname.empty())
|
||||
if(!mSkelBase)
|
||||
return false;
|
||||
|
||||
if(groupname.empty())
|
||||
return resetActiveGroups();
|
||||
|
||||
AnimStateMap::iterator stateiter = mStates.find(groupname);
|
||||
if(stateiter != mStates.end())
|
||||
mStates.erase(stateiter);
|
||||
{
|
||||
stateiter->second.mPriority = priority;
|
||||
return resetActiveGroups();
|
||||
}
|
||||
// HACK: Don't clear all active animations
|
||||
mStates.clear();
|
||||
|
||||
bool movinganim = false;
|
||||
bool foundanim = false;
|
||||
|
||||
/* Look in reverse; last-inserted source has priority. */
|
||||
AnimSourceList::reverse_iterator iter(mAnimSources.rbegin());
|
||||
for(;iter != mAnimSources.rend();iter++)
|
||||
{
|
||||
const NifOgre::TextKeyMap &keys = iter->mTextKeys;
|
||||
NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl = NULL;
|
||||
if(mNonAccumRoot)
|
||||
AnimState state;
|
||||
if(reset(state, iter->mTextKeys, groupname, start, stop, startpoint))
|
||||
{
|
||||
for(size_t i = 0;i < iter->mControllers[0].size();i++)
|
||||
{
|
||||
NifOgre::NodeTargetValue<Ogre::Real> *dstval;
|
||||
dstval = dynamic_cast<NifOgre::NodeTargetValue<Ogre::Real>*>(iter->mControllers[0][i].getDestination().getPointer());
|
||||
if(dstval && dstval->getNode() == mNonAccumRoot)
|
||||
{
|
||||
nonaccumctrl = dstval;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!foundanim)
|
||||
{
|
||||
AnimState state;
|
||||
if(!reset(state, keys, nonaccumctrl, groupname, start, stop, startpoint))
|
||||
continue;
|
||||
foundanim = true;
|
||||
|
||||
state.mSource = &*iter;
|
||||
state.mLoopCount = loops;
|
||||
state.mPlaying = true;
|
||||
state.mPriority = priority;
|
||||
mStates[groupname] = state;
|
||||
|
||||
// FIXME
|
||||
mAnimationValuePtr[0]->setAnimName(groupname);
|
||||
|
||||
mNonAccumCtrl = nonaccumctrl;
|
||||
mAnimVelocity = 0.0f;
|
||||
|
||||
if(mAccumulate == Ogre::Vector3(0.0f))
|
||||
break;
|
||||
}
|
||||
|
||||
if(!nonaccumctrl)
|
||||
break;
|
||||
|
||||
mAnimVelocity = calcAnimVelocity(keys, nonaccumctrl, mAccumulate, groupname);
|
||||
if(mAnimVelocity > 1.0f)
|
||||
{
|
||||
movinganim = (nonaccumctrl==mNonAccumCtrl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!foundanim)
|
||||
if(iter == mAnimSources.rend())
|
||||
std::cerr<< "Failed to find animation "<<groupname <<std::endl;
|
||||
|
||||
return movinganim;
|
||||
return resetActiveGroups();
|
||||
}
|
||||
|
||||
bool Animation::resetActiveGroups()
|
||||
{
|
||||
for(size_t grp = 0;grp < sNumGroups;grp++)
|
||||
{
|
||||
AnimStateMap::const_iterator active = mStates.end();
|
||||
|
||||
AnimStateMap::const_iterator state = mStates.begin();
|
||||
for(;state != mStates.end();state++)
|
||||
{
|
||||
#if 0
|
||||
if(!(state->second.mGroups&(1<<grp)))
|
||||
continue;
|
||||
#endif
|
||||
if(active == mStates.end() || active->second.mPriority < state->second.mPriority)
|
||||
active = state;
|
||||
}
|
||||
|
||||
mAnimationValuePtr[grp]->setAnimName((active == mStates.end()) ?
|
||||
std::string() : active->first);
|
||||
}
|
||||
|
||||
mNonAccumCtrl = NULL;
|
||||
mAnimVelocity = 0.0f;
|
||||
mLastPosition = Ogre::Vector3(0.0f);
|
||||
|
||||
if(!mNonAccumRoot || mAccumulate == Ogre::Vector3(0.0f))
|
||||
return false;
|
||||
|
||||
AnimStateMap::const_iterator state = mStates.find(mAnimationValuePtr[0]->getAnimName());
|
||||
if(state == mStates.end())
|
||||
return false;
|
||||
|
||||
bool ismoving = false;
|
||||
|
||||
const NifOgre::TextKeyMap &keys = state->second.mSource->mTextKeys;
|
||||
std::vector<Ogre::Controller<Ogre::Real> >&ctrls = state->second.mSource->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);
|
||||
ismoving = (mAnimVelocity > 1.0f);
|
||||
|
||||
mLastPosition = dstval->getTranslation(state->second.mTime) * mAccumulate;
|
||||
|
||||
mNonAccumCtrl = dstval;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ismoving;
|
||||
}
|
||||
|
||||
|
||||
bool Animation::getInfo(const std::string &groupname, float *complete, std::string *start, std::string *stop) const
|
||||
{
|
||||
AnimStateMap::const_iterator iter = mStates.find(groupname);
|
||||
|
@ -591,14 +614,14 @@ Ogre::Vector3 Animation::runAnimation(float duration)
|
|||
if(state.mNextKey->first > targetTime)
|
||||
{
|
||||
state.mTime = targetTime;
|
||||
if(mNonAccumCtrl)
|
||||
if(mNonAccumCtrl && stateiter->first == mAnimationValuePtr[0]->getAnimName())
|
||||
updatePosition(state.mTime, movement);
|
||||
break;
|
||||
}
|
||||
|
||||
NifOgre::TextKeyMap::const_iterator key(state.mNextKey++);
|
||||
state.mTime = key->first;
|
||||
if(mNonAccumCtrl)
|
||||
if(mNonAccumCtrl && stateiter->first == mAnimationValuePtr[0]->getAnimName())
|
||||
updatePosition(state.mTime, movement);
|
||||
|
||||
state.mPlaying = (key != state.mStopKey);
|
||||
|
|
|
@ -14,6 +14,14 @@ namespace MWRender
|
|||
|
||||
class Animation
|
||||
{
|
||||
public:
|
||||
enum Priority {
|
||||
Priority_Nil = -1, /* Do not use */
|
||||
Priority_Default,
|
||||
|
||||
Num_Priorities
|
||||
};
|
||||
|
||||
protected:
|
||||
static const size_t sNumGroups = 1;
|
||||
|
||||
|
@ -55,6 +63,8 @@ protected:
|
|||
bool mPlaying;
|
||||
size_t mLoopCount;
|
||||
|
||||
int mPriority;
|
||||
|
||||
AnimState() : mSource(NULL), mTime(0.0f), mPlaying(false), mLoopCount(0)
|
||||
{ }
|
||||
};
|
||||
|
@ -79,6 +89,11 @@ protected:
|
|||
|
||||
Ogre::SharedPtr<AnimationValue> mAnimationValuePtr[sNumGroups];
|
||||
|
||||
/* Sets the appropriate animations on the bone groups based on priority.
|
||||
* Returns true if the NonAccum root will provide movement.
|
||||
*/
|
||||
bool resetActiveGroups();
|
||||
|
||||
static size_t detectAnimGroup(const Ogre::Node *node);
|
||||
|
||||
static float calcAnimVelocity(const NifOgre::TextKeyMap &keys,
|
||||
|
@ -102,7 +117,6 @@ protected:
|
|||
* false.
|
||||
*/
|
||||
bool reset(AnimState &state, const NifOgre::TextKeyMap &keys,
|
||||
NifOgre::NodeTargetValue<Ogre::Real> *nonaccumctrl,
|
||||
const std::string &groupname, const std::string &start, const std::string &stop,
|
||||
float startpoint);
|
||||
|
||||
|
@ -136,6 +150,9 @@ public:
|
|||
|
||||
/** Plays an animation.
|
||||
* \param groupname Name of the animation group to play.
|
||||
* \param priority Priority of the animation. The animation will play on
|
||||
* bone groups that don't have another animation set of a
|
||||
* higher priority.
|
||||
* \param start Key marker from which to start.
|
||||
* \param stop Key marker to stop at.
|
||||
* \param startpoint How far in between the two markers to start. 0 starts
|
||||
|
@ -146,7 +163,7 @@ public:
|
|||
* \return Boolean specifying whether the animation will return movement
|
||||
* for the character at all.
|
||||
*/
|
||||
bool play(const std::string &groupname, const std::string &start, const std::string &stop, float startpoint, size_t loops);
|
||||
bool play(const std::string &groupname, Priority priority, const std::string &start, const std::string &stop, float startpoint, size_t loops);
|
||||
|
||||
void disable(const std::string &groupname);
|
||||
|
||||
|
|
|
@ -172,7 +172,7 @@ namespace MWRender
|
|||
if(groupname != mCurrentAnimGroup)
|
||||
{
|
||||
mCurrentAnimGroup = groupname;
|
||||
mAnimation->play(mCurrentAnimGroup, "start", "stop", 0.0f, 0);
|
||||
mAnimation->play(mCurrentAnimGroup, Animation::Priority_Default, "start", "stop", 0.0f, 0);
|
||||
}
|
||||
|
||||
mAnimation->forceUpdate();
|
||||
|
@ -199,7 +199,7 @@ namespace MWRender
|
|||
mAnimation->showWeapons(true);
|
||||
|
||||
mCurrentAnimGroup = "inventoryhandtohand";
|
||||
mAnimation->play(mCurrentAnimGroup, "start", "stop", 0.0f, 0);
|
||||
mAnimation->play(mCurrentAnimGroup, Animation::Priority_Default, "start", "stop", 0.0f, 0);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------
|
||||
|
@ -233,7 +233,7 @@ namespace MWRender
|
|||
|
||||
void RaceSelectionPreview::onSetup ()
|
||||
{
|
||||
mAnimation->play("idle", "start", "stop", 0.0f, 0);
|
||||
mAnimation->play("idle", Animation::Priority_Default, "start", "stop", 0.0f, 0);
|
||||
|
||||
updateCamera();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue