1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-06-22 09:41:33 +00:00

Preserve record ordering in Store

This fixes the default head/hair used for some races in the chargen UI.
This commit is contained in:
scrawl 2014-12-23 15:28:02 +01:00
parent 9b33eca368
commit b8fa73dfa9
2 changed files with 32 additions and 50 deletions

View file

@ -345,8 +345,7 @@ namespace MWGui
const MWWorld::Store<ESM::Race> &races = const MWWorld::Store<ESM::Race> &races =
MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>(); MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>();
std::map<std::string, std::string> items; // ID, name
int index = 0;
MWWorld::Store<ESM::Race>::iterator it = races.begin(); MWWorld::Store<ESM::Race>::iterator it = races.begin();
for (; it != races.end(); ++it) for (; it != races.end(); ++it)
{ {
@ -354,8 +353,14 @@ namespace MWGui
if (!playable) // Only display playable races if (!playable) // Only display playable races
continue; continue;
mRaceList->addItem(it->mName, it->mId); items[it->mId] = it->mName;
if (Misc::StringUtils::ciEqual(it->mId, mCurrentRaceId)) }
int index = 0;
for (std::map<std::string, std::string>::const_iterator it = items.begin(); it != items.end(); ++it)
{
mRaceList->addItem(it->second, it->first);
if (Misc::StringUtils::ciEqual(it->first, mCurrentRaceId))
mRaceList->setIndexSelected(index); mRaceList->setIndexSelected(index);
++index; ++index;
} }

View file

@ -99,7 +99,9 @@ namespace MWWorld
class Store : public StoreBase class Store : public StoreBase
{ {
std::map<std::string, T> mStatic; std::map<std::string, T> mStatic;
std::vector<T *> mShared; std::vector<T *> mShared; // Preserves the record order as it came from the content files (this
// is relevant for the spell autocalc code and selection order
// for heads/hairs in the character creation)
std::map<std::string, T> mDynamic; std::map<std::string, T> mDynamic;
typedef std::map<std::string, T> Dynamic; typedef std::map<std::string, T> Dynamic;
@ -137,8 +139,9 @@ namespace MWWorld
// setUp needs to be called again after // setUp needs to be called again after
virtual void clearDynamic() virtual void clearDynamic()
{ {
// remove the dynamic part of mShared
mShared.erase(mShared.begin() + mStatic.size(), mShared.end());
mDynamic.clear(); mDynamic.clear();
mShared.clear();
} }
const T *search(const std::string &id) const { const T *search(const std::string &id) const {
@ -203,18 +206,18 @@ namespace MWWorld
void load(ESM::ESMReader &esm, const std::string &id) { void load(ESM::ESMReader &esm, const std::string &id) {
std::string idLower = Misc::StringUtils::lowerCase(id); std::string idLower = Misc::StringUtils::lowerCase(id);
mStatic[idLower] = T();
mStatic[idLower].mId = idLower; std::pair<typename Static::iterator, bool> inserted = mStatic.insert(std::make_pair(idLower, T()));
mStatic[idLower].load(esm); if (inserted.second)
mShared.push_back(&inserted.first->second);
inserted.first->second.mId = idLower;
inserted.first->second.load(esm);
} }
void setUp() { void setUp() {
mShared.clear(); // remove the dynamic part of mShared
mShared.reserve(mStatic.size()); mShared.erase(mShared.begin() + mStatic.size(), mShared.end());
typename std::map<std::string, T>::iterator it = mStatic.begin();
for (; it != mStatic.end(); ++it) {
mShared.push_back(&(it->second));
}
} }
iterator begin() const { iterator begin() const {
@ -356,10 +359,9 @@ namespace MWWorld
std::map<std::string, ESM::Dialogue>::iterator it = mStatic.find(idLower); std::map<std::string, ESM::Dialogue>::iterator it = mStatic.find(idLower);
if (it == mStatic.end()) { if (it == mStatic.end()) {
it = mStatic.insert( std::make_pair( idLower, ESM::Dialogue() ) ).first; it = mStatic.insert( std::make_pair( idLower, ESM::Dialogue() ) ).first;
it->second.mId = id; // don't smash case here, as this line is printed... I think it->second.mId = id; // don't smash case here, as this line is printed
} }
//I am not sure is it need to load the dialog from a plugin if it was already loaded from prevois plugins
it->second.load(esm); it->second.load(esm);
} }
@ -368,7 +370,10 @@ namespace MWWorld
ESM::Script scpt; ESM::Script scpt;
scpt.load(esm); scpt.load(esm);
Misc::StringUtils::toLower(scpt.mId); Misc::StringUtils::toLower(scpt.mId);
mStatic[scpt.mId] = scpt;
std::pair<typename Static::iterator, bool> inserted = mStatic.insert(std::make_pair(scpt.mId, scpt));
if (inserted.second)
mShared.push_back(&inserted.first->second);
} }
template <> template <>
@ -376,7 +381,10 @@ namespace MWWorld
ESM::StartScript s; ESM::StartScript s;
s.load(esm); s.load(esm);
s.mId = Misc::StringUtils::toLower(s.mScript); s.mId = Misc::StringUtils::toLower(s.mScript);
mStatic[s.mId] = s;
std::pair<typename Static::iterator, bool> inserted = mStatic.insert(std::make_pair(s.mId, s));
if (inserted.second)
mShared.push_back(&inserted.first->second);
} }
template <> template <>
@ -1067,37 +1075,6 @@ namespace MWWorld
} }
}; };
// Specialisation for ESM::Spell to preserve record order as it was in the content files.
// The NPC spell autocalc code heavily depends on this order.
// We could also do this in the base class, but it's usually not a good idea to depend on record order.
template<>
inline void Store<ESM::Spell>::clearDynamic()
{
// remove the dynamic part of mShared
mShared.erase(mShared.begin() + mStatic.size(), mShared.end());
mDynamic.clear();
}
template<>
inline void Store<ESM::Spell>::load(ESM::ESMReader &esm, const std::string &id) {
std::string idLower = Misc::StringUtils::lowerCase(id);
std::pair<Static::iterator, bool> inserted = mStatic.insert(std::make_pair(idLower, ESM::Spell()));
if (inserted.second)
mShared.push_back(&mStatic[idLower]);
inserted.first->second.mId = idLower;
inserted.first->second.load(esm);
}
template<>
inline void Store<ESM::Spell>::setUp()
{
// remove the dynamic part of mShared
mShared.erase(mShared.begin() + mStatic.size(), mShared.end());
}
template<> template<>
inline void Store<ESM::Dialogue>::setUp() inline void Store<ESM::Dialogue>::setUp()
{ {