diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 4e33873d32..4448360bd1 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -23,7 +23,6 @@ Animation::Animation(const MWWorld::Ptr &ptr) , mTime(0.0f) , mCurGroup(mTextKeys.end()) , mNextGroup(mTextKeys.end()) - , mAnimState(NULL) , mSkipFrame(false) { } @@ -80,10 +79,8 @@ void Animation::createEntityList(Ogre::SceneNode *node, const std::string &model while(as.hasMoreElements()) { Ogre::AnimationState *state = as.getNext(); - state->setEnabled(true); + state->setEnabled(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) { - mAnimState->setTimePosition(time); + mCurGroup.mAnimState->setTimePosition(time); if(mNonAccumRoot) { /* Update the animation and get the non-accumulation root's difference from the * last update. */ - mEntityList.mSkelBase->getSkeleton()->setAnimationState(*mAnimState->getParent()); + mEntityList.mSkelBase->getSkeleton()->setAnimationState(*mCurGroup.mAnimState->getParent()); Ogre::Vector3 posdiff = mNonAccumRoot->getPosition() - mLastPosition; /* Translate the accumulation root back to compensate for the move. */ @@ -118,10 +115,10 @@ void Animation::updatePosition(float time) void Animation::resetPosition(float time) { - mAnimState->setTimePosition(time); + mCurGroup.mAnimState->setTimePosition(time); if(mNonAccumRoot) { - mEntityList.mSkelBase->getSkeleton()->setAnimationState(*mAnimState->getParent()); + mEntityList.mSkelBase->getSkeleton()->setAnimationState(*mCurGroup.mAnimState->getParent()); mLastPosition = mNonAccumRoot->getPosition(); 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) { - if(mTextKeys.size() == 0) - { - std::cerr<< "Trying to animate an unanimate object" <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, ×)) - { - std::cerr<< "Failed to find animation group "<setEnabled(false); mCurGroup = times; mNextGroup = GroupTimes(mTextKeys.end()); mTime = ((mode==2) ? mCurGroup.mLoopStart : mCurGroup.mStart)->first; + mCurGroup.mAnimState->setEnabled(true); resetPosition(mTime); } } @@ -201,7 +204,7 @@ void Animation::skipAnim() void Animation::runAnimation(float timepassed) { - if(mAnimState && !mSkipFrame) + if(mCurGroup.mAnimState && !mSkipFrame) { mTime += timepassed; recheck: @@ -221,9 +224,11 @@ void Animation::runAnimation(float timepassed) { updatePosition(mCurGroup.mStop->first); mTime = mTime - mCurGroup.mStop->first + mNextGroup.mStart->first; - resetPosition(mNextGroup.mStart->first); + mCurGroup.mAnimState->setEnabled(false); mCurGroup = mNextGroup; mNextGroup = GroupTimes(mTextKeys.end()); + mCurGroup.mAnimState->setEnabled(true); + resetPosition(mNextGroup.mStart->first); goto recheck; } mTime = mCurGroup.mStop->first; diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 44a2eaf3ee..e84ebb3585 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -16,11 +16,12 @@ class Animation NifOgre::TextKeyMap::const_iterator mLoopStart; NifOgre::TextKeyMap::const_iterator mLoopStop; + Ogre::AnimationState *mAnimState; size_t mLoops; GroupTimes(NifOgre::TextKeyMap::const_iterator iter) : mStart(iter), mStop(iter), mLoopStart(iter), mLoopStop(iter), - mLoops(0) + mAnimState(NULL), mLoops(0) { } }; @@ -38,7 +39,6 @@ protected: float mTime; GroupTimes mCurGroup; GroupTimes mNextGroup; - Ogre::AnimationState *mAnimState; bool mSkipFrame; diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 803496bf9e..c4846cdfd9 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -410,7 +410,45 @@ void loadResource(Ogre::Resource *resource) 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(data); + break; + } + boneiter.moveNext(); + } + buildAnimation(skel, "all", ctrls, targets, 0.0f, std::numeric_limits::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)