#include "PrecompiledHeader.h" #include "OptionItem.h" #include "PlayerData.h" #include "Translate.h" #include "Subtypes.h" #include "TranslateKeys.h" #include #include "SimpleMenu.h" #include "Pos.h" #include "CardGui.h" /** Provides an interface to retrieve some standardized colors. The idea here is that a child of WGuiBase could override, for example, the color of the background based on whether or notit is highlighted (as WGuiButton does), or be given a particular styling with the WDecoStyled decorator. */ 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); } /** Renders the backdrop of a WGui item. Meant to be overriden in subclasses that require a unique backdrop. */ void WGuiBase::renderBack(WGuiBase * it) { if (!it) return; WDecoStyled * styled = dynamic_cast (it); if (styled) styled->renderBack(styled->getDecorated()); else subBack(it); } WGuiBase::CONFIRM_TYPE WGuiBase::needsConfirm() { for (vector::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::iterator it = items.begin(); it != items.end(); ++it) if ((*it)->yieldFocus()) { return true; } return false; } //WGuiItem void WGuiItem::Entering(JButton) { mFocus = true; } float WGuiItem::minWidth() { WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::OPTION_FONT); return mFont->GetStringWidth(_(displayValue).c_str()) + 4; } float WGuiItem::minHeight() { WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::OPTION_FONT); return mFont->GetHeight(); } bool WGuiItem::Leaving(JButton) { mFocus = false; return true; } void WGuiItem::Render() { WFont * mFont = WResourceManager::Instance()->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 (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 = WResourceManager::Instance()->GetWFont(Fonts::OPTION_FONT); // save the current scaling factor. We don't want the lists to change font size these lists should stay the same no matter what float currentScale = mFont->GetScale(); mFont->SetScale(SCALE_NORMAL); mFont->SetColor(getColor(WGuiColor::TEXT)); mFont->DrawString(_(displayValue).c_str(), x + width / 2, y, JGETEXT_CENTER); mFont->SetScale(currentScale); } 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 (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, 1, item->getColor( WGuiColor::BACK)); //inner border renderer->DrawRoundRect(item->getX(), item->getY(), item->getWidth() - 4, item->getHeight() - 2, 1, ARGB(255,89,89,89)); //outer border //renderer->DrawRect(item->getX()-1.5f, item->getY()-1, item->getWidth()+1, item->getHeight() +2, ARGB(80,240,240,240)); } } void WGuiMenu::setSelected(int newItem) { if (newItem != currentItem) { items[currentItem]->Leaving(JGE_BTN_NONE); currentItem = newItem; items[currentItem]->Entering(JGE_BTN_NONE); } } bool WGuiMenu::yieldFocus() { for (vector::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), startWindow(-1), endWindow(-1) { 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 = WResourceManager::Instance()->GetWFont(Fonts::OPTION_FONT); // save the current scaling factor. We don't want the lists to change font size these lists should stay the same no matter what float fontScaleFactor = mFont->GetScale(); mFont->SetScale(SCALE_NORMAL); mFont->SetColor(getColor(WGuiColor::TEXT_FAIL)); mFont->DrawString(_(failMsg).c_str(), x + width / 2, y, JGETEXT_RIGHT); mFont->SetScale(fontScaleFactor); 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 (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 (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 (items[nowPos - 1]->getHeight() + 5); } if (vHeight <= SCREEN_HEIGHT - 40 && nowPos < start) start = nowPos; } vHeight = 0; nowPos = 0; //Render items. if (start >= 0) { int pos; //Render current underlay. if (currentItem >= 0 && currentItem < nbitems && items[currentItem]->Visible()) items[currentItem]->Underlay(); for (pos = 0; pos < nbitems; pos++) { if (!items[pos]->Visible()) continue; if (pos < start) { vHeight += static_cast (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 (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; } startWindow = start; endWindow = pos; //Draw scrollbar if (listHeight > SCREEN_HEIGHT && listSelectable > 1) { float barPosition = static_cast (y - 5 + ((float) adjustedCurrent / listSelectable) * (SCREEN_HEIGHT - y)); float barLength = static_cast ((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, 1, 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); } bool WGuiList::CheckUserInput(JButton key) { JGE * mEngine = JGE::GetInstance(); int i, j; if ((key == JGE_BTN_OK) && mEngine->GetLeftClickCoordinates(i, j)) { // a dude clicked somwhere, we're gonna select the closest object from where he clicked int n = currentItem; unsigned int distance2; unsigned int minDistance2 = -1; int begin = (startWindow == -1) ? 0 : startWindow; int end = (endWindow == -1) ? items.size() : endWindow; for(int k = begin; k < end; k++) { WGuiBase* pItem = (items[k]); distance2 = static_cast((pItem->getY() - j) * (pItem->getY() - j) + (pItem->getX() - i) * (pItem->getX() - i)); if (distance2 < minDistance2 && pItem->Selectable()) { minDistance2 = distance2; n = k; } } if (n != currentItem && items[n]->Selectable()) { setSelected(n); mEngine->LeftClickedProcessed(); if (sync) syncMove(); return true; } } // mEngine->LeftClickedProcessed(); return WGuiMenu::CheckUserInput(key); } string WDecoEnum::lookupVal(int value) { if (edef == NULL) { int id = getId(); if (id != INVALID_ID) { GameOptionEnum * goEnum = dynamic_cast (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 = WResourceManager::Instance()->GetWFont(Fonts::OPTION_FONT); mFont->SetColor(getColor(WGuiColor::TEXT)); mFont->DrawString(_(getDisplay()).c_str(), getX() + 2, getY() + 3); OptionInteger* opt = dynamic_cast (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(JGE::GetInstance(), WResourceManager::Instance(), 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, bool custom) : WGuiItem("") { right = _right; left = _left; bRight = false; if(!custom) percentRight = 0.5f; else percentRight = 0.67f; 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) { bool result = false; if (hasFocus()) { int i,j; if (key == JGE_BTN_NONE && JGE::GetInstance()->GetLeftClickCoordinates(i, j)) { // a dude clicked somwhere, we're gonna select the closest object from where he clicked unsigned int distanceLeft, distanceRight; distanceLeft = static_cast((left->getY() - j) * (left->getY() - j) + (left->getX() - i) * (left->getX() - i)); distanceRight = static_cast((right->getY() - j) * (right->getY() - j) + (right->getX() - i) * (right->getX() - i)); if (distanceLeft < distanceRight && bRight) { key = JGE_BTN_LEFT; } else if(!bRight && distanceLeft > distanceRight) { key = JGE_BTN_RIGHT; } } if (!bRight) { if (left->CheckUserInput(key)) { result = true; goto done; } if (key == JGE_BTN_RIGHT && !isModal() && right->Selectable() && left->Leaving(JGE_BTN_RIGHT)) { bRight = !bRight; right->Entering(JGE_BTN_RIGHT); result = true; goto done; } } else { if (right->CheckUserInput(key)) { result = true; goto done; } if (key == JGE_BTN_LEFT && !isModal() && left->Selectable() && right->Leaving(JGE_BTN_LEFT)) { bRight = !bRight; left->Entering(JGE_BTN_LEFT); result = true; goto done; } } } done: if(result == true) { JGE::GetInstance()->LeftClickedProcessed(); } return result; } 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, JButton prev, bool dPad, WSyncable * syncme) : WGuiItem("") { buttonNext = next; buttonPrev = prev; currentItem = -1; mDPad = dPad; sync = syncme; held = JGE_BTN_NONE; } WGuiMenu::~WGuiMenu() { for (vector::iterator it = items.begin(); it != items.end(); it++) SAFE_DELETE(*it); } void WGuiMenu::setData() { for (vector::iterator it = items.begin(); it != items.end(); it++) (*it)->setData(); } ; void WGuiMenu::Reload() { for (vector::iterator it = items.begin(); it != items.end(); it++) (*it)->Reload(); } ; void WGuiMenu::Render() { for (vector::iterator it = items.begin(); it != items.end(); it++) (*it)->Render(); } void WGuiMenu::confirmChange(bool confirmed) { for (vector::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 result = false; bool kidModal = false; int nbitems = (int) items.size(); JGE * mEngine = JGE::GetInstance(); int i, j; if (!mEngine->GetButtonState(held)) //Key isn't held down. held = JGE_BTN_NONE; if (mEngine->GetLeftClickCoordinates(i, j)) { // a dude clicked somwhere, we're gonna select the closest object from where he clicked int n = currentItem; unsigned int distance2; unsigned int minDistance2 = -1; for(size_t k = 0; k < items.size(); k++) { WGuiBase* pItem = items[k]; distance2 = static_cast((pItem->getY() - j) * (pItem->getY() - j) + (pItem->getX() - i) * (pItem->getX() - i)); if (distance2 < minDistance2 && pItem->Selectable()) { minDistance2 = distance2; n = k; } } if (n != currentItem && items[n]->Selectable()) { setSelected(n); mEngine->LeftClickedProcessed(); if (sync) syncMove(); return true; } } 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) result = items[currentItem]->CheckUserInput(key); mEngine->LeftClickedProcessed(); return result; } 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(); 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 != 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 != 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 = WResourceManager::Instance()->GetWFont(Fonts::OPTION_FONT); JRenderer * renderer = JRenderer::GetInstance(); if (!items.size()) return; float offset = x; mFont->SetScale(0.8f); for (vector::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 + 6.5f, 5, w + 6.5f, 25, 0, (*it)->getColor(WGuiColor::BACK_TAB)); //inside border renderer->DrawRoundRect(offset + 6.5f, 5, w + 6.5f, 25, 0, ARGB(180,89,89,89)); //outside border //renderer->DrawRoundRect(offset + 5.5f, 4, w + 8.5f, 27, 0, ARGB(180,240,240,240)); mFont->DrawString(_((*it)->getDisplay()).c_str(), offset + 10, 10); offset += w + 10 + 2; } mFont->SetScale(1); WGuiBase * c = Current(); if (c) c->Render(); } bool WGuiTabMenu::CheckUserInput(JButton key) { bool result = false; bool kidModal = false; int nbitems = (int) items.size(); JGE * mEngine = JGE::GetInstance(); int i, j; if (!mEngine->GetButtonState(held)) //Key isn't held down. held = JGE_BTN_NONE; if (mEngine->GetLeftClickCoordinates(i, j)) { if(j <= 25) { // a dude clicked in the tab title bar, let's compute which tab from i float offset = x; WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::OPTION_FONT); mFont->SetScale(0.8f); for (vector::iterator it = items.begin(); it != items.end(); it++) { float w = mFont->GetStringWidth(_((*it)->getDisplay()).c_str()); if(i >= offset+5 && i <= offset+w+10+2) { setSelected(it); mEngine->LeftClickedProcessed(); return true; } offset += w + 10 + 2; } mFont->SetScale(1); } } 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) result = items[currentItem]->CheckUserInput(key); return result; } void WGuiTabMenu::save() { confirmChange(true); setData(); ::options.save(); } //WGuiAward void WGuiAward::Overlay() { JRenderer * r = JRenderer::GetInstance(); WFont * mFont = WResourceManager::Instance()->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; JQuadPtr button = WResourceManager::Instance()->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.get(), 10, 12, 0, .5, .5); mFont->DrawString(::_(s), 30, 16); } mFont->SetScale(1); } void WGuiAward::Underlay() { char buf[1024]; JQuadPtr trophy; #if defined (PSP) string n = id ? Options::getName(id) : textId; if (n.size()) { sprintf(buf, "psptrophy_%s.png", n.c_str()); //Trophy specific to the award trophy = WResourceManager::Instance()->RetrieveTempQuad(buf); //Themed version... } if (!trophy && id >= Options::SET_UNLOCKS) { trophy = WResourceManager::Instance()->RetrieveTempQuad("psptrophy_set.png"); //TODO FIXME: Should look in set dir too. } if (!trophy.get()) //Fallback to basic trophy image. trophy = WResourceManager::Instance()->RetrieveTempQuad("psptrophy.png"); #else string n = id ? Options::getName(id) : textId; if (n.size()) { sprintf(buf, "trophy_%s.png", n.c_str()); //Trophy specific to the award trophy = WResourceManager::Instance()->RetrieveTempQuad(buf); //Themed version... } if (!trophy && id >= Options::SET_UNLOCKS) { trophy = WResourceManager::Instance()->RetrieveTempQuad("trophy_set.png"); //TODO FIXME: Should look in set dir too. } if (!trophy.get()) //Fallback to basic trophy image. trophy = WResourceManager::Instance()->RetrieveTempQuad("trophy.png"); #endif if (trophy.get()) { trophy->SetHotSpot(0,trophy->mHeight); if(trophy->mHeight == 268.f && trophy->mWidth == 203.f) { trophy->SetHotSpot(0,0); JRenderer::GetInstance()->RenderQuad(trophy.get(), 0, SCREEN_HEIGHT-trophy->mHeight); } else if(trophy->mHeight == 1268.f && trophy->mWidth == 1203.f) { JRenderer::GetInstance()->RenderQuad(trophy.get(), -17, SCREEN_HEIGHT-35, 0, 240.f / trophy->mWidth, 210.f / trophy->mHeight); } else JRenderer::GetInstance()->RenderQuad(trophy.get(), 0, SCREEN_HEIGHT, 0, 171.f / trophy->mWidth, 192.f / trophy->mHeight); } } void WGuiAward::Render() { GameOptionAward * goa = id ? dynamic_cast (&options[id]) : dynamic_cast (&options[textId]); if (!goa) return; WFont * mFont = WResourceManager::Instance()->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; JRenderer::GetInstance()->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(string _id, string name, string _text, string _details) : WGuiItem(name) { id = 0; textId = _id; text = _text; height = 60; details = _details; } WGuiAward::~WGuiAward() { GameOptionAward * goa = dynamic_cast (&options[id]); if (goa) goa->setViewed(true); } bool WGuiAward::Visible() { //WGuiAward is only visible when it's tied to an already achieved award. GameOptionAward * goa = id ? dynamic_cast (&options[id]) : dynamic_cast (&options[textId]); 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() { JQuadPtr q = source->getImage(); if (imgH == 0) { if (source && q.get()) return MAX(height,q->mHeight+(2*margin)); } return MAX(height,imgH+(2*margin)); } void WGuiImage::Render() { if (!source) return; JQuadPtr 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; JRenderer::GetInstance()->RenderQuad(q.get(), 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. JQuadPtr q; if (bThumb) { q = WResourceManager::Instance()->GetQuad(kGenericCardThumbnailID); #if defined WIN32 || defined LINUX if(!q) q = WResourceManager::Instance()->GetQuad(kGenericCardID); #endif } else q = WResourceManager::Instance()->GetQuad(kGenericCardID); float scale = p.actZ * 257.f / q->mHeight; q->SetColor(ARGB(255,255,255,255)); renderer->RenderQuad(q.get(), p.x, p.y, 0, scale, scale); } else { //Have card. if (bThumb) { //Thumbnail. JQuadPtr q; 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.get()) { q = CardGui::AlternateThumbQuad(c); if (q.get() == NULL) return; //TODO Some kind of error image. } renderer->RenderQuad(q.get(), p.x, p.y); } else { //Normal card. JQuadPtr q = source->getImage(mOffset.getPos()); int mode = (!q.get() || options[Options::DISABLECARDS].number) ? DrawMode::kText : DrawMode::kNormal; CardGui::DrawCard(c, p, mode); } } } //WGuiCardDistort WGuiCardDistort::WGuiCardDistort(WDataSource * wds, bool _thumb, WDataSource *) : WGuiCardImage(wds, _thumb) { mesh = NEW hgeDistortionMesh(2, 2); distortSrc = NULL; } WGuiCardDistort::~WGuiCardDistort() { SAFE_DELETE(mesh); } void WGuiCardDistort::Render() { JQuadPtr q; if (distortSrc) { WDistort * dt = distortSrc->getDistort(mOffset.getPos()); if (dt) xy = *dt; } if (!source) { //Default to back. if (bThumb) { q = WResourceManager::Instance()->GetQuad(kGenericCardThumbnailID); #if defined WIN32 || defined LINUX if(!q) q = WResourceManager::Instance()->GetQuad(kGenericCardID); #endif } else q = WResourceManager::Instance()->GetQuad(kGenericCardID); } 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.get()) 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() { int start = 0, nowPos = 0; int nbitems = (int) items.size(); //List is empty. if (!items.size() && failMsg != "") { WFont * mFont = WResourceManager::Instance()->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; } } } 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(items[pos]->minWidth()); float temp = items[pos]->getHeight() + 3; if (temp > tallestRow) tallestRow = temp; if (temp > cTallest) cTallest = temp; nowPos += static_cast (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::NB_Colors) { f = NEW WCFilterAND(f, NEW WCFilterColor(recolorTo)); } source->addFilter(f); } else { if (recolorTo > -1 && recolorTo < Constants::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("Return"), -102, -11, this); WGuiButton * mid = NEW WGuiButton(NEW WGuiItem("Clear"), -102, -66, this); WGuiSplit * sub = NEW WGuiSplit(mid, r); sub->setHeight(25); sub->setWidth(240); l->setHeight(25); l->setWidth(160); WGuiSplit * wgs = NEW WGuiSplit(l, sub, true); //WGuiSplit * wgs = NEW WGuiSplit(mid, r); subMenu = NULL; list->Add(NEW WGuiHeader(displayValue)); //list->Add(l); 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::iterator row, col; for (row = list->items.begin(); row != list->items.end(); row++) { WGuiList * wgl = dynamic_cast (*row); if (wgl) { if (res.size()) res += "|("; else res += "("; for (col = wgl->items.begin(); col != wgl->items.end(); col++) { WGuiFilterItem * fi = dynamic_cast (*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->isClosed()) subMenu->Update(dt); if (list) { list->Update(dt); WGuiList * wgl = dynamic_cast (list->Current()); if (!wgl) return; vector::iterator it; bool bDeleted = false; for (it = wgl->items.begin(); it != wgl->items.end(); it++) { WGuiFilterItem * wgfi = dynamic_cast (*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->isClosed()) subMenu->Render(); } bool WGuiFilters::CheckUserInput(JButton key) { if (subMenu && !subMenu->isClosed() && 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 (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 (list->Current()); if (wgl) { vector::iterator it; for (it = wgl->items.begin(); it != wgl->items.end(); it++) { WGuiFilterItem * wgfi = dynamic_cast (*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 (list->Current()); if (wgl) { vector::iterator it; for (it = wgl->items.begin(); it != wgl->items.end(); it++) { WGuiFilterItem * wgfi = dynamic_cast (*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 (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(JGE::GetInstance(), WResourceManager::Instance(), -1234, this, Fonts::MENU_FONT, 20, 20, "Filter By...", 6); 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(kCancelMenuID, "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(JGE::GetInstance(), WResourceManager::Instance(), -1234, this, Fonts::MAIN_FONT, 20, 20, "Filter:"); if (filterType == FILTER_TYPE) { mParent->addArg("Artifact", "t:Artifact;"); mParent->addArg("Artifact Creature", "t:Artifact;&t:Creature;"); mParent->addArg("Aura", "t:Aura;"); mParent->addArg("Basic", "t:Basic;"); mParent->addArg("Creature", "t:Creature;"); mParent->addArg("Enchantment", "t:Enchantment;"); mParent->addArg("Equipment", "t:Equipment;"); mParent->addArg("Instant", "t:Instant;"); mParent->addArg("Land", "t:Land;"); mParent->addArg("Legendary", "t:Legendary;"); mParent->addArg("Sorcery", "t:Sorcery;"); mParent->addArg("Tribal", "t:Tribal;"); mParent->addArg("Planeswalker", "t:Planeswalker;"); } else if (filterType == FILTER_SUBTYPE) { vector stlist; for (int i = Subtypes::LAST_TYPE + 1;; i++) { string s = MTGAllCards::findType(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 < 17; 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 < 17; 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 < 17; 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]; vector baString; for (int i = 0; i < Constants::NB_BASIC_ABILITIES; i++) {//remove some others if(i != 119 || i != 120 || i != 135 || i != 136 || i != 137 || i != 139 || i != 140 || i != 141 || i != 143 || i != 144 || i != 145 || i != 146 || i != 147 || i != 148 || i != 149 || i != 150 || i != 151 || i != 152 || i != 153 || i != 154) baString.push_back(Constants::MTGBasicAbilities[i]); } //sort sort(baString.begin(),baString.end()); for (unsigned int i = 0; i < baString.size(); i++) { string s = baString[i]; sprintf(buf, "a:%s;", s.c_str()); s[0] = toupper(s[0]); mParent->addArg(s, buf); } } else if (filterType == FILTER_SET) { vector > orderedSet; for(int i = 0; i < setlist.size(); i++){ if (options[Options::optionSet(i)].number == 0) continue; if (options[Options::SORTINGSETS].number == Constants::BY_DATE) // Now sets can be sorted by sector(orderindex) or name or release date. orderedSet.push_back(pair (setlist.getInfo(i)->getDate(), setlist[i].c_str())); else if (options[Options::SORTINGSETS].number == Constants::BY_NAME) orderedSet.push_back(pair (setlist.getInfo(i)->getName(), setlist[i].c_str())); else orderedSet.push_back(pair (setlist.getInfo(i)->getOrderIndex(), setlist[i].c_str())); } sort(orderedSet.begin(),orderedSet.end()); for (unsigned int i = 0; i < orderedSet.size(); i++){ mParent->addArg(setlist.getInfo(setlist.findSet(orderedSet.at(i).second))->getName(), "s:" + orderedSet.at(i).second + ";"); } } 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(kCancelMenuID, "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, 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("") { populateKeyBindingList(); } void WGuiKeyBinder::Update(float dt) { OptionKey* o = dynamic_cast (items[1]); if (!o) return; if (LOCAL_KEY_NONE != o->from) { items.insert(items.begin() + 1, NEW OptionKey(parent, LOCAL_KEY_NONE, JGE_BTN_NONE)); if (1 == currentItem) ++currentItem; } for (vector::iterator it = items.begin(); it != items.end(); ++it) (*it)->Update(dt); if (confirmMenu) confirmMenu->Update(dt); } bool WGuiKeyBinder::isModal() { for (vector::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::iterator it = items.begin(); it != items.end(); ++it) { OptionKey* o = static_cast (*it); if (o && LOCAL_KEY_NONE != o->from && JGE_BTN_NONE != o->to) j->BindKey(o->from, o->to); } j->ResetInput(); } #if (!defined IOS) 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 }; #endif #define C(o) (static_cast(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::iterator it = items.begin(); it != items.end(); ++it) { if (!(*it)->Visible()) continue; vector boundFunctionsList; for (vector::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::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(JGE::GetInstance(), WResourceManager::Instance(), 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. #if (!defined IOS) 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::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(JGE::GetInstance(), WResourceManager::Instance(), 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; } #endif // IOS return CONFIRM_OK; } void WGuiKeyBinder::ButtonPressed(int controllerId, int controlId) { if (1 == controlId) { confirmed = CONFIRM_CANCEL; } else if (2 == controlId) { switch (controllerId) { case 0: confirmedKeys.insert(confirmingKey); break; case 1: confirmedButtons.insert(confirmingButton); break; } } else if (3 == controlId) { switch (controllerId) { case -102: JGE::GetInstance()->ResetBindings(); populateKeyBindingList(); break; } } SAFE_DELETE(confirmMenu); confirmMenu = NULL; } void WGuiKeyBinder::Render() { WGuiList::Render(); if (confirmMenu) { JRenderer * renderer = JRenderer::GetInstance(); WFont * mFont = WResourceManager::Instance()->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; } void WGuiKeyBinder::populateKeyBindingList() { items.clear(); Add(NEW WGuiButton(NEW WGuiItem("Load Defaults..."), -102, 3, this)); Add(NEW OptionKey(parent, LOCAL_KEY_NONE, JGE_BTN_NONE)); JGE* j = JGE::GetInstance(); JGE::keybindings_it start = j->KeyBindings_begin(), end = j->KeyBindings_end(); for (JGE::keybindings_it it = start; it != end; ++it) Add(NEW OptionKey(parent, it->first, it->second)); }