2010-11-03 20:21:08 +00:00
# include "dialogue.hpp"
# include <assert.h>
# include <iostream>
# include <iterator>
# include <boost/algorithm/string.hpp>
# include <boost/lexical_cast.hpp>
2012-05-17 15:15:44 +00:00
# include <components/esm_store/store.hpp>
# include "../mwbase/environment.hpp"
# include "../mwdialogue/dialoguemanager.hpp"
# include "dialogue_history.hpp"
# include "window_manager.hpp"
# include "widgets.hpp"
# include "list.hpp"
# include "tradewindow.hpp"
2012-05-17 19:15:48 +00:00
# include "inventorywindow.hpp"
2012-05-17 15:15:44 +00:00
2010-11-03 20:21:08 +00:00
using namespace MWGui ;
using namespace Widgets ;
2012-02-05 09:54:56 +00:00
/**
* Copied from the internet .
*/
std : : string lower_string ( const std : : string & str )
{
2012-02-10 15:21:04 +00:00
std : : string lowerCase ;
std : : transform ( str . begin ( ) , str . end ( ) , std : : back_inserter ( lowerCase ) ,
( int ( * ) ( int ) ) std : : tolower ) ;
return lowerCase ;
2012-02-05 09:54:56 +00:00
}
std : : string : : size_type find_str_ci ( const std : : string & str , const std : : string & substr , size_t pos )
{
return lower_string ( str ) . find ( lower_string ( substr ) , pos ) ;
}
2012-04-23 13:27:03 +00:00
DialogueWindow : : DialogueWindow ( WindowManager & parWindowManager )
: WindowBase ( " openmw_dialogue_window_layout.xml " , parWindowManager )
2012-05-11 05:18:41 +00:00
, mEnabled ( true )
2012-05-17 12:54:03 +00:00
, mShowTrade ( false )
2010-11-03 20:21:08 +00:00
{
// Centre dialog
2010-11-06 10:47:46 +00:00
center ( ) ;
2010-11-03 20:21:08 +00:00
//History view
getWidget ( history , " History " ) ;
history - > setOverflowToTheLeft ( true ) ;
2012-02-11 11:18:47 +00:00
history - > setMaxTextLength ( 1000000 ) ;
2012-03-22 14:01:37 +00:00
Widget * eventbox ;
//An EditBox cannot receive mouse click events, so we use an
//invisible widget on top of the editbox to receive them
getWidget ( eventbox , " EventBox " ) ;
eventbox - > eventMouseButtonClick + = MyGUI : : newDelegate ( this , & DialogueWindow : : onHistoryClicked ) ;
2012-04-29 22:57:41 +00:00
eventbox - > eventMouseWheel + = MyGUI : : newDelegate ( this , & DialogueWindow : : onMouseWheel ) ;
2012-04-23 13:27:03 +00:00
2012-03-19 18:21:08 +00:00
//Topics list
2010-11-03 20:21:08 +00:00
getWidget ( topicsList , " TopicsList " ) ;
2012-05-04 21:53:50 +00:00
topicsList - > eventItemSelected + = MyGUI : : newDelegate ( this , & DialogueWindow : : onSelectTopic ) ;
2010-11-03 20:21:08 +00:00
MyGUI : : ButtonPtr byeButton ;
getWidget ( byeButton , " ByeButton " ) ;
2012-03-21 12:27:08 +00:00
byeButton - > eventMouseButtonClick + = MyGUI : : newDelegate ( this , & DialogueWindow : : onByeClicked ) ;
2010-11-03 20:21:08 +00:00
2012-02-05 09:54:56 +00:00
getWidget ( pDispositionBar , " Disposition " ) ;
getWidget ( pDispositionText , " DispositionText " ) ;
2012-05-10 09:19:22 +00:00
static_cast < MyGUI : : Window * > ( mMainWidget ) - > eventWindowChangeCoord + = MyGUI : : newDelegate ( this , & DialogueWindow : : onWindowResize ) ;
2010-11-03 20:21:08 +00:00
}
void DialogueWindow : : onHistoryClicked ( MyGUI : : Widget * _sender )
{
2012-03-22 14:01:37 +00:00
ISubWidgetText * t = history - > getClient ( ) - > getSubWidgetText ( ) ;
2010-11-03 20:21:08 +00:00
if ( t = = nullptr )
return ;
2012-03-21 12:48:57 +00:00
const IntPoint & lastPressed = InputManager : : getInstance ( ) . getLastPressedPosition ( MyGUI : : MouseButton : : Left ) ;
2010-11-03 20:21:08 +00:00
size_t cursorPosition = t - > getCursorPosition ( lastPressed ) ;
2012-01-28 15:16:49 +00:00
MyGUI : : UString color = history - > getColorAtPos ( cursorPosition ) ;
2012-05-11 05:18:41 +00:00
if ( ! mEnabled & & color = = " #572D21 " )
MWBase : : Environment : : get ( ) . getDialogueManager ( ) - > goodbyeSelected ( ) ;
2012-01-28 15:16:49 +00:00
if ( color ! = " #B29154 " )
2010-11-03 20:21:08 +00:00
{
UString key = history - > getColorTextAt ( cursorPosition ) ;
2012-04-23 13:27:03 +00:00
if ( color = = " #686EBA " ) MWBase : : Environment : : get ( ) . getDialogueManager ( ) - > keywordSelected ( lower_string ( key ) ) ;
2012-01-28 15:16:49 +00:00
2012-04-29 16:13:03 +00:00
if ( color = = " #572D21 " ) MWBase : : Environment : : get ( ) . getDialogueManager ( ) - > questionAnswered ( lower_string ( key ) ) ;
2010-11-03 20:21:08 +00:00
}
}
2012-05-10 09:19:22 +00:00
void DialogueWindow : : onWindowResize ( MyGUI : : Window * _sender )
{
topicsList - > adjustSize ( ) ;
}
2012-04-29 22:57:41 +00:00
void DialogueWindow : : onMouseWheel ( MyGUI : : Widget * _sender , int _rel )
{
if ( history - > getVScrollPosition ( ) - _rel * 0.3 < 0 )
history - > setVScrollPosition ( 0 ) ;
else
history - > setVScrollPosition ( history - > getVScrollPosition ( ) - _rel * 0.3 ) ;
}
2010-11-03 20:21:08 +00:00
void DialogueWindow : : onByeClicked ( MyGUI : : Widget * _sender )
{
2012-04-23 13:27:03 +00:00
MWBase : : Environment : : get ( ) . getDialogueManager ( ) - > goodbyeSelected ( ) ;
2010-11-03 20:21:08 +00:00
}
2012-05-04 21:53:50 +00:00
void DialogueWindow : : onSelectTopic ( std : : string topic )
2010-11-03 20:21:08 +00:00
{
2012-05-11 05:18:41 +00:00
if ( ! mEnabled ) return ;
2012-05-17 15:15:44 +00:00
if ( topic = = MWBase : : Environment : : get ( ) . getWorld ( ) - > getStore ( ) . gameSettings . search ( " sBarter " ) - > str )
{
/// \todo check if the player is allowed to trade with this actor (e.g. faction rank high enough)?
2012-05-23 10:23:35 +00:00
mWindowManager . pushGuiMode ( GM_Barter ) ;
2012-05-26 23:14:33 +00:00
mWindowManager . getTradeWindow ( ) - > startTrade ( mPtr ) ;
2012-05-17 15:15:44 +00:00
}
else
MWBase : : Environment : : get ( ) . getDialogueManager ( ) - > keywordSelected ( lower_string ( topic ) ) ;
2010-11-03 20:21:08 +00:00
}
2012-05-17 15:15:44 +00:00
void DialogueWindow : : startDialogue ( MWWorld : : Ptr actor , std : : string npcName )
2012-01-27 13:50:13 +00:00
{
2012-05-11 05:18:41 +00:00
mEnabled = true ;
2012-05-26 23:14:33 +00:00
mPtr = actor ;
2012-05-11 05:18:41 +00:00
topicsList - > setEnabled ( true ) ;
2012-05-18 15:27:55 +00:00
setTitle ( npcName ) ;
2012-05-23 10:23:35 +00:00
topicsList - > clear ( ) ;
history - > eraseText ( 0 , history - > getTextLength ( ) ) ;
updateOptions ( ) ;
2012-01-27 13:50:13 +00:00
}
2012-03-19 17:30:52 +00:00
void DialogueWindow : : setKeywords ( std : : list < std : : string > keyWords )
2012-01-27 13:50:13 +00:00
{
2012-05-04 21:53:50 +00:00
topicsList - > clear ( ) ;
2012-05-17 12:54:03 +00:00
bool anyService = mShowTrade ;
if ( mShowTrade )
topicsList - > addItem ( MWBase : : Environment : : get ( ) . getWorld ( ) - > getStore ( ) . gameSettings . search ( " sBarter " ) - > str ) ;
if ( anyService )
topicsList - > addSeparator ( ) ;
2012-06-06 18:29:30 +00:00
for ( std : : list < std : : string > : : iterator it = keyWords . begin ( ) ; it ! = keyWords . end ( ) ; + + it )
2012-01-27 13:50:13 +00:00
{
2012-03-19 17:30:52 +00:00
topicsList - > addItem ( * it ) ;
2012-01-27 13:50:13 +00:00
}
2012-05-17 11:12:38 +00:00
topicsList - > adjustSize ( ) ;
2012-01-27 13:50:13 +00:00
}
void DialogueWindow : : removeKeyword ( std : : string keyWord )
{
2012-05-04 21:53:50 +00:00
if ( topicsList - > hasItem ( keyWord ) )
2012-01-27 13:50:13 +00:00
{
2012-05-04 21:53:50 +00:00
topicsList - > removeItem ( keyWord ) ;
2012-01-27 13:50:13 +00:00
}
2012-05-17 11:12:38 +00:00
topicsList - > adjustSize ( ) ;
2012-01-27 13:50:13 +00:00
}
2012-02-05 09:54:56 +00:00
void addColorInString ( std : : string & str , const std : : string & keyword , std : : string color1 , std : : string color2 )
2012-01-27 13:50:13 +00:00
{
size_t pos = 0 ;
2012-02-05 09:54:56 +00:00
while ( ( pos = find_str_ci ( str , keyword , pos ) ) ! = std : : string : : npos )
2012-01-27 13:50:13 +00:00
{
2012-02-15 12:23:59 +00:00
if ( pos = = 0 )
{
str . insert ( pos , color1 ) ;
pos + = color1 . length ( ) ;
pos + = keyword . length ( ) ;
str . insert ( pos , color2 ) ;
pos + = color2 . length ( ) ;
}
2012-03-19 18:21:08 +00:00
else
2012-02-15 12:23:59 +00:00
{
2012-03-17 15:56:22 +00:00
if ( str . substr ( pos - 1 , 1 ) = = " " )
{
str . insert ( pos , color1 ) ;
pos + = color1 . length ( ) ;
pos + = keyword . length ( ) ;
str . insert ( pos , color2 ) ;
pos + = color2 . length ( ) ;
}
else
{
pos + = keyword . length ( ) ;
}
2012-02-15 12:23:59 +00:00
}
2012-01-27 13:50:13 +00:00
}
}
std : : string DialogueWindow : : parseText ( std : : string text )
{
2012-06-19 13:24:52 +00:00
bool separatorReached = false ; // only parse topics that are below the separator (this prevents actions like "Barter" that are not topics from getting blue-colored)
2012-03-17 14:47:22 +00:00
for ( unsigned int i = 0 ; i < topicsList - > getItemCount ( ) ; i + + )
2012-01-27 13:50:13 +00:00
{
2012-03-17 14:47:22 +00:00
std : : string keyWord = topicsList - > getItemNameAt ( i ) ;
2012-06-19 13:24:52 +00:00
if ( separatorReached & & keyWord ! = " " )
2012-05-17 12:54:03 +00:00
addColorInString ( text , keyWord , " #686EBA " , " #B29154 " ) ;
2012-06-19 13:24:52 +00:00
else
separatorReached = true ;
2012-01-27 13:50:13 +00:00
}
return text ;
}
2012-02-05 09:54:56 +00:00
void DialogueWindow : : addText ( std : : string text )
{
2012-02-12 21:24:23 +00:00
history - > addDialogText ( " #B29154 " + parseText ( text ) + " #B29154 " ) ;
2012-02-05 09:54:56 +00:00
}
2012-03-16 16:30:59 +00:00
void DialogueWindow : : addTitle ( std : : string text )
{
2012-04-17 21:47:50 +00:00
// This is called from the dialogue manager, so text is
// case-smashed - thus we have to retrieve the correct case
// of the text through the topic list.
for ( size_t i = 0 ; i < topicsList - > getItemCount ( ) ; + + i )
{
std : : string item = topicsList - > getItemNameAt ( i ) ;
if ( lower_string ( item ) = = text )
text = item ;
}
2012-03-16 16:30:59 +00:00
history - > addDialogHeading ( text ) ;
}
void DialogueWindow : : askQuestion ( std : : string question )
2012-01-28 15:08:22 +00:00
{
2012-03-07 17:44:09 +00:00
history - > addDialogText ( " #572D21 " + question + " #B29154 " + " " ) ;
2012-01-28 15:08:22 +00:00
}
2010-11-03 20:21:08 +00:00
void DialogueWindow : : updateOptions ( )
{
//Clear the list of topics
2012-05-04 21:53:50 +00:00
topicsList - > clear ( ) ;
2012-01-27 13:50:13 +00:00
history - > eraseText ( 0 , history - > getTextLength ( ) ) ;
2012-02-05 09:54:56 +00:00
pDispositionBar - > setProgressRange ( 100 ) ;
pDispositionBar - > setProgressPosition ( 40 ) ;
pDispositionText - > eraseText ( 0 , pDispositionText - > getTextLength ( ) ) ;
pDispositionText - > addText ( " #B29154 " + std : : string ( " 40/100 " ) + " #B29154 " ) ;
2010-11-03 20:21:08 +00:00
}
2012-05-11 05:18:41 +00:00
void DialogueWindow : : goodbye ( )
{
history - > addDialogText ( " \n #572D21 " + MWBase : : Environment : : get ( ) . getWorld ( ) - > getStore ( ) . gameSettings . search ( " sGoodbye " ) - > str ) ;
topicsList - > setEnabled ( false ) ;
mEnabled = false ;
}
2012-05-26 23:14:33 +00:00
void DialogueWindow : : onReferenceUnavailable ( )
{
mWindowManager . removeGuiMode ( GM_Dialogue ) ;
}