diff --git a/projects/mtg/include/TextScroller.h b/projects/mtg/include/TextScroller.h index a968db4f9..0026cd98f 100644 --- a/projects/mtg/include/TextScroller.h +++ b/projects/mtg/include/TextScroller.h @@ -12,27 +12,47 @@ protected: string mText; string tempText; int fontId; - float mWidth; - float mSpeed; + float mWidth; // width of the text scroller object + float mScrollSpeed; float mX; float mY; float start; int timer; - size_t minimumItems; - + vector strings; unsigned int currentId; int mRandom; int scrollDirection; public: + TextScroller(int fontId, float x, float y, float width, float speed = 100); void Add(string text); void Reset(); void setRandom(int mode = 1); - TextScroller(int fontId, float x, float y, float width, float speed = 30, int scrollerType = 0, size_t _minimumItems = 2); void Render(); void Update(float dt); virtual ostream& toString(ostream& out) const; }; +class VerticalTextScroller: + public TextScroller +{ +private: + size_t mNbItemsShown; + bool mScrollerInitialized; + float mHeight; // maximum height availble for display + int marginX; + int marginY; // margin used to allow text to scroll off screen without + // affecting look and feel. Should be enough + // for at least one line of text ( marginY) + +protected: + string wordWrap(string sentence, float width); + +public: + VerticalTextScroller(int fontId, float x, float y, float width, float height, float scrollSpeed = 30, size_t _minimumItems = 1); + void Render(); + void Update(float dt); + +}; #endif diff --git a/projects/mtg/src/DeckEditorMenu.cpp b/projects/mtg/src/DeckEditorMenu.cpp index e99dea894..11fb6e56f 100644 --- a/projects/mtg/src/DeckEditorMenu.cpp +++ b/projects/mtg/src/DeckEditorMenu.cpp @@ -36,7 +36,7 @@ DeckEditorMenu::DeckEditorMenu(int id, JGuiListener* listener, int fontId, const float scrollerWidth = 80; SAFE_DELETE(mScroller); // need to delete the scroller init in the base class - mScroller = NEW TextScroller(Fonts::MAIN_FONT, 40, 230, scrollerWidth, 100, 1, 1); + mScroller = NEW VerticalTextScroller(Fonts::MAIN_FONT, 40, 230, scrollerWidth, 100); } diff --git a/projects/mtg/src/DeckMenu.cpp b/projects/mtg/src/DeckMenu.cpp index 44c329365..7aab1c59b 100644 --- a/projects/mtg/src/DeckMenu.cpp +++ b/projects/mtg/src/DeckMenu.cpp @@ -18,7 +18,6 @@ namespace const float kDescriptionVerticalBoxPadding = 5; const float kDescriptionHorizontalBoxPadding = 5; - const float kDescriptiveTextFontScale = 0.85f; const float kDefaultFontScale = 1.0f; const int DETAILED_INFO_THRESHOLD = 20; @@ -71,8 +70,9 @@ JGuiController(id, listener), fontId(fontId), mShowDetailsScreen( showDetailsOve menuInitialized = false; - float scrollerWidth = 60; - mScroller = NEW TextScroller(Fonts::MAIN_FONT, 20, 235, scrollerWidth, 100, 1, 1); + float scrollerWidth = 200.0f; + float scrollerHeight = 28.0f; + mScroller = NEW VerticalTextScroller(Fonts::MAIN_FONT, 14, 235, scrollerWidth, 28.0f, 100); mAutoTranslate = true; maxItems = 7; @@ -214,7 +214,6 @@ void DeckMenu::Render() } // fill in the description part of the screen string text = currentMenuItem->desc; - mainFont->SetScale(kDescriptiveTextFontScale); mainFont->DrawString(text.c_str(), descX, descY); mFont->SetColor(ARGB(255,255,255,255)); @@ -232,22 +231,18 @@ void DeckMenu::Render() { mFont->SetColor(ARGB(150,255,255,255)); } - mFont->SetScale(kDefaultFontScale); currentMenuItem->RenderWithOffset(-kLineHeight * startId); } } - - RenderBackground(); - - mFont->SetScale(kDescriptiveTextFontScale); - mScroller->Render(); - mFont->SetScale(kDefaultFontScale); if (!title.empty()) { mFont->SetColor(ARGB(255,255,255,255)); mFont->DrawString(title.c_str(), titleX, titleY, JGETEXT_CENTER); } + + mScroller->Render(); + RenderBackground(); } void DeckMenu::Update(float dt) diff --git a/projects/mtg/src/GameStateMenu.cpp b/projects/mtg/src/GameStateMenu.cpp index 3f28fdc39..d2217fa6d 100644 --- a/projects/mtg/src/GameStateMenu.cpp +++ b/projects/mtg/src/GameStateMenu.cpp @@ -124,7 +124,7 @@ void GameStateMenu::Create() { currentState = MENU_STATE_MAJOR_LANG | MENU_STATE_MINOR_NONE; } - scroller = NEW TextScroller(Fonts::MAIN_FONT, SCREEN_WIDTH / 2 - 90, SCREEN_HEIGHT - 17, 180); + scroller = NEW TextScroller(Fonts::MAIN_FONT, SCREEN_WIDTH / 2 - 90, SCREEN_HEIGHT - 17, 200); scrollerSet = 0; splashTex = NULL; diff --git a/projects/mtg/src/SimplePopup.cpp b/projects/mtg/src/SimplePopup.cpp index 5bec295d5..bf647241c 100644 --- a/projects/mtg/src/SimplePopup.cpp +++ b/projects/mtg/src/SimplePopup.cpp @@ -16,11 +16,11 @@ SimplePopup::SimplePopup(int id, JGuiListener* listener, const int fontId, const char * _title, DeckMetaData* deckMetaData, MTGAllCards * collection) : JGuiController(id, listener), mFontId(fontId), mCollection(collection) { - mX = 18; + mX = 19; mY = 66; mWidth = 180.0f; mTitle = _title; - mMaxLines = 11; + mMaxLines = 12; mTextFont = resources.GetWFont(fontId); this->mCount = 1; // a hack to ensure the menus do book keeping correctly. Since we aren't adding items to the menu, this is required @@ -35,7 +35,6 @@ void SimplePopup::Render() JRenderer *r = JRenderer::GetInstance(); string detailedInformation = getDetailedInformation(mDeckInformation->getFilename()); - mTextFont->SetScale(0.85f); const float textHeight = mTextFont->GetHeight() * mMaxLines; r->DrawRoundRect(mX, mY, mWidth, textHeight, 2.0f, ARGB( 255, 125, 255, 0) ); r->FillRoundRect(mX, mY, mWidth, textHeight, 2.0f, ARGB( 255, 0, 0, 0 ) ); @@ -45,10 +44,11 @@ void SimplePopup::Render() #if 0 drawBoundingBox( mX, mY, mWidth, textHeight ); #endif - mTextFont->DrawString(detailedInformation.c_str(), mX + 20 , mY + 15); + mTextFont->DrawString(detailedInformation.c_str(), mX + 9 , mY + 15); } +// draws a bounding box around the popup. void SimplePopup::drawBoundingBox( float x, float y, float width, float height ) { JRenderer *r = JRenderer::GetInstance(); diff --git a/projects/mtg/src/TextScroller.cpp b/projects/mtg/src/TextScroller.cpp index bc5b90b1f..aab90b038 100644 --- a/projects/mtg/src/TextScroller.cpp +++ b/projects/mtg/src/TextScroller.cpp @@ -5,24 +5,18 @@ #include "utils.h" #include "WFont.h" -enum -{ - HORIZONTAL_SCROLLER = 0, VERTICAL_SCROLLER = 1 -}; -TextScroller::TextScroller(int fontId, float x, float y, float width, float speed, int scrollerType, size_t numItems) : +TextScroller::TextScroller(int fontId, float x, float y, float width, float scrollSpeed) : JGuiObject(0), fontId(fontId) { mWidth = width; - mSpeed = speed; - minimumItems = numItems; + mScrollSpeed = scrollSpeed; mX = x; mY = y; start = -width; timer = 0; currentId = 0; mRandom = 0; - scrollDirection = scrollerType; } void TextScroller::setRandom(int mode) @@ -50,58 +44,131 @@ void TextScroller::Reset() void TextScroller::Update(float dt) { if (!strings.size()) return; - if (scrollDirection == HORIZONTAL_SCROLLER) - { - start += mSpeed * dt; - WFont * mFont = resources.GetWFont(fontId); - if (start > mFont->GetStringWidth(mText.c_str())) - { - start = -mWidth; - if (mRandom) - { - currentId = (rand() % strings.size()); - } - else - { - currentId++; - if (currentId >= strings.size()) currentId = 0; - } - mText = strings[currentId]; - } - } - else - { - // we want to display 2 at a time - ostringstream scrollerText; - if (timer == 0) - { - size_t nbItemsToDisplay = (minimumItems < strings.size() ? minimumItems : strings.size()); - for (size_t idx = 0; idx < nbItemsToDisplay; ++idx) - { - size_t index = (currentId + idx) % strings.size(); - scrollerText << strings[index]; - } - currentId++; - if (currentId >= strings.size()) currentId = 0; - mText = wordWrap(scrollerText.str(), (int) mWidth); - } - timer = ++timer % ((int) mSpeed); - } + + start += mScrollSpeed * dt; + WFont * mFont = resources.GetWFont(fontId); + if (start > mFont->GetStringWidth(mText.c_str())) + { + start = -mWidth; + if (mRandom) + { + currentId = (rand() % strings.size()); + } + else + { + currentId++; + if (currentId >= strings.size()) currentId = 0; + } + mText = strings[currentId]; + } } void TextScroller::Render() { WFont * mFont = resources.GetWFont(fontId); - if (scrollDirection == HORIZONTAL_SCROLLER) - mFont->DrawString(mText.c_str(), mX, mY, JGETEXT_LEFT, start, mWidth); - else - mFont->DrawString(mText.c_str(), mX, mY); + mFont->DrawString(mText.c_str(), mX, mY, JGETEXT_LEFT, start, mWidth); } ostream& TextScroller::toString(ostream& out) const { - return out << "TextScroller ::: mText : " << mText << " ; tempText : " << tempText << " ; mWidth : " << mWidth - << " ; mSpeed : " << mSpeed << " ; mX,mY : " << mX << "," << mY << " ; start : " << start << " ; timer : " - << timer << " ; strings : ?" // << strings - << " ; currentId : " << currentId << " ; mRandom : " << mRandom; + return out << "TextScroller ::: mText : " << mText + << " ; tempText : " << tempText + << " ; mWidth : " << mWidth + << " ; mSpeed : " << mScrollSpeed + << " ; mX,mY : " << mX << "," << mY + << " ; start : " << start + << " ; timer : " << timer + << " ; strings : ?" + << " ; currentId : " << currentId + << " ; mRandom : " << mRandom; +} + + + +VerticalTextScroller::VerticalTextScroller(int fontId, float x, float y, float width, float height, float scrollSpeed, size_t numItemsShown) : +TextScroller( fontId, x, y, width, scrollSpeed) +{ + mHeight = height; + mNbItemsShown = numItemsShown; + + marginX = 0; + marginY = 215; + mScrollerInitialized = false; + +} + +void VerticalTextScroller::Update(float dt) +{ + if (!strings.size()) return; + WFont * mFont = resources.GetWFont(fontId); + ostringstream scrollerText; + if ( mScrollerInitialized && timer % 10 == 0 ) + { + mY -= 1; + if ( mY < marginY ) + mY = marginY + 20; + } + + if (timer == 0) + { + mScrollerInitialized = false; + size_t nbItemsToDisplay = (mNbItemsShown < strings.size() ? mNbItemsShown : strings.size()); + for (size_t idx = 0; idx < nbItemsToDisplay; ++idx) + { + size_t index = (currentId + idx) % strings.size(); + scrollerText << strings[index]; + } + currentId++; + if (currentId >= strings.size()) + currentId = 0; + mText = wordWrap(scrollerText.str(), mWidth); + mY = marginY + 20; + + } + timer = ++timer % ((int) mScrollSpeed); +} + +void VerticalTextScroller::Render() +{ + WFont * mFont = resources.GetWFont(fontId); + mFont->DrawString(mText.c_str(), mX, mY); +} + + + +// This is a customized word wrap based on pixel width. It tries it's best +// to wrap strings using spaces as delimiters. +// Not sure how this translates into non-english fonts. +std::string VerticalTextScroller::wordWrap(std::string sentence, float width) +{ + WFont * mFont = resources.GetWFont(fontId); + float lineWidth = mFont->GetStringWidth( sentence.c_str() ); + string retVal = sentence; + if ( lineWidth < width ) return sentence; + + int numLines = 1; + int breakIdx = 0; + for( size_t idx = 0; idx < sentence.length(); idx ++ ) + { + if ( sentence[idx] == ' ' ) + { + string currentSentence = sentence.substr(breakIdx, idx - breakIdx); + float stringLength = mFont->GetStringWidth( currentSentence.c_str() ); + if (stringLength >= width) + { + if ( stringLength > width ) + { + while ( sentence[idx-1] != ' ' ) + idx--; + } + retVal[idx-1] = '\n'; + breakIdx = idx; + numLines++; + } + } + } + if ( numLines * mFont->GetHeight() > mHeight ) + mScrollerInitialized = true; + + return retVal; }