Files
wagic/projects/mtg/src/DeckMenu.cpp
T
techdragon.nguyen@gmail.com e4c8469490 implemented vertical scrolling.
created new class VerticalTextScroller to handle task display in deck selection screens
modified detailed popup placement on deck selection screen to compensate for lack of border
2010-11-24 16:12:18 +00:00

332 lines
10 KiB
C++

#include "PrecompiledHeader.h"
#include "DeckMenu.h"
#include "DeckMenuItem.h"
#include "DeckMetaData.h"
#include "JTypes.h"
#include "GameApp.h"
#include "Translate.h"
#include "TextScroller.h"
#include "Tasks.h"
#include <iomanip>
namespace
{
const float kVerticalMargin = 16;
const float kHorizontalMargin = 20;
const float kLineHeight = 20;
const float kDescriptionVerticalBoxPadding = 5;
const float kDescriptionHorizontalBoxPadding = 5;
const float kDefaultFontScale = 1.0f;
const int DETAILED_INFO_THRESHOLD = 20;
}
hgeParticleSystem* DeckMenu::stars = NULL;
//
// For the additional info window, maximum characters per line is roughly 30 characters across.
// TODO: figure a way to get incoming text to wrap.
//
// used fixed locations where the menu, title and descriptive text are located.
// * menu at (125, 60 )
// * descriptive information 125
// *** Need to make this configurable in a file somewhere to allow for class reuse
DeckMenu::DeckMenu(int id, JGuiListener* listener, int fontId, const string _title, const int& startIndex, bool showDetailsOverride) :
JGuiController(id, listener), fontId(fontId), mShowDetailsScreen( showDetailsOverride )
{
backgroundName = "DeckMenuBackdrop";
mAlwaysShowDetailsButton = false;
mSelectedDeck = NULL;
mY = 50;
mWidth = 176;
mX = 110;
titleX = 110; // center point in title box
titleY = 15;
titleWidth = 180; // width of inner box of title
descX = 260 + kDescriptionVerticalBoxPadding;
descY = 100 + kDescriptionHorizontalBoxPadding;
descHeight = 145;
descWidth = 220;
detailedInfoBoxX = 400;
detailedInfoBoxY = 235;
starsOffsetX = 50;
statsX = 300;
statsY = 15;
statsHeight = 50;
statsWidth = 227;
mSelectedDeckId = startIndex;
avatarX = 232;
avatarY = 11;
menuInitialized = false;
float scrollerWidth = 200.0f;
float scrollerHeight = 28.0f;
mScroller = NEW VerticalTextScroller(Fonts::MAIN_FONT, 14, 235, scrollerWidth, 28.0f, 100);
mAutoTranslate = true;
maxItems = 7;
mHeight = 2 * kVerticalMargin + (maxItems * kLineHeight);
// we want to cap the deck titles to 15 characters to avoid overflowing deck names
title = _(_title);
displayTitle = title;
mFont = resources.GetWFont(fontId);
startId = 0;
selectionT = 0;
timeOpen = 0;
mClosed = false;
if (mFont->GetStringWidth(title.c_str()) > titleWidth)
titleFontScale = 0.75f;
else
titleFontScale = 1.0f;
mSelectionTargetY = selectionY = kVerticalMargin;
if (NULL == stars) stars = NEW hgeParticleSystem(resources.RetrievePSI("stars.psi", resources.GetQuad("stars")));
stars->FireAt(mX, mY);
updateScroller();
}
void DeckMenu::RenderBackground()
{
ostringstream bgFilename;
bgFilename << backgroundName << ".png";
static bool loadBackground = true;
if (loadBackground)
{
JQuad *background = resources.RetrieveTempQuad(bgFilename.str(), TEXTURE_SUB_5551);
if (background)
JRenderer::GetInstance()->RenderQuad(background, 0, 0);
else
loadBackground = false;
}
}
DeckMetaData * DeckMenu::getSelectedDeck()
{
if (mSelectedDeck) return mSelectedDeck;
return NULL;
}
void DeckMenu::enableDisplayDetailsOverride()
{
mAlwaysShowDetailsButton = true;
}
bool DeckMenu::showDetailsScreen()
{
DeckMetaData * currentMenuItem = getSelectedDeck();
if (currentMenuItem)
{
if (mAlwaysShowDetailsButton) return true;
if (mShowDetailsScreen && currentMenuItem->getVictories() > DETAILED_INFO_THRESHOLD) return true;
}
return false;
}
void DeckMenu::initMenuItems()
{
float sY = mY + kVerticalMargin;
for (int i = startId; i < mCount; ++i)
{
float y = mY + kVerticalMargin + i * kLineHeight;
DeckMenuItem * currentMenuItem = static_cast<DeckMenuItem*> (mObjects[i]);
currentMenuItem->Relocate(mX, y);
if (currentMenuItem->hasFocus()) sY = y;
}
mSelectionTargetY = selectionY = sY;
//Grab a texture in VRAM.
pspIconsTexture = resources.RetrieveTexture("iconspsp.png", RETRIEVE_LOCK);
char buf[512];
for (int i = 0; i < 8; i++)
{
sprintf(buf, "iconspsp%d", i);
pspIcons[i] = resources.RetrieveQuad("iconspsp.png", (float) i * 32, 0, 32, 32, buf);
pspIcons[i]->SetHotSpot(16, 16);
}
}
void DeckMenu::Render()
{
JRenderer * renderer = JRenderer::GetInstance();
float height = mHeight;
if (!menuInitialized)
{
initMenuItems();
stars->Fire();
timeOpen = 0;
menuInitialized = true;
}
if (timeOpen < 1) height *= timeOpen > 0 ? timeOpen : -timeOpen;
for (int i = startId; i < startId + maxItems; i++)
{
if (i > mCount - 1) break;
DeckMenuItem *currentMenuItem = static_cast<DeckMenuItem*> (mObjects[i]);
if (currentMenuItem->mY - kLineHeight * startId < mY + height - kLineHeight + 7)
{
if (currentMenuItem->hasFocus())
{
mSelectedDeckId = i;
mSelectedDeck = currentMenuItem->meta;
WFont *mainFont = resources.GetWFont(Fonts::MAIN_FONT);
// display the "more info" button if special condition is met
if (showDetailsScreen())
{
float pspIconsSize = 0.5;
const string detailedInfoString = "Detailed Info";
float stringWidth = mainFont->GetStringWidth(detailedInfoString.c_str());
float boxStartX = detailedInfoBoxX - stringWidth / 2;
DWORD currentColor = mainFont->GetColor();
renderer->FillRoundRect( boxStartX, detailedInfoBoxY - 5, stringWidth, mainFont->GetHeight() + 15, .5, ARGB( 255, 0, 0, 0) );
renderer->RenderQuad(pspIcons[5], detailedInfoBoxX, detailedInfoBoxY + 2, 0, pspIconsSize, pspIconsSize);
mainFont->SetColor(currentColor);
mainFont->DrawString(detailedInfoString, boxStartX, detailedInfoBoxY + 10);
}
// display the avatar image
if (currentMenuItem->imageFilename.size() > 0)
{
JQuad * quad = resources.RetrieveTempQuad(currentMenuItem->imageFilename, TEXTURE_SUB_AVATAR);
if (quad) renderer->RenderQuad(quad, avatarX, avatarY);
}
// fill in the description part of the screen
string text = currentMenuItem->desc;
mainFont->DrawString(text.c_str(), descX, descY);
mFont->SetColor(ARGB(255,255,255,255));
// fill in the statistical portion
if (currentMenuItem->meta)
{
ostringstream oss;
oss << "Deck: " << currentMenuItem->meta->getName() << endl;
oss << currentMenuItem->meta->getStatsSummary();
mainFont->DrawString(oss.str(), statsX, statsY);
}
}
else
{
mFont->SetColor(ARGB(150,255,255,255));
}
currentMenuItem->RenderWithOffset(-kLineHeight * startId);
}
}
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)
{
JGuiController::Update(dt);
if (mCurr > startId + maxItems - 1)
startId = mCurr - maxItems + 1;
else if (mCurr < startId) startId = mCurr;
stars->Update(dt);
selectionT += 3 * dt;
selectionY += (mSelectionTargetY - selectionY) * 8 * dt;
float starsX = starsOffsetX + ((mWidth - 2 * kHorizontalMargin) * (1 + cos(selectionT)) / 2);
float starsY = selectionY + 5 * cos(selectionT * 2.35f) + kLineHeight / 2 - kLineHeight * startId;
stars->MoveTo(starsX, starsY);
if (timeOpen < 0)
{
timeOpen += dt * 10;
if (timeOpen >= 0)
{
timeOpen = 0;
mClosed = true;
stars->FireAt(mX, mY);
}
}
else
{
mClosed = false;
timeOpen += dt * 10;
}
if (mScroller) mScroller->Update(dt);
}
void DeckMenu::Add(int id, const char * text, string desc, bool forceFocus, DeckMetaData * deckMetaData)
{
DeckMenuItem * menuItem = NEW DeckMenuItem(this, id, fontId, text, 0,
mY + kVerticalMargin + mCount * kLineHeight, (mCount == 0), mAutoTranslate, deckMetaData);
Translator * t = Translator::GetInstance();
map<string, string>::iterator it = t->deckValues.find(text);
if (it != t->deckValues.end()) //translate decks desc
menuItem->desc = it->second;
else
menuItem->desc = deckMetaData ? deckMetaData->getDescription() : desc;
JGuiController::Add(menuItem);
if (mCount <= maxItems) mHeight += kLineHeight;
if (forceFocus)
{
mObjects[mCurr]->Leaving(JGE_BTN_DOWN);
mCurr = mCount - 1;
menuItem->Entering();
}
}
void DeckMenu::updateScroller()
{
// add all the items from the Tasks db.
TaskList taskList;
mScroller->Reset();
for (vector<Task*>::iterator it = taskList.tasks.begin(); it != taskList.tasks.end(); it++)
{
ostringstream taskDescription;
taskDescription << "[ " << setw(4) << (*it)->getReward() << " / " << (*it)->getExpiration() << " ] "
<< (*it)->getDesc() << endl;
mScroller->Add(taskDescription.str());
}
}
void DeckMenu::Close()
{
timeOpen = -1.0;
stars->Stop(true);
}
void DeckMenu::destroy()
{
SAFE_DELETE(DeckMenu::stars);
}
DeckMenu::~DeckMenu()
{
resources.Release(pspIconsTexture);
SAFE_DELETE(mScroller);
mScroller = NULL;
}