From ef7e0070a62f1c90c9a9150c397d3666c61a0b0a Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 8 Jan 2015 02:34:37 +0100 Subject: [PATCH 01/14] Don't right-shift signed integers which is implementation-defined --- apps/openmw/mwgui/formatting.cpp | 2 +- apps/openmw/mwrender/animation.cpp | 2 +- components/esm/loadligh.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/formatting.cpp b/apps/openmw/mwgui/formatting.cpp index 583116003..765402a01 100644 --- a/apps/openmw/mwgui/formatting.cpp +++ b/apps/openmw/mwgui/formatting.cpp @@ -340,7 +340,7 @@ namespace MWGui { if (attr.find("color") != attr.end()) { - int color; + unsigned int color; std::stringstream ss; ss << attr.at("color"); ss >> std::hex >> color; diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 1ef7a3533..ea40721cb 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -336,7 +336,7 @@ void Animation::addExtraLight(Ogre::SceneManager *sceneMgr, NifOgre::ObjectScene { const MWWorld::Fallback *fallback = MWBase::Environment::get().getWorld()->getFallback(); - const int clr = light->mData.mColor; + const unsigned int clr = light->mData.mColor; Ogre::ColourValue color(((clr >> 0) & 0xFF) / 255.0f, ((clr >> 8) & 0xFF) / 255.0f, ((clr >> 16) & 0xFF) / 255.0f); diff --git a/components/esm/loadligh.hpp b/components/esm/loadligh.hpp index ffc291609..2c83248f8 100644 --- a/components/esm/loadligh.hpp +++ b/components/esm/loadligh.hpp @@ -37,7 +37,7 @@ struct Light int mValue; int mTime; // Duration int mRadius; - int mColor; // 4-byte rgba value + unsigned int mColor; // 4-byte rgba value int mFlags; }; // Size = 24 bytes From 928b9ee41b2f3296426102d4df1fc9bf85d8ed91 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 8 Jan 2015 03:29:13 +0100 Subject: [PATCH 02/14] Fix missing GUI mode update when showing soulgem dialog --- apps/openmw/mwgui/windowmanagerimp.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 72805dd31..5546480ec 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1455,6 +1455,8 @@ namespace MWGui void WindowManager::showSoulgemDialog(MWWorld::Ptr item) { mSoulgemDialog->show(item); + MWBase::Environment::get().getInputManager()->changeInputMode(isGuiMode()); + updateVisible(); } void WindowManager::frameStarted (float dt) From d31ae2b345e0058696a41308d370cb6e851f55a2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 8 Jan 2015 16:17:13 +0100 Subject: [PATCH 03/14] Fix mIds mapping for dynamic records being lost on save/reload --- apps/openmw/mwworld/esmstore.cpp | 10 +++++++++- apps/openmw/mwworld/store.hpp | 6 +++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index 2a3fd9179..8e0f58a6b 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -192,7 +192,15 @@ void ESMStore::setUp() case ESM::REC_LEVI: case ESM::REC_LEVC: - mStores[type]->read (reader); + { + std::string id = reader.getHNString ("NAME"); + mStores[type]->read (reader, id); + + // FIXME: there might be stale dynamic IDs in mIds from an earlier savegame + // that really should be cleared instead of just overwritten + + mIds[id] = type; + } if (type==ESM::REC_NPC_) { diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index dcfbb4eb1..97ba4652f 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -30,7 +30,7 @@ namespace MWWorld virtual void write (ESM::ESMWriter& writer) const {} - virtual void read (ESM::ESMReader& reader) {} + virtual void read (ESM::ESMReader& reader, const std::string& id) {} ///< Read into dynamic storage }; @@ -329,10 +329,10 @@ namespace MWWorld } } - void read (ESM::ESMReader& reader) + void read (ESM::ESMReader& reader, const std::string& id) { T record; - record.mId = reader.getHNString ("NAME"); + record.mId = id; record.load (reader); insert (record); } From 2ddbe22da311b5f740a53fa1c4eecc39cbde4b9d Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 9 Jan 2015 00:44:22 +0100 Subject: [PATCH 04/14] Fix for NPC store clearDynamic bug It was clearing the whole mShared vector, instead of only the dynamic part. Actually, that whole overload was pointless to begin with. All it does is making sure the Player record isn't cleared, but ESMStore::clearDynamic re-inserts the player record anyway after clearing. --- apps/openmw/mwworld/store.hpp | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index 97ba4652f..e94624ade 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -140,7 +140,8 @@ namespace MWWorld virtual void clearDynamic() { // remove the dynamic part of mShared - mShared.erase(mShared.begin() + mStatic.size(), mShared.end()); + if (mShared.size() > mStatic.size()) + mShared.erase(mShared.begin() + mStatic.size(), mShared.end()); mDynamic.clear(); } @@ -217,7 +218,8 @@ namespace MWWorld void setUp() { // remove the dynamic part of mShared - mShared.erase(mShared.begin() + mStatic.size(), mShared.end()); + if (mShared.size() > mStatic.size()) + mShared.erase(mShared.begin() + mStatic.size(), mShared.end()); } iterator begin() const { @@ -305,7 +307,8 @@ namespace MWWorld mDynamic.erase(it); // have to reinit the whole shared part - mShared.erase(mShared.begin() + mStatic.size(), mShared.end()); + if (mShared.size() > mStatic.size()) + mShared.erase(mShared.begin() + mStatic.size(), mShared.end()); for (it = mDynamic.begin(); it != mDynamic.end(); ++it) { mShared.push_back(&it->second); } @@ -338,20 +341,6 @@ namespace MWWorld } }; - template <> - inline void Store::clearDynamic() - { - std::map::iterator iter = mDynamic.begin(); - - while (iter!=mDynamic.end()) - if (iter->first=="player") - ++iter; - else - mDynamic.erase (iter++); - - mShared.clear(); - } - template <> inline void Store::load(ESM::ESMReader &esm, const std::string &id) { std::string idLower = Misc::StringUtils::lowerCase(id); From c77660ba206168cd186c26d03f170e3cee3d31a8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 9 Jan 2015 01:01:55 +0100 Subject: [PATCH 05/14] Remove some nonsense code --- apps/openmw/mwworld/esmstore.hpp | 3 --- apps/openmw/mwworld/store.cpp | 3 +-- apps/openmw/mwworld/store.hpp | 6 ------ 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/apps/openmw/mwworld/esmstore.hpp b/apps/openmw/mwworld/esmstore.hpp index 5d794db89..01770e6b3 100644 --- a/apps/openmw/mwworld/esmstore.hpp +++ b/apps/openmw/mwworld/esmstore.hpp @@ -99,9 +99,6 @@ namespace MWWorld ESMStore() : mDynamicCount(0) { - // Cell store needs access to this for tracking moved references - mCells.mEsmStore = this; - mStores[ESM::REC_ACTI] = &mActivators; mStores[ESM::REC_ALCH] = &mPotions; mStores[ESM::REC_APPA] = &mAppas; diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index caf4083fe..7d58013e7 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -11,8 +11,7 @@ void Store::handleMovedCellRefs(ESM::ESMReader& esm, ESM::Cell* cell) ESM::MovedCellRef cMRef; cell->getNextMVRF(esm, cMRef); - MWWorld::Store &cStore = const_cast&>(mEsmStore->get()); - ESM::Cell *cellAlt = const_cast(cStore.searchOrCreate(cMRef.mTarget[0], cMRef.mTarget[1])); + ESM::Cell *cellAlt = const_cast(searchOrCreate(cMRef.mTarget[0], cMRef.mTarget[1])); // Get regular moved reference data. Adapted from CellStore::loadRefs. Maybe we can optimize the following // implementation when the oher implementation works as well. diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index e94624ade..71e77d0c7 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -582,14 +582,8 @@ namespace MWWorld void handleMovedCellRefs(ESM::ESMReader& esm, ESM::Cell* cell); public: - ESMStore *mEsmStore; - typedef SharedIterator iterator; - Store() - : mEsmStore(NULL) - {} - const ESM::Cell *search(const std::string &id) const { ESM::Cell cell; cell.mName = Misc::StringUtils::lowerCase(id); From ddd6e682bcf2bae8b8447b1203a2f5b8792ee3fc Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 9 Jan 2015 04:19:38 +0100 Subject: [PATCH 06/14] Dialogue: add conflict resolution for overlapping keywords (Fixes #2245) --- apps/openmw/mwdialogue/hypertextparser.cpp | 10 +++-- apps/openmw/mwdialogue/keywordsearch.hpp | 47 ++++++++++++++++++---- apps/openmw/mwgui/dialogue.cpp | 9 +++-- apps/openmw/mwgui/journalviewmodel.cpp | 10 +++-- 4 files changed, 58 insertions(+), 18 deletions(-) diff --git a/apps/openmw/mwdialogue/hypertextparser.cpp b/apps/openmw/mwdialogue/hypertextparser.cpp index 776edac94..aa748e772 100644 --- a/apps/openmw/mwdialogue/hypertextparser.cpp +++ b/apps/openmw/mwdialogue/hypertextparser.cpp @@ -56,13 +56,17 @@ namespace MWDialogue keywordList.sort(Misc::StringUtils::ciLess); KeywordSearch keywordSearch; - KeywordSearch::Match match; for (std::list::const_iterator it = keywordList.begin(); it != keywordList.end(); ++it) keywordSearch.seed(*it, 0 /*unused*/); - for (std::string::const_iterator it = text.begin(); it != text.end() && keywordSearch.search(it, text.end(), match, text.begin()); it = match.mEnd) - tokens.push_back(Token(std::string(match.mBeg, match.mEnd), Token::ImplicitKeyword)); + std::vector::Match> matches; + keywordSearch.highlightKeywords(text.begin(), text.end(), matches); + + for (std::vector::Match>::const_iterator it = matches.begin(); it != matches.end(); ++it) + { + tokens.push_back(Token(std::string(it->mBeg, it->mEnd), Token::ImplicitKeyword)); + } } size_t removePseudoAsterisks(std::string & phrase) diff --git a/apps/openmw/mwdialogue/keywordsearch.hpp b/apps/openmw/mwdialogue/keywordsearch.hpp index 51508890c..5ce492441 100644 --- a/apps/openmw/mwdialogue/keywordsearch.hpp +++ b/apps/openmw/mwdialogue/keywordsearch.hpp @@ -66,19 +66,20 @@ public: return false; } - bool search (Point beg, Point end, Match & match, Point start) + void highlightKeywords (Point beg, Point end, std::vector& out) { for (Point i = beg; i != end; ++i) { // check if previous character marked start of new word - if (i != start) + if (i != beg) { Point prev = i; - --prev; + --prev; if(isalpha(*prev)) continue; } + // check first character typename Entry::childen_t::iterator candidate = mRoot.mChildren.find (std::tolower (*i, mLocale)); @@ -137,16 +138,48 @@ public: if (t != candidate->second.mKeyword.end ()) continue; - // we did it, report the good news + // found a keyword, but there might still be longer keywords that start somewhere _within_ this keyword + // we will resolve these overlapping keywords later, choosing the longest one in case of conflict + Match match; match.mValue = candidate->second.mValue; match.mBeg = i; match.mEnd = k; - return true; + out.push_back(match); + break; } } - // no match in range, report the bad news - return false; + // resolve overlapping keywords + for (typename std::vector::iterator it = out.begin(); it != out.end();) + { + typename std::vector::iterator next = it; + ++next; + + if (next == out.end()) + break; + + if (it->mEnd <= next->mBeg) + { + ++it; + continue; // no overlap + } + else + { + // prefer the longer keyword + int size = it->mEnd - it->mBeg; + int nextSize = next->mEnd - next->mBeg; + if (size >= nextSize) // if both are the same length, then prefer the first keyword + { + out.erase(next); + continue; + } + else + { + it = out.erase(it); + continue; + } + } + } } private: diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index e1e016714..db9fa9f6b 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -177,11 +177,13 @@ namespace MWGui } else { - std::string::const_iterator i = text.begin (); - KeywordSearchT::Match match; + std::vector matches; + keywordSearch->highlightKeywords(text.begin(), text.end(), matches); - while (i != text.end () && keywordSearch->search (i, text.end (), match, text.begin ())) + std::string::const_iterator i = text.begin (); + for (std::vector::iterator it = matches.begin(); it != matches.end(); ++it) { + KeywordSearchT::Match match = *it; if (i != match.mBeg) addTopicLink (typesetter, 0, i - text.begin (), match.mBeg - text.begin ()); @@ -189,7 +191,6 @@ namespace MWGui i = match.mEnd; } - if (i != text.end ()) addTopicLink (typesetter, 0, i - text.begin (), text.size ()); } diff --git a/apps/openmw/mwgui/journalviewmodel.cpp b/apps/openmw/mwgui/journalviewmodel.cpp index 059af463f..add2ac62c 100644 --- a/apps/openmw/mwgui/journalviewmodel.cpp +++ b/apps/openmw/mwgui/journalviewmodel.cpp @@ -174,12 +174,14 @@ struct JournalViewModelImpl : JournalViewModel } else { + std::vector matches; + mModel->mKeywordSearch.highlightKeywords(utf8text.begin(), utf8text.end(), matches); + std::string::const_iterator i = utf8text.begin (); - - KeywordSearchT::Match match; - - while (i != utf8text.end () && mModel->mKeywordSearch.search (i, utf8text.end (), match, utf8text.begin())) + for (std::vector::const_iterator it = matches.begin(); it != matches.end(); ++it) { + const KeywordSearchT::Match& match = *it; + if (i != match.mBeg) visitor (0, i - utf8text.begin (), match.mBeg - utf8text.begin ()); From 65ab31eae6d069a9f835f637dc507780116e83b8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 9 Jan 2015 04:31:02 +0100 Subject: [PATCH 07/14] Remove now redundant Store::setUp implementation --- apps/openmw/mwworld/store.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index 71e77d0c7..f3a5aad11 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -217,9 +217,6 @@ namespace MWWorld } void setUp() { - // remove the dynamic part of mShared - if (mShared.size() > mStatic.size()) - mShared.erase(mShared.begin() + mStatic.size(), mShared.end()); } iterator begin() const { From ce2cbab4025204ccf643d6ef1ecd4dc4e18bad35 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 9 Jan 2015 20:08:52 +0100 Subject: [PATCH 08/14] Dialogue: improve conflict resolution for chains of overlapping keywords (unit test for such a case will follow) --- apps/openmw/mwdialogue/keywordsearch.hpp | 61 +++++++++++++++--------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/apps/openmw/mwdialogue/keywordsearch.hpp b/apps/openmw/mwdialogue/keywordsearch.hpp index 5ce492441..c44139f32 100644 --- a/apps/openmw/mwdialogue/keywordsearch.hpp +++ b/apps/openmw/mwdialogue/keywordsearch.hpp @@ -66,8 +66,14 @@ public: return false; } + static bool sortMatches(const Match& left, const Match& right) + { + return left.mBeg < right.mBeg; + } + void highlightKeywords (Point beg, Point end, std::vector& out) { + std::vector matches; for (Point i = beg; i != end; ++i) { // check if previous character marked start of new word @@ -144,42 +150,51 @@ public: match.mValue = candidate->second.mValue; match.mBeg = i; match.mEnd = k; - out.push_back(match); + matches.push_back(match); break; } } // resolve overlapping keywords - for (typename std::vector::iterator it = out.begin(); it != out.end();) + while (matches.size()) { - typename std::vector::iterator next = it; - ++next; - - if (next == out.end()) - break; - - if (it->mEnd <= next->mBeg) + int longestKeywordSize = 0; + typename std::vector::iterator longestKeyword; + for (typename std::vector::iterator it = matches.begin(); it != matches.end(); ++it) { - ++it; - continue; // no overlap - } - else - { - // prefer the longer keyword int size = it->mEnd - it->mBeg; - int nextSize = next->mEnd - next->mBeg; - if (size >= nextSize) // if both are the same length, then prefer the first keyword + if (size > longestKeywordSize) { - out.erase(next); - continue; + longestKeywordSize = size; + longestKeyword = it; } + + typename std::vector::iterator next = it; + ++next; + + if (next == matches.end()) + break; + + if (it->mEnd <= next->mBeg) + { + break; // no overlap + } + } + + Match keyword = *longestKeyword; + matches.erase(longestKeyword); + out.push_back(keyword); + // erase anything that overlaps with the keyword we just added to the output + for (typename std::vector::iterator it = matches.begin(); it != matches.end();) + { + if (it->mBeg < keyword.mEnd && it->mEnd > keyword.mBeg) + it = matches.erase(it); else - { - it = out.erase(it); - continue; - } + ++it; } } + + std::sort(out.begin(), out.end(), sortMatches); } private: From 9d07edda1394b479a5bf6bf6b751fc4ba073622c Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 9 Jan 2015 20:48:36 +0100 Subject: [PATCH 09/14] UnitTests: remove GMock which wasn't used anyway, and the gmock headers fail to compile together with gtest on ubuntu 14.04 --- CMakeLists.txt | 2 +- apps/openmw_test_suite/CMakeLists.txt | 11 +-- apps/openmw_test_suite/openmw_test_suite.cpp | 12 +-- cmake/FindGMock.cmake | 91 -------------------- 4 files changed, 6 insertions(+), 110 deletions(-) delete mode 100644 cmake/FindGMock.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 323b743bc..60c37d0f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,7 +61,7 @@ option(BUILD_MWINIIMPORTER "build MWiniImporter" ON) option(BUILD_OPENCS "build OpenMW Construction Set" ON) option(BUILD_WIZARD "build Installation Wizard" ON) option(BUILD_WITH_CODE_COVERAGE "Enable code coverage with gconv" OFF) -option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest and GMock frameworks" OFF) +option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest" OFF) option(BUILD_NIFTEST "build nif file tester" OFF) option(BUILD_MYGUI_PLUGIN "build MyGUI plugin for OpenMW resources, to use with MyGUI tools" ON) diff --git a/apps/openmw_test_suite/CMakeLists.txt b/apps/openmw_test_suite/CMakeLists.txt index 9fe7890ac..44354eac8 100644 --- a/apps/openmw_test_suite/CMakeLists.txt +++ b/apps/openmw_test_suite/CMakeLists.txt @@ -1,14 +1,7 @@ -# TODO: This should not be needed, check how it was done in FindGTEST -set(GMOCK_ROOT "/usr/include") -set(GMOCK_BUILD "/usr/lib") - find_package(GTest REQUIRED) -find_package(GMock REQUIRED) - -if (GTEST_FOUND AND GMOCK_FOUND) +if (GTEST_FOUND) include_directories(${GTEST_INCLUDE_DIRS}) - include_directories(${GMOCK_INCLUDE_DIRS}) file(GLOB UNITTEST_SRC_FILES components/misc/test_*.cpp @@ -18,7 +11,7 @@ if (GTEST_FOUND AND GMOCK_FOUND) add_executable(openmw_test_suite openmw_test_suite.cpp ${UNITTEST_SRC_FILES}) - target_link_libraries(openmw_test_suite ${GMOCK_BOTH_LIBRARIES} ${GTEST_BOTH_LIBRARIES} components) + target_link_libraries(openmw_test_suite ${GTEST_BOTH_LIBRARIES} components) # Fix for not visible pthreads functions for linker with glibc 2.15 if (UNIX AND NOT APPLE) target_link_libraries(openmw_test_suite ${CMAKE_THREAD_LIBS_INIT}) diff --git a/apps/openmw_test_suite/openmw_test_suite.cpp b/apps/openmw_test_suite/openmw_test_suite.cpp index 81476325e..7cc76b25b 100644 --- a/apps/openmw_test_suite/openmw_test_suite.cpp +++ b/apps/openmw_test_suite/openmw_test_suite.cpp @@ -1,12 +1,6 @@ -#include #include - -int main(int argc, char** argv) { - // The following line causes Google Mock to throw an exception on failure, - // which will be interpreted by your testing framework as a test failure. - ::testing::GTEST_FLAG(throw_on_failure) = false; - ::testing::InitGoogleMock(&argc, argv); - - return RUN_ALL_TESTS(); +GTEST_API_ int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); } diff --git a/cmake/FindGMock.cmake b/cmake/FindGMock.cmake deleted file mode 100644 index eda7d4d72..000000000 --- a/cmake/FindGMock.cmake +++ /dev/null @@ -1,91 +0,0 @@ -# Locate the Google C++ Mocking Framework. -# -# Defines the following variables: -# -# GMOCK_FOUND - Found the Google Mocking framework -# GMOCK_INCLUDE_DIRS - Include directories -# -# Also defines the library variables below as normal -# variables. These contain debug/optimized keywords when -# a debugging library is found. -# -# GMOCK_BOTH_LIBRARIES - Both libgmock & libgmock-main -# GMOCK_LIBRARIES - libgmock -# GMOCK_MAIN_LIBRARIES - libgmock-main -# -# Accepts the following variables as input: -# -# GMOCK_ROOT - (as CMake or env. variable) -# The root directory of the gmock install prefix -# -#----------------------- -# Example Usage: -# -# enable_testing(true) -# find_package(GMock REQUIRED) -# include_directories(${GMOCK_INCLUDE_DIRS}) -# -# add_executable(foo foo.cc) -# target_link_libraries(foo ${GMOCK_BOTH_LIBRARIES}) -# -# add_test(AllTestsInFoo foo) -# - -#set (GMOCK_FOUND FALSE) - - -#set (GMOCK_ROOT $ENV{GMOCK_ROOT} CACHE PATH "Path to the gmock root directory.") -if (NOT EXISTS ${GMOCK_ROOT}) - message (FATAL_ERROR "GMOCK_ROOT does not exist.") -endif () - -#set (GMOCK_BUILD ${GMOCK_ROOT}/build CACHE PATH "Path to the gmock build directory.") -if (NOT EXISTS ${GMOCK_BUILD}) - message (FATAL_ERROR "GMOCK_BUILD does not exist.") -endif () - -# Find the include directory -find_path(GMOCK_INCLUDE_DIRS gmock/gmock.h - HINTS - $ENV{GMOCK_ROOT}/include - ${GMOCK_ROOT}/include -) -mark_as_advanced(GMOCK_INCLUDE_DIRS) - -function(_gmock_find_library _name) - find_library(${_name} - NAMES ${ARGN} - HINTS - $ENV{GMOCK_BUILD} - ${GMOCK_BUILD} - ) - mark_as_advanced(${_name}) -endfunction() - -# Find the gmock libraries -if (MSVC) - _gmock_find_library (GMOCK_LIBRARIES_DEBUG gmock ${GMOCK_BUILD}/Debug) - _gmock_find_library (GMOCK_LIBRARIES_RELEASE gmock ${GMOCK_BUILD}/Release) - _gmock_find_library (GMOCK_MAIN_LIBRARIES_DEBUG gmock_main ${GMOCK_BUILD}/Debug) - _gmock_find_library (GMOCK_MAIN_LIBRARIES_RELEASE gmock_main ${GMOCK_BUILD}/Release) - set (GMOCK_LIBRARIES - debug ${GMOCK_LIBRARIES_DEBUG} - optimized ${GMOCK_LIBRARIES_RELEASE} - ) - set (GMOCK_MAIN_LIBRARIES - debug ${GMOCK_MAIN_LIBRARIES_DEBUG} - optimized ${GMOCK_MAIN_LIBRARIES_RELEASE} - ) -else () - _gmock_find_library (GMOCK_LIBRARIES gmock ${GMOCK_BUILD}) - _gmock_find_library (GMOCK_MAIN_LIBRARIES gmock_main ${GMOCK_BUILD} ${GMOCK_BUILD}/Debug) -endif () - -FIND_PACKAGE_HANDLE_STANDARD_ARGS(GMock DEFAULT_MSG GMOCK_LIBRARIES GMOCK_INCLUDE_DIRS GMOCK_MAIN_LIBRARIES) - -if(GMOCK_FOUND) - set(GMOCK_INCLUDE_DIRS ${GMOCK_INCLUDE_DIR}) - set(GMOCK_BOTH_LIBRARIES ${GMOCK_LIBRARIES} ${GMOCK_MAIN_LIBRARIES}) -endif() - - From 1b302b750cca4b6f88cb4794b97739acc140480c Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 9 Jan 2015 20:52:31 +0100 Subject: [PATCH 10/14] UnitTests: add tests for KeywordSearch conflict resolution --- apps/openmw_test_suite/CMakeLists.txt | 1 + .../mwdialogue/test_keywordsearch.cpp | 48 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 apps/openmw_test_suite/mwdialogue/test_keywordsearch.cpp diff --git a/apps/openmw_test_suite/CMakeLists.txt b/apps/openmw_test_suite/CMakeLists.txt index 44354eac8..2ffb7ffa0 100644 --- a/apps/openmw_test_suite/CMakeLists.txt +++ b/apps/openmw_test_suite/CMakeLists.txt @@ -5,6 +5,7 @@ if (GTEST_FOUND) file(GLOB UNITTEST_SRC_FILES components/misc/test_*.cpp + mwdialogue/test_*.cpp ) source_group(apps\\openmw_test_suite FILES openmw_test_suite.cpp ${UNITTEST_SRC_FILES}) diff --git a/apps/openmw_test_suite/mwdialogue/test_keywordsearch.cpp b/apps/openmw_test_suite/mwdialogue/test_keywordsearch.cpp new file mode 100644 index 000000000..c8ea9d01c --- /dev/null +++ b/apps/openmw_test_suite/mwdialogue/test_keywordsearch.cpp @@ -0,0 +1,48 @@ +#include +#include "apps/openmw/mwdialogue/keywordsearch.hpp" + +struct KeywordSearchTest : public ::testing::Test +{ + protected: + virtual void SetUp() + { + } + + virtual void TearDown() + { + } +}; + +TEST_F(KeywordSearchTest, keyword_test_conflict_resolution) +{ + // test to make sure the longest keyword in a chain of conflicting keywords gets chosen + MWDialogue::KeywordSearch search; + search.seed("foo bar", 0); + search.seed("bar lock", 0); + search.seed("lock switch", 0); + + std::string text = "foo bar lock switch"; + + std::vector::Match> matches; + search.highlightKeywords(text.begin(), text.end(), matches); + + // Should contain: "foo bar", "lock switch" + ASSERT_TRUE (matches.size() == 2); + ASSERT_TRUE (std::string(matches.front().mBeg, matches.front().mEnd) == "foo bar"); + ASSERT_TRUE (std::string(matches.rbegin()->mBeg, matches.rbegin()->mEnd) == "lock switch"); +} + +TEST_F(KeywordSearchTest, keyword_test_conflict_resolution2) +{ + MWDialogue::KeywordSearch search; + search.seed("the dwemer", 0); + search.seed("dwemer language", 0); + + std::string text = "the dwemer language"; + + std::vector::Match> matches; + search.highlightKeywords(text.begin(), text.end(), matches); + + ASSERT_TRUE (matches.size() == 1); + ASSERT_TRUE (std::string(matches.front().mBeg, matches.front().mEnd) == "dwemer language"); +} From dfdf26e95e93981f4fa6ff0b3a0de0215d89266e Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 9 Jan 2015 20:58:53 +0100 Subject: [PATCH 11/14] Add assertion to Store --- apps/openmw/mwworld/store.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index f3a5aad11..d9e4285fe 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -140,8 +140,8 @@ namespace MWWorld virtual void clearDynamic() { // remove the dynamic part of mShared - if (mShared.size() > mStatic.size()) - mShared.erase(mShared.begin() + mStatic.size(), mShared.end()); + assert(mShared.size() >= mStatic.size()); + mShared.erase(mShared.begin() + mStatic.size(), mShared.end()); mDynamic.clear(); } @@ -304,8 +304,8 @@ namespace MWWorld mDynamic.erase(it); // have to reinit the whole shared part - if (mShared.size() > mStatic.size()) - mShared.erase(mShared.begin() + mStatic.size(), mShared.end()); + assert(mShared.size() >= mStatic.size()); + mShared.erase(mShared.begin() + mStatic.size(), mShared.end()); for (it = mDynamic.begin(); it != mDynamic.end(); ++it) { mShared.push_back(&it->second); } From efbc8742a03b9037f465ce6bb350f9a4675bb34a Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 9 Jan 2015 21:13:57 +0100 Subject: [PATCH 12/14] Remove some unnecessary includes --- components/misc/stringops.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/components/misc/stringops.cpp b/components/misc/stringops.cpp index 0f801e554..723c1c1e0 100644 --- a/components/misc/stringops.cpp +++ b/components/misc/stringops.cpp @@ -1,14 +1,5 @@ #include "stringops.hpp" -#include -#include -#include - -#include -#include - - - namespace Misc { From 2ac23008f5eec975f444a2cd72cba49745d1c579 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 10 Jan 2015 00:07:40 +0100 Subject: [PATCH 13/14] Remove an old workaround (Fixes #2263) The workaround was added when we were still using OIS for input. It doesn't seem to be needed with SDL. --- apps/openmw/mwinput/inputmanagerimp.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 2f6149f09..ece189c75 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -409,8 +409,7 @@ namespace MWInput if (mControlSwitch["playerviewswitch"]) { - // work around preview mode toggle when pressing Alt+Tab - if (actionIsActive(A_TogglePOV) && !mInputManager->isModifierHeld(SDL_Keymod(KMOD_ALT))) { + if (actionIsActive(A_TogglePOV)) { if (mPreviewPOVDelay <= 0.5 && (mPreviewPOVDelay += dt) > 0.5) { From 66e7e0480717164fabbd4aae1e5190771db85d0c Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 10 Jan 2015 00:26:13 +0100 Subject: [PATCH 14/14] UnitTests: add another dialogue keyword test --- .../mwdialogue/test_keywordsearch.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/apps/openmw_test_suite/mwdialogue/test_keywordsearch.cpp b/apps/openmw_test_suite/mwdialogue/test_keywordsearch.cpp index c8ea9d01c..e0e1871d2 100644 --- a/apps/openmw_test_suite/mwdialogue/test_keywordsearch.cpp +++ b/apps/openmw_test_suite/mwdialogue/test_keywordsearch.cpp @@ -46,3 +46,22 @@ TEST_F(KeywordSearchTest, keyword_test_conflict_resolution2) ASSERT_TRUE (matches.size() == 1); ASSERT_TRUE (std::string(matches.front().mBeg, matches.front().mEnd) == "dwemer language"); } + + +TEST_F(KeywordSearchTest, keyword_test_conflict_resolution3) +{ + // testing that the longest keyword is chosen, rather than maximizing the + // amount of highlighted characters by highlighting the first and last keyword + MWDialogue::KeywordSearch search; + search.seed("foo bar", 0); + search.seed("bar lock", 0); + search.seed("lock so", 0); + + std::string text = "foo bar lock so"; + + std::vector::Match> matches; + search.highlightKeywords(text.begin(), text.end(), matches); + + ASSERT_TRUE (matches.size() == 1); + ASSERT_TRUE (std::string(matches.front().mBeg, matches.front().mEnd) == "bar lock"); +}