reworked journal to match bethesda's implemenation

actorid
Nathan Jeffords 12 years ago
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);
}

@ -1,14 +1,18 @@
#ifndef MWGUI_JOURNAL_H
#define MWGUI_JOURNAL_H
#include <memory>
namespace MWBase { class WindowManager; }
namespace MWGui
{
struct IJournalViewModel;
struct IJournalWindow
{
/// construct a new instance of the one JournalWindow implementation
static IJournalWindow * create ();
static IJournalWindow * create (std::shared_ptr <IJournalViewModel> Model);
/// destroy this instance of the JournalWindow implementation
virtual ~IJournalWindow () {};

@ -7,6 +7,7 @@
#include "console.hpp"
#include "journalwindow.hpp"
#include "journalviewmodel.hpp"
#include "charactercreation.hpp"
#include "dialogue.hpp"
#include "dialoguehistory.hpp"
@ -147,7 +148,7 @@ namespace MWGui
mMap = new MapWindow(cacheDir);
mStatsWindow = new StatsWindow();
mConsole = new Console(w,h, consoleOnlyScripts);
mJournal = IJournalWindow::create();
mJournal = IJournalWindow::create(IJournalViewModel::create ());
mMessageBoxManager = new MessageBoxManager();
mInventoryWindow = new InventoryWindow(mDragAndDrop);
mTradeWindow = new TradeWindow();

@ -22,6 +22,26 @@
</Codes>
</Resource>
<Resource type="ResourceTrueTypeFont" name="EB Garamond 24">
<Property key="Source" value="EBGaramond-Regular.ttf"/>
<Property key="Size" value="24"/>
<Property key="Resolution" value="72"/>
<Property key="Antialias" value="false"/>
<Property key="TabWidth" value="8"/>
<Property key="OffsetHeight" value="0"/>
<Codes>
<Code range="33 126"/>
<Code range="192 382"/> <!-- Central and Eastern European languages glyphs -->
<Code range="1025 1105"/>
<Code range="8470"/>
<Code range="8211"/> <!-- Minus -->
<Code range="8216 8217"/> <!-- Single quotes -->
<Code range="8220 8221"/> <!-- Right and Left Double Quotation mark -->
<Code hide="128"/>
<Code hide="1026 1039"/>
<Code hide="1104"/>
</Codes>
</Resource>
<Resource type="ResourceTrueTypeFont" name="Daedric">
<!--<Property key="Source" value="Oblivion/Oblivion Worn.ttf"/>-->
<Property key="Source" value="Oblivion/Oblivion.ttf"/>

@ -7,7 +7,7 @@
<Widget type="ImageBox" skin="ImageBox" position="0 0 565 390" align="Top|Right" name="JImage">
<Property key="ImageTexture" value="textures\tx_menubook.dds"/>
<Property key="ImageCoord" value="50 0 412 256"/>
<!-- buttons -->
<Widget type="ImageButton" skin="ImageBox" position="40 350 64 32" name="OptionsBTN">
<Property key="ImageHighlighted" value="textures\tx_menubook_options_over.dds"/>
@ -44,28 +44,55 @@
<Property key="ImageNormal" value="textures\tx_menubook_journal_idle.dds"/>
<Property key="ImagePushed" value="textures\tx_menubook_journal_pressed.dds"/>
</Widget>
<!-- text pages -->
<Widget type="EditBox" skin="MW_BookPage" position="30 22 240 300" name="LeftText"/>
<Widget type="EditBox" skin="MW_BookPage" position="300 22 240 300" name="RightText"/>
<Widget type="BookPage" skin="MW_BookPage" position="30 22 240 300" name="LeftBookPage"/>
<Widget type="BookPage" skin="MW_BookPage" position="300 22 240 300" name="RightBookPage"/>
<!-- options overlay -->
</Widget>
<!-- "options" -->
<Widget type="ImageBox" skin="ImageBox" position="300 0 224 350" name="OptionsOverlay">
<Property key="ImageTexture" value="textures\tx_menubook_bookmark.dds"/>
<Property key="ImageCoord" value="0 0 164 256"/>
<Widget type="BookPage" skin="MW_BookPage" position="20 15 92 250" name="LeftTopicIndex"/>
<Widget type="BookPage" skin="MW_BookPage" position="112 15 92 250" name="RightTopicIndex"/>
<Widget type="ScrollView" skin="MW_ScrollView" position="20 15 184 245" name="TopicsList" align="Right VStretch">
<Property key="CanvasAlign" value="Left Top"/>
<Widget type="BookPage" skin="MW_BookPage" position="0 0 30000 30000" name="TopicsPage"/>
</Widget>
<Widget type="ScrollView" skin="MW_ScrollView" position="20 35 184 245" name="QuestsList" align="Right VStretch">
<Property key="CanvasAlign" value="Left Top"/>
<Widget type="BookPage" skin="MW_BookPage" position="0 0 30000 30000" name="QuestsPage"/>
</Widget>
<Widget type="ImageButton" skin="ImageBox" position="62 15 100 20" Align="Top|Left" name="ShowActiveBTN">
<Property key="ImageCoord" value="0 0 100 20"/>
<Property key="ImageHighlighted" value="textures\tx_menubook_quests_active_over.dds"/>
<Property key="ImageNormal" value="textures\tx_menubook_quests_active_idle.dds"/>
<Property key="ImagePushed" value="textures\tx_menubook_quests_active_pressed.dds"/>
</Widget>
<Widget type="ImageButton" skin="ImageBox" position="76 15 72 20" Align="Top|Left" name="ShowAllBTN">
<Property key="ImageCoord" value="0 0 72 20"/>
<Property key="ImageHighlighted" value="textures\tx_menubook_quests_all_over.dds"/>
<Property key="ImageNormal" value="textures\tx_menubook_quests_all_idle.dds"/>
<Property key="ImagePushed" value="textures\tx_menubook_quests_all_pressed.dds"/>
</Widget>
<Widget type="ImageButton" skin="ImageBox" position="40 265 56 32" Align="Top|Left" name="TopicsBTN">
<Property key="ImageCoord" value="0 0 56 32"/>
<Property key="ImageHighlighted" value="textures\tx_menubook_topics_over.dds"/>
<Property key="ImageNormal" value="textures\tx_menubook_topics_idle.dds"/>
<Property key="ImagePushed" value="textures\tx_menubook_topics_pressed.dds"/>
</Widget>
<Widget type="ImageButton" skin="ImageBox" position="130 265 56 32" Align="Top|Left" name="QuestsBTN">
<Property key="ImageCoord" value="0 0 56 32"/>
<Property key="ImageHighlighted" value="textures\tx_menubook_quests_over.dds"/>
@ -79,7 +106,7 @@
<Property key="ImageNormal" value="textures\tx_menubook_cancel_idle.dds"/>
<Property key="ImagePushed" value="textures\tx_menubook_cancel_pressed.dds"/>
</Widget>
</Widget>
</Widget>
</MyGUI>

@ -10,8 +10,6 @@
</Skin>
<Skin name="MW_BookPage" size="0 0 50 50">
<Property key="WordWrap" value = "true" />
<Child type="TextBox" skin="MW_BookClient" offset="0 0 35 10" align = "ALIGN_STRETCH" name = "Client"/>
<!--Child type="ScrollBar" skin="VScroll" offset = "35 0 15 50" align = "Right VStretch" name = "VScroll"/-->
<BasisSkin type="PageDisplay"/>
</Skin>
</MyGUI>

Loading…
Cancel
Save