mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-19 20:23:54 +00:00
Merge remote-tracking branch 'lazydev/master'
This commit is contained in:
commit
4a8bf40a83
11 changed files with 232 additions and 31 deletions
|
@ -360,7 +360,7 @@ void OMW::Engine::go()
|
|||
|
||||
// Create dialog system
|
||||
mEnvironment.setJournal (new MWDialogue::Journal);
|
||||
mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions, mVerboseScripts));
|
||||
mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions, mVerboseScripts, mTranslationDataStorage));
|
||||
|
||||
// Sets up the input system
|
||||
mEnvironment.setInputManager (new MWInput::InputManager (*mOgre,
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include <components/translation/translation.hpp>
|
||||
|
||||
#include "../mwmechanics/stat.hpp"
|
||||
|
||||
#include "../mwgui/mode.hpp"
|
||||
|
@ -233,6 +235,8 @@ namespace MWBase
|
|||
virtual void startSpellMaking(MWWorld::Ptr actor) = 0;
|
||||
virtual void startEnchanting(MWWorld::Ptr actor) = 0;
|
||||
virtual void startTraining(MWWorld::Ptr actor) = 0;
|
||||
|
||||
virtual const Translation::Storage& getTranslationDataStorage() const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -42,11 +42,12 @@
|
|||
|
||||
namespace MWDialogue
|
||||
{
|
||||
DialogueManager::DialogueManager (const Compiler::Extensions& extensions, bool scriptVerbose) :
|
||||
DialogueManager::DialogueManager (const Compiler::Extensions& extensions, bool scriptVerbose, Translation::Storage& translationDataStorage) :
|
||||
mCompilerContext (MWScript::CompilerContext::Type_Dialgoue),
|
||||
mErrorStream(std::cout.rdbuf()),mErrorHandler(mErrorStream)
|
||||
, mTemporaryDispositionChange(0.f)
|
||||
, mPermanentDispositionChange(0.f), mScriptVerbose (scriptVerbose)
|
||||
, mTranslationDataStorage(translationDataStorage)
|
||||
{
|
||||
mChoice = -1;
|
||||
mIsInChoice = false;
|
||||
|
@ -71,15 +72,44 @@ namespace MWDialogue
|
|||
|
||||
void DialogueManager::parseText (const std::string& text)
|
||||
{
|
||||
std::list<std::string>::iterator it;
|
||||
for(it = mActorKnownTopics.begin();it != mActorKnownTopics.end();++it)
|
||||
std::vector<HyperTextToken> hypertext = ParseHyperText(text);
|
||||
|
||||
//calculation of standard form fir all hyperlinks
|
||||
for (size_t i = 0; i < hypertext.size(); ++i)
|
||||
{
|
||||
size_t pos = Misc::StringUtils::lowerCase(text).find(*it, 0);
|
||||
if(pos !=std::string::npos)
|
||||
if (hypertext[i].mLink)
|
||||
{
|
||||
mKnownTopics[*it] = true;
|
||||
size_t asterisk_count = MWDialogue::RemovePseudoAsterisks(hypertext[i].mText);
|
||||
for(; asterisk_count > 0; --asterisk_count)
|
||||
hypertext[i].mText.append("*");
|
||||
|
||||
hypertext[i].mText = mTranslationDataStorage.topicStandardForm(hypertext[i].mText);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < hypertext.size(); ++i)
|
||||
{
|
||||
std::list<std::string>::iterator it;
|
||||
for(it = mActorKnownTopics.begin(); it != mActorKnownTopics.end(); ++it)
|
||||
{
|
||||
if (hypertext[i].mLink)
|
||||
{
|
||||
if( hypertext[i].mText == *it )
|
||||
{
|
||||
mKnownTopics[hypertext[i].mText] = true;
|
||||
}
|
||||
}
|
||||
else if( !mTranslationDataStorage.hasTranslation() )
|
||||
{
|
||||
size_t pos = Misc::StringUtils::lowerCase(hypertext[i].mText).find(*it, 0);
|
||||
if(pos !=std::string::npos)
|
||||
{
|
||||
mKnownTopics[*it] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateTopics();
|
||||
}
|
||||
|
||||
|
@ -122,7 +152,7 @@ namespace MWDialogue
|
|||
}
|
||||
|
||||
parseText (info->mResponse);
|
||||
|
||||
|
||||
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
|
||||
win->addText (Interpreter::fixDefinesDialog(info->mResponse, interpreterContext));
|
||||
executeScript (info->mResultScript);
|
||||
|
@ -382,7 +412,7 @@ namespace MWDialogue
|
|||
mIsInChoice = false;
|
||||
std::string text = info->mResponse;
|
||||
parseText (text);
|
||||
|
||||
|
||||
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
|
||||
MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addText (Interpreter::fixDefinesDialog(text, interpreterContext));
|
||||
executeScript (info->mResultScript);
|
||||
|
@ -466,4 +496,57 @@ namespace MWDialogue
|
|||
{
|
||||
mTemporaryDispositionChange += delta;
|
||||
}
|
||||
|
||||
std::vector<HyperTextToken> ParseHyperText(const std::string& text)
|
||||
{
|
||||
std::vector<HyperTextToken> result;
|
||||
|
||||
MyGUI::UString utext(text);
|
||||
|
||||
size_t pos_begin, pos_end, iteration_pos = 0;
|
||||
for(;;)
|
||||
{
|
||||
pos_begin = utext.find('@', iteration_pos);
|
||||
if (pos_begin != std::string::npos)
|
||||
pos_end = utext.find('#', pos_begin);
|
||||
|
||||
if (pos_begin != std::string::npos && pos_end != std::string::npos)
|
||||
{
|
||||
result.push_back( HyperTextToken(utext.substr(iteration_pos, pos_begin - iteration_pos), false) );
|
||||
|
||||
std::string link = utext.substr(pos_begin + 1, pos_end - pos_begin - 1);
|
||||
result.push_back( HyperTextToken(link, true) );
|
||||
|
||||
iteration_pos = pos_end + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back( HyperTextToken(utext.substr(iteration_pos), false) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t RemovePseudoAsterisks(std::string& phrase)
|
||||
{
|
||||
size_t pseudoAsterisksCount = 0;
|
||||
const char specialPseudoAsteriskCharacter = 127;
|
||||
|
||||
if( !phrase.empty() )
|
||||
{
|
||||
std::string::reverse_iterator rit = phrase.rbegin();
|
||||
|
||||
while( rit != phrase.rend() && *rit == specialPseudoAsteriskCharacter )
|
||||
{
|
||||
pseudoAsterisksCount++;
|
||||
++rit;
|
||||
}
|
||||
}
|
||||
|
||||
phrase = phrase.substr(0, phrase.length() - pseudoAsterisksCount);
|
||||
|
||||
return pseudoAsterisksCount;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <list>
|
||||
|
||||
#include <components/compiler/streamerrorhandler.hpp>
|
||||
#include <components/translation/translation.hpp>
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
||||
|
@ -20,6 +21,7 @@ namespace MWDialogue
|
|||
std::map<std::string, bool> mKnownTopics;// Those are the topics the player knows.
|
||||
std::list<std::string> mActorKnownTopics;
|
||||
|
||||
Translation::Storage& mTranslationDataStorage;
|
||||
MWScript::CompilerContext mCompilerContext;
|
||||
std::ostream mErrorStream;
|
||||
Compiler::StreamErrorHandler mErrorHandler;
|
||||
|
@ -50,7 +52,7 @@ namespace MWDialogue
|
|||
|
||||
public:
|
||||
|
||||
DialogueManager (const Compiler::Extensions& extensions, bool scriptVerbose);
|
||||
DialogueManager (const Compiler::Extensions& extensions, bool scriptVerbose, Translation::Storage& translationDataStorage);
|
||||
|
||||
virtual void startDialogue (const MWWorld::Ptr& actor);
|
||||
|
||||
|
@ -72,6 +74,21 @@ namespace MWDialogue
|
|||
virtual int getTemporaryDispositionChange () const;
|
||||
virtual void applyTemporaryDispositionChange (int delta);
|
||||
};
|
||||
|
||||
|
||||
struct HyperTextToken
|
||||
{
|
||||
HyperTextToken(const std::string& text, bool link) : mText(text), mLink(link) {}
|
||||
|
||||
std::string mText;
|
||||
bool mLink;
|
||||
};
|
||||
|
||||
// In translations (at least Russian) the links are marked with @#, so
|
||||
// it should be a function to parse it
|
||||
std::vector<HyperTextToken> ParseHyperText(const std::string& text);
|
||||
|
||||
size_t RemovePseudoAsterisks(std::string& phrase);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
#include "../mwmechanics/npcstats.hpp"
|
||||
|
||||
#include "../mwdialogue/dialoguemanagerimp.hpp"
|
||||
|
||||
#include "dialogue_history.hpp"
|
||||
#include "widgets.hpp"
|
||||
#include "list.hpp"
|
||||
|
@ -52,7 +54,6 @@ bool sortByLength (const std::string& left, const std::string& right)
|
|||
{
|
||||
return left.size() > right.size();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -180,9 +181,30 @@ void DialogueWindow::onHistoryClicked(MyGUI::Widget* _sender)
|
|||
if(color != "#B29154")
|
||||
{
|
||||
MyGUI::UString key = mHistory->getColorTextAt(cursorPosition);
|
||||
if(color == "#686EBA") MWBase::Environment::get().getDialogueManager()->keywordSelected(lower_string(key));
|
||||
|
||||
if(color == "#572D21") MWBase::Environment::get().getDialogueManager()->questionAnswered(lower_string(key));
|
||||
if(color == "#686EBA")
|
||||
{
|
||||
std::map<size_t, HyperLink>::iterator i = mHyperLinks.upper_bound(cursorPosition);
|
||||
if( !mHyperLinks.empty() )
|
||||
{
|
||||
--i;
|
||||
|
||||
if( i->first + i->second.mLength > cursorPosition)
|
||||
{
|
||||
MWBase::Environment::get().getDialogueManager()->keywordSelected(i->second.mTrueValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// the link was colored, but it is not in mHyperLinks.
|
||||
// It means that those liunks are not marked with @# and found
|
||||
// by topic name search
|
||||
MWBase::Environment::get().getDialogueManager()->keywordSelected(lower_string(key));
|
||||
}
|
||||
}
|
||||
|
||||
if(color == "#572D21")
|
||||
MWBase::Environment::get().getDialogueManager()->questionAnswered(lower_string(key));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,6 +280,7 @@ void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName)
|
|||
setTitle(npcName);
|
||||
|
||||
mTopicsList->clear();
|
||||
mHyperLinks.clear();
|
||||
mHistory->setCaption("");
|
||||
updateOptions();
|
||||
}
|
||||
|
@ -340,7 +363,7 @@ void addColorInString(std::string& str, const std::string& keyword,std::string c
|
|||
}
|
||||
}
|
||||
|
||||
std::string DialogueWindow::parseText(std::string text)
|
||||
std::string DialogueWindow::parseText(const std::string& text)
|
||||
{
|
||||
bool separatorReached = false; // only parse topics that are below the separator (this prevents actions like "Barter" that are not topics from getting blue-colored)
|
||||
|
||||
|
@ -358,11 +381,56 @@ std::string DialogueWindow::parseText(std::string text)
|
|||
// sort by length to make sure longer topics are replaced first
|
||||
std::sort(topics.begin(), topics.end(), sortByLength);
|
||||
|
||||
for(std::vector<std::string>::const_iterator it = topics.begin(); it != topics.end(); ++it)
|
||||
std::vector<MWDialogue::HyperTextToken> hypertext = MWDialogue::ParseHyperText(text);
|
||||
|
||||
size_t historySize = 0;
|
||||
if(mHistory->getClient()->getSubWidgetText() != nullptr)
|
||||
{
|
||||
addColorInString(text,*it,"#686EBA","#B29154");
|
||||
historySize = mHistory->getOnlyText().size();
|
||||
}
|
||||
return text;
|
||||
|
||||
std::string result;
|
||||
size_t hypertextPos = 0;
|
||||
for (size_t i = 0; i < hypertext.size(); ++i)
|
||||
{
|
||||
if (hypertext[i].mLink)
|
||||
{
|
||||
size_t asterisk_count = MWDialogue::RemovePseudoAsterisks(hypertext[i].mText);
|
||||
std::string standardForm = hypertext[i].mText;
|
||||
for(; asterisk_count > 0; --asterisk_count)
|
||||
standardForm.append("*");
|
||||
|
||||
standardForm =
|
||||
MWBase::Environment::get().getWindowManager()->
|
||||
getTranslationDataStorage().topicStandardForm(standardForm);
|
||||
|
||||
if( std::find(topics.begin(), topics.end(), std::string(standardForm) ) != topics.end() )
|
||||
{
|
||||
result.append("#686EBA").append(hypertext[i].mText).append("#B29154");
|
||||
|
||||
mHyperLinks[historySize+hypertextPos].mLength = MyGUI::UString(hypertext[i].mText).length();
|
||||
mHyperLinks[historySize+hypertextPos].mTrueValue = lower_string(standardForm);
|
||||
}
|
||||
else
|
||||
result += hypertext[i].mText;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !mWindowManager.getTranslationDataStorage().hasTranslation() )
|
||||
{
|
||||
for(std::vector<std::string>::const_iterator it = topics.begin(); it != topics.end(); ++it)
|
||||
{
|
||||
addColorInString(hypertext[i].mText, *it, "#686EBA", "#B29154");
|
||||
}
|
||||
}
|
||||
|
||||
result += hypertext[i].mText;
|
||||
}
|
||||
|
||||
hypertextPos += MyGUI::UString(hypertext[i].mText).length();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void DialogueWindow::addText(std::string text)
|
||||
|
@ -399,6 +467,7 @@ void DialogueWindow::updateOptions()
|
|||
{
|
||||
//Clear the list of topics
|
||||
mTopicsList->clear();
|
||||
mHyperLinks.clear();
|
||||
mHistory->eraseText(0, mHistory->getTextLength());
|
||||
|
||||
if (mPtr.getTypeName() == typeid(ESM::NPC).name())
|
||||
|
|
|
@ -93,12 +93,18 @@ namespace MWGui
|
|||
|
||||
virtual void onReferenceUnavailable();
|
||||
|
||||
struct HyperLink
|
||||
{
|
||||
size_t mLength;
|
||||
std::string mTrueValue;
|
||||
};
|
||||
|
||||
private:
|
||||
void updateOptions();
|
||||
/**
|
||||
*Helper function that add topic keyword in blue in a text.
|
||||
*/
|
||||
std::string parseText(std::string text);
|
||||
std::string parseText(const std::string& text);
|
||||
|
||||
int mServices;
|
||||
|
||||
|
@ -110,6 +116,8 @@ namespace MWGui
|
|||
MyGUI::EditPtr mDispositionText;
|
||||
|
||||
PersuasionDialog mPersuasionDialog;
|
||||
|
||||
std::map<size_t, HyperLink> mHyperLinks;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -82,7 +82,7 @@ namespace MWGui
|
|||
oss << price;
|
||||
toAdd->setUserString("price",oss.str());
|
||||
|
||||
toAdd->setCaptionWithReplacing(travelId+" - "+boost::lexical_cast<std::string>(price)+"#{sgp}");
|
||||
toAdd->setCaptionWithReplacing("#{sCell=" + travelId + "} - " + boost::lexical_cast<std::string>(price)+"#{sgp}");
|
||||
toAdd->setSize(toAdd->getTextSize().width,sLineHeight);
|
||||
toAdd->eventMouseWheel += MyGUI::newDelegate(this, &TravelWindow::onMouseWheel);
|
||||
toAdd->setUserString("Destination", travelId);
|
||||
|
|
|
@ -1055,3 +1055,8 @@ void WindowManager::startTraining(MWWorld::Ptr actor)
|
|||
{
|
||||
mTrainingWindow->startTraining(actor);
|
||||
}
|
||||
|
||||
const Translation::Storage& WindowManager::getTranslationDataStorage() const
|
||||
{
|
||||
return mTranslationDataStorage;
|
||||
}
|
||||
|
|
|
@ -225,6 +225,8 @@ namespace MWGui
|
|||
virtual void startEnchanting(MWWorld::Ptr actor);
|
||||
virtual void startTraining(MWWorld::Ptr actor);
|
||||
|
||||
virtual const Translation::Storage& getTranslationDataStorage() const;
|
||||
|
||||
private:
|
||||
OEngine::GUI::MyGUIManager *mGuiManager;
|
||||
HUD *mHud;
|
||||
|
|
|
@ -81,17 +81,7 @@ namespace Translation
|
|||
|
||||
std::string Storage::topicID(const std::string& phrase) const
|
||||
{
|
||||
std::string result;
|
||||
|
||||
//seeking for the standard phrase form
|
||||
std::map<std::string, std::string>::const_iterator phraseFormsIterator =
|
||||
mPhraseForms.find(phrase);
|
||||
|
||||
if (phraseFormsIterator != mPhraseForms.end())
|
||||
result = phraseFormsIterator->second;
|
||||
else
|
||||
result = phrase;
|
||||
|
||||
std::string result = topicStandardForm(phrase);
|
||||
|
||||
//seeking for the topic ID
|
||||
std::map<std::string, std::string>::const_iterator topicIDIterator =
|
||||
|
@ -103,8 +93,26 @@ namespace Translation
|
|||
return result;
|
||||
}
|
||||
|
||||
std::string Storage::topicStandardForm(const std::string& phrase) const
|
||||
{
|
||||
std::map<std::string, std::string>::const_iterator phraseFormsIterator =
|
||||
mPhraseForms.find(phrase);
|
||||
|
||||
if (phraseFormsIterator != mPhraseForms.end())
|
||||
return phraseFormsIterator->second;
|
||||
else
|
||||
return phrase;
|
||||
}
|
||||
|
||||
void Storage::setEncoding (const ToUTF8::FromType& encoding)
|
||||
{
|
||||
mEncoding = encoding;
|
||||
}
|
||||
|
||||
bool Storage::hasTranslation() const
|
||||
{
|
||||
return !mCellNamesTranslations.empty() ||
|
||||
!mTopicIDs.empty() ||
|
||||
!mPhraseForms.empty();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,8 +16,13 @@ namespace Translation
|
|||
std::string translateCellName(const std::string& cellName) const;
|
||||
std::string topicID(const std::string& phrase) const;
|
||||
|
||||
// Standard form usually means nominative case
|
||||
std::string topicStandardForm(const std::string& phrase) const;
|
||||
|
||||
void setEncoding (const ToUTF8::FromType& encoding);
|
||||
|
||||
bool hasTranslation() const;
|
||||
|
||||
private:
|
||||
typedef std::map<std::string, std::string> ContainerType;
|
||||
|
||||
|
@ -30,7 +35,7 @@ namespace Translation
|
|||
|
||||
|
||||
ToUTF8::FromType mEncoding;
|
||||
std::map<std::string, std::string> mCellNamesTranslations, mTopicIDs, mPhraseForms;
|
||||
ContainerType mCellNamesTranslations, mTopicIDs, mPhraseForms;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue