1. Dialogs in Russian version now works.

2. Destination names it travel window are now translated
actorid
lazydev 12 years ago
parent 2736e84e49
commit cd5d95ed22

@ -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;
};
}

@ -52,7 +52,7 @@ namespace
return lowerCase;
}
bool stringCompareNoCase (std::string first, std::string second)
bool stringCompareNoCase (const std::string& first, const std::string& second)
{
unsigned int i=0;
while ( (i<first.length()) && (i<second.length()) )
@ -76,11 +76,12 @@ namespace
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;
@ -105,15 +106,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 = find_str_ci(text,*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 = find_str_ci(hypertext[i].mText, *it, 0);
if(pos !=std::string::npos)
{
mKnownTopics[*it] = true;
}
}
}
}
updateTopics();
}
@ -156,7 +186,7 @@ namespace MWDialogue
}
parseText (info->mResponse);
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
win->addText (Interpreter::fixDefinesDialog(info->mResponse, interpreterContext));
executeScript (info->mResultScript);
@ -298,7 +328,7 @@ namespace MWDialogue
{
if (filter.search (*iter))
{
mActorKnownTopics.push_back (toLower (iter->mId));
mActorKnownTopics.push_back(toLower (iter->mId));
//does the player know the topic?
if (mKnownTopics.find (toLower (iter->mId)) != mKnownTopics.end())
@ -415,7 +445,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);
@ -499,4 +529,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();
}
}
@ -131,6 +132,7 @@ DialogueWindow::DialogueWindow(MWBase::WindowManager& parWindowManager)
, mPersuasionDialog(parWindowManager)
, mEnabled(false)
, mServices(0)
, mWindowManager(parWindowManager)
{
// Centre dialog
center();
@ -180,9 +182,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 +281,7 @@ void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName)
setTitle(npcName);
mTopicsList->clear();
mHyperLinks.clear();
mHistory->setCaption("");
updateOptions();
}
@ -340,7 +364,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 +382,55 @@ 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)
{
historySize = mHistory->getOnlyText().size();
}
std::string result;
size_t hypertextPos = 0;
for (size_t i = 0; i < hypertext.size(); ++i)
{
addColorInString(text,*it,"#686EBA","#B29154");
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 =
mWindowManager.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 text;
return result;
}
void DialogueWindow::addText(std::string text)
@ -394,6 +462,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())

@ -92,12 +92,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;
@ -109,6 +115,10 @@ namespace MWGui
MyGUI::EditPtr mDispositionText;
PersuasionDialog mPersuasionDialog;
MWBase::WindowManager& mWindowManager;
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);

@ -1050,3 +1050,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…
Cancel
Save