From 0d4b0bfd9396846971f112c948f8334fb89f9dc4 Mon Sep 17 00:00:00 2001 From: Nikolay Kasyanov Date: Thu, 7 Feb 2013 23:40:20 +0400 Subject: [PATCH 01/12] Trying to resolve sound issues on OS X with ffmpeg backend --- apps/openmw/CMakeLists.txt | 6 ++++++ apps/openmw/mwsound/ffmpeg_decoder.cpp | 1 + 2 files changed, 7 insertions(+) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index e2cb0e5c41..b685c60831 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -125,6 +125,12 @@ if(APPLE) find_library(COCOA_FRAMEWORK Cocoa) find_library(IOKIT_FRAMEWORK IOKit) target_link_libraries(openmw ${CARBON_FRAMEWORK} ${COCOA_FRAMEWORK} ${IOKIT_FRAMEWORK}) + + if (FFMPEG_FOUND) + find_library(COREVIDEO_FRAMEWORK CoreVideo) + find_library(VDA_FRAMEWORK VideoDecodeAcceleration) + target_link_libraries(openmw ${COREVIDEO_FRAMEWORK} ${VDA_FRAMEWORK}) + endif() endif(APPLE) if(DPKG_PROGRAM) diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index 261a86ca60..00530a9628 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -160,6 +160,7 @@ void FFmpeg_Decoder::open(const std::string &fname) { if(mFormatCtx->streams[j]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + mFormatCtx->streams[j]->codec->request_sample_fmt = AV_SAMPLE_FMT_S16; mStream = &mFormatCtx->streams[j]; break; } From 158c6fc9fad2c8e3447e42bd495891d53ea1fbcb Mon Sep 17 00:00:00 2001 From: Tom Mason Date: Sun, 10 Feb 2013 14:58:46 +0000 Subject: [PATCH 02/12] pressing enter when a messagebox is prompting for "ok", will activate ok button --- apps/openmw/mwbase/windowmanager.hpp | 1 + apps/openmw/mwgui/messagebox.cpp | 24 ++++++++++++++++++++++++ apps/openmw/mwgui/messagebox.hpp | 6 +++++- apps/openmw/mwgui/windowmanagerimp.cpp | 5 +++++ apps/openmw/mwgui/windowmanagerimp.hpp | 1 + apps/openmw/mwinput/inputmanagerimp.cpp | 13 ++++++++++++- apps/openmw/mwinput/inputmanagerimp.hpp | 2 ++ 7 files changed, 50 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 30bfced06a..4f7435fadc 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -199,6 +199,7 @@ namespace MWBase ///< Hides dialog and schedules dialog to be deleted. virtual void messageBox (const std::string& message, const std::vector& buttons) = 0; + virtual void enterPressed () = 0; virtual int readPressedButton() = 0; ///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox) diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index b660af7dd4..08f9508684 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -1,3 +1,5 @@ +#include + #include "messagebox.hpp" using namespace MWGui; @@ -133,6 +135,10 @@ void MessageBoxManager::setMessageBoxSpeed (int speed) mMessageBoxSpeed = speed; } +void MessageBoxManager::enterPressed () +{ + mInterMessageBoxe->enterPressed(); +} int MessageBoxManager::readPressedButton () { @@ -359,7 +365,25 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan } } +void InteractiveMessageBox::enterPressed() +{ + + std::string ok = Misc::StringUtils::lowerCase(MyGUI::LanguageManager::getInstance().replaceTags("#{sOK}")); + std::vector::const_iterator button; + for(button = mButtons.begin(); button != mButtons.end(); ++button) + { + if(Misc::StringUtils::lowerCase((*button)->getCaption()) == ok) + buttonActivated(*button); + } + +} + void InteractiveMessageBox::mousePressed (MyGUI::Widget* pressed) +{ + buttonActivated (pressed); +} + +void InteractiveMessageBox::buttonActivated (MyGUI::Widget* pressed) { mMarkedToDelete = true; int index = 0; diff --git a/apps/openmw/mwgui/messagebox.hpp b/apps/openmw/mwgui/messagebox.hpp index 5e4c468d56..4be8bc5b79 100644 --- a/apps/openmw/mwgui/messagebox.hpp +++ b/apps/openmw/mwgui/messagebox.hpp @@ -34,7 +34,8 @@ namespace MWGui void removeMessageBox (float time, MessageBox *msgbox); bool removeMessageBox (MessageBox *msgbox); void setMessageBoxSpeed (int speed); - + + void enterPressed(); int readPressedButton (); MWBase::WindowManager *mWindowManager; @@ -70,12 +71,15 @@ namespace MWGui { public: InteractiveMessageBox (MessageBoxManager& parMessageBoxManager, const std::string& message, const std::vector& buttons); + void enterPressed (); void mousePressed (MyGUI::Widget* _widget); int readPressedButton (); bool mMarkedToDelete; private: + void buttonActivated (MyGUI::Widget* _widget); + MessageBoxManager& mMessageBoxManager; MyGUI::EditPtr mMessageWidget; MyGUI::WidgetPtr mButtonsWidget; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 8ec495550e..ae314dd68a 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -560,6 +560,11 @@ void WindowManager::messageBox (const std::string& message, const std::vectorenterPressed(); +} + int WindowManager::readPressedButton () { return mMessageBoxManager->readPressedButton(); diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 8bcb88e224..fff627366e 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -189,6 +189,7 @@ namespace MWGui virtual void removeDialog(OEngine::GUI::Layout* dialog); ///< Hides dialog and schedules dialog to be deleted. virtual void messageBox (const std::string& message, const std::vector& buttons); + virtual void enterPressed (); virtual int readPressedButton (); ///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox) virtual void onFrame (float frameDuration); diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 1f270df8be..153bbba8d9 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -51,6 +51,7 @@ namespace MWInput , mUIYMultiplier (Settings::Manager::getFloat("ui y multiplier", "Input")) , mPreviewPOVDelay(0.f) , mTimeIdle(0.f) + , mEnterPressed(false) { Ogre::RenderWindow* window = ogre.getWindow (); size_t windowHnd; @@ -239,6 +240,10 @@ namespace MWInput void InputManager::update(float dt, bool loading) { + // Pressing enter when a messagebox is prompting for "ok" will activate the ok button + if(mEnterPressed && MWBase::Environment::get().getWindowManager()->isGuiMode() && MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_InterMessageBox) + MWBase::Environment::get().getWindowManager()->enterPressed(); + // Tell OIS to handle all input events mKeyboard->capture(); mMouse->capture(); @@ -251,7 +256,7 @@ namespace MWInput // update values of channels (as a result of pressed keys) if (!loading) mInputCtrl->update(dt); - + // Update windows/gui as a result of input events // For instance this could mean opening a new window/dialog, // by doing this after the input events are handled we @@ -426,6 +431,9 @@ namespace MWInput bool InputManager::keyPressed( const OIS::KeyEvent &arg ) { + if(arg.key == OIS::KC_RETURN && MWBase::Environment::get().getWindowManager()->isGuiMode() && MWBase::Environment::get().getWindowManager()->getMode() != MWGui::GM_Console) + mEnterPressed = true; + mInputCtrl->keyPressed (arg); unsigned int text = arg.text; #ifdef __APPLE__ // filter \016 symbol for F-keys on OS X @@ -442,6 +450,9 @@ namespace MWInput bool InputManager::keyReleased( const OIS::KeyEvent &arg ) { + if(arg.key == OIS::KC_RETURN) + mEnterPressed = false; + mInputCtrl->keyReleased (arg); MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode::Enum(arg.key)); diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index 9deed1f285..c7ba7b7565 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -151,6 +151,8 @@ namespace MWInput std::map mControlSwitch; + bool mEnterPressed; + private: void adjustMouseRegion(int width, int height); From c32c31f6d642c38450b03076319d7d73d72b161c Mon Sep 17 00:00:00 2001 From: Tom Mason Date: Sun, 10 Feb 2013 15:41:02 +0000 Subject: [PATCH 03/12] break after activating button --- apps/openmw/mwgui/messagebox.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index 08f9508684..896ab3bb56 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -373,7 +373,10 @@ void InteractiveMessageBox::enterPressed() for(button = mButtons.begin(); button != mButtons.end(); ++button) { if(Misc::StringUtils::lowerCase((*button)->getCaption()) == ok) + { buttonActivated(*button); + break; + } } } From 62c711d709d9c3bf314b97bd31b198f3768255e9 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 11 Feb 2013 02:28:02 +0100 Subject: [PATCH 04/12] Small change to delete microcode cache more aggressively. --- extern/shiny/Main/Factory.cpp | 18 +++++++++++------- extern/shiny/Main/Factory.hpp | 5 ++++- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/extern/shiny/Main/Factory.cpp b/extern/shiny/Main/Factory.cpp index 21f13e30b6..40c695fd4a 100644 --- a/extern/shiny/Main/Factory.cpp +++ b/extern/shiny/Main/Factory.cpp @@ -15,6 +15,7 @@ namespace sh { Factory* Factory::sThis = 0; + const std::string Factory::mBinaryCacheName = "binaryCache"; Factory& Factory::getInstance() { @@ -198,16 +199,16 @@ namespace sh if (mShadersLastModified[sourceRelative] != lastModified) { // delete any outdated shaders based on this shader set - removeCache (it->first); - // remove the whole binary cache (removing only the individual shaders does not seem to be possible at this point with OGRE) - removeBinaryCache = true; + if (removeCache (it->first)) + removeBinaryCache = true; } } else { // if we get here, this is either the first run or a new shader file was added // in both cases we can safely delete - removeCache (it->first); + if (removeCache (it->first)) + removeBinaryCache = true; } mShaderSets.insert(std::make_pair(it->first, newSet)); } @@ -304,7 +305,7 @@ namespace sh if (mPlatform->supportsShaderSerialization () && mReadMicrocodeCache && !removeBinaryCache) { - std::string file = mPlatform->getCacheFolder () + "/shShaderCache.txt"; + std::string file = mPlatform->getCacheFolder () + "/" + mBinaryCacheName; if (boost::filesystem::exists(file)) { mPlatform->deserializeShaders (file); @@ -316,7 +317,7 @@ namespace sh { if (mPlatform->supportsShaderSerialization () && mWriteMicrocodeCache) { - std::string file = mPlatform->getCacheFolder () + "/shShaderCache.txt"; + std::string file = mPlatform->getCacheFolder () + "/" + mBinaryCacheName; mPlatform->serializeShaders (file); } @@ -590,8 +591,9 @@ namespace sh m->createForConfiguration (configuration, 0); } - void Factory::removeCache(const std::string& pattern) + bool Factory::removeCache(const std::string& pattern) { + bool ret = false; if ( boost::filesystem::exists(mPlatform->getCacheFolder()) && boost::filesystem::is_directory(mPlatform->getCacheFolder())) { @@ -620,10 +622,12 @@ namespace sh if (shaderName == pattern) { boost::filesystem::remove(file); + ret = true; std::cout << "Removing outdated shader: " << file << std::endl; } } } } + return ret; } } diff --git a/extern/shiny/Main/Factory.hpp b/extern/shiny/Main/Factory.hpp index 6d4175c976..846860b89a 100644 --- a/extern/shiny/Main/Factory.hpp +++ b/extern/shiny/Main/Factory.hpp @@ -203,7 +203,10 @@ namespace sh MaterialInstance* findInstance (const std::string& name); MaterialInstance* searchInstance (const std::string& name); - void removeCache (const std::string& pattern); + /// @return was anything removed? + bool removeCache (const std::string& pattern); + + static const std::string mBinaryCacheName; }; } From 55dd17c27c81268916b6045e828029cd4ed31c2f Mon Sep 17 00:00:00 2001 From: graffy76 Date: Mon, 11 Feb 2013 04:30:16 -0600 Subject: [PATCH 05/12] Added setBarColor() function to CSVDoc::Operation. Created four color types for existing operations (save, verify, compile and search), with a default for future / undefined ops. --- apps/opencs/view/doc/operation.cpp | 70 +++++++++++++++++++++++++++++- apps/opencs/view/doc/operation.hpp | 6 ++- 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/apps/opencs/view/doc/operation.cpp b/apps/opencs/view/doc/operation.cpp index 3f415da032..c301195bc7 100644 --- a/apps/opencs/view/doc/operation.cpp +++ b/apps/opencs/view/doc/operation.cpp @@ -35,7 +35,7 @@ void CSVDoc::Operation::updateLabel (int threads) CSVDoc::Operation::Operation (int type) : mType (type), mStalling (false) { /// \todo Add a cancel button or a pop up menu with a cancel item - + setBarColor( type); updateLabel(); /// \todo assign different progress bar colours to allow the user to distinguish easily between operation types @@ -51,4 +51,70 @@ void CSVDoc::Operation::setProgress (int current, int max, int threads) int CSVDoc::Operation::getType() const { return mType; -} \ No newline at end of file +} + +void CSVDoc::Operation::setBarColor (int type) +{ + QString style ="QProgressBar {" + "text-align: center;" + "}" + "QProgressBar::chunk {" + "background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 %1, stop:.50 %2 stop: .51 %3 stop:1 %4);" + "text-align: center;" + "margin: 2px 1px 1p 2px;" + "}"; + + // "QProgressBar::chunk {background-color: %1;}"; + + QString topColor = "#F2F6F8"; + QString bottomColor = "#E0EFF9"; + QString midTopColor = "#D8E1E7"; + QString midBottomColor = "#B5C6D0"; // default gray gloss + + // colors inspired by samples from: + // http://www.colorzilla.com/gradient-editor/ + + switch (type) + { + case CSMDoc::State_Saving: + + topColor = "#FECCB1"; + midTopColor = "#F17432"; + midBottomColor = "#EA5507"; + bottomColor = "#FB955E"; // red gloss #2 + //break; + + case CSMDoc::State_Searching: + + topColor = "#EBF1F6"; + midTopColor = "#ABD3EE"; + midBottomColor = "#89C3EB"; + bottomColor = "#D5EBFB"; //blue gloss #4 + //break; + + case CSMDoc::State_Verifying: + + topColor = "#BFD255"; + midTopColor = "#8EB92A"; + midBottomColor = "#72AA00"; + bottomColor = "#9ECB2D"; //green gloss + //break; + + case CSMDoc::State_Compiling: + + topColor = "#F3E2C7"; + midTopColor = "#C19E67"; + midBottomColor = "#B68D4C"; + bottomColor = "#E9D4B3"; //l Brown 3D + //break; + + default: + + topColor = "#F2F6F8"; + bottomColor = "#E0EFF9"; + midTopColor = "#D8E1E7"; + midBottomColor = "#B5C6D0"; // gray gloss for undefined ops + } + + setStyleSheet(style.arg(topColor).arg(midTopColor).arg(midBottomColor).arg(bottomColor)); +} diff --git a/apps/opencs/view/doc/operation.hpp b/apps/opencs/view/doc/operation.hpp index 362725b6f4..a5abf73b79 100644 --- a/apps/opencs/view/doc/operation.hpp +++ b/apps/opencs/view/doc/operation.hpp @@ -25,7 +25,11 @@ namespace CSVDoc void setProgress (int current, int max, int threads); int getType() const; + + private: + + void setBarColor (int type); }; } -#endif \ No newline at end of file +#endif From ba97c8f7d675067b389bbb3e8a127cc67038a7f6 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 11 Feb 2013 19:54:32 +0100 Subject: [PATCH 06/12] updated credits file --- credits.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/credits.txt b/credits.txt index 5d486c74e7..936f3efd9b 100644 --- a/credits.txt +++ b/credits.txt @@ -26,6 +26,7 @@ gugus / gus Jacob Essex (Yacoby) Jannik Heller (scrawl) Jason Hooks (jhooks) +Joel Graff (graffy) Karl-Felix Glatzer (k1ll) lazydev Leon Saunders (emoose) From 3b64389668d181754ec08fc2f4c010bc5a9d3b98 Mon Sep 17 00:00:00 2001 From: Sergey Shambir Date: Tue, 12 Feb 2013 11:14:30 +0400 Subject: [PATCH 07/12] BookTextParser: fixed infinitive loop --- apps/openmw/mwgui/formatting.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/formatting.cpp b/apps/openmw/mwgui/formatting.cpp index 4090b592d9..1689d2fb1f 100644 --- a/apps/openmw/mwgui/formatting.cpp +++ b/apps/openmw/mwgui/formatting.cpp @@ -160,7 +160,7 @@ std::vector BookTextParser::split(std::string text, const int width ++i; } - if (currentHeight > height-spacing) + if (currentHeight > height-spacing && currentText.size() != currentWord.size()) { // remove the last word currentText.erase(currentText.size()-currentWord.size(), currentText.size()); From 03803f19b5ded40a476181189027d3b5fc706ba1 Mon Sep 17 00:00:00 2001 From: Sergey Shambir Date: Tue, 12 Feb 2013 11:22:19 +0400 Subject: [PATCH 08/12] BookTextParser: moved to Ogre::UTFString Font height and unicode characters glyph width now accounted correctly. --- apps/openmw/mwgui/formatting.cpp | 168 +++++++++++++++++-------------- apps/openmw/mwgui/formatting.hpp | 2 + 2 files changed, 96 insertions(+), 74 deletions(-) diff --git a/apps/openmw/mwgui/formatting.cpp b/apps/openmw/mwgui/formatting.cpp index 1689d2fb1f..c50381a87f 100644 --- a/apps/openmw/mwgui/formatting.cpp +++ b/apps/openmw/mwgui/formatting.cpp @@ -6,7 +6,9 @@ #include "../mwworld/ptr.hpp" #include +#include #include +#include using namespace MWGui; @@ -67,118 +69,134 @@ namespace return value; } + + Ogre::UTFString::unicode_char unicodeCharFromChar(char ch) + { + std::string s; + s += ch; + Ogre::UTFString string(s); + return string.getChar(0); + } } -std::vector BookTextParser::split(std::string text, const int width, const int height) +std::vector BookTextParser::split(std::string utf8Text, const int width, const int height) { + using Ogre::UTFString; std::vector result; MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor - text = Interpreter::fixDefinesBook(text, interpreterContext); + utf8Text = Interpreter::fixDefinesBook(utf8Text, interpreterContext); - boost::algorithm::replace_all(text, "
", "\n"); - boost::algorithm::replace_all(text, "

", "\n\n"); + boost::algorithm::replace_all(utf8Text, "
", "\n"); + boost::algorithm::replace_all(utf8Text, "

", "\n\n"); + UTFString text(utf8Text); const int spacing = 48; - while (text.size() > 0) + const UTFString::unicode_char LEFT_ANGLE = unicodeCharFromChar('<'); + const UTFString::unicode_char NEWLINE = unicodeCharFromChar('\n'); + const UTFString::unicode_char SPACE = unicodeCharFromChar(' '); + + while (!text.empty()) { // 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) + const size_t tagStart = index + 1; + const size_t tagEnd = text.find('>', tagStart); + if (tagEnd == UTFString::npos) throw std::runtime_error("BookTextParser Error: Tag is not terminated"); + const std::string tag = text.substr(tagStart, tagEnd - tagStart).asUTF8(); - if (text.size() > i+4 && text.substr(i, 4) == "', i)-i), false); - currentHeight += (mHeight-h); + const int h = mHeight; + parseImage(tag, 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 + parseFont(tag); + if (currentWidth != 0) { + currentHeight += currentFontHeight(); + currentWidth = 0; + } 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; + parseDiv(tag); + if (currentWidth != 0) { + currentHeight += currentFontHeight(); + currentWidth = 0; + } } - - currentText += text.substr(i, text.find('>', i)-i+1); - i = text.find('>', i); + index = tagEnd; } - else if (text[i] == '\n') + else if (ch == NEWLINE) { - currentHeight += 18; // keep this in sync with the font size + currentHeight += currentFontHeight(); currentWidth = 0; - currentWord = ""; - currentText += text[i]; + currentWordStart = index; } - else if (text[i] == ' ') + else if (ch == SPACE) { currentWidth += 3; // keep this in sync with the font's SpaceWidth property - currentWord = ""; - currentText += text[i]; + currentWordStart = index; } 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]; + currentWidth += widthForCharGlyph(ch); } if (currentWidth > width) { - currentHeight += 18; // keep this in sync with the font size + currentHeight += currentFontHeight(); currentWidth = 0; - // add size of the current word - unsigned int j=0; - while (jgetGlyphInfo(static_cast(currentWord[j]))->width; - ++j; - } + UTFString word = text.substr(currentWordStart, index - currentWordStart); + for (UTFString::const_iterator it = word.begin(), end = word.end(); it != end; ++it) + currentWidth += widthForCharGlyph(it.getCharacter()); } - - ++i; - } - if (currentHeight > height-spacing && currentText.size() != currentWord.size()) - { - // remove the last word - currentText.erase(currentText.size()-currentWord.size(), currentText.size()); + index += UTFString::_utf16_char_length(ch); } + const size_t pageEnd = (currentHeight > height - spacing && currentWordStart != 0) + ? currentWordStart : index; - result.push_back(currentText); - text.erase(0, currentText.size()); + result.push_back(text.substr(0, pageEnd).asUTF8()); + text.erase(0, pageEnd); } return result; } +float BookTextParser::widthForCharGlyph(unsigned unicodeChar) const +{ + std::string fontName(mTextStyle.mFont == "Default" ? "EB Garamond" : mTextStyle.mFont); + return MyGUI::FontManager::getInstance().getByName(fontName) + ->getGlyphInfo(unicodeChar)->width; +} + +float BookTextParser::currentFontHeight() const +{ + std::string fontName(mTextStyle.mFont == "Default" ? "EB Garamond" : mTextStyle.mFont); + return MyGUI::FontManager::getInstance().getByName(fontName)->getDefaultHeight(); +} + MyGUI::IntSize BookTextParser::parse(std::string text, MyGUI::Widget* parent, const int width) { MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor text = Interpreter::fixDefinesBook(text, interpreterContext); - mParent = parent; mWidth = width; mHeight = 0; @@ -193,8 +211,8 @@ MyGUI::IntSize BookTextParser::parse(std::string text, MyGUI::Widget* parent, co boost::algorithm::replace_all(text, "

", "\n\n"); // remove leading newlines - //while (text[0] == '\n') - // text.erase(0); +// while (text[0] == '\n') +// text.erase(0); // remove trailing " if (text[text.size()-1] == '\"') @@ -279,28 +297,30 @@ void BookTextParser::parseSubText(std::string text) { if (text[0] == '<') { - if (text.find('>') == std::string::npos) + const size_t tagStart = 1; + const size_t tagEnd = text.find('>', tagStart); + if (tagEnd == std::string::npos) throw std::runtime_error("BookTextParser Error: Tag is not terminated"); + const std::string tag = text.substr(tagStart, tagEnd - tagStart); - if (text.size() > 4 && text.substr(0, 4) == "'))); - else if (text.size() > 5 && text.substr(0, 5) == "'))); - else if (text.size() > 4 && text.substr(0, 4) == "'))); + if (boost::algorithm::starts_with(tag, "IMG")) + parseImage(tag); + if (boost::algorithm::starts_with(tag, "FONT")) + parseFont(tag); + if (boost::algorithm::starts_with(tag, "DOV")) + parseDiv(tag); - text.erase(0, text.find('>')+1); + text.erase(0, tagEnd + 1); } - bool tagFound = false; + size_t tagStart = std::string::npos; std::string realText; // real text, without tags - unsigned int i=0; - for (; isetSize(box->getSize().width, box->getTextSize().height); mHeight += box->getTextSize().height; - if (tagFound) + if (tagStart != std::string::npos) { - parseSubText(text.substr(i, text.size())); + parseSubText(text.substr(tagStart, text.size())); } } diff --git a/apps/openmw/mwgui/formatting.hpp b/apps/openmw/mwgui/formatting.hpp index a1e115491d..ab1ee3af4d 100644 --- a/apps/openmw/mwgui/formatting.hpp +++ b/apps/openmw/mwgui/formatting.hpp @@ -40,6 +40,8 @@ namespace MWGui std::vector split(std::string text, const int width, const int height); protected: + float widthForCharGlyph(unsigned unicodeChar) const; + float currentFontHeight() const; void parseSubText(std::string text); void parseImage(std::string tag, bool createWidget=true); From 7d7a1119daccbf4a342555a3395c00fbd5e9f817 Mon Sep 17 00:00:00 2001 From: Sergey Shambir Date: Tue, 12 Feb 2013 11:49:20 +0400 Subject: [PATCH 09/12] Fixed book text misalignment, at least in some cases https://bugs.openmw.org/issues/284 --- apps/openmw/mwgui/formatting.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/openmw/mwgui/formatting.cpp b/apps/openmw/mwgui/formatting.cpp index c50381a87f..7f28e9e17d 100644 --- a/apps/openmw/mwgui/formatting.cpp +++ b/apps/openmw/mwgui/formatting.cpp @@ -87,6 +87,7 @@ std::vector BookTextParser::split(std::string utf8Text, const int w MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor utf8Text = Interpreter::fixDefinesBook(utf8Text, interpreterContext); + boost::algorithm::replace_all(utf8Text, "\n", ""); boost::algorithm::replace_all(utf8Text, "
", "\n"); boost::algorithm::replace_all(utf8Text, "

", "\n\n"); @@ -207,6 +208,7 @@ MyGUI::IntSize BookTextParser::parse(std::string text, MyGUI::Widget* parent, co MyGUI::Gui::getInstance().destroyWidget(mParent->getChildAt(0)); } + boost::algorithm::replace_all(text, "\n", ""); boost::algorithm::replace_all(text, "
", "\n"); boost::algorithm::replace_all(text, "

", "\n\n"); From f9a0a19ee1303ac3242695fcdf329169d6410523 Mon Sep 17 00:00:00 2001 From: "Alexander \"Ace\" Olofsson" Date: Tue, 12 Feb 2013 13:23:25 +0100 Subject: [PATCH 10/12] Fix a small issue in the windows installer, also added the OpenMW version to the installed package name --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 577b6f6b2d..cfd1c7dd39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -391,11 +391,11 @@ if(WIN32) INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION ".") SET(CPACK_GENERATOR "NSIS") - SET(CPACK_PACKAGE_NAME "OpenMW") + SET(CPACK_PACKAGE_NAME "OpenMW ${OPENMW_VERSION}") SET(CPACK_PACKAGE_VENDOR "OpenMW.org") SET(CPACK_PACKAGE_VERSION ${OPENMW_VERSION}) SET(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR}) - SET(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO}) + SET(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINOR}) SET(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE}) SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW;omwlauncher;OpenMW Launcher") SET(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '\$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Readme.lnk' '\$INSTDIR\\\\readme.txt'") From 0ae01794f1e1b106bf7fbfe592aade099036a285 Mon Sep 17 00:00:00 2001 From: "Alexander \"Ace\" Olofsson" Date: Tue, 12 Feb 2013 13:57:16 +0100 Subject: [PATCH 11/12] Fixed build errors in OpenCS --- apps/opencs/model/world/record.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/world/record.cpp b/apps/opencs/model/world/record.cpp index 229985a8a2..14f63c155d 100644 --- a/apps/opencs/model/world/record.cpp +++ b/apps/opencs/model/world/record.cpp @@ -3,19 +3,19 @@ CSMWorld::RecordBase::~RecordBase() {} -bool CSMWorld::RecordBase::RecordBase::isDeleted() const +bool CSMWorld::RecordBase::isDeleted() const { return mState==State_Deleted || mState==State_Erased; } -bool CSMWorld::RecordBase::RecordBase::isErased() const +bool CSMWorld::RecordBase::isErased() const { return mState==State_Erased; } -bool CSMWorld::RecordBase::RecordBase::isModified() const +bool CSMWorld::RecordBase::isModified() const { return mState==State_Modified || mState==State_ModifiedOnly; } \ No newline at end of file From bbb845824d90a87661df67366f8e8129b68d25e2 Mon Sep 17 00:00:00 2001 From: "Alexander \"Ace\" Olofsson" Date: Tue, 12 Feb 2013 13:59:24 +0100 Subject: [PATCH 12/12] Added typedef for ssize_t in windows and fixed a use of __PRETTY_FUNCTION__ --- apps/openmw/mwrender/videoplayer.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/apps/openmw/mwrender/videoplayer.cpp b/apps/openmw/mwrender/videoplayer.cpp index baec2f7409..b710225042 100644 --- a/apps/openmw/mwrender/videoplayer.cpp +++ b/apps/openmw/mwrender/videoplayer.cpp @@ -17,6 +17,11 @@ #include "../mwsound/sound_decoder.hpp" #include "../mwsound/sound.hpp" +#ifdef _WIN32 +#include + +typedef SSIZE_T ssize_t; +#endif namespace MWRender { @@ -361,7 +366,11 @@ class MovieAudioDecoder : public MWSound::Sound_Decoder } void open(const std::string&) +#ifdef _WIN32 + { fail(std::string("Invalid call to ")+__FUNCSIG__); } +#else { fail(std::string("Invalid call to ")+__PRETTY_FUNCTION__); } +#endif void close() { }