1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-06 00:55:50 +00:00
OpenMW/apps/openmw/mwrender/weaponanimation.hpp
Bo Svensson 7f9beac3a7
refactors a case insensitive map (#3184)
This PR aims to spark the retirement of a questionable pattern I have found all over our code base. I will illustrate how this pattern encourages code duplication, lacks type safety, requires documentation and can be prone to bugs.
```
std::map<std::string, Object> mMap; // Stored in all lowercase for a case-insensitive lookup

std::string lowerKey = Misc::StringUtils::lowerCase(key);
mMap.emplace(lowerKey, object);

std::string lowerKey = Misc::StringUtils::lowerCase(key);
mMap.find(lowerKey);

mMap.find(key); // Not found. Oops!
```
An alternative approach produces no such issues.
```
std::unordered_map<std::string, Object, Misc::StringUtils::CiHash, Misc::StringUtils::CiEqual> mMap;

mMap.emplace(key, object);

mMap.find(key);
```
Of course, such an alternative will work for a `map` as well, but an `unordered_map` is generally preferable over a `map` with these changes because we have moved `lowerCase` into the comparison operator. 

In this PR I have refactored `Animation::mNodeMap` accordingly. I have reviewed and adapted all direct and indirect usage of `Animation::mNodeMap` to ensure we do not change behaviour with this PR.
2021-10-25 09:18:26 +02:00

74 lines
2.3 KiB
C++

#ifndef OPENMW_MWRENDER_WEAPONANIMATION_H
#define OPENMW_MWRENDER_WEAPONANIMATION_H
#include <components/sceneutil/controller.hpp>
#include "../mwworld/ptr.hpp"
#include "animation.hpp"
namespace MWRender
{
class RotateController;
class WeaponAnimationTime : public SceneUtil::ControllerSource
{
private:
Animation* mAnimation;
std::string mWeaponGroup;
float mStartTime;
bool mRelativeTime;
public:
WeaponAnimationTime(Animation* animation) : mAnimation(animation), mStartTime(0), mRelativeTime(false) {}
void setGroup(const std::string& group, bool relativeTime);
void updateStartTime();
float getValue(osg::NodeVisitor* nv) override;
};
/// Handles attach & release of projectiles for ranged weapons
class WeaponAnimation
{
public:
WeaponAnimation();
virtual ~WeaponAnimation();
/// @note If no weapon (or an invalid weapon) is equipped, this function is a no-op.
void attachArrow(const MWWorld::Ptr &actor);
void detachArrow(MWWorld::Ptr actor);
/// @note If no weapon (or an invalid weapon) is equipped, this function is a no-op.
void releaseArrow(MWWorld::Ptr actor, float attackStrength);
/// Add WeaponAnimation-related controllers to \a nodes and store the added controllers in \a map.
void addControllers(const Animation::NodeMap& nodes, std::vector<std::pair<osg::ref_ptr<osg::Node>, osg::ref_ptr<osg::Callback>>>& map, osg::Node* objectRoot);
void deleteControllers();
/// Configure controllers, should be called every animation frame.
void configureControllers(float characterPitchRadians);
protected:
PartHolderPtr mAmmunition;
osg::ref_ptr<RotateController> mSpineControllers[2];
void setControllerRotate(const osg::Quat& rotate);
void setControllerEnabled(bool enabled);
virtual osg::Group* getArrowBone() = 0;
virtual osg::Node* getWeaponNode() = 0;
virtual Resource::ResourceSystem* getResourceSystem() = 0;
virtual void showWeapon(bool show) = 0;
/// A relative factor (0-1) that decides if and how much the skeleton should be pitched
/// to indicate the facing orientation of the character, for ranged weapon aiming.
float mPitchFactor;
};
}
#endif