aboutsummaryrefslogtreecommitdiff
path: root/engines/agi/menu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/agi/menu.cpp')
-rw-r--r--engines/agi/menu.cpp800
1 files changed, 361 insertions, 439 deletions
diff --git a/engines/agi/menu.cpp b/engines/agi/menu.cpp
index 008c208c82..411cd002fd 100644
--- a/engines/agi/menu.cpp
+++ b/engines/agi/menu.cpp
@@ -22,534 +22,456 @@
#include "agi/agi.h"
#include "agi/graphics.h"
+#include "agi/text.h"
#include "agi/keyboard.h"
#include "agi/menu.h"
namespace Agi {
-// TODO: add constructor/destructor for agi_menu, agi_menu_option
-
-struct AgiMenuOption {
- int enabled; /**< option is enabled or disabled */
- int event; /**< menu event */
- int index; /**< number of option in this menu */
- char *text; /**< text of menu option */
-};
-
-struct AgiMenu {
- MenuOptionList down; /**< list head for menu options */
- int index; /**< number of menu in menubar */
- int width; /**< width of menu in characters */
- int height; /**< height of menu in characters */
- int col; /**< column of menubar entry */
- int wincol; /**< column of menu window */
- char *text; /**< menu name */
-};
-
-AgiMenu *Menu::getMenu(int i) {
- MenuList::iterator iter;
- for (iter = _menubar.begin(); iter != _menubar.end(); ++iter) {
- AgiMenu *m = *iter;
- if (m->index == i)
- return m;
- }
- return NULL;
-}
-
-AgiMenuOption *Menu::getMenuOption(int i, int j) {
- AgiMenu *m = getMenu(i);
- MenuOptionList::iterator iter;
-
- for (iter = m->down.begin(); iter != m->down.end(); ++iter) {
- AgiMenuOption* d = *iter;
- if (d->index == j)
- return d;
- }
-
- return NULL;
-}
+GfxMenu::GfxMenu(AgiEngine *vm, GfxMgr *gfx, PictureMgr *picture, TextMgr *text) {
+ _vm = vm;
+ _gfx = gfx;
+ _picture = picture;
+ _text = text;
-void Menu::drawMenuBar() {
- _vm->clearLines(0, 0, MENU_BG);
- _vm->flushLines(0, 0);
+ _allowed = true;
+ _submitted = false;
+ _delayedExecute = false;
- MenuList::iterator iter;
- for (iter = _menubar.begin(); iter != _menubar.end(); ++iter) {
- AgiMenu *m = *iter;
-
- _vm->printText(m->text, 0, m->col, 0, 40, MENU_FG, MENU_BG);
- }
+ _setupMenuColumn = 1;
+ _setupMenuItemColumn = 1;
+ _selectedMenuNr = 0;
+ _selectedMenuHeight = 0;
+ _selectedMenuWidth = 0;
+ _selectedMenuRow = 0;
+ _selectedMenuColumn = 0;
}
-void Menu::drawMenuHilite(int curMenu) {
- AgiMenu *m = getMenu(curMenu);
-
- debugC(6, kDebugLevelMenu, "[%s]", m->text);
+GfxMenu::~GfxMenu() {
+ for (GuiMenuArray::iterator itemIter = _array.begin(); itemIter != _array.end(); ++itemIter)
+ delete *itemIter;
+ _array.clear();
- _vm->printText(m->text, 0, m->col, 0, 40, MENU_BG, MENU_FG);
- _vm->flushLines(0, 0);
+ for (GuiMenuItemArray::iterator menuIter = _itemArray.begin(); menuIter != _itemArray.end(); ++menuIter)
+ delete *menuIter;
+ _itemArray.clear();
}
-// draw box and pulldowns.
-void Menu::drawMenuOption(int hMenu) {
- // find which vertical menu it is
- AgiMenu *m = getMenu(hMenu);
-
- _gfx->drawBox(m->wincol * CHAR_COLS, 1 * CHAR_LINES, (m->wincol + m->width + 2) * CHAR_COLS,
- (1 + m->height + 2) * CHAR_LINES, MENU_BG, MENU_LINE, 0);
+void GfxMenu::addMenu(const char *menuText) {
+ // already submitted? in that case no further changes possible
+ if (_submitted)
+ return;
- MenuOptionList::iterator iter;
+ GuiMenuEntry *menuEntry = new GuiMenuEntry();
- for (iter = m->down.begin(); iter != m->down.end(); ++iter) {
- AgiMenuOption* d = *iter;
+ menuEntry->text = menuText;
+ menuEntry->textLen = menuEntry->text.size();
+ menuEntry->row = 0;
+ menuEntry->column = _setupMenuColumn;
+ menuEntry->itemCount = 0;
+ menuEntry->firstItemNr = _itemArray.size();
+ menuEntry->selectedItemNr = menuEntry->firstItemNr;
+ menuEntry->maxItemTextLen = 0;
+ _array.push_back(menuEntry);
- _vm->printText(d->text, 0, m->wincol + 1, d->index + 2, m->width + 2,
- MENU_FG, MENU_BG, !d->enabled);
- }
+ _setupMenuColumn += menuEntry->textLen + 1;
}
-void Menu::drawMenuOptionHilite(int hMenu, int vMenu) {
- AgiMenu *m = getMenu(hMenu);
- AgiMenuOption *d = getMenuOption(hMenu, vMenu);
+void GfxMenu::addMenuItem(const char *menuItemText, uint16 controllerSlot) {
+ int16 arrayCount = _array.size();
- // Disabled menu items are "greyed out" with a checkerboard effect,
- // rather than having a different color. -- dsymonds
- _vm->printText(d->text, 0, m->wincol + 1, vMenu + 2, m->width + 2,
- MENU_BG, MENU_FG, !d->enabled);
-}
+ // already submitted? in that case no further changes possible
+ if (_submitted)
+ return;
-void Menu::newMenuSelected(int i) {
- _picture->showPic();
- drawMenuBar();
- drawMenuHilite(i);
- drawMenuOption(i);
-}
+ if (arrayCount == 0)
+ error("tried to add a menu item before adding an actual menu");
-bool Menu::mouseOverText(int line, int col, char *s) {
- if (_vm->_mouse.x < col * CHAR_COLS)
- return false;
+ // go to latest menu entry
+ GuiMenuEntry *curMenuEntry = _array.back();
- if (_vm->_mouse.x > (int)(col + strlen(s)) * CHAR_COLS)
- return false;
+ GuiMenuItemEntry *menuItemEntry = new GuiMenuItemEntry();
- if (_vm->_mouse.y < line * CHAR_LINES)
- return false;
+ menuItemEntry->enabled = true;
+ menuItemEntry->text = menuItemText;
+ menuItemEntry->textLen = menuItemEntry->text.size();
+ menuItemEntry->controllerSlot = controllerSlot;
- if (_vm->_mouse.y >= (line + 1) * CHAR_LINES)
- return false;
+ // Original interpreter on PC used the length of the first item for drawing
+ // At least in KQ2 on Apple IIgs follow-up items are longer, which would result in graphic glitches.
+ // That's why we remember the longest item and draw according to that
+ if (curMenuEntry->maxItemTextLen < menuItemEntry->textLen) {
+ curMenuEntry->maxItemTextLen = menuItemEntry->textLen;
+ }
- return true;
-}
+ if (curMenuEntry->itemCount == 0) {
+ // for first menu item of menu calculated column
+ if (menuItemEntry->textLen + curMenuEntry->column < (FONT_COLUMN_CHARACTERS - 1)) {
+ _setupMenuItemColumn = curMenuEntry->column;
+ } else {
+ _setupMenuItemColumn = ( FONT_COLUMN_CHARACTERS - 1 ) - menuItemEntry->textLen;
+ }
+ }
-#if 0
-static void add_about_option() {
- const char *text = "About AGI engine";
-
- agi_menu_option *d = new agi_menu_option;
- d->text = strdup(text);
- d->enabled = true;
- d->event = 255;
- d->index = (v_max_menu[0] += 1);
-
- agi_menu *m = *menubar.begin();
- m->down.push_back(d);
- m->height++;
- if (m->width < (int)strlen(text))
- m->width = strlen(text);
-}
-#endif
+ menuItemEntry->row = 2 + curMenuEntry->itemCount;
+ menuItemEntry->column = _setupMenuItemColumn;
-/*
- * Public functions
- */
+ _itemArray.push_back(menuItemEntry);
-Menu::Menu(AgiEngine *vm, GfxMgr *gfx, PictureMgr *picture) {
- _vm = vm;
- _gfx = gfx;
- _picture = picture;
- _hIndex = 0;
- _hCol = 1;
- _hMaxMenu = 0;
- _hCurMenu = 0;
- _vCurMenu = 0;
+ curMenuEntry->itemCount++;
}
-Menu::~Menu() {
- MenuList::iterator iterh;
- for (iterh = _menubar.reverse_begin(); iterh != _menubar.end(); ) {
- AgiMenu *m = *iterh;
-
- debugC(3, kDebugLevelMenu, "deiniting hmenu %s", m->text);
-
- MenuOptionList::iterator iterv;
-
- for (iterv = m->down.reverse_begin(); iterv != m->down.end(); ) {
- AgiMenuOption *d = *iterv;
-
- debugC(3, kDebugLevelMenu, " deiniting vmenu %s", d->text);
-
- free(d->text);
- delete d;
+void GfxMenu::submit() {
+ GuiMenuEntry *menuEntry = nullptr;
+ GuiMenuItemEntry *menuItemEntry = nullptr;
+ int16 menuCount = _array.size();
+ int16 menuNr = 0;
+ int16 menuItemNr = 0;
+ int16 menuItemLastNr = 0;
+
+ if ((_array.size() == 0) || (_itemArray.size() == 0))
+ return;
+
+ _submitted = true;
+
+ // WORKAROUND: For Apple II gs we try to fix the menu text
+ // On this platform it seems a system font was used and the menu was drawn differently (probably system menu?)
+ // Still the text was misaligned anyway, but it looks worse in our (the original PC) implementation
+ // Atari ST SQ1 had one bad menu entry as well, we fix that too.
+ switch (_vm->getPlatform()) {
+ case Common::kPlatformApple2GS:
+ case Common::kPlatformAtariST:
+ // Go through all menus
+ for (menuNr = 0; menuNr < menuCount; menuNr++) {
+ menuEntry = _array[menuNr];
+ menuItemLastNr = menuEntry->firstItemNr + menuEntry->itemCount;
+
+ // Go through all items of current menu
+ for (menuItemNr = menuEntry->firstItemNr; menuItemNr < menuItemLastNr; menuItemNr++) {
+ menuItemEntry = _itemArray[menuItemNr];
+
+ if (menuItemEntry->textLen < menuEntry->maxItemTextLen) {
+ // current item text is shorter than the maximum?
+ int16 missingCharCount = menuEntry->maxItemTextLen - menuItemEntry->textLen;
+
+ if (menuItemEntry->text.contains('>')) {
+ // text contains '>', we now try to find a '<'
+ // and then add spaces in case this item is shorter than the first item
+ int16 textPos = menuItemEntry->textLen - 1;
+
+ while (textPos > 0) {
+ if (menuItemEntry->text[textPos] == '<')
+ break;
+ textPos--;
+ }
+
+ if (textPos > 0) {
+ while (missingCharCount) {
+ menuItemEntry->text.insertChar(' ', textPos);
+ missingCharCount--;
+ }
+ }
+ } else {
+ // Also check if text consists only of '-', which is the separator
+ // These were sometimes also too small
+ int16 separatorCount = 0;
+ int16 charPos = 0;
+
+ while (charPos < menuItemEntry->textLen) {
+ if (menuItemEntry->text[charPos] != '-')
+ break;
+ separatorCount++;
+ charPos++;
+ }
+
+ if (separatorCount == menuItemEntry->textLen) {
+ // Separator detected
+ while (missingCharCount) {
+ menuItemEntry->text.insertChar('-', 0);
+ missingCharCount--;
+ }
+ } else {
+ // Append spaces to the end to fill it up
+ int16 textPos = menuItemEntry->textLen;
+ while (missingCharCount) {
+ menuItemEntry->text.insertChar(' ', textPos);
+ textPos++;
+ missingCharCount--;
+ }
+ }
+ }
- iterv = m->down.reverse_erase(iterv);
+ menuItemEntry->textLen = menuItemEntry->text.size();
+ }
+ }
}
- free(m->text);
- delete m;
-
- iterh = _menubar.reverse_erase(iterh);
+ break;
+ default:
+ break;
}
}
-void Menu::add(const char *s) {
- AgiMenu *m = new AgiMenu;
- m->text = strdup(s);
-
- while (m->text[strlen(m->text) - 1] == ' ')
- m->text[strlen(m->text) - 1] = 0;
-
- m->width = 0;
- m->height = 0;
- m->index = _hIndex++;
- m->col = _hCol;
- m->wincol = _hCol - 1;
- _vIndex = 0;
- _vMaxMenu[m->index] = 0;
- _hCol += strlen(m->text) + 1;
- _hMaxMenu = m->index;
-
- debugC(3, kDebugLevelMenu, "add menu: '%s' %02x", s, m->text[strlen(m->text)]);
- _menubar.push_back(m);
+void GfxMenu::itemEnable(uint16 controllerSlot) {
+ itemEnableDisable(controllerSlot, true);
}
-void Menu::addItem(const char *s, int code) {
- int l;
-
- AgiMenuOption* d = new AgiMenuOption;
-
- d->text = strdup(s);
- d->enabled = true;
- d->event = code;
- d->index = _vIndex++;
-
- // add to last menu in list
- assert(_menubar.reverse_begin() != _menubar.end());
- AgiMenu *m = *_menubar.reverse_begin();
- m->height++;
-
- _vMaxMenu[m->index] = d->index;
-
- l = strlen(d->text);
- if (l > 40)
- l = 38;
- if (m->wincol + l > 38)
- m->wincol = 38 - l;
- if (l > m->width)
- m->width = l;
-
- debugC(3, kDebugLevelMenu, "Adding menu item: %s (size = %d)", s, m->height);
-
- m->down.push_back(d);
+void GfxMenu::itemDisable(uint16 controllerSlot) {
+ itemEnableDisable(controllerSlot, false);
}
-void Menu::submit() {
- debugC(3, kDebugLevelMenu, "Submitting menu");
-
- // add_about_option ();
-
- // If a menu has no options, delete it
- MenuList::iterator iter;
- for (iter = _menubar.reverse_begin(); iter != _menubar.end(); ) {
- AgiMenu *m = *iter;
+void GfxMenu::itemEnableDisable(uint16 controllerSlot, bool enabled) {
+ GuiMenuItemArray::iterator listIterator;
+ GuiMenuItemArray::iterator listEnd = _itemArray.end();
+ GuiMenuItemEntry *menuItemEntry;
- if (m->down.empty()) {
- free(m->text);
- delete m;
-
- _hMaxMenu--;
-
- iter = _menubar.reverse_erase(iter);
- } else {
- --iter;
+ listIterator = _itemArray.begin();
+ while (listIterator != listEnd) {
+ menuItemEntry = *listIterator;
+ if (menuItemEntry->controllerSlot == controllerSlot) {
+ menuItemEntry->enabled = enabled;
}
+
+ listIterator++;
}
}
-bool Menu::keyhandler(int key) {
- static int clockVal;
- static int menuActive = false;
- static int buttonUsed = 0;
- bool exitMenu = false;
+void GfxMenu::itemEnableAll() {
+ GuiMenuItemArray::iterator listIterator;
+ GuiMenuItemArray::iterator listEnd = _itemArray.end();
+ GuiMenuItemEntry *menuItemEntry;
- if (!_vm->getflag(fMenusWork) && !(_vm->getFeatures() & GF_MENUS))
- return false;
+ listIterator = _itemArray.begin();
+ while (listIterator != listEnd) {
+ menuItemEntry = *listIterator;
+ menuItemEntry->enabled = true;
- if (!menuActive) {
- clockVal = _vm->_game.clockEnabled;
- _vm->_game.clockEnabled = false;
- drawMenuBar();
+ listIterator++;
}
+}
- // Mouse handling
- if (_vm->_mouse.button) {
- int hmenu, vmenu;
-
- buttonUsed = 1; // Button has been used at least once
-
- if (_vm->_mouse.y <= CHAR_LINES) {
- // on the menubar
- hmenu = 0;
+// return true, in case a menu was actually created and submitted by the scripts
+bool GfxMenu::isAvailable() {
+ return _submitted;
+}
- MenuList::iterator iterh;
+void GfxMenu::accessAllow() {
+ _allowed = true;
+}
- for (iterh = _menubar.begin(); iterh != _menubar.end(); ++iterh) {
- AgiMenu *m = *iterh;
+void GfxMenu::accessDeny() {
+ _allowed = false;
+}
- if (mouseOverText(0, m->col, m->text)) {
- break;
- } else {
- hmenu++;
- }
- }
+void GfxMenu::delayedExecute() {
+ _delayedExecute = true;
+}
- if (hmenu <= _hMaxMenu) {
- if (_hCurMenu != hmenu) {
- _vCurMenu = -1;
- newMenuSelected(hmenu);
- }
- _hCurMenu = hmenu;
- }
- } else {
- // not in menubar
- vmenu = 0;
+bool GfxMenu::delayedExecuteActive() {
+ return _delayedExecute;
+}
- AgiMenu *m = getMenu(_hCurMenu);
+void GfxMenu::execute() {
+ _delayedExecute = false;
- MenuOptionList::iterator iterv;
+ // got submitted? -> safety check
+ if (!_submitted)
+ return;
- for (iterv = m->down.begin(); iterv != m->down.end(); ++iterv) {
- AgiMenuOption *do1 = *iterv;
+ // access allowed at the moment?
+ if (!_allowed)
+ return;
- if (mouseOverText(2 + do1->index, m->wincol + 1, do1->text)) {
- break;
- } else {
- vmenu++;
- }
- }
+ _text->charPos_Push();
+ _text->charAttrib_Push();
+ _text->clearLine(0, _text->calculateTextBackground(15));
- if (vmenu <= _vMaxMenu[_hCurMenu]) {
- if (_vCurMenu != vmenu) {
- drawMenuOption(_hCurMenu);
- drawMenuOptionHilite(_hCurMenu, vmenu);
- }
- _vCurMenu = vmenu;
- }
- }
- } else if (buttonUsed) {
- // Button released
- buttonUsed = 0;
+ // Draw all menus
+ for (uint16 menuNr = 0; menuNr < _array.size(); menuNr++) {
+ drawMenuName(menuNr, false);
+ }
+ drawActiveMenu();
- debugC(6, kDebugLevelMenu | kDebugLevelInput, "button released!");
+ _vm->cycleInnerLoopActive(CYCLE_INNERLOOP_MENU);
+ do {
+ _vm->mainCycle();
+ } while (_vm->cycleInnerLoopIsActive() && !(_vm->shouldQuit() || _vm->_restartGame));
- if (_vCurMenu < 0)
- _vCurMenu = 0;
+ removeActiveMenu();
- drawMenuOptionHilite(_hCurMenu, _vCurMenu);
+ _text->charAttrib_Pop();
+ _text->charPos_Pop();
- if (_vm->_mouse.y <= CHAR_LINES) {
- // on the menubar
- } else {
- // see which option we selected
- AgiMenu *m = getMenu(_hCurMenu);
- MenuOptionList::iterator iterv;
-
- for (iterv = m->down.begin(); iterv != m->down.end(); ++iterv) {
- AgiMenuOption *d = *iterv;
-
- if (mouseOverText(2 + d->index, m->wincol + 1, d->text)) {
- // activate that option
- if (d->enabled) {
- debugC(6, kDebugLevelMenu | kDebugLevelInput, "event %d registered", d->event);
- _vm->_game.controllerOccured[d->event] = true;
- _vm->_menuSelected = true;
- break;
- }
- }
- }
- exitMenu = true;
- }
+ // Restore status line
+ if (_text->statusEnabled()) {
+ _text->statusDraw();
+ } else {
+ _text->clearLine(0, 0);
}
+}
- if (!exitMenu) {
- if (!menuActive) {
- if (_hCurMenu >= 0) {
- drawMenuHilite(_hCurMenu);
- drawMenuOption(_hCurMenu);
- if (!buttonUsed && _vCurMenu >= 0)
- drawMenuOptionHilite(_hCurMenu, _vCurMenu);
- }
- menuActive = true;
- }
+void GfxMenu::drawMenuName(int16 menuNr, bool inverted) {
+ GuiMenuEntry *menuEntry = _array[menuNr];
+ bool disabledLook = false;
- switch (key) {
- case KEY_ESCAPE:
- debugC(6, kDebugLevelMenu | kDebugLevelInput, "KEY_ESCAPE");
- exitMenu = true;
- break;
- case KEY_ENTER:
- {
- debugC(6, kDebugLevelMenu | kDebugLevelInput, "KEY_ENTER");
- AgiMenuOption* d = getMenuOption(_hCurMenu, _vCurMenu);
-
- if (d->enabled) {
- debugC(6, kDebugLevelMenu | kDebugLevelInput, "event %d registered", d->event);
- _vm->_game.controllerOccured[d->event] = true;
- _vm->_menuSelected = true;
- exitMenu = true;
- }
- break;
- }
- case KEY_DOWN:
- case KEY_UP:
- _vCurMenu += key == KEY_DOWN ? 1 : -1;
-
- if (_vCurMenu < 0)
- _vCurMenu = _vMaxMenu[_hCurMenu];
- if (_vCurMenu > _vMaxMenu[_hCurMenu])
- _vCurMenu = 0;
-
- drawMenuOption(_hCurMenu);
- drawMenuOptionHilite(_hCurMenu, _vCurMenu);
- break;
- case KEY_RIGHT:
- case KEY_LEFT:
- _hCurMenu += key == KEY_RIGHT ? 1 : -1;
-
- if (_hCurMenu < 0)
- _hCurMenu = _hMaxMenu;
- if (_hCurMenu > _hMaxMenu)
- _hCurMenu = 0;
-
- _vCurMenu = 0;
- newMenuSelected(_hCurMenu);
- drawMenuOptionHilite(_hCurMenu, _vCurMenu);
- break;
- }
+ if (!inverted) {
+ _text->charAttrib_Set(0, _text->calculateTextBackground(15));
+ } else {
+ _text->charAttrib_Set(15, _text->calculateTextBackground(0));
}
- if (exitMenu) {
- buttonUsed = 0;
- _picture->showPic();
- _vm->writeStatus();
-
- _vm->setvar(vKey, 0);
- _vm->_game.keypress = 0;
- _vm->_game.clockEnabled = clockVal;
- _vm->oldInputMode();
+ _text->charPos_Set(menuEntry->row, menuEntry->column);
- debugC(3, kDebugLevelMenu, "exit_menu: input mode reset to %d", _vm->_game.inputMode);
- menuActive = false;
- }
+ if (menuEntry->itemCount == 0)
+ disabledLook = true;
- return true;
+ _text->displayText(menuEntry->text.c_str(), disabledLook);
}
-void Menu::setItem(int event, int state) {
- // scan all menus for event number #
+void GfxMenu::drawItemName(int16 itemNr, bool inverted) {
+ GuiMenuItemEntry *itemEntry = _itemArray[itemNr];
+ bool disabledLook = false;
- debugC(6, kDebugLevelMenu, "event = %d, state = %d", event, state);
- MenuList::iterator iterh;
+ if (!inverted) {
+ _text->charAttrib_Set(0, _text->calculateTextBackground(15));
+ } else {
+ _text->charAttrib_Set(15, _text->calculateTextBackground(0));
+ }
- for (iterh = _menubar.begin(); iterh != _menubar.end(); ++iterh) {
- AgiMenu *m = *iterh;
- MenuOptionList::iterator iterv;
+ _text->charPos_Set(itemEntry->row, itemEntry->column);
- for (iterv = m->down.begin(); iterv != m->down.end(); ++iterv) {
- AgiMenuOption *d = *iterv;
+ if (itemEntry->enabled == false)
+ disabledLook = true;
- if (d->event == event) {
- d->enabled = state;
- // keep going; we need to set the state of every menu item
- // with this event code. -- dsymonds
- }
- }
- }
+ _text->displayText(itemEntry->text.c_str(), disabledLook);
}
-void Menu::enableAll() {
- MenuList::iterator iterh;
- for (iterh = _menubar.begin(); iterh != _menubar.end(); ++iterh) {
- AgiMenu *m = *iterh;
- MenuOptionList::iterator iterv;
-
- for (iterv = m->down.begin(); iterv != m->down.end(); ++iterv) {
- AgiMenuOption *d = *iterv;
-
- d->enabled = true;
+void GfxMenu::drawActiveMenu() {
+ GuiMenuEntry *menuEntry = _array[_selectedMenuNr];
+ GuiMenuItemEntry *itemEntry = _itemArray[menuEntry->firstItemNr];
+ int16 itemNr = menuEntry->firstItemNr;
+ int16 itemCount = menuEntry->itemCount;
+
+ // draw menu name as inverted
+ drawMenuName(_selectedMenuNr, true);
+
+ // calculate active menu dimensions
+ _selectedMenuHeight = (menuEntry->itemCount + 2) * FONT_VISUAL_HEIGHT;
+ _selectedMenuWidth = (menuEntry->maxItemTextLen * FONT_VISUAL_WIDTH) + 8;
+ _selectedMenuRow = (menuEntry->itemCount + 3 - _text->getWindowRowMin()) * FONT_VISUAL_HEIGHT - 1;
+ _selectedMenuColumn = (itemEntry->column - 1) * FONT_VISUAL_WIDTH;
+
+ _gfx->drawBox(_selectedMenuColumn, _selectedMenuRow, _selectedMenuWidth, _selectedMenuHeight, 15, 0);
+
+ while (itemCount) {
+ if (itemNr == menuEntry->selectedItemNr) {
+ drawItemName(itemNr, true);
+ } else {
+ drawItemName(itemNr, false);
}
+ itemNr++;
+ itemCount--;
}
}
+void GfxMenu::removeActiveMenu() {
+ // draw menu name normally again
+ drawMenuName(_selectedMenuNr, false);
-AgiTextColor AgiButtonStyle::getColor(bool hasFocus, bool pressed, bool positive) const {
- if (_amigaStyle) {
- if (positive) {
- if (pressed) { // Positive pressed Amiga-style button
- if (_olderAgi) {
- return AgiTextColor(amigaBlack, amigaOrange);
- } else {
- return AgiTextColor(amigaBlack, amigaPurple);
- }
- } else { // Positive unpressed Amiga-style button
- return AgiTextColor(amigaWhite, amigaGreen);
- }
- } else { // _amigaStyle && !positive
- if (pressed) { // Negative pressed Amiga-style button
- return AgiTextColor(amigaBlack, amigaCyan);
- } else { // Negative unpressed Amiga-style button
- return AgiTextColor(amigaWhite, amigaRed);
- }
- }
- } else { // PC-style button
- if (hasFocus || pressed) { // A pressed or in focus PC-style button
- return AgiTextColor(pcWhite, pcBlack);
- } else { // An unpressed PC-style button without focus
- return AgiTextColor(pcBlack, pcWhite);
- }
- }
+ // overwrite actual menu items by rendering play screen
+ _gfx->render_Block(_selectedMenuColumn, _selectedMenuRow, _selectedMenuWidth, _selectedMenuHeight);
}
-AgiTextColor AgiButtonStyle::getColor(bool hasFocus, bool pressed, int baseFgColor, int baseBgColor) const {
- return getColor(hasFocus, pressed, AgiTextColor(baseFgColor, baseBgColor));
-}
+void GfxMenu::charPress(int16 newChar) {
+ GuiMenuEntry *menuEntry = _array[_selectedMenuNr];
+ GuiMenuItemEntry *itemEntry = _itemArray[menuEntry->selectedItemNr];
+ int16 newMenuNr = _selectedMenuNr;
+ int16 newItemNr = menuEntry->selectedItemNr;
+
+ switch (newChar) {
+ case AGI_KEY_ENTER:
+ // check, if current item is actually enabled
+ if (!itemEntry->enabled)
+ return;
+
+ // Trigger controller
+ _vm->_game.controllerOccured[itemEntry->controllerSlot] = true;
+
+ _vm->cycleInnerLoopInactive(); // exit execute-loop
+ break;
+ case AGI_KEY_ESCAPE:
+ _vm->cycleInnerLoopInactive(); // exit execute-loop
+ break;
+
+ // these here change menu item
+ case AGI_KEY_UP:
+ newItemNr--;
+ break;
+ case AGI_KEY_DOWN:
+ newItemNr++;
+ break;
+ case AGI_KEY_PAGE_UP:
+ // select first item of current menu
+ newItemNr = menuEntry->firstItemNr;
+ break;
+ case AGI_KEY_PAGE_DOWN:
+ // select last item of current menu
+ newItemNr = menuEntry->firstItemNr + menuEntry->itemCount - 1;
+ break;
+
+ case AGI_KEY_LEFT:
+ newMenuNr--;
+ break;
+ case AGI_KEY_RIGHT:
+ newMenuNr++;
+ break;
+ case AGI_KEY_HOME:
+ // select first menu
+ newMenuNr = 0;
+ break;
+ case AGI_KEY_END:
+ // select last menu
+ newMenuNr = _array.size() - 1;
+ break;
+
+ default:
+ break;
+ }
-AgiTextColor AgiButtonStyle::getColor(bool hasFocus, bool pressed, const AgiTextColor &baseColor) const {
- if (hasFocus || pressed)
- return baseColor.swap();
- else
- return baseColor;
-}
+ if (newMenuNr != _selectedMenuNr) {
+ // selected menu was changed
+ int16 lastMenuNr = _array.size() - 1;
-int AgiButtonStyle::getTextOffset(bool hasFocus, bool pressed) const {
- return (pressed && !_amigaStyle) ? 1 : 0;
-}
+ if (newMenuNr < 0) {
+ newMenuNr = lastMenuNr;
+ } else if (newMenuNr > lastMenuNr) {
+ newMenuNr = 0;
+ }
-bool AgiButtonStyle::getBorder(bool hasFocus, bool pressed) const {
- return _amigaStyle && !_authenticAmiga && (hasFocus || pressed);
-}
+ if (newMenuNr != _selectedMenuNr) {
+ removeActiveMenu();
+ _selectedMenuNr = newMenuNr;
+ drawActiveMenu();
+ }
+ }
-void AgiButtonStyle::setAmigaStyle(bool amigaStyle, bool olderAgi, bool authenticAmiga) {
- _amigaStyle = amigaStyle;
- _olderAgi = olderAgi;
- _authenticAmiga = authenticAmiga;
-}
+ if (newItemNr != menuEntry->selectedItemNr) {
+ // selected item was changed
+ int16 lastItemNr = menuEntry->firstItemNr + menuEntry->itemCount - 1;
-void AgiButtonStyle::setPcStyle(bool pcStyle) {
- setAmigaStyle(!pcStyle);
-}
+ if (newItemNr < menuEntry->firstItemNr) {
+ newItemNr = lastItemNr;
+ } else if (newItemNr > lastItemNr) {
+ newItemNr = menuEntry->firstItemNr;
+ }
-AgiButtonStyle::AgiButtonStyle(Common::RenderMode renderMode) {
- setAmigaStyle(renderMode == Common::kRenderAmiga);
+ if (newItemNr != menuEntry->selectedItemNr) {
+ // still changed after clip -> draw changes
+ drawItemName(menuEntry->selectedItemNr, false);
+ drawItemName(newItemNr, true);
+ menuEntry->selectedItemNr = newItemNr;
+ }
+ }
}
} // End of namespace Agi