summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpsi29a <psi29a@gmail.com>2021-12-25 16:00:15 +0000
committerpsi29a <psi29a@gmail.com>2021-12-25 16:00:15 +0000
commit5c67c5316da08e72de9ef726313103faf9d7d26a (patch)
tree54c986682a30dff8d13b523cc15299ef9c6a4153
parent04346b43b0a1efaf0bf79ddaf4ad0244f8cc6868 (diff)
parent88fc038cebcc25106ef24026c0b29346e0298f3c (diff)
Merge branch 'issue_6501' into 'master'
Fix Stuttering in the dialogue menu #6501 See merge request OpenMW/openmw!1492
-rw-r--r--apps/openmw/mwdialogue/hypertextparser.cpp15
-rw-r--r--apps/openmw/mwdialogue/keywordsearch.hpp10
-rw-r--r--apps/openmw/mwworld/store.cpp73
-rw-r--r--apps/openmw/mwworld/store.hpp38
4 files changed, 112 insertions, 24 deletions
diff --git a/apps/openmw/mwdialogue/hypertextparser.cpp b/apps/openmw/mwdialogue/hypertextparser.cpp
index caafa5f324..89a42bf2ea 100644
--- a/apps/openmw/mwdialogue/hypertextparser.cpp
+++ b/apps/openmw/mwdialogue/hypertextparser.cpp
@@ -47,19 +47,8 @@ namespace MWDialogue
void tokenizeKeywords(const std::string & text, std::vector<Token> & tokens)
{
- const MWWorld::Store<ESM::Dialogue> & dialogs =
- MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>();
-
- std::vector<std::string> keywordList;
- keywordList.reserve(dialogs.getSize());
- for (const auto& it : dialogs)
- keywordList.push_back(Misc::StringUtils::lowerCase(it.mId));
- sort(keywordList.begin(), keywordList.end());
-
- KeywordSearch<std::string, int /*unused*/> keywordSearch;
-
- for (const auto& it : keywordList)
- keywordSearch.seed(it, 0 /*unused*/);
+ const auto& keywordSearch =
+ MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>().getDialogIdKeywordSearch();
std::vector<KeywordSearch<std::string, int /*unused*/>::Match> matches;
keywordSearch.highlightKeywords(text.begin(), text.end(), matches);
diff --git a/apps/openmw/mwdialogue/keywordsearch.hpp b/apps/openmw/mwdialogue/keywordsearch.hpp
index 39599457ef..3f932084fe 100644
--- a/apps/openmw/mwdialogue/keywordsearch.hpp
+++ b/apps/openmw/mwdialogue/keywordsearch.hpp
@@ -74,13 +74,13 @@ public:
return left.mBeg < right.mBeg;
}
- void highlightKeywords (Point beg, Point end, std::vector<Match>& out)
+ void highlightKeywords (Point beg, Point end, std::vector<Match>& out) const
{
std::vector<Match> matches;
for (Point i = beg; i != end; ++i)
{
// check first character
- typename Entry::childen_t::iterator candidate = mRoot.mChildren.find (Misc::StringUtils::toLower (*i));
+ typename Entry::childen_t::const_iterator candidate = mRoot.mChildren.find (Misc::StringUtils::toLower (*i));
// no match, on to next character
if (candidate == mRoot.mChildren.end ())
@@ -91,11 +91,11 @@ public:
// some keywords might be longer variations of other keywords, so we definitely need a list of candidates
// the first element in the pair is length of the match, i.e. depth from the first character on
- std::vector< typename std::pair<int, typename Entry::childen_t::iterator> > candidates;
+ std::vector< typename std::pair<int, typename Entry::childen_t::const_iterator> > candidates;
while ((j + 1) != end)
{
- typename Entry::childen_t::iterator next = candidate->second.mChildren.find (Misc::StringUtils::toLower (*++j));
+ typename Entry::childen_t::const_iterator next = candidate->second.mChildren.find (Misc::StringUtils::toLower (*++j));
if (next == candidate->second.mChildren.end ())
{
@@ -116,7 +116,7 @@ public:
// shorter candidates will be added to the vector first. however, we want to check against longer candidates first
std::reverse(candidates.begin(), candidates.end());
- for (typename std::vector< std::pair<int, typename Entry::childen_t::iterator> >::iterator it = candidates.begin();
+ for (typename std::vector< std::pair<int, typename Entry::childen_t::const_iterator> >::iterator it = candidates.begin();
it != candidates.end(); ++it)
{
candidate = it->second;
diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp
index 4d720a11a7..c767bd669a 100644
--- a/apps/openmw/mwworld/store.cpp
+++ b/apps/openmw/mwworld/store.cpp
@@ -981,8 +981,11 @@ namespace MWWorld
// Dialogue
//=========================================================================
+ Store<ESM::Dialogue>::Store()
+ : mKeywordSearchModFlag(true)
+ {
+ }
- template<>
void Store<ESM::Dialogue>::setUp()
{
// DialInfos marked as deleted are kept during the loading phase, so that the linked list
@@ -997,9 +1000,46 @@ namespace MWWorld
// TODO: verify and document this inconsistent behaviour
// TODO: if we require this behaviour, maybe we should move it to the place that requires it
std::sort(mShared.begin(), mShared.end(), [](const ESM::Dialogue* l, const ESM::Dialogue* r) -> bool { return l->mId < r->mId; });
+
+ mKeywordSearchModFlag = true;
+ }
+
+ const ESM::Dialogue *Store<ESM::Dialogue>::search(const std::string &id) const
+ {
+ typename Static::const_iterator it = mStatic.find(id);
+ if (it != mStatic.end())
+ return &(it->second);
+
+ return nullptr;
+ }
+
+ const ESM::Dialogue *Store<ESM::Dialogue>::find(const std::string &id) const
+ {
+ const ESM::Dialogue *ptr = search(id);
+ if (ptr == nullptr)
+ {
+ std::stringstream msg;
+ msg << ESM::Dialogue::getRecordType() << " '" << id << "' not found";
+ throw std::runtime_error(msg.str());
+ }
+ return ptr;
+ }
+
+ typename Store<ESM::Dialogue>::iterator Store<ESM::Dialogue>::begin() const
+ {
+ return mShared.begin();
+ }
+
+ typename Store<ESM::Dialogue>::iterator Store<ESM::Dialogue>::end() const
+ {
+ return mShared.end();
+ }
+
+ size_t Store<ESM::Dialogue>::getSize() const
+ {
+ return mShared.size();
}
- template <>
inline RecordId Store<ESM::Dialogue>::load(ESM::ESMReader &esm) {
// The original letter case of a dialogue ID is saved, because it's printed
ESM::Dialogue dialogue;
@@ -1018,17 +1058,40 @@ namespace MWWorld
found->second.loadData(esm, isDeleted);
dialogue.mId = found->second.mId;
}
+
+ mKeywordSearchModFlag = true;
return RecordId(dialogue.mId, isDeleted);
}
- template<>
bool Store<ESM::Dialogue>::eraseStatic(const std::string &id)
{
- mStatic.erase(id);
+ if (mStatic.erase(id))
+ mKeywordSearchModFlag = true;
+
return true;
}
+ const MWDialogue::KeywordSearch<std::string, int>& Store<ESM::Dialogue>::getDialogIdKeywordSearch() const
+ {
+ if (mKeywordSearchModFlag)
+ {
+ mKeywordSearch.clear();
+
+ std::vector<std::string> keywordList;
+ keywordList.reserve(getSize());
+ for (const auto& it : *this)
+ keywordList.push_back(Misc::StringUtils::lowerCase(it.mId));
+ sort(keywordList.begin(), keywordList.end());
+
+ for (const auto& it : keywordList)
+ mKeywordSearch.seed(it, 0 /*unused*/);
+
+ mKeywordSearchModFlag = false;
+ }
+
+ return mKeywordSearch;
+ }
}
template class MWWorld::Store<ESM::Activator>;
@@ -1044,7 +1107,7 @@ template class MWWorld::Store<ESM::Clothing>;
template class MWWorld::Store<ESM::Container>;
template class MWWorld::Store<ESM::Creature>;
template class MWWorld::Store<ESM::CreatureLevList>;
-template class MWWorld::Store<ESM::Dialogue>;
+//template class MWWorld::Store<ESM::Dialogue>;
template class MWWorld::Store<ESM::Door>;
template class MWWorld::Store<ESM::Enchantment>;
template class MWWorld::Store<ESM::Faction>;
diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp
index 22f36da690..1ec51ad5fd 100644
--- a/apps/openmw/mwworld/store.hpp
+++ b/apps/openmw/mwworld/store.hpp
@@ -11,6 +11,8 @@
#include <components/esm/records.hpp>
#include <components/misc/stringops.hpp>
+#include "../mwdialogue/keywordsearch.hpp"
+
namespace ESM
{
struct Land;
@@ -154,7 +156,6 @@ namespace MWWorld
/// @par mShared usually 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)
- /// @warning ESM::Dialogue Store currently implements a sorted order for unknown reasons.
std::vector<T*> mShared;
typedef std::unordered_map<std::string, T, Misc::StringUtils::CiHash, Misc::StringUtils::CiEqual> Dynamic;
Dynamic mDynamic;
@@ -440,6 +441,41 @@ namespace MWWorld
iterator end() const;
};
+ template <>
+ class Store<ESM::Dialogue> : public StoreBase
+ {
+ typedef std::unordered_map<std::string, ESM::Dialogue, Misc::StringUtils::CiHash, Misc::StringUtils::CiEqual> Static;
+ Static mStatic;
+ /// @par mShared usually 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)
+ /// @warning ESM::Dialogue Store currently implements a sorted order for unknown reasons.
+ std::vector<ESM::Dialogue*> mShared;
+
+ mutable bool mKeywordSearchModFlag;
+ mutable MWDialogue::KeywordSearch<std::string, int /*unused*/> mKeywordSearch;
+
+ public:
+ Store();
+
+ typedef SharedIterator<ESM::Dialogue> iterator;
+
+ void setUp() override;
+
+ const ESM::Dialogue *search(const std::string &id) const;
+ const ESM::Dialogue *find(const std::string &id) const;
+
+ iterator begin() const;
+ iterator end() const;
+
+ size_t getSize() const override;
+
+ bool eraseStatic(const std::string &id) override;
+
+ RecordId load(ESM::ESMReader &esm) override;
+
+ const MWDialogue::KeywordSearch<std::string, int>& getDialogIdKeywordSearch() const;
+ };
} //end namespace