forked from teamnwah/openmw-tes3coop
Build separate animations for each group
This commit is contained in:
parent
e44729cd43
commit
bb98542c5a
3 changed files with 70 additions and 27 deletions
|
@ -23,7 +23,6 @@ Animation::Animation(const MWWorld::Ptr &ptr)
|
||||||
, mTime(0.0f)
|
, mTime(0.0f)
|
||||||
, mCurGroup(mTextKeys.end())
|
, mCurGroup(mTextKeys.end())
|
||||||
, mNextGroup(mTextKeys.end())
|
, mNextGroup(mTextKeys.end())
|
||||||
, mAnimState(NULL)
|
|
||||||
, mSkipFrame(false)
|
, mSkipFrame(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -80,10 +79,8 @@ void Animation::createEntityList(Ogre::SceneNode *node, const std::string &model
|
||||||
while(as.hasMoreElements())
|
while(as.hasMoreElements())
|
||||||
{
|
{
|
||||||
Ogre::AnimationState *state = as.getNext();
|
Ogre::AnimationState *state = as.getNext();
|
||||||
state->setEnabled(true);
|
state->setEnabled(false);
|
||||||
state->setLoop(false);
|
state->setLoop(false);
|
||||||
if(!mAnimState)
|
|
||||||
mAnimState = state;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,12 +89,12 @@ void Animation::createEntityList(Ogre::SceneNode *node, const std::string &model
|
||||||
|
|
||||||
void Animation::updatePosition(float time)
|
void Animation::updatePosition(float time)
|
||||||
{
|
{
|
||||||
mAnimState->setTimePosition(time);
|
mCurGroup.mAnimState->setTimePosition(time);
|
||||||
if(mNonAccumRoot)
|
if(mNonAccumRoot)
|
||||||
{
|
{
|
||||||
/* Update the animation and get the non-accumulation root's difference from the
|
/* Update the animation and get the non-accumulation root's difference from the
|
||||||
* last update. */
|
* last update. */
|
||||||
mEntityList.mSkelBase->getSkeleton()->setAnimationState(*mAnimState->getParent());
|
mEntityList.mSkelBase->getSkeleton()->setAnimationState(*mCurGroup.mAnimState->getParent());
|
||||||
Ogre::Vector3 posdiff = mNonAccumRoot->getPosition() - mLastPosition;
|
Ogre::Vector3 posdiff = mNonAccumRoot->getPosition() - mLastPosition;
|
||||||
|
|
||||||
/* Translate the accumulation root back to compensate for the move. */
|
/* Translate the accumulation root back to compensate for the move. */
|
||||||
|
@ -118,10 +115,10 @@ void Animation::updatePosition(float time)
|
||||||
|
|
||||||
void Animation::resetPosition(float time)
|
void Animation::resetPosition(float time)
|
||||||
{
|
{
|
||||||
mAnimState->setTimePosition(time);
|
mCurGroup.mAnimState->setTimePosition(time);
|
||||||
if(mNonAccumRoot)
|
if(mNonAccumRoot)
|
||||||
{
|
{
|
||||||
mEntityList.mSkelBase->getSkeleton()->setAnimationState(*mAnimState->getParent());
|
mEntityList.mSkelBase->getSkeleton()->setAnimationState(*mCurGroup.mAnimState->getParent());
|
||||||
mLastPosition = mNonAccumRoot->getPosition();
|
mLastPosition = mNonAccumRoot->getPosition();
|
||||||
mAccumRoot->setPosition(mStartPosition - mLastPosition);
|
mAccumRoot->setPosition(mStartPosition - mLastPosition);
|
||||||
}
|
}
|
||||||
|
@ -162,24 +159,27 @@ bool Animation::findGroupTimes(const std::string &groupname, Animation::GroupTim
|
||||||
|
|
||||||
void Animation::playGroup(std::string groupname, int mode, int loops)
|
void Animation::playGroup(std::string groupname, int mode, int loops)
|
||||||
{
|
{
|
||||||
if(mTextKeys.size() == 0)
|
|
||||||
{
|
|
||||||
std::cerr<< "Trying to animate an unanimate object" <<std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
GroupTimes times(mTextKeys.end());
|
GroupTimes times(mTextKeys.end());
|
||||||
times.mLoops = loops;
|
|
||||||
|
|
||||||
std::transform(groupname.begin(), groupname.end(), groupname.begin(), ::tolower);
|
try {
|
||||||
if(groupname == "all")
|
if(mTextKeys.size() == 0)
|
||||||
{
|
throw std::runtime_error("Trying to animate an unanimate object");
|
||||||
times.mStart = times.mLoopStart = mTextKeys.begin();
|
|
||||||
times.mLoopStop = times.mStop = mTextKeys.end();
|
std::transform(groupname.begin(), groupname.end(), groupname.begin(), ::tolower);
|
||||||
times.mLoopStop--; times.mStop--;
|
times.mAnimState = mEntityList.mSkelBase->getAnimationState(groupname);
|
||||||
|
times.mLoops = loops;
|
||||||
|
|
||||||
|
if(groupname == "all")
|
||||||
|
{
|
||||||
|
times.mStart = times.mLoopStart = mTextKeys.begin();
|
||||||
|
times.mLoopStop = times.mStop = mTextKeys.end();
|
||||||
|
times.mLoopStop--; times.mStop--;
|
||||||
|
}
|
||||||
|
else if(!findGroupTimes(groupname, ×))
|
||||||
|
throw std::runtime_error("Failed to find animation group "+groupname);
|
||||||
}
|
}
|
||||||
else if(!findGroupTimes(groupname, ×))
|
catch(std::exception &e) {
|
||||||
{
|
std::cerr<< e.what() <<std::endl;
|
||||||
std::cerr<< "Failed to find animation group "<<groupname <<std::endl;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,9 +187,12 @@ void Animation::playGroup(std::string groupname, int mode, int loops)
|
||||||
mNextGroup = times;
|
mNextGroup = times;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if(mCurGroup.mAnimState)
|
||||||
|
mCurGroup.mAnimState->setEnabled(false);
|
||||||
mCurGroup = times;
|
mCurGroup = times;
|
||||||
mNextGroup = GroupTimes(mTextKeys.end());
|
mNextGroup = GroupTimes(mTextKeys.end());
|
||||||
mTime = ((mode==2) ? mCurGroup.mLoopStart : mCurGroup.mStart)->first;
|
mTime = ((mode==2) ? mCurGroup.mLoopStart : mCurGroup.mStart)->first;
|
||||||
|
mCurGroup.mAnimState->setEnabled(true);
|
||||||
resetPosition(mTime);
|
resetPosition(mTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,7 +204,7 @@ void Animation::skipAnim()
|
||||||
|
|
||||||
void Animation::runAnimation(float timepassed)
|
void Animation::runAnimation(float timepassed)
|
||||||
{
|
{
|
||||||
if(mAnimState && !mSkipFrame)
|
if(mCurGroup.mAnimState && !mSkipFrame)
|
||||||
{
|
{
|
||||||
mTime += timepassed;
|
mTime += timepassed;
|
||||||
recheck:
|
recheck:
|
||||||
|
@ -221,9 +224,11 @@ void Animation::runAnimation(float timepassed)
|
||||||
{
|
{
|
||||||
updatePosition(mCurGroup.mStop->first);
|
updatePosition(mCurGroup.mStop->first);
|
||||||
mTime = mTime - mCurGroup.mStop->first + mNextGroup.mStart->first;
|
mTime = mTime - mCurGroup.mStop->first + mNextGroup.mStart->first;
|
||||||
resetPosition(mNextGroup.mStart->first);
|
mCurGroup.mAnimState->setEnabled(false);
|
||||||
mCurGroup = mNextGroup;
|
mCurGroup = mNextGroup;
|
||||||
mNextGroup = GroupTimes(mTextKeys.end());
|
mNextGroup = GroupTimes(mTextKeys.end());
|
||||||
|
mCurGroup.mAnimState->setEnabled(true);
|
||||||
|
resetPosition(mNextGroup.mStart->first);
|
||||||
goto recheck;
|
goto recheck;
|
||||||
}
|
}
|
||||||
mTime = mCurGroup.mStop->first;
|
mTime = mCurGroup.mStop->first;
|
||||||
|
|
|
@ -16,11 +16,12 @@ class Animation
|
||||||
NifOgre::TextKeyMap::const_iterator mLoopStart;
|
NifOgre::TextKeyMap::const_iterator mLoopStart;
|
||||||
NifOgre::TextKeyMap::const_iterator mLoopStop;
|
NifOgre::TextKeyMap::const_iterator mLoopStop;
|
||||||
|
|
||||||
|
Ogre::AnimationState *mAnimState;
|
||||||
size_t mLoops;
|
size_t mLoops;
|
||||||
|
|
||||||
GroupTimes(NifOgre::TextKeyMap::const_iterator iter)
|
GroupTimes(NifOgre::TextKeyMap::const_iterator iter)
|
||||||
: mStart(iter), mStop(iter), mLoopStart(iter), mLoopStop(iter),
|
: mStart(iter), mStop(iter), mLoopStart(iter), mLoopStop(iter),
|
||||||
mLoops(0)
|
mAnimState(NULL), mLoops(0)
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -38,7 +39,6 @@ protected:
|
||||||
float mTime;
|
float mTime;
|
||||||
GroupTimes mCurGroup;
|
GroupTimes mCurGroup;
|
||||||
GroupTimes mNextGroup;
|
GroupTimes mNextGroup;
|
||||||
Ogre::AnimationState *mAnimState;
|
|
||||||
|
|
||||||
bool mSkipFrame;
|
bool mSkipFrame;
|
||||||
|
|
||||||
|
|
|
@ -410,7 +410,45 @@ void loadResource(Ogre::Resource *resource)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextKeyMap textkeys;
|
||||||
|
Ogre::Skeleton::BoneIterator boneiter = skel->getBoneIterator();
|
||||||
|
while(boneiter.hasMoreElements())
|
||||||
|
{
|
||||||
|
Ogre::Bone *bone = boneiter.peekNext();
|
||||||
|
const Ogre::Any &data = bone->getUserObjectBindings().getUserAny(sTextKeyExtraDataID);
|
||||||
|
if(!data.isEmpty())
|
||||||
|
{
|
||||||
|
textkeys = Ogre::any_cast<NifOgre::TextKeyMap>(data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
boneiter.moveNext();
|
||||||
|
}
|
||||||
|
|
||||||
buildAnimation(skel, "all", ctrls, targets, 0.0f, std::numeric_limits<float>::max());
|
buildAnimation(skel, "all", ctrls, targets, 0.0f, std::numeric_limits<float>::max());
|
||||||
|
|
||||||
|
std::string currentgroup;
|
||||||
|
TextKeyMap::const_iterator keyiter = textkeys.begin();
|
||||||
|
for(keyiter = textkeys.begin();keyiter != textkeys.end();keyiter++)
|
||||||
|
{
|
||||||
|
std::string::size_type sep = keyiter->second.find(':');
|
||||||
|
if(sep == currentgroup.length() && keyiter->second.compare(0, sep, currentgroup) == 0)
|
||||||
|
continue;
|
||||||
|
currentgroup = keyiter->second.substr(0, sep);
|
||||||
|
|
||||||
|
if(skel->hasAnimation(currentgroup))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
TextKeyMap::const_reverse_iterator lastkeyiter = textkeys.rbegin();
|
||||||
|
while(lastkeyiter->first > keyiter->first)
|
||||||
|
{
|
||||||
|
if(lastkeyiter->second.find(':') == currentgroup.length() &&
|
||||||
|
lastkeyiter->second.compare(0, currentgroup.length(), currentgroup) == 0)
|
||||||
|
break;
|
||||||
|
lastkeyiter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildAnimation(skel, currentgroup, ctrls, targets, keyiter->first, lastkeyiter->first);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool createSkeleton(const std::string &name, const std::string &group, const Nif::Node *node)
|
bool createSkeleton(const std::string &name, const std::string &group, const Nif::Node *node)
|
||||||
|
|
Loading…
Reference in a new issue