mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 12:23:53 +00:00
Merge pull request #2862 from elsid/optimize_has_animation
Optimize MWRender::Animation::hasAnimation
This commit is contained in:
commit
357a845d00
7 changed files with 117 additions and 42 deletions
|
@ -942,7 +942,7 @@ void split(const std::string &s, char delim, std::vector<std::string> &elems) {
|
|||
}
|
||||
}
|
||||
|
||||
void CharacterController::handleTextKey(const std::string &groupname, const std::multimap<float, std::string>::const_iterator &key, const std::multimap<float, std::string> &map)
|
||||
void CharacterController::handleTextKey(const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key, const NifOsg::TextKeyMap& map)
|
||||
{
|
||||
const std::string &evt = key->second;
|
||||
|
||||
|
|
|
@ -238,8 +238,7 @@ public:
|
|||
CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim);
|
||||
virtual ~CharacterController();
|
||||
|
||||
virtual void handleTextKey(const std::string &groupname, const std::multimap<float, std::string>::const_iterator &key,
|
||||
const std::multimap<float, std::string>& map);
|
||||
virtual void handleTextKey(const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key, const NifOsg::TextKeyMap& map);
|
||||
|
||||
// Be careful when to call this, see comment in Actors
|
||||
void updateContinuousVfx();
|
||||
|
|
|
@ -151,20 +151,8 @@ namespace
|
|||
}
|
||||
};
|
||||
|
||||
NifOsg::TextKeyMap::const_iterator findGroupStart(const NifOsg::TextKeyMap &keys, const std::string &groupname)
|
||||
{
|
||||
NifOsg::TextKeyMap::const_iterator iter(keys.begin());
|
||||
for(;iter != keys.end();++iter)
|
||||
{
|
||||
if(iter->second.compare(0, groupname.size(), groupname) == 0 &&
|
||||
iter->second.compare(groupname.size(), 2, ": ") == 0)
|
||||
break;
|
||||
}
|
||||
return iter;
|
||||
}
|
||||
|
||||
float calcAnimVelocity(const std::multimap<float, std::string>& keys,
|
||||
NifOsg::KeyframeController *nonaccumctrl, const osg::Vec3f& accum, const std::string &groupname)
|
||||
float calcAnimVelocity(const NifOsg::TextKeyMap& keys, NifOsg::KeyframeController *nonaccumctrl,
|
||||
const osg::Vec3f& accum, const std::string &groupname)
|
||||
{
|
||||
const std::string start = groupname+": start";
|
||||
const std::string loopstart = groupname+": loop start";
|
||||
|
@ -179,7 +167,7 @@ namespace
|
|||
// but the animation velocity calculation uses the second one.
|
||||
// As result the animation velocity calculation is not correct, and this incorrect velocity must be replicated,
|
||||
// because otherwise the Creature's Speed (dagoth uthol) would not be sufficient to move fast enough.
|
||||
NifOsg::TextKeyMap::const_reverse_iterator keyiter(keys.rbegin());
|
||||
auto keyiter = keys.rbegin();
|
||||
while(keyiter != keys.rend())
|
||||
{
|
||||
if(keyiter->second == start || keyiter->second == loopstart)
|
||||
|
@ -553,7 +541,7 @@ namespace MWRender
|
|||
|
||||
ControllerMap mControllerMap[Animation::sNumBlendMasks];
|
||||
|
||||
const std::multimap<float, std::string>& getTextKeys() const;
|
||||
const NifOsg::TextKeyMap& getTextKeys() const;
|
||||
};
|
||||
|
||||
void UpdateVfxCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
|
@ -702,7 +690,7 @@ namespace MWRender
|
|||
return 0;
|
||||
}
|
||||
|
||||
const std::multimap<float, std::string> &Animation::AnimSource::getTextKeys() const
|
||||
const NifOsg::TextKeyMap &Animation::AnimSource::getTextKeys() const
|
||||
{
|
||||
return mKeyframes->mTextKeys;
|
||||
}
|
||||
|
@ -825,7 +813,7 @@ namespace MWRender
|
|||
for(;iter != mAnimSources.end();++iter)
|
||||
{
|
||||
const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys();
|
||||
if(findGroupStart(keys, anim) != keys.end())
|
||||
if (keys.hasGroupStart(anim))
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -838,7 +826,7 @@ namespace MWRender
|
|||
{
|
||||
const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys();
|
||||
|
||||
NifOsg::TextKeyMap::const_iterator found = findGroupStart(keys, groupname);
|
||||
const auto found = keys.findGroupStart(groupname);
|
||||
if(found != keys.end())
|
||||
return found->first;
|
||||
}
|
||||
|
@ -851,7 +839,7 @@ namespace MWRender
|
|||
{
|
||||
const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys();
|
||||
|
||||
for(NifOsg::TextKeyMap::const_iterator iterKey(keys.begin()); iterKey != keys.end(); ++iterKey)
|
||||
for(auto iterKey = keys.begin(); iterKey != keys.end(); ++iterKey)
|
||||
{
|
||||
if(iterKey->second.compare(0, textKey.size(), textKey) == 0)
|
||||
return iterKey->first;
|
||||
|
@ -861,8 +849,8 @@ namespace MWRender
|
|||
return -1.f;
|
||||
}
|
||||
|
||||
void Animation::handleTextKey(AnimState &state, const std::string &groupname, const std::multimap<float, std::string>::const_iterator &key,
|
||||
const std::multimap<float, std::string>& map)
|
||||
void Animation::handleTextKey(AnimState &state, const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key,
|
||||
const NifOsg::TextKeyMap& map)
|
||||
{
|
||||
const std::string &evt = key->second;
|
||||
|
||||
|
@ -939,7 +927,7 @@ namespace MWRender
|
|||
|
||||
if (state.mPlaying)
|
||||
{
|
||||
NifOsg::TextKeyMap::const_iterator textkey(textkeys.lower_bound(state.getTime()));
|
||||
auto textkey = textkeys.lowerBound(state.getTime());
|
||||
while(textkey != textkeys.end() && textkey->first <= state.getTime())
|
||||
{
|
||||
handleTextKey(state, groupname, textkey, textkeys);
|
||||
|
@ -955,7 +943,7 @@ namespace MWRender
|
|||
if(state.getTime() >= state.mLoopStopTime)
|
||||
break;
|
||||
|
||||
NifOsg::TextKeyMap::const_iterator textkey(textkeys.lower_bound(state.getTime()));
|
||||
auto textkey = textkeys.lowerBound(state.getTime());
|
||||
while(textkey != textkeys.end() && textkey->first <= state.getTime())
|
||||
{
|
||||
handleTextKey(state, groupname, textkey, textkeys);
|
||||
|
@ -974,7 +962,7 @@ namespace MWRender
|
|||
{
|
||||
// Look for text keys in reverse. This normally wouldn't matter, but for some reason undeadwolf_2.nif has two
|
||||
// separate walkforward keys, and the last one is supposed to be used.
|
||||
NifOsg::TextKeyMap::const_reverse_iterator groupend(keys.rbegin());
|
||||
auto groupend = keys.rbegin();
|
||||
for(;groupend != keys.rend();++groupend)
|
||||
{
|
||||
if(groupend->second.compare(0, groupname.size(), groupname) == 0 &&
|
||||
|
@ -983,7 +971,7 @@ namespace MWRender
|
|||
}
|
||||
|
||||
std::string starttag = groupname+": "+start;
|
||||
NifOsg::TextKeyMap::const_reverse_iterator startkey(groupend);
|
||||
auto startkey = groupend;
|
||||
while(startkey != keys.rend() && startkey->second != starttag)
|
||||
++startkey;
|
||||
if(startkey == keys.rend() && start == "loop start")
|
||||
|
@ -997,7 +985,7 @@ namespace MWRender
|
|||
return false;
|
||||
|
||||
const std::string stoptag = groupname+": "+stop;
|
||||
NifOsg::TextKeyMap::const_reverse_iterator stopkey(groupend);
|
||||
auto stopkey = groupend;
|
||||
while(stopkey != keys.rend()
|
||||
// We have to ignore extra garbage at the end.
|
||||
// The Scrib's idle3 animation has "Idle3: Stop." instead of "Idle3: Stop".
|
||||
|
@ -1030,7 +1018,7 @@ namespace MWRender
|
|||
const std::string loopstarttag = groupname+": loop start";
|
||||
const std::string loopstoptag = groupname+": loop stop";
|
||||
|
||||
NifOsg::TextKeyMap::const_reverse_iterator key(groupend);
|
||||
auto key = groupend;
|
||||
for (; key != startkey && key != keys.rend(); ++key)
|
||||
{
|
||||
if (key->first > state.getTime())
|
||||
|
@ -1201,7 +1189,7 @@ namespace MWRender
|
|||
for(;animsrc != mAnimSources.rend();++animsrc)
|
||||
{
|
||||
const NifOsg::TextKeyMap &keys = (*animsrc)->getTextKeys();
|
||||
if(findGroupStart(keys, groupname) != keys.end())
|
||||
if (keys.hasGroupStart(groupname))
|
||||
break;
|
||||
}
|
||||
if(animsrc == mAnimSources.rend())
|
||||
|
@ -1280,7 +1268,7 @@ namespace MWRender
|
|||
}
|
||||
|
||||
const NifOsg::TextKeyMap &textkeys = state.mSource->getTextKeys();
|
||||
NifOsg::TextKeyMap::const_iterator textkey(textkeys.upper_bound(state.getTime()));
|
||||
auto textkey = textkeys.upperBound(state.getTime());
|
||||
|
||||
float timepassed = duration * state.mSpeedMult;
|
||||
while(state.mPlaying)
|
||||
|
@ -1316,7 +1304,7 @@ namespace MWRender
|
|||
state.setTime(state.mLoopStartTime);
|
||||
state.mPlaying = true;
|
||||
|
||||
textkey = textkeys.lower_bound(state.getTime());
|
||||
textkey = textkeys.lowerBound(state.getTime());
|
||||
while(textkey != textkeys.end() && textkey->first <= state.getTime())
|
||||
{
|
||||
handleTextKey(state, stateiter->first, textkey, textkeys);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <components/sceneutil/controller.hpp>
|
||||
#include <components/sceneutil/util.hpp>
|
||||
#include <components/nifosg/textkeymap.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
@ -149,8 +150,8 @@ public:
|
|||
class TextKeyListener
|
||||
{
|
||||
public:
|
||||
virtual void handleTextKey(const std::string &groupname, const std::multimap<float, std::string>::const_iterator &key,
|
||||
const std::multimap<float, std::string>& map) = 0;
|
||||
virtual void handleTextKey(const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key,
|
||||
const NifOsg::TextKeyMap& map) = 0;
|
||||
|
||||
virtual ~TextKeyListener() = default;
|
||||
};
|
||||
|
@ -297,12 +298,12 @@ protected:
|
|||
* the marker is not found, or if the markers are the same, it returns
|
||||
* false.
|
||||
*/
|
||||
bool reset(AnimState &state, const std::multimap<float, std::string> &keys,
|
||||
bool reset(AnimState &state, const NifOsg::TextKeyMap &keys,
|
||||
const std::string &groupname, const std::string &start, const std::string &stop,
|
||||
float startpoint, bool loopfallback);
|
||||
|
||||
void handleTextKey(AnimState &state, const std::string &groupname, const std::multimap<float, std::string>::const_iterator &key,
|
||||
const std::multimap<float, std::string>& map);
|
||||
void handleTextKey(AnimState &state, const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key,
|
||||
const NifOsg::TextKeyMap& map);
|
||||
|
||||
/** Sets the root model of the object.
|
||||
*
|
||||
|
|
|
@ -157,7 +157,8 @@ namespace
|
|||
nextpos = std::distance(str.begin(), ++last);
|
||||
}
|
||||
std::string result = str.substr(pos, nextpos-pos);
|
||||
textkeys.insert(std::make_pair(tk->list[i].time, Misc::StringUtils::lowerCase(result)));
|
||||
Misc::StringUtils::lowerCaseInPlace(result);
|
||||
textkeys.emplace(tk->list[i].time, std::move(result));
|
||||
|
||||
pos = nextpos;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <osg/Referenced>
|
||||
|
||||
#include "controller.hpp"
|
||||
#include "textkeymap.hpp"
|
||||
|
||||
namespace osg
|
||||
{
|
||||
|
@ -20,8 +21,6 @@ namespace Resource
|
|||
|
||||
namespace NifOsg
|
||||
{
|
||||
typedef std::multimap<float,std::string> TextKeyMap;
|
||||
|
||||
struct TextKeyMapHolder : public osg::Object
|
||||
{
|
||||
public:
|
||||
|
|
87
components/nifosg/textkeymap.hpp
Normal file
87
components/nifosg/textkeymap.hpp
Normal file
|
@ -0,0 +1,87 @@
|
|||
#ifndef OPENMW_COMPONENTS_NIFOSG_TEXTKEYMAP
|
||||
#define OPENMW_COMPONENTS_NIFOSG_TEXTKEYMAP
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
namespace NifOsg
|
||||
{
|
||||
class TextKeyMap
|
||||
{
|
||||
public:
|
||||
using ConstIterator = std::multimap<float, std::string>::const_iterator;
|
||||
|
||||
auto begin() const noexcept
|
||||
{
|
||||
return mTextKeyByTime.begin();
|
||||
}
|
||||
|
||||
auto end() const noexcept
|
||||
{
|
||||
return mTextKeyByTime.end();
|
||||
}
|
||||
|
||||
auto rbegin() const noexcept
|
||||
{
|
||||
return mTextKeyByTime.rbegin();
|
||||
}
|
||||
|
||||
auto rend() const noexcept
|
||||
{
|
||||
return mTextKeyByTime.rend();
|
||||
}
|
||||
|
||||
auto lowerBound(float time) const
|
||||
{
|
||||
return mTextKeyByTime.lower_bound(time);
|
||||
}
|
||||
|
||||
auto upperBound(float time) const
|
||||
{
|
||||
return mTextKeyByTime.upper_bound(time);
|
||||
}
|
||||
|
||||
void emplace(float time, std::string&& textKey)
|
||||
{
|
||||
const auto separator = textKey.find(": ");
|
||||
if (separator != std::string::npos)
|
||||
mGroups.emplace(textKey.substr(0, separator));
|
||||
|
||||
mTextKeyByTime.emplace(time, std::move(textKey));
|
||||
}
|
||||
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return mTextKeyByTime.empty();
|
||||
}
|
||||
|
||||
auto findGroupStart(const std::string &groupName) const
|
||||
{
|
||||
return std::find_if(mTextKeyByTime.begin(), mTextKeyByTime.end(), IsGroupStart{groupName});
|
||||
}
|
||||
|
||||
bool hasGroupStart(const std::string &groupName) const
|
||||
{
|
||||
return mGroups.count(groupName) > 0;
|
||||
}
|
||||
|
||||
private:
|
||||
struct IsGroupStart
|
||||
{
|
||||
const std::string &mGroupName;
|
||||
|
||||
bool operator ()(const std::multimap<float, std::string>::value_type& value) const
|
||||
{
|
||||
return value.second.compare(0, mGroupName.size(), mGroupName) == 0 &&
|
||||
value.second.compare(mGroupName.size(), 2, ": ") == 0;
|
||||
}
|
||||
};
|
||||
|
||||
std::set<std::string> mGroups;
|
||||
std::multimap<float, std::string> mTextKeyByTime;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue