diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index bd15b6a73..8f813ceb1 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1051,6 +1051,9 @@ bool CharacterController::updateWeaponState() } } + MWRender::Animation::AnimPriority priorityWeapon(Priority_Weapon); + priorityWeapon.mPriority[MWRender::Animation::BoneGroup_LowerBody] = 0; + bool forcestateupdate = false; if(weaptype != mWeaponType && mHitState != CharState_KnockDown && mHitState != CharState_KnockOut && mHitState != CharState_Hit) @@ -1063,8 +1066,8 @@ bool CharacterController::updateWeaponState() if(weaptype == WeapType_None) { getWeaponGroup(mWeaponType, weapgroup); - mAnimation->play(weapgroup, Priority_Weapon, - MWRender::Animation::BlendMask_UpperBody, true, + mAnimation->play(weapgroup, priorityWeapon, + MWRender::Animation::BlendMask_All, true, 1.0f, "unequip start", "unequip stop", 0.0f, 0); mUpperBodyState = UpperCharState_UnEquipingWeap; } @@ -1074,8 +1077,8 @@ bool CharacterController::updateWeaponState() mAnimation->showWeapons(false); mAnimation->setWeaponGroup(weapgroup); - mAnimation->play(weapgroup, Priority_Weapon, - MWRender::Animation::BlendMask_UpperBody, true, + mAnimation->play(weapgroup, priorityWeapon, + MWRender::Animation::BlendMask_All, true, 1.0f, "equip start", "equip stop", 0.0f, 0); mUpperBodyState = UpperCharState_EquipingWeap; @@ -1191,8 +1194,8 @@ bool CharacterController::updateWeaponState() case 2: mAttackType = "target"; break; } - mAnimation->play(mCurrentWeapon, Priority_Weapon, - MWRender::Animation::BlendMask_UpperBody, true, + mAnimation->play(mCurrentWeapon, priorityWeapon, + MWRender::Animation::BlendMask_All, true, weapSpeed, mAttackType+" start", mAttackType+" stop", 0.0f, 0); mUpperBodyState = UpperCharState_CastingSpell; @@ -1223,8 +1226,8 @@ bool CharacterController::updateWeaponState() else if(item.getTypeName() == typeid(ESM::Probe).name()) Security(mPtr).probeTrap(target, item, resultMessage, resultSound); } - mAnimation->play(mCurrentWeapon, Priority_Weapon, - MWRender::Animation::BlendMask_UpperBody, true, + mAnimation->play(mCurrentWeapon, priorityWeapon, + MWRender::Animation::BlendMask_All, true, 1.0f, "start", "stop", 0.0, 0); mUpperBodyState = UpperCharState_FollowStartToFollowStop; @@ -1250,8 +1253,8 @@ bool CharacterController::updateWeaponState() determineAttackType(); } - mAnimation->play(mCurrentWeapon, Priority_Weapon, - MWRender::Animation::BlendMask_UpperBody, false, + mAnimation->play(mCurrentWeapon, priorityWeapon, + MWRender::Animation::BlendMask_All, false, weapSpeed, mAttackType+" start", mAttackType+" min attack", 0.0f, 0); mUpperBodyState = UpperCharState_StartToMinAttack; @@ -1301,8 +1304,8 @@ bool CharacterController::updateWeaponState() mAttackStrength = attackStrength; mAnimation->disable(mCurrentWeapon); - mAnimation->play(mCurrentWeapon, Priority_Weapon, - MWRender::Animation::BlendMask_UpperBody, false, + mAnimation->play(mCurrentWeapon, priorityWeapon, + MWRender::Animation::BlendMask_All, false, weapSpeed, mAttackType+" max attack", mAttackType+" min hit", 1.0f-complete, 0); @@ -1397,8 +1400,8 @@ bool CharacterController::updateWeaponState() case UpperCharState_MinAttackToMaxAttack: //hack to avoid body pos desync when jumping/sneaking in 'max attack' state if(!mAnimation->isPlaying(mCurrentWeapon)) - mAnimation->play(mCurrentWeapon, Priority_Weapon, - MWRender::Animation::BlendMask_UpperBody, false, + mAnimation->play(mCurrentWeapon, priorityWeapon, + MWRender::Animation::BlendMask_All, false, 0, mAttackType+" min attack", mAttackType+" max attack", 0.999f, 0); break; case UpperCharState_MaxAttackToMinHit: @@ -1440,33 +1443,16 @@ bool CharacterController::updateWeaponState() { mAnimation->disable(mCurrentWeapon); if (mUpperBodyState == UpperCharState_FollowStartToFollowStop) - mAnimation->play(mCurrentWeapon, Priority_Weapon, - MWRender::Animation::BlendMask_UpperBody, true, + mAnimation->play(mCurrentWeapon, priorityWeapon, + MWRender::Animation::BlendMask_All, true, weapSpeed, start, stop, 0.0f, 0); else - mAnimation->play(mCurrentWeapon, Priority_Weapon, - MWRender::Animation::BlendMask_UpperBody, false, + mAnimation->play(mCurrentWeapon, priorityWeapon, + MWRender::Animation::BlendMask_All, false, weapSpeed, start, stop, 0.0f, 0); } } - //if playing combat animation and lowerbody is not busy switch to whole body animation - if((weaptype != WeapType_None || mUpperBodyState == UpperCharState_UnEquipingWeap) && animPlaying) - { - if( mMovementState != CharState_None || - mJumpState != JumpState_None || - mHitState != CharState_None || - MWBase::Environment::get().getWorld()->isSwimming(mPtr) || - cls.getCreatureStats(mPtr).getMovementFlag(CreatureStats::Flag_Sneak)) - { - mAnimation->changeBlendMask(mCurrentWeapon, MWRender::Animation::BlendMask_UpperBody); - } - else - { - mAnimation->changeBlendMask(mCurrentWeapon, MWRender::Animation::BlendMask_All); - } - } - if (mPtr.getClass().hasInventoryStore(mPtr)) { MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr); diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 90d2a68a3..35c0b5346 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -67,9 +67,15 @@ typedef boost::shared_ptr PartHolderPtr; class Animation { public: + enum BoneGroup { + BoneGroup_LowerBody = 0, + BoneGroup_Torso, + BoneGroup_LeftArm, + BoneGroup_RightArm + }; + enum BlendMask { BlendMask_LowerBody = 1<<0, - BlendMask_Torso = 1<<1, BlendMask_LeftArm = 1<<2, BlendMask_RightArm = 1<<3, @@ -78,47 +84,10 @@ public: BlendMask_All = BlendMask_LowerBody | BlendMask_UpperBody }; - - class TextKeyListener - { - public: - virtual void handleTextKey(const std::string &groupname, const std::multimap::const_iterator &key, - const std::multimap& map) = 0; - }; - - void setTextKeyListener(TextKeyListener* listener); - -protected: - /* This is the number of *discrete* groups. */ + /* This is the number of *discrete* blend masks. */ static const size_t sNumBlendMasks = 4; - class AnimationTime : public SceneUtil::ControllerSource - { - private: - boost::shared_ptr mTimePtr; - - public: - - void setTimePtr(boost::shared_ptr time) - { mTimePtr = time; } - boost::shared_ptr getTimePtr() const - { return mTimePtr; } - - virtual float getValue(osg::NodeVisitor* nv); - }; - - class NullAnimationTime : public SceneUtil::ControllerSource - { - public: - virtual float getValue(osg::NodeVisitor *nv) - { - return 0.f; - } - }; - - struct AnimSource; - - /// Holds an animation priority value for each distinct bone blendmask. + /// Holds an animation priority value for each BoneGroup. struct AnimPriority { /// Convenience constructor, initialises all priorities to the same value. @@ -147,6 +116,42 @@ protected: int mPriority[sNumBlendMasks]; }; + class TextKeyListener + { + public: + virtual void handleTextKey(const std::string &groupname, const std::multimap::const_iterator &key, + const std::multimap& map) = 0; + }; + + void setTextKeyListener(TextKeyListener* listener); + +protected: + class AnimationTime : public SceneUtil::ControllerSource + { + private: + boost::shared_ptr mTimePtr; + + public: + + void setTimePtr(boost::shared_ptr time) + { mTimePtr = time; } + boost::shared_ptr getTimePtr() const + { return mTimePtr; } + + virtual float getValue(osg::NodeVisitor* nv); + }; + + class NullAnimationTime : public SceneUtil::ControllerSource + { + public: + virtual float getValue(osg::NodeVisitor *nv) + { + return 0.f; + } + }; + + struct AnimSource; + struct AnimState { boost::shared_ptr mSource; float mStartTime;