diff --git a/apps/openmw/mwgui/bookwindow.cpp b/apps/openmw/mwgui/bookwindow.cpp index 75be6280a..8de45984c 100644 --- a/apps/openmw/mwgui/bookwindow.cpp +++ b/apps/openmw/mwgui/bookwindow.cpp @@ -7,6 +7,8 @@ #include "../mwsound/soundmanager.hpp" #include "../mwworld/actiontake.hpp" +#include + using namespace MWGui; BookWindow::BookWindow (WindowManager& parWindowManager) : @@ -24,20 +26,57 @@ BookWindow::BookWindow (WindowManager& parWindowManager) : getWidget(mPrevPageButton, "PrevPageBTN"); mPrevPageButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BookWindow::onPrevPageButtonClicked); + getWidget(mLeftPageNumber, "LeftPageNumber"); + getWidget(mRightPageNumber, "RightPageNumber"); + + getWidget(mLeftPage, "LeftPage"); + getWidget(mRightPage, "RightPage"); + center(); } -void BookWindow::open (MWWorld::Ptr book) +void BookWindow::clearPages() { - MWBase::Environment::get().getSoundManager()->playSound3D (book, "book open", 1.0, 1.0); + for (std::vector::iterator it=mPages.begin(); + it!=mPages.end(); ++it) + { + MyGUI::Gui::getInstance().destroyWidget(*it); + } + mPages.clear(); +} +void BookWindow::open (MWWorld::Ptr book) +{ mBook = book; + clearPages(); + mCurrentPage = 0; + + MWBase::Environment::get().getSoundManager()->playSound3D (book, "book open", 1.0, 1.0); + ESMS::LiveCellRef *ref = mBook.get(); - //BookTextParser parser; - //parser.parse(ref->base->text, 0, 0); + BookTextParser parser; + std::vector results = parser.split(ref->base->text, mLeftPage->getSize().width, mLeftPage->getSize().height); + + int i=0; + for (std::vector::iterator it=results.begin(); + it!=results.end(); ++it) + { + MyGUI::Widget* parent; + if (i%2 == 0) + parent = mLeftPage; + else + parent = mRightPage; + + MyGUI::Widget* pageWidget = parent->createWidgetReal("", MyGUI::FloatCoord(0.0,0.0,1.0,1.0), MyGUI::Align::Default, "BookPage" + boost::lexical_cast(i)); + parser.parse(*it, pageWidget, mLeftPage->getSize().width); + mPages.push_back(pageWidget); + ++i; + } + + updatePages(); } void BookWindow::onCloseButtonClicked (MyGUI::Widget* _sender) @@ -54,15 +93,48 @@ void BookWindow::onTakeButtonClicked (MyGUI::Widget* _sender) MWWorld::ActionTake take(mBook); take.execute(); - /// \todo what about scripts? - MWBase::Environment::get().getInputManager()->setGuiMode (GM_Game); } void BookWindow::onNextPageButtonClicked (MyGUI::Widget* _sender) { + if ((mCurrentPage+1)*2 < mPages.size()) + { + MWBase::Environment::get().getSoundManager()->playSound ("book page2", 1.0, 1.0); + + ++mCurrentPage; + + updatePages(); + } } void BookWindow::onPrevPageButtonClicked (MyGUI::Widget* _sender) { + if (mCurrentPage > 0) + { + MWBase::Environment::get().getSoundManager()->playSound ("book page", 1.0, 1.0); + + --mCurrentPage; + + updatePages(); + } +} + +void BookWindow::updatePages() +{ + mLeftPageNumber->setCaption( boost::lexical_cast(mCurrentPage*2 + 1) ); + mRightPageNumber->setCaption( boost::lexical_cast(mCurrentPage*2 + 2) ); + + unsigned int i=0; + for (std::vector::iterator it = mPages.begin(); + it != mPages.end(); ++it) + { + if (mCurrentPage*2 == i || mCurrentPage*2+1 == i) + (*it)->setVisible(true); + else + { + (*it)->setVisible(false); + } + ++i; + } } diff --git a/apps/openmw/mwgui/bookwindow.hpp b/apps/openmw/mwgui/bookwindow.hpp index bc017e326..fcea1d11f 100644 --- a/apps/openmw/mwgui/bookwindow.hpp +++ b/apps/openmw/mwgui/bookwindow.hpp @@ -19,11 +19,21 @@ namespace MWGui void onCloseButtonClicked (MyGUI::Widget* _sender); void onTakeButtonClicked (MyGUI::Widget* _sender); + void updatePages(); + void clearPages(); + private: MyGUI::Button* mCloseButton; MyGUI::Button* mTakeButton; MyGUI::Button* mNextPageButton; MyGUI::Button* mPrevPageButton; + MyGUI::TextBox* mLeftPageNumber; + MyGUI::TextBox* mRightPageNumber; + MyGUI::Widget* mLeftPage; + MyGUI::Widget* mRightPage; + + unsigned int mCurrentPage; // 0 is first page + std::vector mPages; MWWorld::Ptr mBook; }; diff --git a/apps/openmw/mwgui/formatting.cpp b/apps/openmw/mwgui/formatting.cpp index 6b50fd04d..e031678ae 100644 --- a/apps/openmw/mwgui/formatting.cpp +++ b/apps/openmw/mwgui/formatting.cpp @@ -11,7 +11,7 @@ namespace int convertFromHex(std::string hex) { int value = 0; - + int a = 0; int b = hex.length() - 1; for (; b >= 0; a++, b--) @@ -28,43 +28,144 @@ namespace case 'a': value += 10 * (1 << (a * 4)); break; - + case 'B': case 'b': value += 11 * (1 << (a * 4)); break; - + case 'C': case 'c': value += 12 * (1 << (a * 4)); break; - + case 'D': case 'd': value += 13 * (1 << (a * 4)); break; - + case 'E': case 'e': value += 14 * (1 << (a * 4)); break; - + case 'F': case 'f': value += 15 * (1 << (a * 4)); break; - + default: throw std::runtime_error("invalid character in hex number"); break; } } } - + return value; } } +std::vector BookTextParser::split(std::string text, const int width, const int height) +{ + std::vector result; + + boost::algorithm::replace_all(text, "
", "\n"); + boost::algorithm::replace_all(text, "

", "\n\n"); + + const int spacing = 48; + + while (text.size() > 0) + { + // read in characters until we have exceeded the size, or run out of text + int currentWidth = 0; + int currentHeight = 0; + std::string currentText; + std::string currentWord; + + unsigned int i=0; + while (currentHeight <= height-spacing && i', i) == std::string::npos) + throw std::runtime_error("BookTextParser Error: Tag is not terminated"); + + if (text.size() > i+4 && text.substr(i, 4) == "', i)-i), false); + currentHeight += (mHeight-h); + currentWidth = 0; + } + else if (text.size() > i+5 && text.substr(i, 5) == "', i)-i)); + currentHeight += 18; // keep this in sync with the font size + currentWidth = 0; + } + else if (text.size() > i+4 && text.substr(i, 4) == "', i)-i)); + currentHeight += 18; // keep this in sync with the font size + currentWidth = 0; + } + + currentText += text.substr(i, text.find('>', i)-i+1); + i = text.find('>', i); + } + else if (text[i] == '\n') + { + currentHeight += 18; // keep this in sync with the font size + currentWidth = 0; + currentWord = ""; + currentText += text[i]; + } + else if (text[i] == ' ') + { + currentWidth += 3; // keep this in sync with the font's SpaceWidth property + currentWord = ""; + currentText += text[i]; + } + else + { + currentWidth += + MyGUI::FontManager::getInstance().getByName (mTextStyle.mFont == "Default" ? "EB Garamond" : mTextStyle.mFont) + ->getGlyphInfo(static_cast(text[i]))->width; + currentWord += text[i]; + currentText += text[i]; + } + + if (currentWidth > width) + { + currentHeight += 18; // keep this in sync with the font size + currentWidth = 0; + + // add size of the current word + unsigned int j=0; + while (jgetGlyphInfo(static_cast(currentWord[j]))->width; + ++j; + } + } + + ++i; + } + if (currentHeight > height-spacing) + { + // remove the last word + currentText.erase(currentText.size()-currentWord.size(), currentText.size()); + } + + result.push_back(currentText); + text.erase(0, currentText.size()); + } + + return result; +} + MyGUI::IntSize BookTextParser::parse(std::string text, MyGUI::Widget* parent, const int width) { mParent = parent; @@ -92,7 +193,7 @@ MyGUI::IntSize BookTextParser::parse(std::string text, MyGUI::Widget* parent, co return MyGUI::IntSize(mWidth, mHeight); } -void BookTextParser::parseImage(std::string tag) +void BookTextParser::parseImage(std::string tag, bool createWidget) { int src_start = tag.find("SRC=")+5; std::string image = tag.substr(src_start, tag.find('"', src_start)-src_start); @@ -111,11 +212,14 @@ void BookTextParser::parseImage(std::string tag) int height_start = tag.find("HEIGHT=")+8; int height = boost::lexical_cast(tag.substr(height_start, tag.find('"', height_start)-height_start)); - MyGUI::ImageBox* box = mParent->createWidget ("ImageBox", - MyGUI::IntCoord(0, mHeight, width, height), MyGUI::Align::Left | MyGUI::Align::Top, - mParent->getName() + boost::lexical_cast(mParent->getChildCount())); - box->setImageTexture("bookart\\" + image); - box->setProperty("NeedMouse", "false"); + if (createWidget) + { + MyGUI::ImageBox* box = mParent->createWidget ("ImageBox", + MyGUI::IntCoord(0, mHeight, width, height), MyGUI::Align::Left | MyGUI::Align::Top, + mParent->getName() + boost::lexical_cast(mParent->getChildCount())); + box->setImageTexture("bookart\\" + image); + box->setProperty("NeedMouse", "false"); + } mWidth = std::max(mWidth, width); mHeight += height; diff --git a/apps/openmw/mwgui/formatting.hpp b/apps/openmw/mwgui/formatting.hpp index 19b696918..c8f2c9e44 100644 --- a/apps/openmw/mwgui/formatting.hpp +++ b/apps/openmw/mwgui/formatting.hpp @@ -36,10 +36,15 @@ namespace MWGui */ MyGUI::IntSize parse(std::string text, MyGUI::Widget* parent, const int width); + /** + * Split the specified text into pieces that fit in the area specified by width and height parameters + */ + std::vector split(std::string text, const int width, const int height); + protected: void parseSubText(std::string text); - void parseImage(std::string tag); + void parseImage(std::string tag, bool createWidget=true); void parseDiv(std::string tag); void parseFont(std::string tag); private: diff --git a/apps/openmw/mwgui/scrollwindow.cpp b/apps/openmw/mwgui/scrollwindow.cpp index b1c5ec337..38e2f77c1 100644 --- a/apps/openmw/mwgui/scrollwindow.cpp +++ b/apps/openmw/mwgui/scrollwindow.cpp @@ -57,7 +57,5 @@ void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender) MWWorld::ActionTake take(mScroll); take.execute(); - /// \todo what about scripts? - MWBase::Environment::get().getInputManager()->setGuiMode (GM_Game); } diff --git a/files/mygui/openmw_book_layout.xml b/files/mygui/openmw_book_layout.xml index 36f93a067..07ebf5030 100644 --- a/files/mygui/openmw_book_layout.xml +++ b/files/mygui/openmw_book_layout.xml @@ -20,8 +20,15 @@ - - + + + + + + + + + diff --git a/files/mygui/openmw_journal_layout.xml b/files/mygui/openmw_journal_layout.xml index 906e87297..75bb5eea1 100644 --- a/files/mygui/openmw_journal_layout.xml +++ b/files/mygui/openmw_journal_layout.xml @@ -13,8 +13,8 @@ - - + +