1962 lines
53 KiB
C++
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;
|
|
}
|