diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 2f234db7b..b73283e7c 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -547,6 +547,7 @@ bool CharacterController::updateWeaponState() { getWeaponGroup(weaptype, weapgroup); mAnimation->showWeapons(false); + mAnimation->setWeaponGroup(weapgroup); mAnimation->play(weapgroup, Priority_Weapon, MWRender::Animation::Group_UpperBody, true, diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index ba729e3da..5417f1820 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -870,6 +870,27 @@ bool Animation::getInfo(const std::string &groupname, float *complete, float *sp return true; } +float Animation::getStartTime(const std::string &groupname) const +{ + AnimSourceList::const_iterator iter(mAnimSources.begin()); + for(;iter != mAnimSources.end();iter++) + { + const NifOgre::TextKeyMap &keys = (*iter)->mTextKeys; + NifOgre::TextKeyMap::const_iterator found = findGroupStart(keys, groupname); + if(found != keys.end()) + return found->first; + } + return -1.f; +} + +float Animation::getCurrentTime(const std::string &groupname) const +{ + AnimStateMap::const_iterator iter = mStates.find(groupname); + if(iter == mStates.end()) + return -1.f; + + return iter->second.mTime; +} void Animation::disable(const std::string &groupname) { diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index da1c1628c..27778d373 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -271,12 +271,20 @@ public: */ bool getInfo(const std::string &groupname, float *complete=NULL, float *speedmult=NULL) const; + /// Get the absolute position in the animation track of the first text key with the given group. + float getStartTime(const std::string &groupname) const; + + /// Get the current absolute position in the animation track for the animation that is currently playing from the given group. + float getCurrentTime(const std::string& groupname) const; + /** Disables the specified animation group; * \param groupname Animation group to disable. */ void disable(const std::string &groupname); void changeGroups(const std::string &groupname, int group); + virtual void setWeaponGroup(const std::string& group) {} + /** Retrieves the velocity (in units per second) that the animation will move. */ float getVelocity(const std::string &groupname) const; diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index bcb6a374c..531d90162 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -71,6 +71,27 @@ float HeadAnimationTime::getValue() const return 1; } +float WeaponAnimationTime::getValue() const +{ + if (mWeaponGroup.empty()) + return 0; + float current = mAnimation->getCurrentTime(mWeaponGroup); + if (current == -1) + return 0; + return current - mStartTime; +} + +void WeaponAnimationTime::setGroup(const std::string &group) +{ + mWeaponGroup = group; + mStartTime = mAnimation->getStartTime(mWeaponGroup); +} + +void WeaponAnimationTime::updateStartTime() +{ + setGroup(mWeaponGroup); +} + static NpcAnimation::PartBoneMap createPartListMap() { NpcAnimation::PartBoneMap result; @@ -126,6 +147,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int v mNpc = mPtr.get()->mBase; mHeadAnimationTime = Ogre::SharedPtr(new HeadAnimationTime(mPtr)); + mWeaponAnimationTime = Ogre::SharedPtr(new WeaponAnimationTime(this)); for(size_t i = 0;i < ESM::PRT_Count;i++) { @@ -223,6 +245,8 @@ void NpcAnimation::updateNpcBase() for(size_t i = 0;i < ESM::PRT_Count;i++) removeIndividualPart((ESM::PartReferenceType)i); updateParts(); + + mWeaponAnimationTime->updateStartTime(); } void NpcAnimation::updateParts() @@ -588,9 +612,6 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g updateSkeletonInstance(mSkelBase->getSkeleton(), skel); } - // TODO: - // type == ESM::PRT_Weapon should get an animation source based on the current offset - // of the weapon attack animation (from its beginning, or start marker?) std::vector >::iterator ctrl(mObjectParts[type]->mControllers.begin()); for(;ctrl != mObjectParts[type]->mControllers.end();ctrl++) { @@ -600,6 +621,8 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g if (type == ESM::PRT_Head) ctrl->setSource(mHeadAnimationTime); + else if (type == ESM::PRT_Weapon) + ctrl->setSource(mWeaponAnimationTime); } } diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index e86ec7d4e..1dd0b41e6 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -25,6 +25,23 @@ public: { } }; +class WeaponAnimationTime : public Ogre::ControllerValue +{ +private: + Animation* mAnimation; + std::string mWeaponGroup; + float mStartTime; +public: + WeaponAnimationTime(Animation* animation) : mAnimation(animation), mStartTime(0) {} + void setGroup(const std::string& group); + void updateStartTime(); + + virtual Ogre::Real getValue() const; + virtual void setValue(Ogre::Real value) + { } +}; + + class NpcAnimation : public Animation, public MWWorld::InventoryStoreListener { public: @@ -71,6 +88,7 @@ private: Ogre::Vector3 mFirstPersonOffset; Ogre::SharedPtr mHeadAnimationTime; + Ogre::SharedPtr mWeaponAnimationTime; float mAlpha; @@ -105,6 +123,8 @@ public: ViewMode viewMode=VM_Normal); virtual ~NpcAnimation(); + virtual void setWeaponGroup(const std::string& group) { mWeaponAnimationTime->setGroup(group); } + virtual Ogre::Vector3 runAnimation(float timepassed); virtual void showWeapons(bool showWeapon);