Files
wagic/projects/mtg/src/WGui.cpp

1962 lines
53 KiB
C++

#include "../include/config.h"
#include "../include/OptionItem.h"
#include "../include/PlayerData.h"
#include "../include/Translate.h"
#include "../include/Subtypes.h"
#include "../include/TranslateKeys.h"
#include <sstream>
#include <algorithm>
#include <hge/hgedistort.h>
//WGuiBase
PIXEL_TYPE WGuiBase::getColor(int type){
switch(type){
case WGuiColor::TEXT_BODY:
case WGuiColor::SCROLLBUTTON:
return ARGB(255,255,255,255);
case WGuiColor::SCROLLBAR:
return ARGB(150,50,50,50);
case WGuiColor::BACK_HEADER:
return ARGB(150,80,80,80);
default:
if(type < WGuiColor::BACK){
if(hasFocus())
return ARGB(255,255,255,0);
else
return ARGB(255,255,255,255);
}
else
if(hasFocus())
return ARGB(150,200,200,200);
else
return ARGB(150,50,50,50);
}
return ARGB(150,50,50,50);
}
void WGuiBase::renderBack(WGuiBase * it){
if(!it) return;
WDecoStyled * styled = dynamic_cast<WDecoStyled*>(it);
if(styled)
styled->renderBack(styled->getDecorated());
else
subBack(it);
}
WGuiBase::CONFIRM_TYPE WGuiBase::needsConfirm() {
for (vector<WGuiBase*>::iterator it = items.begin(); it != items.end(); ++it) {
switch((*it)->needsConfirm()) {
case CONFIRM_NEED: return CONFIRM_NEED;
case CONFIRM_CANCEL: return CONFIRM_CANCEL;
case CONFIRM_OK: /* Nothing special : continue iteration */ ;
}
}
return CONFIRM_OK;
}
bool WGuiBase::yieldFocus() {
for (vector<WGuiBase*>::iterator it = items.begin(); it != items.end(); ++it)
if ((*it)->yieldFocus()) { return true; }
return false;
}
//WGuiItem
void WGuiItem::Entering(JButton key){
mFocus = true;
}
float WGuiItem::minWidth(){
WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT);
return mFont->GetStringWidth(_(displayValue).c_str())+4;
}
float WGuiItem::minHeight(){
WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT);
return mFont->GetHeight();
}
bool WGuiItem::Leaving(JButton key){
mFocus = false;
return true;
}
void WGuiItem::Render(){
JRenderer * renderer = JRenderer::GetInstance();
WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT);
DWORD oldcolor = mFont->GetColor();
mFont->SetColor(getColor(WGuiColor::TEXT));
float fH = (height-mFont->GetHeight())/2;
string trans = _(displayValue);
float fW = mFont->GetStringWidth(trans.c_str());
float boxW = getWidth();
float oldS = mFont->GetScale();
if(fW > boxW){
mFont->SetScale(boxW/fW);
}
mFont->DrawString(trans,x+(width/2),y+fH,JGETEXT_CENTER);
mFont->SetScale(oldS);
mFont->SetColor(oldcolor);
}
WGuiItem::WGuiItem(string _display, u8 _mF){
mFlags=_mF;
displayValue = _display;
mFocus = false;
width=SCREEN_WIDTH;
height=20;
x=0;
y=0;
}
string WGuiItem::_(string input){
if(mFlags & WGuiItem::NO_TRANSLATE)
return input;
return ::_(input);
}
bool WGuiItem::CheckUserInput(JButton key){
if(mFocus && key == JGE_BTN_OK){
updateValue();
return true;
}
return false;
}
//WDecoStyled
void WDecoStyled::subBack(WGuiBase * item){
if(!item)
return;
JRenderer * renderer = JRenderer::GetInstance();
if(mStyle & DS_STYLE_BACKLESS)
return;
//TODO: if(mStyle & DS_STYLE_EDGED) Draw the edged box ala SimpleMenu
else{ //Draw standard style
WGuiSplit * split = dynamic_cast<WGuiSplit*>(item);
if(split && split->left->Visible() && split->right->Visible()){
if(split->left)
renderer->FillRoundRect(split->left->getX()-2,split->getY()-2,split->left->getWidth()-6,split->getHeight(),2,split->left->getColor(WGuiColor::BACK));
if(split->right)
renderer->FillRoundRect(split->right->getX()-2,split->getY()-2,split->right->getWidth(),split->getHeight(),2,split->right->getColor(WGuiColor::BACK));
}
else{
renderer->FillRoundRect(item->getX()-2,item->getY()-2,item->getWidth(),item->getHeight(),2,getColor(WGuiColor::BACK));
}
}
}
PIXEL_TYPE WDecoStyled::getColor(int type){
switch(type){
case WGuiColor::BACK:
case WGuiColor::BACK_HEADER:
if(mStyle & DS_COLOR_DARK)
return ARGB(150,35,35,35);
else if(mStyle & DS_COLOR_BRIGHT)
return ARGB(150,80,80,80);
else if(mStyle & DS_STYLE_ALERT)
return ARGB(150,120,80,80);
else
return ARGB(150,50,50,50);
default:
return WGuiBase::getColor(type);
}
return ARGB(150,50,50,50);
}
//WGuiHeader
void WGuiHeader::Render(){
WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT);
mFont->SetColor(getColor(WGuiColor::TEXT));
JRenderer * renderer = JRenderer::GetInstance();
mFont->DrawString(_(displayValue).c_str(),x+width/2,y,JGETEXT_CENTER);
}
bool WGuiMenu::Leaving(JButton key){
int nbitems = (int) items.size();
if(key == buttonNext && currentItem < nbitems-1)
return false;
else if(key == buttonPrev && currentItem > 0)
return false;
if(currentItem >= 0 && currentItem < nbitems)
if(!items[currentItem]->Leaving(key))
return false;
mFocus = false;
return true;
}
void WGuiMenu::Entering(JButton key){
mFocus = true;
//Try to force a selectable option.
if(currentItem == -1){
for (size_t i = 0 ; i < items.size(); i++){
if(items[i]->Selectable()) {
currentItem = i;
break;
}
}
}
if(currentItem >= 0 && currentItem < (int) items.size())
items[currentItem]->Entering(key);
return;
}
void WGuiMenu::subBack(WGuiBase * item){
if(!item)
return;
JRenderer * renderer = JRenderer::GetInstance();
WGuiSplit * split = dynamic_cast<WGuiSplit*>(item);
if(split && split->left->Visible() && split->right->Visible()){
if(split->left)
subBack(split->left);//renderer->FillRoundRect(split->left->getX()-2,split->getY()-2,split->left->getWidth()-6,split->getHeight(),2,split->left->getColor(WGuiColor::BACK));
if(split->right)
subBack(split->right);//renderer->FillRoundRect(split->right->getX()-2,split->getY()-2,split->right->getWidth(),split->getHeight(),2,split->right->getColor(WGuiColor::BACK));
}
else
renderer->FillRoundRect(item->getX(),item->getY(),item->getWidth()-4,item->getHeight()-2,2,item->getColor(WGuiColor::BACK));
}
void WGuiMenu::setSelected(vector<WGuiBase*>::iterator& it) {
int c = it - items.begin();
if (c != currentItem)
{
items[currentItem]->Leaving(JGE_BTN_NONE);
currentItem = c;
items[currentItem]->Entering(JGE_BTN_NONE);
}
}
bool WGuiMenu::yieldFocus() {
for (vector<WGuiBase*>::iterator it = items.begin(); it != items.end(); ++it)
if ((*it)->yieldFocus()) { setSelected(it); return true; }
return false;
}
//WGuiList
WGuiList::WGuiList(string name, WSyncable * syncme): WGuiMenu(JGE_BTN_DOWN, JGE_BTN_UP, false, syncme){
failMsg = "NO OPTIONS AVAILABLE";
width = SCREEN_WIDTH-10;
height = SCREEN_HEIGHT-10;
y = 5;
x = 5;
mFocus = false;
sync = syncme;
displayValue = name;
}
void WGuiList::confirmChange(bool confirmed){
for(size_t x=0;x<items.size();x++){
if(!items[x])
continue;
items[x]->confirmChange(confirmed);
}
}
void WGuiList::Render(){
JRenderer * renderer = JRenderer::GetInstance();
int listHeight=40;
int listSelectable=0;
int adjustedCurrent=0;
int start = 0, nowPos = 0, vHeight=0;
int nbitems = (int) items.size();
//List is empty.
if (!items.size() && failMsg != ""){
WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT);
mFont->SetColor(getColor(WGuiColor::TEXT_FAIL));
mFont->DrawString(_(failMsg).c_str(),x+width/2, y, JGETEXT_RIGHT);
return;
}
//Force a selectable option.
if(currentItem == -1){
for (int i = 0 ; i < nbitems; i++){
if(items[i]->Selectable()) {
currentItem = i;
if(hasFocus())
items[currentItem]->Entering(JGE_BTN_NONE);
break;
}
}
}
//Find out how large our list is, with all items and margin.
for (int pos=0;pos < nbitems; pos++){
listHeight+=static_cast<int>(items[pos]->getHeight()+1); //What does the +1 do exactly ?
if(items[pos]->Selectable()){
listSelectable++;
if(pos < currentItem) adjustedCurrent++;
}
}
//Always fill screen
if(listHeight > SCREEN_HEIGHT)
{
for (start=currentItem;start > 0; start--){
if(!items[start]->Visible())
continue;
vHeight += static_cast<int>(items[start]->getHeight()+5);
if(vHeight >= (SCREEN_HEIGHT-60)/2)
break;
}
vHeight = 0;
if(start >= 0)
for (nowPos=nbitems;nowPos > 1; nowPos--){
if(!items[start]->Visible())
continue;
vHeight += static_cast<int>(items[nowPos-1]->getHeight()+5);
}
if(vHeight <= SCREEN_HEIGHT-40 && nowPos < start)
start = nowPos;
}
vHeight = 0;
nowPos = 0;
//Render items.
if(start >= 0)
{
//Render current underlay.
if(currentItem >= 0 && currentItem < nbitems && items[currentItem]->Visible())
items[currentItem]->Underlay();
for (int pos=0;pos < nbitems; pos++){
if(!items[pos]->Visible())
continue;
if(pos < start){
vHeight += static_cast<int>(items[pos]->getHeight() + 5);
continue;
}
items[pos]->setY(y+nowPos);
items[pos]->setX(x);
if(listHeight > SCREEN_HEIGHT && listSelectable > 1)
items[pos]->setWidth(width-10);
else
items[pos]->setWidth(width);
nowPos += static_cast<int>(items[pos]->getHeight() + 5);
renderBack(items[pos]);
items[pos]->Render();
if(nowPos > SCREEN_HEIGHT) //Stop displaying things once we reach the bottom of the screen.
break;
}
//Draw scrollbar
if(listHeight > SCREEN_HEIGHT && listSelectable > 1){
float barPosition = static_cast<float>(y-5+((float)adjustedCurrent/listSelectable)*(SCREEN_HEIGHT-y));
float barLength = static_cast<float>((SCREEN_HEIGHT-y) / listSelectable);
if(barLength < 4) barLength = 4;
renderer->FillRect(x+width-2,y-1,2,SCREEN_HEIGHT-y,
getColor(WGuiColor::SCROLLBAR));
renderer->FillRoundRect(x+width-5,barPosition,5,barLength,2,
getColor(WGuiColor::SCROLLBUTTON));
}
//Render current overlay.
if(currentItem >= 0 && currentItem < nbitems && items[currentItem]->Visible())
items[currentItem]->Overlay();
}
}
void WGuiList::setData(){
for (size_t i = 0; i < items.size(); i++){
items[i]->setData();
}
}
void WGuiList::ButtonPressed(int controllerId, int controlId){
WGuiBase * it;
if(!(it = Current()))
return;
it->ButtonPressed(controllerId,controlId);
}
string WDecoEnum::lookupVal(int value){
if(edef == NULL){
int id = getId();
if(id != INVALID_ID){
GameOptionEnum * goEnum = dynamic_cast<GameOptionEnum*>(options.get(getId()));
if(goEnum)
edef = goEnum->def;
}
}
if(edef){
int idx = edef->findIndex(value);
if(idx != INVALID_ID)
return edef->values[idx].second;
}
char buf[32];
sprintf(buf,"%d",value);
return buf;
}
void WDecoEnum::Render()
{
WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT);
mFont->SetColor(getColor(WGuiColor::TEXT));
JRenderer * renderer = JRenderer::GetInstance();
mFont->DrawString(_(getDisplay()).c_str(), getX() + 2, getY() + 3);
OptionInteger* opt = dynamic_cast<OptionInteger*>(it);
if(opt)
mFont->DrawString(_(lookupVal(opt->value)).c_str(), getWidth() - 5, getY() + 3, JGETEXT_RIGHT);
}
WDecoEnum::WDecoEnum(WGuiBase * _it, EnumDefinition *_edef) : WGuiDeco(_it) {edef = _edef;}
//WDecoCheat
WDecoCheat::WDecoCheat(WGuiBase * _it): WGuiDeco(_it){
bVisible = (options[Options::ACTIVE_PROFILE].str == SECRET_PROFILE);
}
void WDecoCheat::Reload(){
bVisible = (options[Options::ACTIVE_PROFILE].str == SECRET_PROFILE);
}
bool WDecoCheat::Visible(){
if(bVisible && it && it->Visible())
return true;
return false;
}
bool WDecoCheat::Selectable(){
if(!it || !Visible())
return false;
return it->Selectable();
}
//WDecoConfirm
WDecoConfirm::WDecoConfirm(JGuiListener * _listener, WGuiBase * _it): WGuiDeco(_it){
listener = _listener;
confirm = "Confirm";
cancel = "Cancel";
confirmMenu = NULL;
bModal = false;
mState = OP_CONFIRMED;
}
WDecoConfirm::~WDecoConfirm(){
SAFE_DELETE(confirmMenu);
}
void WDecoConfirm::Entering(JButton key){
setFocus(true);
if(it)
it->Entering(key);
SAFE_DELETE(confirmMenu);
mState = OP_CONFIRMED;
confirmMenu = NEW SimpleMenu(444, listener,Fonts::MENU_FONT, 50,170);
confirmMenu->Add(1,confirm.c_str());
confirmMenu->Add(2,cancel.c_str());
}
bool WDecoConfirm::isModal(){
if(bModal || (it && it->isModal()))
return true;
return false;
}
void WDecoConfirm::setModal(bool val){
bModal = val;
}
void WDecoConfirm::setData(){
if(!it)
return;
it->setData();
}
bool WDecoConfirm::Leaving(JButton key){
if(!it)
return true;
//Choice must be confirmed.
if(mState == OP_UNCONFIRMED){
if(!isModal())
setModal(true);
if(!it->Changed())
mState = OP_CONFIRMED;
else
mState = OP_CONFIRMING;
}
if(mState == OP_CONFIRMED && it->Leaving(key)){
setFocus(false);
setModal(false);
SAFE_DELETE(confirmMenu);
return true;
}
return false;
}
bool WDecoConfirm::CheckUserInput(JButton key){
if(hasFocus()){
if (mState == OP_CONFIRMED && key == JGE_BTN_OK)
mState = OP_UNCONFIRMED;
if (mState != OP_CONFIRMING && it){
if(it->CheckUserInput(key))
return true;
} else if(confirmMenu && confirmMenu->CheckUserInput(key))
return true;
}
return false;
}
void WDecoConfirm::Update(float dt){
if (hasFocus()){
if (it && mState != OP_CONFIRMING)
it->Update(dt);
else
confirmMenu->Update(dt);
}
}
void WDecoConfirm::Overlay(){
if (confirmMenu && mState == OP_CONFIRMING)
confirmMenu->Render();
if(it)
it->Overlay();
}
void WDecoConfirm::ButtonPressed(int controllerId, int controlId){
if(controllerId == 444){
setModal(false);
switch(controlId){
case 1:
mState = OP_CONFIRMED;
if(it)
it->confirmChange(true);
break;
case 2:
mState = OP_CONFIRMED;
if(it)
it->confirmChange(false);
break;
}
}
else
it->ButtonPressed(controllerId,controlId);
}
WGuiButton::WGuiButton( WGuiBase* _it, int _controller, int _control, JGuiListener * jgl): WGuiDeco(_it) {
control = _control;
controller = _controller;
mListener = jgl;
}
void WGuiButton::updateValue(){
if(mListener)
mListener->ButtonPressed(controller, control);
}
bool WGuiButton::CheckUserInput(JButton key){
if (hasFocus() && key == JGE_BTN_OK){
updateValue();
return true;
}
return false;
}
PIXEL_TYPE WGuiButton::getColor(int type){
if(type == WGuiColor::BACK && hasFocus())
return it->getColor(WGuiColor::BACK_HEADER);
return it->getColor(type);
};
WGuiSplit::WGuiSplit(WGuiBase* _left, WGuiBase* _right) : WGuiItem("") {
right = _right;
left = _left;
bRight = false;
percentRight = 0.5f;
if(!left->Selectable())
bRight = true;
}
WGuiSplit::~WGuiSplit(){
SAFE_DELETE(left);
SAFE_DELETE(right);
}
void WGuiSplit::setData(){
left->setData();
right->setData();
}
void WGuiSplit::setX(float _x){
x = _x;
left->setX(x);
right->setX(x+(1-percentRight)*width);
}
void WGuiSplit::setY(float _y){
y = _y;
left->setY(y);
right->setY(y);
}
void WGuiSplit::setWidth(float _w){
width = _w;
if(right->Visible())
left->setWidth((1-percentRight)*width);
else
left->setWidth(width);
right->setWidth(percentRight*width);
}
void WGuiSplit::setHeight(float _h){
left->setHeight(_h);
right->setHeight(_h);
height = _h;
}
float WGuiSplit::getHeight(){
float lH, rH;
lH = left->getHeight();
rH = right->getHeight();
if(lH > rH)
return lH;
return rH;
}
void WGuiSplit::Render(){
if(right->Visible())
right->Render();
if(left->Visible())
left->Render();
}
bool WGuiSplit::isModal(){
if(bRight)
return right->isModal();
return left->isModal();
}
void WGuiSplit::setModal(bool val){
if(bRight)
return right->setModal(val);
return left->setModal(val);
}
bool WGuiSplit::CheckUserInput(JButton key){
if(hasFocus()){
if (!bRight){
if(left->CheckUserInput(key))
return true;
if(key == JGE_BTN_RIGHT && !isModal()
&& right->Selectable() && left->Leaving(JGE_BTN_RIGHT)){
bRight = !bRight;
right->Entering(JGE_BTN_RIGHT);
return true;
}
}
else
{
if(right->CheckUserInput(key))
return true;
if (key == JGE_BTN_LEFT && !isModal()
&& left->Selectable() && right->Leaving(JGE_BTN_LEFT)){
bRight = !bRight;
left->Entering(JGE_BTN_LEFT);
return true;
}
}
}
return false;
}
void WGuiSplit::Update(float dt){
if(bRight)
right->Update(dt);
else
left->Update(dt);
}
void WGuiSplit::Entering(JButton key){
mFocus = true;
if(bRight)
right->Entering(key);
else
left->Entering(key);
}
bool WGuiSplit::Leaving(JButton key){
if(bRight){
if(right->Leaving(key)){
mFocus = false;
return true;
}
}
else{
if(left->Leaving(key)){
mFocus = false;
return true;
}
}
return false;
}
void WGuiSplit::Overlay(){
if(bRight)
right->Overlay();
else
left->Overlay();
}
void WGuiSplit::Underlay(){
if(bRight)
right->Underlay();
else
left->Underlay();
}
void WGuiSplit::ButtonPressed(int controllerId, int controlId)
{
if(bRight)
right->ButtonPressed(controllerId, controlId);
else
left->ButtonPressed(controllerId, controlId);
}
void WGuiSplit::Reload(){
left->Reload();
right->Reload();
}
void WGuiSplit::confirmChange(bool confirmed){
right->confirmChange(confirmed);
left->confirmChange(confirmed);
}
bool WGuiSplit::yieldFocus() {
if (right->yieldFocus()) { bRight = true; return true; }
if (left->yieldFocus()) { bRight = false; return true; }
return false;
}
//WGuiMenu
WGuiMenu::WGuiMenu(JButton next = JGE_BTN_RIGHT, JButton prev = JGE_BTN_LEFT, bool m, WSyncable * syncme): WGuiItem(""){
buttonNext = next;
buttonPrev = prev;
currentItem = -1;
mDPad = m;
sync = syncme;
held = JGE_BTN_NONE;
}
WGuiMenu::~WGuiMenu(){
for(vector<WGuiBase*>::iterator it = items.begin();it!=items.end();it++)
SAFE_DELETE(*it);
}
void WGuiMenu::setData(){
for(vector<WGuiBase*>::iterator it = items.begin();it!=items.end();it++)
(*it)->setData();
};
void WGuiMenu::Reload(){
for(vector<WGuiBase*>::iterator it = items.begin();it!=items.end();it++)
(*it)->Reload();
};
void WGuiMenu::Render(){
for(vector<WGuiBase*>::iterator it = items.begin();it!=items.end();it++)
(*it)->Render();
}
void WGuiMenu::confirmChange(bool confirmed){
for(vector<WGuiBase*>::iterator it = items.begin();it!=items.end();it++)
(*it)->confirmChange(confirmed);
}
void WGuiMenu::ButtonPressed(int controllerId, int controlId){
WGuiBase * it = Current();
if(!it) return;
it->ButtonPressed(controllerId,controlId);
}
WGuiBase * WGuiMenu::Current(){
if(currentItem >= 0 && currentItem < (int) items.size())
return items[currentItem];
return NULL;
}
void WGuiMenu::Add(WGuiBase * it){
if(it)
items.push_back(it);
}
bool WGuiMenu::CheckUserInput(JButton key){
bool kidModal = false;
bool handledInput = false;
int nbitems = (int) items.size();
JGE * mEngine = JGE::GetInstance();
if(!mEngine->GetButtonState(held)) //Key isn't held down.
held = JGE_BTN_NONE;
if(currentItem >= 0 && currentItem < nbitems)
kidModal = items[currentItem]->isModal();
if(!kidModal && hasFocus()){
if (isButtonDir(key,-1)){
held = buttonPrev;
duration = 0;
if(prevItem())
return true;
}
else if(held == buttonPrev && duration > 1){
duration = .92f;
if(prevItem())
return true;
}
else if (isButtonDir(key,1)){
held = buttonNext;
duration = 0;
if(nextItem())
return true;
}
else if(held == buttonNext && duration > 1){
duration = .92f;
if(nextItem())
return true;
}
}
if(currentItem >= 0 && currentItem < nbitems)
return items[currentItem]->CheckUserInput(key);
return false;
}
void WGuiMenu::syncMove(){
if(!sync)
return;
int i = currentItem - sync->getPos();
while(i < 0 && sync->prev())
i = currentItem - sync->getPos();
while(i > 0 && sync->next())
i = currentItem - sync->getPos();
}
bool WGuiMenu::isButtonDir(JButton key, int dir){
if(!mDPad)
return ((dir > 0 && key == buttonNext) || (dir <= 0 && key == buttonPrev));
if(dir <= 0){
switch(buttonPrev){
case JGE_BTN_LEFT:
if(key == JGE_BTN_UP)
return true;
break;
case JGE_BTN_UP:
if(key == JGE_BTN_LEFT)
return true;
break;
default: ; // Nothing
}
return (key == buttonPrev);
}else {
switch(buttonNext){
case JGE_BTN_RIGHT:
if(key == JGE_BTN_DOWN)
return true;
break;
case JGE_BTN_DOWN:
if(key == JGE_BTN_RIGHT)
return true;
break;
default: ; // Nothing
}
return (key == buttonNext);
}
}
void WGuiMenu::Update(float dt){
int nbitems = (int) items.size();
JGE * mEngine = JGE::GetInstance();
if(held)
duration += dt;
if(currentItem >= 0 && currentItem < nbitems)
items[currentItem]->Update(dt);
for (int i = 0 ; i < nbitems; i++){
if(i != currentItem)
items[i]->Update(dt);
}
}
bool WGuiMenu::nextItem(){
int potential = currentItem;
int nbitems = (int) items.size();
if(nbitems < 2)
return false;
WGuiBase * now = NULL;
if(currentItem < nbitems && currentItem > -1)
now = items[currentItem];
if (potential < nbitems-1)
potential++;
else
potential = 0;
while(potential < nbitems-1 && items[potential]->Selectable() == false)
potential++;
if(potential == nbitems || !items[potential]->Selectable())
potential = -1;
else if(potential != currentItem && (!now || now->Leaving(buttonNext))){
currentItem = potential;
items[currentItem]->Entering(buttonNext);
if(sync)
syncMove();
return true;
}
if(sync)
syncMove();
return false;
}
bool WGuiMenu::prevItem(){
int potential = currentItem;
WGuiBase * now = NULL;
int nbitems = (int) items.size();
if(nbitems < 2)
return false;
if(currentItem < (int)items.size() && currentItem > -1)
now = items[currentItem];
if (potential > 0)
potential--;
else
potential = nbitems-1;
while(potential > 0 && items[potential]->Selectable() == false)
potential--;
if(potential < 0 || !items[potential]->Selectable())
potential = -1;
else if(potential != currentItem && (!now || now->Leaving(buttonNext))){
currentItem = potential;
items[currentItem]->Entering(buttonPrev);
if(sync)
syncMove();
return true;
}
if(sync)
syncMove();
return false;
}
void WGuiMenu::setModal(bool val){
WGuiBase* c = Current();
if(c)
c->setModal(val);
}
bool WGuiMenu::isModal(){
WGuiBase* c = Current();
if(c)
return c->isModal();
return false;
}
//WGuiTabMenu
void WGuiTabMenu::Add(WGuiBase * it){
if (it){
it->setY(it->getY()+35);
it->setHeight(it->getHeight()-35);
WGuiMenu::Add(it);
}
}
void WGuiTabMenu::Render(){
WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT);
JRenderer * renderer = JRenderer::GetInstance();
if (!items.size())
return;
float offset = x;
mFont->SetScale(0.8f);
for(vector<WGuiBase*>::iterator it = items.begin();it!=items.end();it++){
float w = mFont->GetStringWidth(_((*it)->getDisplay()).c_str());
mFont->SetColor((*it)->getColor(WGuiColor::TEXT_TAB));
renderer->FillRoundRect(offset+5,5,w + 5,25,2,(*it)->getColor(WGuiColor::BACK_TAB));
mFont->DrawString(_((*it)->getDisplay()).c_str(),offset+10,10);
offset += w + 10 + 2;
}
mFont->SetScale(1);
WGuiBase * c = Current();
if(c)
c->Render();
}
void WGuiTabMenu::save(){
confirmChange(true);
setData();
::options.save();
}
//WGuiAward
void WGuiAward::Overlay(){
JRenderer * r = JRenderer::GetInstance();
WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT);
mFont->SetScale(0.8f);
mFont->SetColor(getColor(WGuiColor::TEXT));
string s = details;
if(s.size()){
float fW = mFont->GetStringWidth(s.c_str());
float fH = mFont->GetHeight();
if(fH < 16)
fH = 18;
JQuad * button = resources.RetrieveQuad("iconspsp.png", (float)4*32, 0, 32, 32,"",RETRIEVE_NORMAL);
r->FillRoundRect(5,10,fW+32,fH+2,2,getColor(WGuiColor::BACK));
if(button)
r->RenderQuad(button, 10,12,0,.5,.5);
mFont->DrawString(::_(s),30,16);
}
mFont->SetScale(1);
}
void WGuiAward::Underlay(){
char buf[1024];
JRenderer * r = JRenderer::GetInstance();
JQuad * trophy = NULL;
string n = Options::getName(id);
if(n.size()){
sprintf(buf,"trophy_%s.png",n.c_str()); //Trophy specific to the award
trophy = resources.RetrieveTempQuad(buf); //Themed version...
}
if(!trophy && id >= Options::SET_UNLOCKS){
trophy = resources.RetrieveTempQuad("trophy_set.png"); //TODO FIXME: Should look in set dir too.
}
if(!trophy) //Fallback to basic trophy image.
trophy = resources.RetrieveTempQuad("trophy.png");
if(trophy){
r->RenderQuad(trophy, 0, SCREEN_HEIGHT-trophy->mHeight);
}
}
void WGuiAward::Render(){
GameOptionAward * goa = dynamic_cast<GameOptionAward*>(&options[id]);
if(!goa)
return;
JRenderer * renderer = JRenderer::GetInstance();
WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT);
mFont->SetScale(1);
mFont->SetColor(getColor(WGuiColor::TEXT));
float myX = x;
float myY = y;
float fH = mFont->GetHeight();
float fM = fH / 5; //Font Margin is 20% font height
myX += fM;
renderer->FillRoundRect(x-fM/2,y-fM,getWidth()-fM,fH-fM,fM,getColor(WGuiColor::BACK_TAB));
mFont->DrawString(::_(displayValue).c_str(),myX,myY,JGETEXT_LEFT);
myY += fH + 3*fM;
mFont->SetScale(.75);
fH = mFont->GetHeight();
if(text.size()){
mFont->DrawString(_(text.c_str()),myX,myY,JGETEXT_LEFT);
myY+=fH + fM;
}
string s = goa->menuStr();
if(s.size()){
mFont->DrawString(s.c_str(),myX,myY,JGETEXT_LEFT);
myY+=fH + fM;
}
setHeight(myY-y);
mFont->SetScale(1);
}
WGuiAward::WGuiAward(int _id, string name, string _text, string _details): WGuiItem(name){
id = _id;
text = _text;
height = 60;
details = _details;
}
WGuiAward::~WGuiAward(){
GameOptionAward * goa = dynamic_cast<GameOptionAward*>(&options[id]);
if(goa)
goa->setViewed(true);
}
bool WGuiAward::Visible(){
//WGuiAward is only visible when it's tied to an already acchieved award.
GameOptionAward * goa = dynamic_cast<GameOptionAward*>(&options[id]);
if(!goa || !goa->number)
return false;
return true;
}
//WGuiImage
WGuiImage::WGuiImage(WDataSource * wds, float _w, float _h, int _margin): WGuiItem("") {
imgW = _w;
imgH = _h;
margin = _margin;
source = wds;
}
void WGuiImage::imageScale(float _w, float _h){
imgH = _h;
imgW = _w;
}
float WGuiImage::getHeight(){
JQuad * q = NULL;
if(imgH == 0 ){
if(source && (q = source->getImage())) //Intentional assignment.
return MAX(height,q->mHeight+(2*margin));
}
return MAX(height,imgH+(2*margin));
}
void WGuiImage::Render(){
if(!source)
return;
JRenderer * renderer = JRenderer::GetInstance();
JQuad * q = source->getImage();
if(q){
float xS = 1, yS = 1;
if(imgH != 0 && q->mHeight != 0)
yS = imgH / q->mHeight;
if(imgW != 0 && q->mWidth != 0)
xS = imgW / q->mWidth;
renderer->RenderQuad(q,x+margin, y+margin,0,xS,yS);
}
}
WGuiCardImage::WGuiCardImage(WDataSource * wds, bool _thumb) : WGuiImage(wds){
bThumb = _thumb;
};
void WGuiCardImage::Render(){
JRenderer * renderer = JRenderer::GetInstance();
MTGCard * c = NULL;
Pos p(x+margin, y+margin, 1,0,255);
if(!source || (c = source->getCard(mOffset.getPos())) == NULL){ //No card, use card back.
JQuad * q;
if(bThumb){
q = resources.GetQuad("back_thumb");
#if defined WIN32 || defined LINUX
if(!q)
q = resources.GetQuad("back");
#endif
}
else
q = resources.GetQuad("back");
float scale = p.actZ * 257.f / q->mHeight;
q->SetColor(ARGB(255,255,255,255));
renderer->RenderQuad(q,p.x,p.y,0,scale,scale);
}else{ //Have card.
if(bThumb){ //Thumbnail.
JQuad * q = NULL;
if(!options[Options::DISABLECARDS].number){
q = source->getThumb(mOffset.getPos());
#if defined WIN32 || defined LINUX
if(!q)
q = source->getImage(mOffset.getPos());
#endif
}
if(!q && (q = CardGui::alternateThumbQuad(c)) == NULL)
return; //TODO Some kind of error image.
renderer->RenderQuad(q,p.x,p.y);
}
else{ //Normal card.
JQuad * q = source->getImage(mOffset.getPos());
if(!q || options[Options::DISABLECARDS].number)
CardGui::alternateRender(c,p);
else
CardGui::RenderBig(c,p);
}
}
}
//WGuiCardDistort
WGuiCardDistort::WGuiCardDistort(WDataSource * wds, bool _thumb, WDataSource * _distort): WGuiCardImage(wds,_thumb){
mesh = NEW hgeDistortionMesh(2,2);
distortSrc = NULL;
}
WGuiCardDistort::~WGuiCardDistort(){
SAFE_DELETE(mesh);
}
void WGuiCardDistort::Render(){
JRenderer * renderer = JRenderer::GetInstance();
JQuad * q = NULL;
if(distortSrc) {
WDistort * dt = distortSrc->getDistort(mOffset.getPos());
if(dt)
xy = *dt;
}
if(!source){
//Default to back.
if(bThumb){
q = resources.GetQuad("back_thumb");
#if defined WIN32 || defined LINUX
if(!q)
q = resources.GetQuad("back");
#endif
}
else
q = resources.GetQuad("back");
}else {
MTGCard * c = source->getCard(mOffset.getPos());
if(!c)
return;
if(bThumb){
q = source->getThumb(mOffset.getPos());
#if defined WIN32 || defined LINUX
if(!q)
q = source->getImage(mOffset.getPos());
#endif
if(!q || options[Options::DISABLECARDS].number)
q = CardGui::alternateThumbQuad(c);
}
else {
q = source->getImage(mOffset.getPos());
if(!q || options[Options::DISABLECARDS].number)
q = CardGui::alternateThumbQuad(c); //TODO alternateX should render to texture.
}
}
if(!q)
return;
mesh->SetTexture(q->mTex);
float x0,y0,w0,h0;
q->GetTextureRect(&x0,&y0,&w0,&h0);
mesh->SetTextureRect(x0,y0,w0,h0);
mesh->Clear(ARGB(0xFF,0xFF,0xFF,0xFF));
mesh->SetDisplacement(0, 0, xy[0],xy[1], HGEDISP_NODE);
mesh->SetDisplacement(1, 0, xy[2] - w0,xy[3], HGEDISP_NODE);
mesh->SetDisplacement(0, 1,xy[4],xy[5]-h0, HGEDISP_NODE);
mesh->SetDisplacement(1, 1, xy[6]-w0,xy[7]-h0, HGEDISP_NODE);
if(hasFocus()){
mesh->SetColor(1,1,ARGB(255,200,200,200));
mesh->SetColor(0,1,ARGB(255,200,200,200));
mesh->SetColor(1,0,ARGB(255,200,200,200));
mesh->SetColor(0,0,ARGB(255,255,255,200));
}else{
mesh->SetColor(1,1,ARGB(255,100,100,100));
mesh->SetColor(0,1,ARGB(255,100,100,100));
mesh->SetColor(1,0,ARGB(255,100,100,100));
mesh->SetColor(0,0,ARGB(255,200,200,200));
}
mesh->Render(0,0);
}
//WDistort
WDistort::WDistort(){
for(int i=0;i<8;i++)
xy[i] = 0;
}
float & WDistort::operator[](int p){
return xy[p];
}
WDistort::WDistort(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4){
xy[0] = x1; xy[1] = y1;
xy[2] = x2; xy[3] = y2;
xy[4] = x3; xy[5] = y3;
xy[6] = x4; xy[7] = y4;
}
//WGuiListRow
void WGuiListRow::Render(){
JRenderer * renderer = JRenderer::GetInstance();
int listHeight=40;
int listSelectable=0;
int adjustedCurrent=0;
int start = 0, nowPos = 0, vHeight=0;
int nbitems = (int) items.size();
//List is empty.
if (!items.size() && failMsg != ""){
WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT);
mFont->SetColor(getColor(WGuiColor::TEXT_FAIL));
mFont->DrawString(_(failMsg).c_str(),x+width/2, y, JGETEXT_RIGHT);
return;
}
//Force a selectable option.
if(currentItem == -1){
for (int i = 0 ; i < nbitems; i++){
if(items[i]->Selectable()) {
currentItem = i;
if(hasFocus())
items[currentItem]->Entering(JGE_BTN_NONE);
break;
}
}
}
vHeight = 0;
nowPos = 4;
float nowVPos = 4;
float tallestRow = 0;
int numRows = 1;
float cTallest = 0;
//Render items.
if(start >= 0)
{
//Render current underlay.
if(currentItem >= 0 && currentItem < nbitems && items[currentItem]->Visible())
items[currentItem]->Underlay();
for (int pos=0;pos < nbitems; pos++){
if(!items[pos]->Visible())
continue;
items[pos]->setX(x+nowPos);
items[pos]->setY(y+nowVPos);
//items[pos]->setWidth(width/nbitems);
items[pos]->setWidth(items[pos]->minWidth());
float temp = items[pos]->getHeight() + 3;
if(temp > tallestRow)
tallestRow = temp;
if(temp > cTallest)
cTallest = temp;
nowPos += static_cast<int>(items[pos]->getWidth() + 5);
renderBack(items[pos]);
if(x+nowPos+items[pos]->getWidth()+10 > SCREEN_WIDTH){
nowPos = 0 + 20; //Indent newlines.
nowVPos += cTallest;
cTallest = 0;
numRows++;
}
items[pos]->Render();
if(nowVPos > SCREEN_HEIGHT)
break;
}
//Render current overlay.
if(currentItem >= 0 && currentItem < nbitems && items[currentItem]->Visible())
items[currentItem]->Overlay();
}
setHeight(tallestRow*numRows+10);
}
WGuiListRow::WGuiListRow(string n, WSyncable * s) : WGuiList(n,s) {
buttonNext = JGE_BTN_RIGHT;
buttonPrev = JGE_BTN_LEFT;
width = SCREEN_WIDTH;
height = 20;
}
//WGuiFilterUI
bool WGuiFilters::Finish(bool emptyset){
bFinished = true;
string src;
if(source){
src = getCode();
source->clearFilters();
if(src.size()){
WCFilterFactory * wc = WCFilterFactory::GetInstance();
WCardFilter * f = wc->Construct(src);
if(recolorTo > -1 && recolorTo < Constants::MTG_NB_COLORS){
f = NEW WCFilterAND(f,NEW WCFilterColor(recolorTo));
}
source->addFilter(f);
}else {
if(recolorTo > -1 && recolorTo < Constants::MTG_NB_COLORS){
WCardFilter * f = NEW WCFilterColor(recolorTo);
source->addFilter(f);
}
}
if((!source->Size() && !emptyset)){
source->clearFilters(); //TODO: Pop a "No results found" warning
}
}
return true;
}
void WGuiFilters::ButtonPressed(int controllerId, int controlId){
if(controllerId == -102){
if(controlId == -10){
WGuiListRow * wgl= NEW WGuiListRow("");
wgl->Add(NEW WGuiFilterItem(this));
list->Add(wgl);
}else if(controlId == -11){
Finish();
}
else{
if(source)
source->clearFilters();
SAFE_DELETE(list);
buildList();
}
return;
}else{
if(list != NULL)
list->ButtonPressed(controllerId,controlId);
}
}
void WGuiFilters::buildList(){
list = NEW WGuiList("");
WGuiButton * l = NEW WGuiButton(NEW WGuiItem("Add Filter"),-102,-10,this);
WGuiButton * r = NEW WGuiButton(NEW WGuiItem("Done"),-102,-11,this);
WGuiButton * mid = NEW WGuiButton(NEW WGuiItem("Clear"),-102,-66,this);
WGuiSplit * sub = NEW WGuiSplit(mid,r);
WGuiSplit * wgs = NEW WGuiSplit(l,sub);
subMenu = NULL;
list->Add(NEW WGuiHeader(displayValue));
list->Add(wgs);
list->Entering(JGE_BTN_NONE);
}
WGuiFilters::WGuiFilters(string header, WSrcCards * src) : WGuiItem(header) {
bFinished = false;
source = src;
recolorTo = -1;
buildList();
}
void WGuiFilters::recolorFilter(int color){
recolorTo = color;
}
string WGuiFilters::getCode(){
if(!list)
return "";
string res;
vector<WGuiBase*>::iterator row, col;
for(row=list->items.begin();row!=list->items.end();row++){
WGuiList * wgl = dynamic_cast<WGuiList*>(*row);
if(wgl){
if(res.size())
res += "|(";
else
res += "(";
for(col=wgl->items.begin();col!=wgl->items.end();col++){
WGuiFilterItem * fi = dynamic_cast<WGuiFilterItem*>(*col);
if(fi){
string gc = fi->getCode();
if(res.size() && gc.size() && res[res.size()-1] != '(')
res += "&";
res += gc;
}
}
res += ")";
}
}
return res;
}
void WGuiFilters::setSrc(WSrcCards * wsc){
source = wsc;
}
void WGuiFilters::Update(float dt){
if(subMenu && !subMenu->closed)
subMenu->Update(dt);
if(list){
list->Update(dt);
WGuiList * wgl = dynamic_cast<WGuiList*>(list->Current());
if(!wgl)
return;
vector<WGuiBase*>::iterator it;
bool bDeleted=false;
for(it=wgl->items.begin();it!=wgl->items.end();it++){
WGuiFilterItem * wgfi = dynamic_cast<WGuiFilterItem*>(*it);
if(!wgfi || wgfi->mState != WGuiFilterItem::STATE_REMOVE) continue;
SAFE_DELETE(*it);
it = wgl->items.erase(it);
bDeleted = true;
}
if(bDeleted)
wgl->Entering(JGE_BTN_NONE);
}
}
void WGuiFilters::Entering(JButton key){
bFinished = false;
WGuiItem::Entering(key);
}
void WGuiFilters::Render(){
if(!list) return; //Hurrah for paranoia.
JRenderer * r = JRenderer::GetInstance();
float tX, tY;
tX = getX();
tY = getY();
r->FillRect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,ARGB(128,0,0,0));
list->setX(tX); list->setY(tY);
list->Render();
if(subMenu && !subMenu->closed)
subMenu->Render();
}
bool WGuiFilters::CheckUserInput(JButton key){
if(subMenu && !subMenu->closed && subMenu->CheckUserInput(key))
return true;
if(key == JGE_BTN_SEC){//|| key == JGE_BTN_MENU){
//TODO Pop up a "Are you sure?" dialog.
return true;
}
if(list){
return list->CheckUserInput(key);
}
return WGuiItem::CheckUserInput(key);
}
WGuiFilters::~WGuiFilters(){
SAFE_DELETE(list);
SAFE_DELETE(subMenu);
}
void WGuiFilters::addColumn(){
if(!list)
return;
WGuiList * wgl = dynamic_cast<WGuiList*>(list->Current());
if(wgl){
wgl->currentItem = wgl->items.size()-1;
wgl->Add(NEW WGuiFilterItem(this));
}
}
bool WGuiFilters::isAvailableCode(string code){
if(!list) return false;
WGuiList * wgl = dynamic_cast<WGuiList*>(list->Current());
if(wgl){
vector<WGuiBase*>::iterator it;
for(it=wgl->items.begin();it!=wgl->items.end();it++){
WGuiFilterItem * wgfi = dynamic_cast<WGuiFilterItem*>(*it);
if(!wgfi || wgfi->mState != WGuiFilterItem::STATE_FINISHED) continue;
if(!wgfi->mCode.size()) continue;
if(wgfi->mCode == code)
return false;
}
return true;
}
return false; //For some reason, we don't have any rows?
}
bool WGuiFilters::isAvailable(int type){
if(!list) return false;
int colors = 0, ma = 0;
WGuiList * wgl = dynamic_cast<WGuiList*>(list->Current());
if(wgl){
vector<WGuiBase*>::iterator it;
for(it=wgl->items.begin();it!=wgl->items.end();it++){
WGuiFilterItem * wgfi = dynamic_cast<WGuiFilterItem*>(*it);
if(!wgfi || wgfi->mState != WGuiFilterItem::STATE_FINISHED) continue;
switch(type){
case WGuiFilterItem::FILTER_SUBTYPE:
case WGuiFilterItem::FILTER_BASIC:
return true;
case WGuiFilterItem::FILTER_PRODUCE:
if(wgfi->filterType == type)
ma++;
break;
case WGuiFilterItem::FILTER_COLOR:
if(wgfi->filterType == type)
colors++;
break;
default:
if(wgfi->filterType == type)
return false;
}
}
if(colors >= 5)
return false;
if(ma >= 5)
return false;
return true;
}
return false; //For some reason, we don't have any rows?
}
void WGuiFilters::clearArgs(){
tempArgs.clear();
}
void WGuiFilters::addArg(string display, string code){
if(!subMenu || !isAvailableCode(code))
return;
subMenu->Add((int)tempArgs.size(),display.c_str());
tempArgs.push_back(pair<string,string>(display,code));
}
//WGuiFilterItem
WGuiFilterItem::WGuiFilterItem(WGuiFilters * parent): WGuiItem("Cards..."){
filterType = -1; filterVal = -1; mState = 0;
mParent = parent; mNew = true;
};
void WGuiFilterItem::updateValue(){
bool delMenu = true;
char buf_name[512];
char buf_code[512];
if(!mParent)
return;
switch(mState){
case STATE_CANCEL:
mState = STATE_UNSET;
break;
case STATE_FINISHED:
case STATE_UNSET:
SAFE_DELETE(mParent->subMenu);
mState = STATE_CHOOSE_TYPE;
SAFE_DELETE(mParent->subMenu);
mParent->subMenu = NEW SimpleMenu(-1234,this,Fonts::MENU_FONT,20,20,"Filter By...",10);
if(mParent->isAvailable(FILTER_SET)){
mParent->subMenu->Add(FILTER_SET,"Set");
delMenu = false;
}
if(mParent->isAvailable(FILTER_COLOR)){
mParent->subMenu->Add(FILTER_COLOR,"Color");
delMenu = false;
}
if(mParent->isAvailable(FILTER_TYPE)){
mParent->subMenu->Add(FILTER_TYPE,"Type");
delMenu = false;
}
if(mParent->isAvailable(FILTER_SUBTYPE)){
mParent->subMenu->Add(FILTER_SUBTYPE,"Subtype");
delMenu = false;
}
if(mParent->isAvailable(FILTER_RARITY)){
mParent->subMenu->Add(FILTER_RARITY,"Rarity");
delMenu = false;
}
if(mParent->isAvailable(FILTER_CMC)){
mParent->subMenu->Add(FILTER_CMC,"Mana Cost");
delMenu = false;
}
if(mParent->isAvailable(FILTER_BASIC)){
mParent->subMenu->Add(FILTER_BASIC,"Basic Ability");
delMenu = false;
}
if(mParent->isAvailable(FILTER_PRODUCE)){
mParent->subMenu->Add(FILTER_PRODUCE,"Mana Ability");
delMenu = false;
}
if(mParent->isAvailable(FILTER_POWER)){
mParent->subMenu->Add(FILTER_POWER,"Power");
delMenu = false;
}
if(mParent->isAvailable(FILTER_TOUGH)){
mParent->subMenu->Add(FILTER_TOUGH,"Toughness");
delMenu = false;
}
if(mParent->isAvailable(FILTER_ALPHA)){
mParent->subMenu->Add(FILTER_ALPHA,"First Letter");
delMenu = false;
}
if(!mNew)
mParent->subMenu->Add(-2,"Remove");
mParent->subMenu->Add(-1,"Cancel");
if(delMenu){
SAFE_DELETE(mParent->subMenu);
mState = STATE_FINISHED;
}
break;
case STATE_CHOOSE_TYPE:
SAFE_DELETE(mParent->subMenu);
mParent->clearArgs();
mState = STATE_CHOOSE_VAL;
mParent->subMenu = NEW SimpleMenu(-1234,this,Fonts::MENU_FONT,20,20,"Filter:");
if(filterType == FILTER_TYPE){
mParent->addArg("Artifact","t:Artifact;");
mParent->addArg("Artifact Creature","t:Artifact;&t:Creature;");
mParent->addArg("Creature","t:Creature;");
mParent->addArg("Enchantment","t:Enchantment;");
mParent->addArg("Instant","t:Instant;");
mParent->addArg("Land","t:Land;");
mParent->addArg("Legendary","t:Legendary;");
mParent->addArg("Sorcery","t:Sorcery;");
}else if(filterType == FILTER_SUBTYPE){
vector<string> stlist;
for(int i=Subtypes::LAST_TYPE+1;;i++){
string s = Subtypes::subtypesList->find(i);
if(s == "") break;
if(s.find(" ") != string::npos) continue;
if(s == "Nothing")
{//dont add "nothing" to the search filters.
}else{
stlist.push_back(s);
}
}
std::sort(stlist.begin(),stlist.end());
for(size_t t=0;t<stlist.size();t++){
string s=stlist[t];
char buf[1024]; sprintf(buf,"t:%s;",s.c_str());
mParent->addArg(s,buf);
}
}else if(filterType == FILTER_RARITY){
mParent->addArg("Mythic","r:m;");
mParent->addArg("Rare","r:r;");
mParent->addArg("Uncommon","r:u;");
mParent->addArg("Common","r:c;");
mParent->addArg("Special Rarity","{r:m;|r:t;|r:r;|r:u;|r:c;}");
}else if(filterType == FILTER_CMC){
for(int i=0;i<20;i++){
sprintf(buf_code,"cmc:%i;",i);
sprintf(buf_name,"%i Mana",i);
mParent->addArg(buf_name,buf_code);
}
}else if(filterType == FILTER_POWER){
for(int i=0;i<14;i++){
sprintf(buf_code,"pow:%i;",i);
sprintf(buf_name,"%i power",i);
mParent->addArg(buf_name,buf_code);
}
}else if(filterType == FILTER_TOUGH){
for(int i=0;i<14;i++){
sprintf(buf_code,"tgh:%i;",i);
sprintf(buf_name,"%i toughness",i);
mParent->addArg(buf_name,buf_code);
}
}else if(filterType == FILTER_COLOR){
mParent->addArg("White","c:w;");
mParent->addArg("Blue","c:u;");
mParent->addArg("Black","c:b;");
mParent->addArg("Red","c:r;");
mParent->addArg("Green","c:g;");
mParent->addArg("Exclusively White","xc:w;");
mParent->addArg("Exclusively Blue","xc:u;");
mParent->addArg("Exclusively Black","xc:b;");
mParent->addArg("Exclusively Red","xc:r;");
mParent->addArg("Exclusively Green","xc:g;");
}else if(filterType == FILTER_PRODUCE){
mParent->addArg("White mana abiltity","ma:w;");
mParent->addArg("Blue mana abiltity","ma:u;");
mParent->addArg("Black mana abiltity","ma:b;");
mParent->addArg("Red mana abiltity","ma:r;");
mParent->addArg("Green mana abiltity","ma:g;");
mParent->addArg("Colorless mana abiltity","ma:x;");
}else if(filterType == FILTER_BASIC){
char buf[512];
for(int i=0;i<Constants::NB_BASIC_ABILITIES;i++){
string s = Constants::MTGBasicAbilities[i];
sprintf(buf,"a:%s;",s.c_str());
s[0] = toupper(s[0]);
mParent->addArg(s,buf);
}
}else if(filterType == FILTER_SET){
char buf[512];
for(int i=0;i<setlist.size();i++){
if(options[Options::optionSet(i)].number == 0)
continue;
sprintf(buf,"s:%s;",setlist[i].c_str());
mParent->addArg((setlist.getInfo(i))->getName(),buf);
}
}else if(filterType == FILTER_ALPHA){
char buf[24], pretty[16];
for(char c='a';c<='z';c++){
sprintf(buf,"alpha:%c;",c);
sprintf(pretty,"Letter %c",toupper(c));
mParent->addArg(pretty,buf);
}
mParent->addArg("Digit","alpha:#;");
}
mParent->subMenu->Add(-1,"Cancel");
break;
case STATE_CHOOSE_VAL:
mState = STATE_FINISHED;
if(mNew && mParent)
mParent->addColumn();
mNew = false;
if(filterVal > -1 && filterVal < (int) mParent->tempArgs.size()){
displayValue = mParent->tempArgs[filterVal].first;
mCode = mParent->tempArgs[filterVal].second;
}
SAFE_DELETE(mParent->subMenu);
break;
}
}
void WGuiFilterItem::ButtonPressed(int controllerId, int controlId){
if(!mParent) return;
switch(mState){
case STATE_CHOOSE_TYPE:
if(controlId == -1){
mParent->subMenu->Close();
mState = STATE_CANCEL; return;
}else if(controlId == -2){
mParent->subMenu->Close();
mState = STATE_REMOVE; return;
}
filterType = controlId;
break;
case STATE_CHOOSE_VAL:
if(controlId == -1){
mParent->subMenu->Close();
mState = STATE_UNSET; return;
}else if(controlId == -2){
mParent->subMenu->Close();
mState = STATE_REMOVE; return;
}
filterVal = controlId;
break;
}
updateValue();
}
bool WGuiFilterItem::isModal(){
switch(mState){
case STATE_UNSET:
case STATE_REMOVE:
case STATE_CANCEL:
case STATE_FINISHED:
return false;
}
return true;
}
string WGuiFilterItem::getCode(){
if(mState != STATE_FINISHED || !mCode.size())
return "";
return mCode;
}
WGuiKeyBinder::WGuiKeyBinder(string name, GameStateOptions* parent) : WGuiList(name), parent(parent), confirmMenu(NULL), modal(false), confirmed(CONFIRM_NEED), confirmingKey(LOCAL_KEY_NONE), confirmingButton(JGE_BTN_NONE), confirmationString("") {
JGE* j = JGE::GetInstance();
JGE::keybindings_it start = j->KeyBindings_begin(), end = j->KeyBindings_end();
Add(NEW OptionKey(parent, LOCAL_KEY_NONE, JGE_BTN_NONE));
for (JGE::keybindings_it it = start; it != end; ++it)
Add(NEW OptionKey(parent, it->first, it->second));
}
void WGuiKeyBinder::Update(float dt) {
OptionKey* o = dynamic_cast<OptionKey*>(items[0]);
if (!o) return;
if (LOCAL_KEY_NONE != o->from) {
items.insert(items.begin(), NEW OptionKey(parent, LOCAL_KEY_NONE, JGE_BTN_NONE));
if (0 == currentItem) ++currentItem;
}
for (vector<WGuiBase*>::iterator it = items.begin(); it != items.end(); ++it) (*it)->Update(dt);
if (confirmMenu) confirmMenu->Update(dt);
}
bool WGuiKeyBinder::isModal() {
for (vector<WGuiBase*>::iterator it = items.begin(); it != items.end(); ++it)
if ((*it)->isModal()) return true;
return modal;
}
bool WGuiKeyBinder::CheckUserInput(JButton key) {
if (confirmMenu)
return confirmMenu->CheckUserInput(key);
if (!items[currentItem]->CheckUserInput(key))
return WGuiList::CheckUserInput(key);
if (!items[currentItem]->Selectable())
nextItem();
return true;
}
void WGuiKeyBinder::setData() {
JGE* j = JGE::GetInstance();
j->ClearBindings();
for (vector<WGuiBase*>::iterator it = items.begin(); it != items.end(); ++it) {
OptionKey* o = static_cast<OptionKey*>(*it);
if (o && LOCAL_KEY_NONE != o->from && JGE_BTN_NONE != o->to)
j->BindKey(o->from, o->to);
}
j->ResetInput();
}
static const JButton btnToCheck[] = {JGE_BTN_MENU, JGE_BTN_CTRL, JGE_BTN_RIGHT,
JGE_BTN_LEFT, JGE_BTN_UP, JGE_BTN_DOWN,
JGE_BTN_OK, JGE_BTN_CANCEL, JGE_BTN_PRI,
JGE_BTN_SEC, JGE_BTN_PREV, JGE_BTN_NEXT };
#define C(o) (static_cast<OptionKey*>(o))
WGuiBase::CONFIRM_TYPE WGuiKeyBinder::needsConfirm() {
if (CONFIRM_CANCEL == confirmed) { confirmedKeys.clear(); confirmedButtons.clear(); confirmed = CONFIRM_NEED; return CONFIRM_CANCEL; }
if (confirmMenu) return CONFIRM_NEED;
// Check whether any key is bound to two functions.
confirmingKey = LOCAL_KEY_NONE;
for (vector<WGuiBase*>::iterator it = items.begin(); it != items.end(); ++it) {
if (!(*it)->Visible()) continue;
vector<JButton> boundFunctionsList;
for (vector<WGuiBase*>::iterator jt = it + 1; jt != items.end(); ++jt) {
if (!(*jt)->Visible()) continue;
if (C(*it)->from == C(*jt)->from)
if (confirmedKeys.end() == find(confirmedKeys.begin(), confirmedKeys.end(), C(*it)->from)) {
confirmingKey = C(*it)->from;
if (boundFunctionsList.empty()) boundFunctionsList.push_back(C(*it)->to);
boundFunctionsList.push_back(C(*jt)->to);
}
}
if (LOCAL_KEY_NONE != confirmingKey) {
// There is a conflict. Generate the error message...
char s[1024];
snprintf(s, 1024, _("Warning : the %s key is bound to\n%i different functions:").c_str(), translateKey(confirmingKey).first.c_str(), boundFunctionsList.size());
stringstream ss;
ss << s << "\n";
vector<JButton>::iterator jt = boundFunctionsList.begin();
ss << translateKey(*jt).first.c_str();
for (++jt; jt != boundFunctionsList.end(); ++jt) ss << ", " << translateKey(*jt).first.c_str();
confirmationString = ss.str();
// Then create the menu.
confirmMenu = NEW SimpleMenu(0, this, Fonts::MENU_FONT, 40, 130, "Conflict");
confirmMenu->Add(1, _("Cancel and return to the options menu").c_str());
confirmMenu->Add(2, _("This is okay, validate and save").c_str());
return CONFIRM_NEED;
}
}
// Check whether any button has no key associated to it.
confirmingButton = JGE_BTN_NONE;
for (signed int i = (sizeof(btnToCheck) / sizeof(btnToCheck[0])) - 1; i >= 0; --i) {
if (confirmedButtons.end() != find(confirmedButtons.begin(), confirmedButtons.end(), btnToCheck[i])) continue;
bool found = false;
for (vector<WGuiBase*>::iterator it = items.begin(); it != items.end(); ++it)
if (btnToCheck[i] == C(*it)->to) { found = true; break; }
if (found) continue;
char s[1024];
snprintf(s, 1024, _("Warning : no key is associated to\nthe %s function.\nThis may make the game unusable.").c_str(), translateKey(btnToCheck[i]).first.c_str());
confirmationString = s;
confirmingButton = btnToCheck[i];
confirmMenu = NEW SimpleMenu(1, this, Fonts::MENU_FONT, 40, 130, "Binding missing");
confirmMenu->Add(1, _("Cancel and return to the options menu").c_str());
confirmMenu->Add(2, _("This is okay, validate and save").c_str());
return CONFIRM_NEED;
}
return CONFIRM_OK;
}
void WGuiKeyBinder::ButtonPressed(int controllerId, int controlId) {
if (2 == controlId)
switch(controllerId) {
case 0: confirmedKeys.insert(confirmingKey); break;
case 1: confirmedButtons.insert(confirmingButton); break;
}
else
confirmed = CONFIRM_CANCEL;
SAFE_DELETE(confirmMenu);
confirmMenu = NULL;
}
void WGuiKeyBinder::Render() {
WGuiList::Render();
if (confirmMenu) {
JRenderer * renderer = JRenderer::GetInstance();
WFont * mFont = resources.GetWFont(Fonts::OPTION_FONT);
mFont->SetColor(ARGB(255, 255, 0, 0));
renderer->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(230, 255, 240, 240));
size_t pos = 0;
float y = 20;
do {
size_t t = confirmationString.find_first_of("\n", pos);
string s = confirmationString.substr(pos, t - pos);
pos = (string::npos == t) ? t : t + 1;
mFont->DrawString(s, SCREEN_WIDTH / 2, y, JGETEXT_CENTER);
y += 20;
} while (pos != string::npos);
confirmMenu->Render();
}
}
bool WGuiKeyBinder::yieldFocus() {
return true;
}