mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-25 19:25:20 +00:00
e1c36a52b5
- User option to force Hercules hires font for any rendering mode - Also change mouse cursor hotspots from 1,1 to 0,0 - Fix inaccuracy in mouse controlled game menu - Change render_Block(), drawBox(), drawDisplayRect() to use upper Y instead of lower Y. Original AGI uses lower Y, but upper Y makes upscaling way easier.
687 lines
19 KiB
C++
687 lines
19 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "agi/agi.h"
|
|
#include "agi/graphics.h"
|
|
#include "agi/text.h"
|
|
#include "agi/keyboard.h"
|
|
#include "agi/menu.h"
|
|
|
|
namespace Agi {
|
|
|
|
GfxMenu::GfxMenu(AgiEngine *vm, GfxMgr *gfx, PictureMgr *picture, TextMgr *text) {
|
|
_vm = vm;
|
|
_gfx = gfx;
|
|
_picture = picture;
|
|
_text = text;
|
|
|
|
_allowed = true;
|
|
_submitted = false;
|
|
_delayedExecuteViaKeyboard = false;
|
|
_delayedExecuteViaMouse = false;
|
|
|
|
_setupMenuColumn = 1;
|
|
_setupMenuItemColumn = 1;
|
|
|
|
_lastSelectedMenuNr = 0;
|
|
|
|
_mouseModeItemNr = -1;
|
|
|
|
_drawnMenuNr = -1;
|
|
_drawnMenuHeight = 0;
|
|
_drawnMenuWidth = 0;
|
|
_drawnMenuY = 0;
|
|
_drawnMenuX = 0;
|
|
}
|
|
|
|
GfxMenu::~GfxMenu() {
|
|
for (GuiMenuArray::iterator itemIter = _array.begin(); itemIter != _array.end(); ++itemIter)
|
|
delete *itemIter;
|
|
_array.clear();
|
|
|
|
for (GuiMenuItemArray::iterator menuIter = _itemArray.begin(); menuIter != _itemArray.end(); ++menuIter)
|
|
delete *menuIter;
|
|
_itemArray.clear();
|
|
}
|
|
|
|
void GfxMenu::addMenu(const char *menuText) {
|
|
int16 curColumnEnd = _setupMenuColumn;
|
|
|
|
// already submitted? in that case no further changes possible
|
|
if (_submitted)
|
|
return;
|
|
|
|
GuiMenuEntry *menuEntry = new GuiMenuEntry();
|
|
|
|
menuEntry->text = menuText;
|
|
menuEntry->textLen = menuEntry->text.size();
|
|
|
|
// Cut menu name in case menu bar is full
|
|
// Happens in at least the fan game Get Outta Space Quest
|
|
// Original interpreter had graphical issues in this case
|
|
// TODO: this whole code needs to get reworked anyway to support different types of menu bars depending on platform
|
|
curColumnEnd += menuEntry->textLen;
|
|
while ((menuEntry->textLen) && (curColumnEnd > 40)) {
|
|
menuEntry->text.deleteLastChar();
|
|
menuEntry->textLen--;
|
|
curColumnEnd--;
|
|
}
|
|
|
|
menuEntry->row = 0;
|
|
menuEntry->column = _setupMenuColumn;
|
|
menuEntry->itemCount = 0;
|
|
menuEntry->firstItemNr = _itemArray.size();
|
|
menuEntry->selectedItemNr = menuEntry->firstItemNr;
|
|
menuEntry->maxItemTextLen = 0;
|
|
_array.push_back(menuEntry);
|
|
|
|
_setupMenuColumn += menuEntry->textLen + 1;
|
|
}
|
|
|
|
void GfxMenu::addMenuItem(const char *menuItemText, uint16 controllerSlot) {
|
|
int16 arrayCount = _array.size();
|
|
|
|
// already submitted? in that case no further changes possible
|
|
if (_submitted)
|
|
return;
|
|
|
|
if (arrayCount == 0)
|
|
error("tried to add a menu item before adding an actual menu");
|
|
|
|
// go to latest menu entry
|
|
GuiMenuEntry *curMenuEntry = _array.back();
|
|
|
|
GuiMenuItemEntry *menuItemEntry = new GuiMenuItemEntry();
|
|
|
|
menuItemEntry->enabled = true;
|
|
menuItemEntry->text = menuItemText;
|
|
menuItemEntry->textLen = menuItemEntry->text.size();
|
|
menuItemEntry->controllerSlot = controllerSlot;
|
|
|
|
// 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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
menuItemEntry->row = 2 + curMenuEntry->itemCount;
|
|
menuItemEntry->column = _setupMenuItemColumn;
|
|
|
|
_itemArray.push_back(menuItemEntry);
|
|
|
|
curMenuEntry->itemCount++;
|
|
}
|
|
|
|
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--;
|
|
}
|
|
}
|
|
}
|
|
|
|
menuItemEntry->textLen = menuItemEntry->text.size();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void GfxMenu::itemEnable(uint16 controllerSlot) {
|
|
itemEnableDisable(controllerSlot, true);
|
|
}
|
|
|
|
void GfxMenu::itemDisable(uint16 controllerSlot) {
|
|
itemEnableDisable(controllerSlot, false);
|
|
}
|
|
|
|
void GfxMenu::itemEnableDisable(uint16 controllerSlot, bool enabled) {
|
|
GuiMenuItemArray::iterator listIterator;
|
|
GuiMenuItemArray::iterator listEnd = _itemArray.end();
|
|
GuiMenuItemEntry *menuItemEntry;
|
|
|
|
listIterator = _itemArray.begin();
|
|
while (listIterator != listEnd) {
|
|
menuItemEntry = *listIterator;
|
|
if (menuItemEntry->controllerSlot == controllerSlot) {
|
|
menuItemEntry->enabled = enabled;
|
|
}
|
|
|
|
listIterator++;
|
|
}
|
|
}
|
|
|
|
void GfxMenu::itemEnableAll() {
|
|
GuiMenuItemArray::iterator listIterator;
|
|
GuiMenuItemArray::iterator listEnd = _itemArray.end();
|
|
GuiMenuItemEntry *menuItemEntry;
|
|
|
|
listIterator = _itemArray.begin();
|
|
while (listIterator != listEnd) {
|
|
menuItemEntry = *listIterator;
|
|
menuItemEntry->enabled = true;
|
|
|
|
listIterator++;
|
|
}
|
|
}
|
|
|
|
// return true, in case a menu was actually created and submitted by the scripts
|
|
bool GfxMenu::isAvailable() {
|
|
return _submitted;
|
|
}
|
|
|
|
void GfxMenu::accessAllow() {
|
|
_allowed = true;
|
|
}
|
|
|
|
void GfxMenu::accessDeny() {
|
|
_allowed = false;
|
|
}
|
|
|
|
void GfxMenu::delayedExecuteViaKeyboard() {
|
|
_delayedExecuteViaKeyboard = true;
|
|
_delayedExecuteViaMouse = false;
|
|
}
|
|
void GfxMenu::delayedExecuteViaMouse() {
|
|
_delayedExecuteViaKeyboard = false;
|
|
_delayedExecuteViaMouse = true;
|
|
}
|
|
|
|
bool GfxMenu::delayedExecuteActive() {
|
|
return _delayedExecuteViaKeyboard | _delayedExecuteViaMouse;
|
|
}
|
|
|
|
void GfxMenu::execute() {
|
|
bool viaKeyboard = _delayedExecuteViaKeyboard;
|
|
bool viaMouse = _delayedExecuteViaMouse;
|
|
_delayedExecuteViaKeyboard = false;
|
|
_delayedExecuteViaMouse = false;
|
|
|
|
// got submitted? -> safety check
|
|
if (!_submitted)
|
|
return;
|
|
|
|
// access allowed at the moment?
|
|
if (!_allowed)
|
|
return;
|
|
|
|
_text->charPos_Push();
|
|
_text->charAttrib_Push();
|
|
_text->clearLine(0, _text->calculateTextBackground(15));
|
|
|
|
// Draw all menus
|
|
for (uint16 menuNr = 0; menuNr < _array.size(); menuNr++) {
|
|
drawMenuName(menuNr, false);
|
|
}
|
|
|
|
// Draw last selected menu
|
|
_drawnMenuNr = _lastSelectedMenuNr;
|
|
|
|
// Unless we are in "via mouse" mode. In that case check current mouse position
|
|
if (viaMouse) {
|
|
int16 mouseRow = _vm->_mouse.pos.y;
|
|
int16 mouseColumn = _vm->_mouse.pos.x;
|
|
_gfx->translateDisplayPosToFontScreen(mouseColumn, mouseRow);
|
|
|
|
mouseFindMenuSelection(mouseRow, mouseColumn, _drawnMenuNr, _mouseModeItemNr);
|
|
}
|
|
|
|
if (_drawnMenuNr >= 0) {
|
|
if (viaKeyboard) {
|
|
drawMenu(_drawnMenuNr, _array[_drawnMenuNr]->selectedItemNr);
|
|
}
|
|
if (viaMouse) {
|
|
drawMenu(_drawnMenuNr, _mouseModeItemNr);
|
|
}
|
|
}
|
|
|
|
if (viaKeyboard) {
|
|
_vm->cycleInnerLoopActive(CYCLE_INNERLOOP_MENU_VIA_KEYBOARD);
|
|
} else if (viaMouse) {
|
|
_vm->cycleInnerLoopActive(CYCLE_INNERLOOP_MENU_VIA_MOUSE);
|
|
}
|
|
|
|
do {
|
|
_vm->processAGIEvents();
|
|
} while (_vm->cycleInnerLoopIsActive() && !(_vm->shouldQuit() || _vm->_restartGame));
|
|
|
|
if (_drawnMenuNr >= 0) {
|
|
removeActiveMenu(_drawnMenuNr);
|
|
}
|
|
|
|
if (viaKeyboard) {
|
|
// In "via Keyboard" mode, remember last selection
|
|
_lastSelectedMenuNr = _drawnMenuNr;
|
|
}
|
|
|
|
_text->charAttrib_Pop();
|
|
_text->charPos_Pop();
|
|
|
|
// Restore status line
|
|
if (_text->statusEnabled()) {
|
|
_text->statusDraw();
|
|
} else {
|
|
if (_text->getWindowRowMin() == 0) {
|
|
// WORKAROUND: Playarea starts right at the stop, so instead of clearing that part, render it from playarea
|
|
// Required for at least Donald Duck
|
|
// This was not done by original AGI, which means the upper pixel line were cleared in this case.
|
|
_gfx->render_Block(0, 0, SCRIPT_WIDTH, FONT_VISUAL_HEIGHT);
|
|
} else {
|
|
_text->clearLine(0, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
void GfxMenu::drawMenuName(int16 menuNr, bool inverted) {
|
|
GuiMenuEntry *menuEntry = _array[menuNr];
|
|
bool disabledLook = false;
|
|
|
|
// Don't draw in case there is no text
|
|
if (!menuEntry->text.size())
|
|
return;
|
|
|
|
if (!inverted) {
|
|
_text->charAttrib_Set(0, _text->calculateTextBackground(15));
|
|
} else {
|
|
_text->charAttrib_Set(15, _text->calculateTextBackground(0));
|
|
}
|
|
|
|
_text->charPos_Set(menuEntry->row, menuEntry->column);
|
|
|
|
if (menuEntry->itemCount == 0)
|
|
disabledLook = true;
|
|
|
|
_text->displayText(menuEntry->text.c_str(), disabledLook);
|
|
}
|
|
|
|
void GfxMenu::drawItemName(int16 itemNr, bool inverted) {
|
|
GuiMenuItemEntry *itemEntry = _itemArray[itemNr];
|
|
bool disabledLook = false;
|
|
|
|
if (!inverted) {
|
|
_text->charAttrib_Set(0, _text->calculateTextBackground(15));
|
|
} else {
|
|
_text->charAttrib_Set(15, _text->calculateTextBackground(0));
|
|
}
|
|
|
|
_text->charPos_Set(itemEntry->row, itemEntry->column);
|
|
|
|
if (itemEntry->enabled == false)
|
|
disabledLook = true;
|
|
|
|
_text->displayText(itemEntry->text.c_str(), disabledLook);
|
|
}
|
|
|
|
void GfxMenu::drawMenu(int16 selectedMenuNr, int16 selectedMenuItemNr) {
|
|
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
|
|
_drawnMenuHeight = (menuEntry->itemCount + 2) * FONT_VISUAL_HEIGHT;
|
|
_drawnMenuWidth = (menuEntry->maxItemTextLen * FONT_VISUAL_WIDTH) + 8;
|
|
_drawnMenuY = (1 - _text->getWindowRowMin()) * FONT_VISUAL_HEIGHT;
|
|
//(menuEntry->itemCount + 3 - _text->getWindowRowMin()) * FONT_VISUAL_HEIGHT - 1;
|
|
_drawnMenuX = (itemEntry->column - 1) * FONT_VISUAL_WIDTH;
|
|
|
|
_gfx->drawBox(_drawnMenuX, _drawnMenuY, _drawnMenuWidth, _drawnMenuHeight, 15, 0);
|
|
|
|
while (itemCount) {
|
|
if (itemNr == selectedMenuItemNr) {
|
|
drawItemName(itemNr, true);
|
|
} else {
|
|
drawItemName(itemNr, false);
|
|
}
|
|
itemNr++;
|
|
itemCount--;
|
|
}
|
|
}
|
|
|
|
void GfxMenu::removeActiveMenu(int16 selectedMenuNr) {
|
|
// draw menu name normally again
|
|
drawMenuName(selectedMenuNr, false);
|
|
|
|
// overwrite actual menu items by rendering play screen
|
|
_gfx->render_Block(_drawnMenuX, _drawnMenuY, _drawnMenuWidth, _drawnMenuHeight);
|
|
}
|
|
|
|
void GfxMenu::keyPress(uint16 newKey) {
|
|
GuiMenuEntry *menuEntry = _array[_drawnMenuNr];
|
|
GuiMenuItemEntry *itemEntry = _itemArray[menuEntry->selectedItemNr];
|
|
int16 newMenuNr = _drawnMenuNr;
|
|
int16 newItemNr = menuEntry->selectedItemNr;
|
|
|
|
switch (newKey) {
|
|
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;
|
|
}
|
|
|
|
if (newMenuNr != _drawnMenuNr) {
|
|
// selected menu was changed
|
|
int16 lastMenuNr = _array.size() - 1;
|
|
|
|
if (newMenuNr < 0) {
|
|
newMenuNr = lastMenuNr;
|
|
} else if (newMenuNr > lastMenuNr) {
|
|
newMenuNr = 0;
|
|
}
|
|
|
|
if (newMenuNr != _drawnMenuNr) {
|
|
removeActiveMenu(_drawnMenuNr);
|
|
_drawnMenuNr = newMenuNr;
|
|
drawMenu(_drawnMenuNr, _array[_drawnMenuNr]->selectedItemNr);
|
|
}
|
|
}
|
|
|
|
if (newItemNr != menuEntry->selectedItemNr) {
|
|
// selected item was changed
|
|
int16 lastItemNr = menuEntry->firstItemNr + menuEntry->itemCount - 1;
|
|
|
|
if (newItemNr < menuEntry->firstItemNr) {
|
|
newItemNr = lastItemNr;
|
|
} else if (newItemNr > lastItemNr) {
|
|
newItemNr = menuEntry->firstItemNr;
|
|
}
|
|
|
|
if (newItemNr != menuEntry->selectedItemNr) {
|
|
// still changed after clip -> draw changes
|
|
drawItemName(menuEntry->selectedItemNr, false);
|
|
drawItemName(newItemNr, true);
|
|
menuEntry->selectedItemNr = newItemNr;
|
|
}
|
|
}
|
|
}
|
|
|
|
// This gets called:
|
|
// During "via keyboard" mode in case user actively clicks on something
|
|
// During "via mouse" mode all the time, so that current mouse cursor position modifies active selection
|
|
// In "via mouse" mode, we check if user let go of the left mouse button and then select the item that way
|
|
void GfxMenu::mouseEvent(uint16 newKey) {
|
|
// Find out, where current mouse cursor actually is
|
|
int16 mouseRow = _vm->_mouse.pos.y;
|
|
int16 mouseColumn = _vm->_mouse.pos.x;
|
|
|
|
_gfx->translateDisplayPosToFontScreen(mouseColumn, mouseRow);
|
|
|
|
int16 activeMenuNr, activeItemNr;
|
|
mouseFindMenuSelection(mouseRow, mouseColumn, activeMenuNr, activeItemNr);
|
|
|
|
switch (newKey) {
|
|
case AGI_MOUSE_BUTTON_LEFT:
|
|
// User clicked somewhere, in this case check if user clicked on status bar or on one of the currently shown menu items
|
|
// Happens in "via keyboard" mode only
|
|
// We do not close menu in case user clicked on something invalid
|
|
|
|
if (activeItemNr >= 0) {
|
|
GuiMenuItemEntry *itemEntry = _itemArray[activeItemNr];
|
|
if (!itemEntry->enabled)
|
|
return;
|
|
|
|
// Trigger controller
|
|
_vm->_game.controllerOccured[itemEntry->controllerSlot] = true;
|
|
|
|
_vm->cycleInnerLoopInactive(); // exit execute-loop
|
|
return;
|
|
}
|
|
if (activeMenuNr >= 0) {
|
|
// User clicked on a menu, check if that menu is already active
|
|
if (activeMenuNr != _drawnMenuNr) {
|
|
removeActiveMenu(_drawnMenuNr);
|
|
_drawnMenuNr = activeMenuNr;
|
|
drawMenu(_drawnMenuNr, _array[_drawnMenuNr]->selectedItemNr);
|
|
}
|
|
}
|
|
return; // exit all the time, we do not want to change the user selection while in "via keyboard" mode
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// If mouse is not selecting any menu, just use the last menu instead
|
|
if (activeMenuNr < 0) {
|
|
activeMenuNr = _drawnMenuNr;
|
|
}
|
|
|
|
if (activeMenuNr != _drawnMenuNr) {
|
|
if (_drawnMenuNr >= 0) {
|
|
removeActiveMenu(_drawnMenuNr);
|
|
}
|
|
|
|
_drawnMenuNr = activeMenuNr;
|
|
|
|
if (_drawnMenuNr >= 0) {
|
|
drawMenu(_drawnMenuNr, activeItemNr);
|
|
}
|
|
_mouseModeItemNr = activeItemNr;
|
|
}
|
|
|
|
if (activeItemNr != _mouseModeItemNr) {
|
|
if (_mouseModeItemNr >= 0) {
|
|
drawItemName(_mouseModeItemNr, false);
|
|
}
|
|
if (activeItemNr >= 0) {
|
|
drawItemName(activeItemNr, true);
|
|
}
|
|
_mouseModeItemNr = activeItemNr;
|
|
}
|
|
|
|
if (_vm->_mouse.button == kAgiMouseButtonUp) {
|
|
// User has stopped pressing the mouse button, if any item number is selected -> execute it
|
|
if (activeItemNr >= 0) {
|
|
GuiMenuItemEntry *itemEntry = _itemArray[activeItemNr];
|
|
if (itemEntry->enabled) {
|
|
// Trigger controller
|
|
_vm->_game.controllerOccured[itemEntry->controllerSlot] = true;
|
|
}
|
|
}
|
|
|
|
_vm->cycleInnerLoopInactive(); // exit execute-loop
|
|
return;
|
|
}
|
|
}
|
|
|
|
void GfxMenu::mouseFindMenuSelection(int16 mouseRow, int16 mouseColumn, int16 &activeMenuNr, int16 &activeMenuItemNr) {
|
|
GuiMenuEntry *menuEntry = nullptr;
|
|
int16 menuCount = _array.size();
|
|
|
|
for (int16 menuNr = 0; menuNr < menuCount; menuNr++) {
|
|
menuEntry = _array[menuNr];
|
|
|
|
if (mouseRow == menuEntry->row) {
|
|
// line match
|
|
if ((mouseColumn >= menuEntry->column) && (mouseColumn < (menuEntry->column + menuEntry->textLen))) {
|
|
// full match
|
|
activeMenuNr = menuNr;
|
|
activeMenuItemNr = -1; // no item selected
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Now also check current menu
|
|
if (_drawnMenuNr >= 0) {
|
|
// A menu is currently shown
|
|
menuEntry = _array[_drawnMenuNr];
|
|
|
|
int16 itemNr = menuEntry->firstItemNr;
|
|
int16 itemCount = menuEntry->itemCount;
|
|
|
|
while (itemCount) {
|
|
GuiMenuItemEntry *itemEntry = _itemArray[itemNr];
|
|
|
|
if (mouseRow == itemEntry->row) {
|
|
// line match
|
|
if ((mouseColumn >= itemEntry->column) && (mouseColumn < (itemEntry->column + itemEntry->textLen))) {
|
|
// full match
|
|
if (itemEntry->enabled) {
|
|
// Only see it, when it's currently enabled
|
|
activeMenuNr = _drawnMenuNr;
|
|
activeMenuItemNr = itemNr;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
itemNr++;
|
|
itemCount--;
|
|
}
|
|
}
|
|
activeMenuNr = -1;
|
|
activeMenuItemNr = -1;
|
|
return;
|
|
}
|
|
|
|
} // End of namespace Agi
|