From 6b8a687a7914f029669595998f799c991d8e8389 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 10 May 2013 22:22:39 -0700 Subject: [PATCH] Add methods to disable an animation And rename WeaponState to WeaponType --- apps/openmw/mwmechanics/character.cpp | 81 +++++++++++------------ apps/openmw/mwmechanics/character.hpp | 26 +++----- apps/openmw/mwrender/animation.cpp | 19 +++++- apps/openmw/mwrender/animation.hpp | 12 +++- apps/openmw/mwrender/characterpreview.cpp | 7 +- 5 files changed, 81 insertions(+), 64 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 5f4faeb12..85e27e3ca 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -92,21 +92,21 @@ static const struct { static const size_t sStateListSize = sizeof(sStateList)/sizeof(sStateList[0]); static const struct { - WeaponState state; + WeaponType type; const char idlegroup[16]; const char movementgroup[16]; const char actiongroup[16]; -} sWeaponStateList[] = { - { WeapState_HandToHand, "hh", "hh", "handtohand" }, - { WeapState_OneHand, "1h", "1h", "weapononehand" }, - { WeapState_TwoHand, "2c", "2c", "weapontwohand" }, - { WeapState_TwoWide, "2w", "2w", "weapontwowide" }, - { WeapState_BowAndArrow, "1h", "1h", "bowandarrow" }, - { WeapState_Crossbow, "crossbow", "2c", "crossbow" }, - { WeapState_ThowWeapon, "1h", "1h", "throwweapon" }, - { WeapState_Spell, "spell", "", "spellcast" }, +} sWeaponTypeList[] = { + { WeapType_HandToHand, "hh", "hh", "handtohand" }, + { WeapType_OneHand, "1h", "1h", "weapononehand" }, + { WeapType_TwoHand, "2c", "2c", "weapontwohand" }, + { WeapType_TwoWide, "2w", "2w", "weapontwowide" }, + { WeapType_BowAndArrow, "1h", "1h", "bowandarrow" }, + { WeapType_Crossbow, "crossbow", "2c", "crossbow" }, + { WeapType_ThowWeapon, "1h", "1h", "throwweapon" }, + { WeapType_Spell, "spell", "", "spellcast" }, }; -static const size_t sWeaponStateListSize = sizeof(sWeaponStateList)/sizeof(sWeaponStateList[0]); +static const size_t sWeaponTypeListSize = sizeof(sWeaponTypeList)/sizeof(sWeaponTypeList[0]); void CharacterController::getCurrentGroup(std::string &group) const @@ -123,16 +123,16 @@ void CharacterController::getCurrentGroup(std::string &group) const if(name.empty()) throw std::runtime_error("Failed to find character state "+Ogre::StringConverter::toString(mCharState)); - if(!(mCharState >= CharState_Death1) && mWeapState != WeapState_None) + if(!(mCharState >= CharState_Death1) && mWeaponType != WeapType_None) { - for(size_t i = 0;i < sWeaponStateListSize;i++) + for(size_t i = 0;i < sWeaponTypeListSize;i++) { - if(sWeaponStateList[i].state == mWeapState) + if(sWeaponTypeList[i].type == mWeaponType) { if(mCharState == CharState_Idle) - (group=name) += sWeaponStateList[i].idlegroup; + (group=name) += sWeaponTypeList[i].idlegroup; else - (group=name) += sWeaponStateList[i].movementgroup; + (group=name) += sWeaponTypeList[i].movementgroup; break; } } @@ -147,7 +147,7 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim : mPtr(ptr) , mAnimation(anim) , mCharState(state) - , mWeapState(WeapState_None) + , mWeaponType(WeapType_None) , mSkipAnim(false) , mMovingAnim(false) , mSecondsOfRunning(0) @@ -172,7 +172,7 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim std::string group; getCurrentGroup(group); mMovingAnim = mAnimation->play(group, MWRender::Animation::Priority_Default, - MWRender::Animation::Group_All, + MWRender::Animation::Group_All, false, "start", "stop", 1.0f, loop ? (~(size_t)0) : 0); } @@ -229,21 +229,21 @@ void CharacterController::update(float duration, Movement &movement) if(mPtr.getTypeName() == typeid(ESM::NPC).name()) { NpcStats &stats = cls.getNpcStats(mPtr); - WeaponState weapstate = WeapState_None; + WeaponType weaptype = WeapType_None; if(stats.getDrawState() == DrawState_Spell) - weapstate = WeapState_Spell; + weaptype = WeapType_Spell; else if(stats.getDrawState() == MWMechanics::DrawState_Weapon) { MWWorld::InventoryStore &inv = cls.getInventoryStore(mPtr); MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); if(weapon == inv.end()) - weapstate = WeapState_HandToHand; + weaptype = WeapType_HandToHand; else { const std::string &type = weapon->getTypeName(); if(type == typeid(ESM::Lockpick).name() || type == typeid(ESM::Probe).name()) - weapstate = WeapState_OneHand; + weaptype = WeapType_OneHand; else if(type == typeid(ESM::Weapon).name()) { MWWorld::LiveCellRef *ref = weapon->get(); @@ -256,32 +256,36 @@ void CharacterController::update(float duration, Movement &movement) case ESM::Weapon::AxeOneHand: case ESM::Weapon::Arrow: case ESM::Weapon::Bolt: - weapstate = WeapState_OneHand; + weaptype = WeapType_OneHand; break; case ESM::Weapon::LongBladeTwoHand: case ESM::Weapon::BluntTwoClose: case ESM::Weapon::AxeTwoHand: - weapstate = WeapState_TwoHand; + weaptype = WeapType_TwoHand; break; case ESM::Weapon::BluntTwoWide: case ESM::Weapon::SpearTwoWide: - weapstate = WeapState_TwoWide; + weaptype = WeapType_TwoWide; break; case ESM::Weapon::MarksmanBow: - weapstate = WeapState_BowAndArrow; + weaptype = WeapType_BowAndArrow; break; case ESM::Weapon::MarksmanCrossbow: - weapstate = WeapState_Crossbow; + weaptype = WeapType_Crossbow; break; case ESM::Weapon::MarksmanThrown: - weapstate = WeapState_ThowWeapon; + weaptype = WeapType_ThowWeapon; break; } } } } - setWeaponState(weapstate); + if(weaptype != mWeaponType) + { + mWeaponType = weaptype; + forceStateUpdate(); + } } /* FIXME: The state should be set to Jump, and X/Y movement should be disallowed except @@ -349,7 +353,7 @@ void CharacterController::update(float duration, Movement &movement) { mMovingAnim = mAnimation->play(mAnimQueue.front().first, MWRender::Animation::Priority_Default, - MWRender::Animation::Group_All, + MWRender::Animation::Group_All, false, "start", "stop", 0.0f, mAnimQueue.front().second); mAnimQueue.pop_front(); @@ -386,7 +390,7 @@ void CharacterController::playGroup(const std::string &groupname, int mode, int mCharState = CharState_SpecialIdle; mLooping = false; mMovingAnim = mAnimation->play(groupname, MWRender::Animation::Priority_Default, - MWRender::Animation::Group_All, + MWRender::Animation::Group_All, false, ((mode==2) ? "loop start" : "start"), "stop", 0.0f, count-1); } else if(mode == 0) @@ -413,15 +417,6 @@ void CharacterController::setState(CharacterState state, bool loop) forceStateUpdate(); } -void CharacterController::setWeaponState(WeaponState state) -{ - if(state == mWeapState) - return; - mWeapState = state; - - forceStateUpdate(); -} - void CharacterController::forceStateUpdate() { if(!mAnimation) @@ -431,11 +426,11 @@ void CharacterController::forceStateUpdate() std::string group; getCurrentGroup(group); mMovingAnim = mAnimation->play(group, MWRender::Animation::Priority_Default, - MWRender::Animation::Group_All, + MWRender::Animation::Group_All, false, "start", "stop", 0.0f, mLooping ? (~(size_t)0) : 0); - mAnimation->showWeapons(mWeapState != WeapState_None && mWeapState != WeapState_HandToHand && - mWeapState != WeapState_Spell); + mAnimation->showWeapons(mWeaponType != WeapType_None && mWeaponType != WeapType_HandToHand && + mWeaponType != WeapType_Spell); } } diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 64e19e51f..1d7ae33ed 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -67,18 +67,18 @@ enum CharacterState { CharState_Death5 }; -enum WeaponState { - WeapState_None, +enum WeaponType { + WeapType_None, - WeapState_HandToHand, - WeapState_OneHand, - WeapState_TwoHand, - WeapState_TwoWide, - WeapState_BowAndArrow, - WeapState_Crossbow, - WeapState_ThowWeapon, + WeapType_HandToHand, + WeapType_OneHand, + WeapType_TwoHand, + WeapType_TwoWide, + WeapType_BowAndArrow, + WeapType_Crossbow, + WeapType_ThowWeapon, - WeapState_Spell + WeapType_Spell }; class CharacterController @@ -90,7 +90,7 @@ class CharacterController AnimationQueue mAnimQueue; CharacterState mCharState; - WeaponState mWeapState; + WeaponType mWeaponType; bool mLooping; bool mSkipAnim; @@ -118,10 +118,6 @@ public: CharacterState getState() const { return mCharState; } - void setWeaponState(WeaponState state); - WeaponState getWeaponState() const - { return mWeapState; } - void forceStateUpdate(); }; diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 8a4dba521..58be60a45 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -481,7 +481,7 @@ bool Animation::handleTextKey(AnimState &state, const std::string &groupname, co } -bool Animation::play(const std::string &groupname, Priority priority, int groups, const std::string &start, const std::string &stop, float startpoint, size_t loops) +bool Animation::play(const std::string &groupname, Priority priority, int groups, bool autodisable, const std::string &start, const std::string &stop, float startpoint, size_t loops) { if(!mSkelBase) return false; @@ -517,6 +517,7 @@ bool Animation::play(const std::string &groupname, Priority priority, int groups state.mPlaying = true; state.mPriority = priority; state.mGroups = groups; + state.mAutoDisable = autodisable; mStates[groupname] = state; break; @@ -617,13 +618,22 @@ bool Animation::getInfo(const std::string &groupname, float *complete, std::stri } +bool Animation::disable(const std::string &groupname) +{ + AnimStateMap::iterator iter = mStates.find(groupname); + if(iter != mStates.end()) + mStates.erase(iter); + return resetActiveGroups(); +} + + Ogre::Vector3 Animation::runAnimation(float duration) { Ogre::Vector3 movement(0.0f); duration *= mAnimSpeedMult; AnimStateMap::iterator stateiter = mStates.begin(); - for(;stateiter != mStates.end();stateiter++) + while(stateiter != mStates.end()) { AnimState &state = stateiter->second; float timepassed = duration; @@ -649,6 +659,11 @@ Ogre::Vector3 Animation::runAnimation(float duration) if(!handleTextKey(state, stateiter->first, key)) break; } + + if(!state.mPlaying && state.mAutoDisable) + mStates.erase(stateiter++); + else + stateiter++; } for(size_t i = 0;i < mObjectRoot.mControllers.size();i++) diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 747db0fe5..966786245 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -73,6 +73,7 @@ protected: int mPriority; int mGroups; + bool mAutoDisable; AnimState() : mSource(NULL), mTime(0.0f), mPlaying(false), mLoopCount(0) { } @@ -162,6 +163,8 @@ public: * bone groups that don't have another animation set of a * higher priority. * \param groups Bone groups to play the animation on. + * \param autodisable Automatically disable the animation when it stops + * playing. * \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 @@ -172,7 +175,7 @@ public: * \return Boolean specifying whether the animation will return movement * for the character at all. */ - bool play(const std::string &groupname, Priority priority, int groups, + bool play(const std::string &groupname, Priority priority, int groups, bool autodisable, const std::string &start, const std::string &stop, float startpoint, size_t loops); @@ -185,6 +188,13 @@ public: */ bool getInfo(const std::string &groupname, float *complete=NULL, std::string *start=NULL, std::string *stop=NULL) const; + /** Disables the specified animation group; + * \param groupname Animation group to disable. + * \return Boolean specifying whether the animation will continue to return + * movement for the character at all. + */ + bool disable(const std::string &groupname); + virtual Ogre::Vector3 runAnimation(float duration); virtual void showWeapons(bool showWeapon); diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 6156eb8cc..b1c74a771 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -173,7 +173,7 @@ namespace MWRender { mCurrentAnimGroup = groupname; mAnimation->play(mCurrentAnimGroup, Animation::Priority_Default, - Animation::Group_All, "start", "stop", 0.0f, 0); + Animation::Group_All, false, "start", "stop", 0.0f, 0); } mAnimation->forceUpdate(); @@ -201,7 +201,7 @@ namespace MWRender mCurrentAnimGroup = "inventoryhandtohand"; mAnimation->play(mCurrentAnimGroup, Animation::Priority_Default, - Animation::Group_All, "start", "stop", 0.0f, 0); + Animation::Group_All, false, "start", "stop", 0.0f, 0); } // -------------------------------------------------------------------------------------------------- @@ -235,7 +235,8 @@ namespace MWRender void RaceSelectionPreview::onSetup () { - mAnimation->play("idle", Animation::Priority_Default, Animation::Group_All, "start", "stop", 0.0f, 0); + mAnimation->play("idle", Animation::Priority_Default, Animation::Group_All, + false, "start", "stop", 0.0f, 0); updateCamera(); }