forked from mirror/openmw-tes3mp
reworked journal to match bethesda's implemenation
parent
f02a53b121
commit
718af692c9
@ -1,221 +1,422 @@
|
||||
#include "journalwindow.hpp"
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/journal.hpp"
|
||||
#include "../mwbase/soundmanager.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "list.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <set>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include "boost/lexical_cast.hpp"
|
||||
|
||||
#include "bookpage.hpp"
|
||||
#include "windowbase.hpp"
|
||||
#include "imagebutton.hpp"
|
||||
#include "journalviewmodel.hpp"
|
||||
#include "journalbooks.hpp"
|
||||
|
||||
using namespace MyGUI;
|
||||
using namespace MWGui;
|
||||
|
||||
namespace
|
||||
{
|
||||
struct book
|
||||
{
|
||||
int endLine;
|
||||
std::list<std::string> pages;
|
||||
};
|
||||
}
|
||||
#define CONTROL_ID(name) \
|
||||
static char const name [] = #name;
|
||||
|
||||
book formatText(std::string text,book mBook,int maxLine, int lineSize)
|
||||
{
|
||||
//stringList.push_back("");
|
||||
CONTROL_ID(OptionsOverlay)
|
||||
|
||||
int cLineSize = 0;
|
||||
int cLine = mBook.endLine +1;
|
||||
std::string cString;
|
||||
CONTROL_ID(OptionsBTN)
|
||||
CONTROL_ID(PrevPageBTN);
|
||||
CONTROL_ID(NextPageBTN);
|
||||
CONTROL_ID(CloseBTN);
|
||||
CONTROL_ID(JournalBTN);
|
||||
CONTROL_ID(TopicsBTN);
|
||||
CONTROL_ID(QuestsBTN);
|
||||
CONTROL_ID(CancelBTN);
|
||||
CONTROL_ID(ShowAllBTN);
|
||||
CONTROL_ID(ShowActiveBTN);
|
||||
CONTROL_ID(PageOneNum)
|
||||
CONTROL_ID(PageTwoNum)
|
||||
CONTROL_ID(TopicsList);
|
||||
CONTROL_ID(TopicsPage);
|
||||
CONTROL_ID(QuestsList);
|
||||
CONTROL_ID(QuestsPage);
|
||||
CONTROL_ID(LeftBookPage);
|
||||
CONTROL_ID(RightBookPage);
|
||||
CONTROL_ID(LeftTopicIndex);
|
||||
CONTROL_ID(RightTopicIndex);
|
||||
|
||||
if(mBook.pages.empty())
|
||||
{
|
||||
cString = "";
|
||||
cLine = 0;
|
||||
}
|
||||
else
|
||||
struct JournalWindow : WindowBase, JournalBooks, IJournalWindow
|
||||
{
|
||||
cString = mBook.pages.back() + std::string("\n");
|
||||
mBook.pages.pop_back();
|
||||
}
|
||||
struct display_state
|
||||
{
|
||||
int mPage;
|
||||
book mBook;
|
||||
};
|
||||
|
||||
//std::string::iterator wordBegin = text.begin();
|
||||
//std::string::iterator wordEnd;
|
||||
typedef std::stack <display_state> display_state_stack;
|
||||
|
||||
std::string cText = text;
|
||||
display_state_stack mStates;
|
||||
book mTopicIndexBook;
|
||||
bool mQuestMode;
|
||||
bool mAllQuests;
|
||||
|
||||
while(cText.length() != 0)
|
||||
{
|
||||
size_t firstSpace = cText.find_first_of(' ');
|
||||
if(firstSpace == std::string::npos)
|
||||
template <typename widget_type>
|
||||
widget_type * getWidget (char const * name)
|
||||
{
|
||||
cString = cString + cText;
|
||||
mBook.pages.push_back(cString);
|
||||
//TODO:finnish this
|
||||
break;
|
||||
widget_type * widget;
|
||||
WindowBase::getWidget (widget, name);
|
||||
return widget;
|
||||
}
|
||||
if(static_cast<int> (firstSpace) + cLineSize <= lineSize)
|
||||
|
||||
template <typename value_type>
|
||||
void setText (char const * name, value_type const & value)
|
||||
{
|
||||
cLineSize = firstSpace + cLineSize;
|
||||
cString = cString + cText.substr(0,firstSpace +1);
|
||||
getWidget <TextBox> (name) ->
|
||||
setCaption (boost::lexical_cast <std::string> (value));
|
||||
}
|
||||
else
|
||||
|
||||
void setVisible (char const * name, bool visible)
|
||||
{
|
||||
cLineSize = firstSpace;
|
||||
if(cLine +1 <= maxLine)
|
||||
getWidget <Widget> (name) ->
|
||||
setVisible (visible);
|
||||
}
|
||||
|
||||
void adviseButtonClick (char const * name, void (JournalWindow::*Handler) (Widget* _sender))
|
||||
{
|
||||
getWidget <MWGui::ImageButton> (name) ->
|
||||
eventMouseButtonClick += newDelegate(this, Handler);
|
||||
}
|
||||
|
||||
MWGui::IBookPage* getPage (char const * name)
|
||||
{
|
||||
return getWidget <MWGui::IBookPage> (name);
|
||||
}
|
||||
|
||||
JournalWindow (IJournalViewModel::ptr Model)
|
||||
: WindowBase("openmw_journal.layout"), JournalBooks (Model)
|
||||
{
|
||||
mMainWidget->setVisible(false);
|
||||
center();
|
||||
|
||||
adviseButtonClick (OptionsBTN, &JournalWindow::notifyOptions );
|
||||
adviseButtonClick (PrevPageBTN, &JournalWindow::notifyPrevPage );
|
||||
adviseButtonClick (NextPageBTN, &JournalWindow::notifyNextPage );
|
||||
adviseButtonClick (CloseBTN, &JournalWindow::notifyClose );
|
||||
adviseButtonClick (JournalBTN, &JournalWindow::notifyJournal );
|
||||
|
||||
adviseButtonClick (TopicsBTN, &JournalWindow::notifyTopics );
|
||||
adviseButtonClick (QuestsBTN, &JournalWindow::notifyQuests );
|
||||
adviseButtonClick (CancelBTN, &JournalWindow::notifyCancel );
|
||||
|
||||
adviseButtonClick (ShowAllBTN, &JournalWindow::notifyShowAll );
|
||||
adviseButtonClick (ShowActiveBTN, &JournalWindow::notifyShowActive);
|
||||
|
||||
{
|
||||
auto callback = std::bind (&JournalWindow::notifyTopicClicked, this, std::placeholders::_1);
|
||||
|
||||
getPage (TopicsPage)->adviseLinkClicked (callback);
|
||||
getPage (LeftBookPage)->adviseLinkClicked (callback);
|
||||
getPage (RightBookPage)->adviseLinkClicked (callback);
|
||||
}
|
||||
|
||||
{
|
||||
cLine = cLine + 1;
|
||||
cString = cString + std::string("\n") + cText.substr(0,firstSpace +1);
|
||||
auto callback = std::bind (&JournalWindow::notifyIndexLinkClicked, this, std::placeholders::_1);
|
||||
|
||||
getPage (LeftTopicIndex)->adviseLinkClicked (callback);
|
||||
getPage (RightTopicIndex)->adviseLinkClicked (callback);
|
||||
}
|
||||
else
|
||||
|
||||
{
|
||||
cLine = 0;
|
||||
mBook.pages.push_back(cString);
|
||||
cString = cText.substr(0,firstSpace +1);
|
||||
auto callback = std::bind (&JournalWindow::notifyQuestClicked, this, std::placeholders::_1);
|
||||
|
||||
getPage (QuestsPage)->adviseLinkClicked (callback);
|
||||
}
|
||||
|
||||
mQuestMode = false;
|
||||
mAllQuests = false;
|
||||
}
|
||||
//std::cout << cText << "\n";
|
||||
//std::cout << cText.length();
|
||||
cText = cText.substr(firstSpace +1,cText.length() - firstSpace -1);
|
||||
}
|
||||
mBook.endLine = cLine;
|
||||
return mBook;
|
||||
//std::string
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct JournalWindow : WindowBase, IJournalWindow
|
||||
{
|
||||
MyGUI::EditPtr mLeftTextWidget;
|
||||
MyGUI::EditPtr mRightTextWidget;
|
||||
MWGui::ImageButton* mPrevBtn;
|
||||
MWGui::ImageButton* mNextBtn;
|
||||
std::vector<std::string> mLeftPages;
|
||||
std::vector<std::string> mRightPages;
|
||||
int mPageNumber; //store the number of the current left page
|
||||
|
||||
JournalWindow ()
|
||||
: WindowBase("openmw_journal.layout")
|
||||
, mPageNumber(0)
|
||||
void open()
|
||||
{
|
||||
mMainWidget->setVisible(false);
|
||||
//setCoord(0,0,498, 342);
|
||||
center();
|
||||
Model->load ();
|
||||
|
||||
getWidget(mLeftTextWidget, "LeftText");
|
||||
getWidget(mRightTextWidget, "RightText");
|
||||
getWidget(mPrevBtn, "PrevPageBTN");
|
||||
mPrevBtn->eventMouseButtonClick += MyGUI::newDelegate(this,&JournalWindow::notifyPrevPage);
|
||||
getWidget(mNextBtn, "NextPageBTN");
|
||||
mNextBtn->eventMouseButtonClick += MyGUI::newDelegate(this,&JournalWindow::notifyNextPage);
|
||||
setBookMode ();
|
||||
|
||||
MWBase::Environment::get().getSoundManager()->playSound ("book open", 1.0, 1.0);
|
||||
|
||||
book journalBook;
|
||||
if (Model->is_empty ())
|
||||
journalBook = createEmptyJournalBook ();
|
||||
else
|
||||
journalBook = createJournalBook ();
|
||||
|
||||
mLeftTextWidget->setEditReadOnly(true);
|
||||
mRightTextWidget->setEditReadOnly(true);
|
||||
mRightTextWidget->setEditStatic(true);
|
||||
mLeftTextWidget->setEditStatic(true);
|
||||
pushBook (journalBook, 0);
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
Model->unload ();
|
||||
|
||||
getPage (LeftBookPage)->showPage (book (), 0);
|
||||
getPage (RightBookPage)->showPage (book (), 0);
|
||||
|
||||
decltype (mStates) clr;
|
||||
mStates.swap (clr);
|
||||
|
||||
mTopicIndexBook.reset ();
|
||||
|
||||
MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0);
|
||||
}
|
||||
|
||||
void open()
|
||||
void setVisible (bool newValue)
|
||||
{
|
||||
mPageNumber = 0;
|
||||
MWBase::Environment::get().getSoundManager()->playSound ("book open", 1.0, 1.0);
|
||||
if(MWBase::Environment::get().getJournal()->begin()!=MWBase::Environment::get().getJournal()->end())
|
||||
{
|
||||
book journal;
|
||||
journal.endLine = 0;
|
||||
WindowBase::setVisible (newValue);
|
||||
}
|
||||
|
||||
for(std::deque<MWDialogue::StampedJournalEntry>::const_iterator it = MWBase::Environment::get().getJournal()->begin();it!=MWBase::Environment::get().getJournal()->end();++it)
|
||||
{
|
||||
std::string a = it->getText(MWBase::Environment::get().getWorld()->getStore());
|
||||
journal = formatText(a,journal,10,17);
|
||||
journal.endLine = journal.endLine +1;
|
||||
journal.pages.back() = journal.pages.back() + std::string("\n");
|
||||
}
|
||||
//std::string a = MWBase::Environment::get().getJournal()->begin()->getText(MWBase::Environment::get().getWorld()->getStore());
|
||||
//std::list<std::string> journal = formatText(a,10,20,1);
|
||||
bool left = true;
|
||||
for(std::list<std::string>::iterator it = journal.pages.begin(); it != journal.pages.end();++it)
|
||||
{
|
||||
if(left)
|
||||
{
|
||||
mLeftPages.push_back(*it);
|
||||
}
|
||||
else
|
||||
{
|
||||
mRightPages.push_back(*it);
|
||||
}
|
||||
left = !left;
|
||||
}
|
||||
if(!left) mRightPages.push_back("");
|
||||
void setBookMode ()
|
||||
{
|
||||
setVisible (OptionsBTN, true);
|
||||
setVisible (OptionsOverlay, false);
|
||||
|
||||
updateShowingPages ();
|
||||
updateCloseJournalButton ();
|
||||
}
|
||||
|
||||
void setOptionsMode ()
|
||||
{
|
||||
setVisible (OptionsBTN, false);
|
||||
setVisible (OptionsOverlay, true);
|
||||
|
||||
setVisible (PrevPageBTN, false);
|
||||
setVisible (NextPageBTN, false);
|
||||
setVisible (CloseBTN, false);
|
||||
setVisible (JournalBTN, false);
|
||||
|
||||
setVisible (TopicsList, false);
|
||||
setVisible (QuestsList, mQuestMode);
|
||||
setVisible (LeftTopicIndex, !mQuestMode);
|
||||
setVisible (RightTopicIndex, !mQuestMode);
|
||||
setVisible (ShowAllBTN, mQuestMode && !mAllQuests);
|
||||
setVisible (ShowActiveBTN, mQuestMode && mAllQuests);
|
||||
|
||||
//TODO: figure out how to make "options" page overlay book page
|
||||
// correctly, so that text may show underneath
|
||||
getPage (RightBookPage)->showPage (book (), 0);
|
||||
}
|
||||
|
||||
mPageNumber = mLeftPages.size()-1;
|
||||
displayLeftText(mLeftPages[mPageNumber]);
|
||||
displayRightText(mRightPages[mPageNumber]);
|
||||
void pushBook (book Book, int Page)
|
||||
{
|
||||
display_state bs;
|
||||
bs.mPage = Page;
|
||||
bs.mBook = Book;
|
||||
mStates.push (bs);
|
||||
updateShowingPages ();
|
||||
updateCloseJournalButton ();
|
||||
}
|
||||
|
||||
void replaceBook (book Book, int Page)
|
||||
{
|
||||
assert (!mStates.empty ());
|
||||
mStates.top ().mBook = Book;
|
||||
mStates.top ().mPage = Page;
|
||||
updateShowingPages ();
|
||||
}
|
||||
|
||||
void popBook ()
|
||||
{
|
||||
mStates.pop ();
|
||||
updateShowingPages ();
|
||||
updateCloseJournalButton ();
|
||||
}
|
||||
|
||||
void updateCloseJournalButton ()
|
||||
{
|
||||
setVisible (CloseBTN, mStates.size () < 2);
|
||||
setVisible (JournalBTN, mStates.size () >= 2);
|
||||
}
|
||||
|
||||
void updateShowingPages ()
|
||||
{
|
||||
book Book;
|
||||
int Page;
|
||||
int relPages;
|
||||
|
||||
if (!mStates.empty ())
|
||||
{
|
||||
Book = mStates.top ().mBook;
|
||||
Page = mStates.top ().mPage;
|
||||
relPages = Book->pageCount () - Page;
|
||||
}
|
||||
else
|
||||
{
|
||||
//std::cout << MWBase::Environment::get().getJournal()->begin()->getText(MWBase::Environment::get().getWorld()->getStore());
|
||||
Page = 0;
|
||||
relPages = 0;
|
||||
}
|
||||
|
||||
setVisible (PrevPageBTN, Page > 0);
|
||||
setVisible (NextPageBTN, relPages > 2);
|
||||
|
||||
setVisible (PageOneNum, relPages > 0);
|
||||
setVisible (PageTwoNum, relPages > 1);
|
||||
|
||||
getPage (LeftBookPage)->showPage ((relPages > 0) ? Book : book (), Page+0);
|
||||
getPage (RightBookPage)->showPage ((relPages > 0) ? Book : book (), Page+1);
|
||||
|
||||
setText (PageOneNum, Page + 1);
|
||||
setText (PageTwoNum, Page + 2);
|
||||
}
|
||||
|
||||
void setVisible (bool newValue)
|
||||
void notifyTopicClicked (intptr_t linkId)
|
||||
{
|
||||
WindowBase::setVisible (newValue);
|
||||
auto topicBook = createTopicBook (linkId);
|
||||
|
||||
if (mStates.size () > 1)
|
||||
replaceBook (topicBook, 0);
|
||||
else
|
||||
pushBook (topicBook, 0);
|
||||
|
||||
setVisible (OptionsOverlay, false);
|
||||
setVisible (OptionsBTN, true);
|
||||
setVisible (JournalBTN, true);
|
||||
}
|
||||
|
||||
void notifyQuestClicked (intptr_t questId)
|
||||
{
|
||||
auto Book = createQuestBook (questId);
|
||||
|
||||
if (mStates.size () > 1)
|
||||
replaceBook (Book, 0);
|
||||
else
|
||||
pushBook (Book, 0);
|
||||
|
||||
setVisible (OptionsOverlay, false);
|
||||
setVisible (OptionsBTN, true);
|
||||
setVisible (JournalBTN, true);
|
||||
}
|
||||
|
||||
void displayLeftText(std::string text)
|
||||
void notifyOptions(Widget* _sender)
|
||||
{
|
||||
mLeftTextWidget->eraseText(0,mLeftTextWidget->getTextLength());
|
||||
mLeftTextWidget->addText(text);
|
||||
setOptionsMode ();
|
||||
|
||||
if (!mTopicIndexBook)
|
||||
mTopicIndexBook = createTopicIndexBook ();
|
||||
|
||||
getPage (LeftTopicIndex)->showPage (mTopicIndexBook, 0);
|
||||
getPage (RightTopicIndex)->showPage (mTopicIndexBook, 1);
|
||||
}
|
||||
|
||||
void displayRightText(std::string text)
|
||||
void notifyJournal(Widget* _sender)
|
||||
{
|
||||
mRightTextWidget->eraseText(0,mRightTextWidget->getTextLength());
|
||||
mRightTextWidget->addText(text);
|
||||
assert (mStates.size () > 1);
|
||||
popBook ();
|
||||
}
|
||||
|
||||
void showList (char const * ListId, char const * PageId, book book)
|
||||
{
|
||||
auto size = book->getSize ();
|
||||
|
||||
getPage (PageId)->showPage (book, 0);
|
||||
|
||||
getWidget <ScrollView> (ListId)->setCanvasSize (size.first, size.second);
|
||||
}
|
||||
|
||||
void notifyNextPage(MyGUI::Widget* _sender)
|
||||
void notifyIndexLinkClicked (ITypesetBook::interactive_id character)
|
||||
{
|
||||
if(mPageNumber < int(mLeftPages.size())-1)
|
||||
setVisible (LeftTopicIndex, false);
|
||||
setVisible (RightTopicIndex, false);
|
||||
setVisible (TopicsList, true);
|
||||
|
||||
showList (TopicsList, TopicsPage, createTopicIndexBook ((char)character));
|
||||
}
|
||||
|
||||
void notifyTopics(Widget* _sender)
|
||||
{
|
||||
mQuestMode = false;
|
||||
setVisible (LeftTopicIndex, true);
|
||||
setVisible (RightTopicIndex, true);
|
||||
setVisible (TopicsList, false);
|
||||
setVisible (QuestsList, false);
|
||||
setVisible (ShowAllBTN, false);
|
||||
setVisible (ShowActiveBTN, false);
|
||||
}
|
||||
|
||||
void notifyQuests(Widget* _sender)
|
||||
{
|
||||
mQuestMode = true;
|
||||
setVisible (LeftTopicIndex, false);
|
||||
setVisible (RightTopicIndex, false);
|
||||
setVisible (TopicsList, false);
|
||||
setVisible (QuestsList, true);
|
||||
setVisible (ShowAllBTN, !mAllQuests);
|
||||
setVisible (ShowActiveBTN, mAllQuests);
|
||||
|
||||
showList (QuestsList, QuestsPage, createQuestIndexBook (!mAllQuests));
|
||||
}
|
||||
|
||||
void notifyShowAll(Widget* _sender)
|
||||
{
|
||||
mAllQuests = true;
|
||||
setVisible (ShowAllBTN, !mAllQuests);
|
||||
setVisible (ShowActiveBTN, mAllQuests);
|
||||
showList (QuestsList, QuestsPage, createQuestIndexBook (!mAllQuests));
|
||||
}
|
||||
|
||||
void notifyShowActive(Widget* _sender)
|
||||
{
|
||||
mAllQuests = false;
|
||||
setVisible (ShowAllBTN, !mAllQuests);
|
||||
setVisible (ShowActiveBTN, mAllQuests);
|
||||
showList (QuestsList, QuestsPage, createQuestIndexBook (!mAllQuests));
|
||||
}
|
||||
|
||||
void notifyCancel(Widget* _sender)
|
||||
{
|
||||
setBookMode ();
|
||||
}
|
||||
|
||||
void notifyClose(Widget* _sender)
|
||||
{
|
||||
|
||||
MWBase::Environment::get().getWindowManager ()->popGuiMode ();
|
||||
}
|
||||
|
||||
void notifyNextPage(Widget* _sender)
|
||||
{
|
||||
if (!mStates.empty ())
|
||||
{
|
||||
std::string nextSound = "book page2";
|
||||
MWBase::Environment::get().getSoundManager()->playSound (nextSound, 1.0, 1.0);
|
||||
mPageNumber = mPageNumber + 1;
|
||||
displayLeftText(mLeftPages[mPageNumber]);
|
||||
displayRightText(mRightPages[mPageNumber]);
|
||||
auto & Page = mStates.top ().mPage;
|
||||
auto Book = mStates.top ().mBook;
|
||||
|
||||
if (Page < Book->pageCount () - 2)
|
||||
{
|
||||
Page += 2;
|
||||
updateShowingPages ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void notifyPrevPage(MyGUI::Widget* _sender)
|
||||
void notifyPrevPage(Widget* _sender)
|
||||
{
|
||||
if(mPageNumber > 0)
|
||||
if (!mStates.empty ())
|
||||
{
|
||||
std::string prevSound = "book page";
|
||||
MWBase::Environment::get().getSoundManager()->playSound (prevSound, 1.0, 1.0);
|
||||
mPageNumber = mPageNumber - 1;
|
||||
displayLeftText(mLeftPages[mPageNumber]);
|
||||
displayRightText(mRightPages[mPageNumber]);
|
||||
auto & Page = mStates.top ().mPage;
|
||||
|
||||
if(Page > 0)
|
||||
{
|
||||
Page -= 2;
|
||||
updateShowingPages ();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// glue the implementation to the interface
|
||||
IJournalWindow * MWGui::IJournalWindow::create () { return new JournalWindow (); }
|
||||
IJournalWindow * MWGui::IJournalWindow::create (IJournalViewModel::ptr Model)
|
||||
{
|
||||
return new JournalWindow (Model);
|
||||
}
|
||||
|
Loading…
Reference in New Issue