From 8be433b96066bbdee815ef719815a2904ef2621b Mon Sep 17 00:00:00 2001 From: Strangerke Date: Wed, 18 Sep 2013 07:47:52 +0200 Subject: AVALANCHE: Rename DropDown into Menu, add some access functions --- engines/avalanche/animation.cpp | 4 +- engines/avalanche/avalanche.cpp | 6 +- engines/avalanche/avalanche.h | 4 +- engines/avalanche/avalot.cpp | 8 +- engines/avalanche/celer.cpp | 2 +- engines/avalanche/dropdown.cpp | 789 --------------------------------------- engines/avalanche/dropdown.h | 167 --------- engines/avalanche/gyro.cpp | 2 +- engines/avalanche/gyro.h | 1 - engines/avalanche/lucerna.cpp | 6 +- engines/avalanche/menu.cpp | 799 ++++++++++++++++++++++++++++++++++++++++ engines/avalanche/menu.h | 168 +++++++++ engines/avalanche/module.mk | 2 +- engines/avalanche/parser.cpp | 4 +- engines/avalanche/timer.cpp | 2 +- 15 files changed, 986 insertions(+), 978 deletions(-) delete mode 100644 engines/avalanche/dropdown.cpp delete mode 100644 engines/avalanche/dropdown.h create mode 100644 engines/avalanche/menu.cpp create mode 100644 engines/avalanche/menu.h (limited to 'engines/avalanche') diff --git a/engines/avalanche/animation.cpp b/engines/avalanche/animation.cpp index edcc53cdcf..e3634e0677 100644 --- a/engines/avalanche/animation.cpp +++ b/engines/avalanche/animation.cpp @@ -1226,7 +1226,7 @@ void Animation::drawSprites() { * @remarks Originally called 'trippancy_link' */ void Animation::animLink() { - if (_vm->_gyro->_dropdownActive | _vm->_gyro->_onToolbar | _vm->_gyro->_seeScroll) + if (_vm->_menu->isActive() | _vm->_gyro->_onToolbar | _vm->_gyro->_seeScroll) return; for (int16 i = 0; i < kSpriteNumbMax; i++) { if (_sprites[i]._quick && _sprites[i]._visible) @@ -1377,7 +1377,7 @@ void Animation::handleMoveKey(const Common::Event &event) { if (!_vm->_gyro->_userMovesAvvy) return; - if (_vm->_dropdown->_activeMenuItem._activeNow) + if (_vm->_menu->_activeMenuItem._activeNow) _vm->_parser->tryDropdown(); else { switch (event.kbd.keycode) { diff --git a/engines/avalanche/avalanche.cpp b/engines/avalanche/avalanche.cpp index 33c72c848f..980fcab96a 100644 --- a/engines/avalanche/avalanche.cpp +++ b/engines/avalanche/avalanche.cpp @@ -70,7 +70,7 @@ AvalancheEngine::~AvalancheEngine() { delete _timer; delete _animation; delete _acci; - delete _dropdown; + delete _menu; delete _closing; delete _gyro; } @@ -89,7 +89,7 @@ Common::ErrorCode AvalancheEngine::initialize() { _timer = new Timer(this); _animation = new Animation(this); _acci = new Acci(this); - _dropdown = new Dropdown(this); + _menu = new Menu(this); _closing = new Closing(this); _graphics->init(); @@ -440,7 +440,7 @@ bool AvalancheEngine::loadGame(const int16 slot) { _celer->forgetBackgroundSprites(); _lucerna->minorRedraw(); - _dropdown->setupMenu(); + _menu->setup(); _gyro->_whereIs[Gyro::kPeopleAvalot - 150] = _gyro->_room; _gyro->_alive = true; _lucerna->refreshObjectList(); diff --git a/engines/avalanche/avalanche.h b/engines/avalanche/avalanche.h index 8da159165d..4a01c729d2 100644 --- a/engines/avalanche/avalanche.h +++ b/engines/avalanche/avalanche.h @@ -43,7 +43,7 @@ #include "avalanche/timer.h" #include "avalanche/animation.h" #include "avalanche/acci.h" -#include "avalanche/dropdown.h" +#include "avalanche/menu.h" #include "avalanche/closing.h" #include "common/serializer.h" @@ -78,7 +78,7 @@ public: Timer *_timer; Animation *_animation; Acci *_acci; - Dropdown *_dropdown; + Menu *_menu; Closing *_closing; OSystem *_system; diff --git a/engines/avalanche/avalot.cpp b/engines/avalanche/avalot.cpp index 2d93ed8954..687572c2af 100644 --- a/engines/avalanche/avalot.cpp +++ b/engines/avalanche/avalot.cpp @@ -28,7 +28,6 @@ /* AVALOT The kernel of the program. */ #include "avalanche/avalanche.h" - #include "avalanche/graphics.h" #include "avalanche/avalot.h" #include "avalanche/gyro.h" @@ -36,7 +35,7 @@ #include "avalanche/gyro.h" #include "avalanche/lucerna.h" #include "avalanche/scrolls.h" -#include "avalanche/dropdown.h" +#include "avalanche/menu.h" #include "avalanche/pingo.h" #include "avalanche/timer.h" #include "avalanche/celer.h" @@ -136,7 +135,6 @@ void Avalot::setup() { _vm->_gyro->setMousePointerWait(); _vm->_gyro->_dropsOk = true; _vm->_gyro->_mouseText = ""; - _vm->_gyro->_dropdownActive = false; _vm->_lucerna->loadDigits(); _vm->_gyro->_cheat = false; _vm->_gyro->_cp = 0; @@ -161,7 +159,7 @@ void Avalot::setup() { _vm->_animation->_sprites[0]._speedX = _vm->_gyro->kWalk; _vm->_animation->updateSpeed(); - + _vm->_menu->init(); int16 loadSlot = Common::ConfigManager::instance().getInt("save_slot"); if (loadSlot >= 0) { @@ -190,7 +188,7 @@ void Avalot::run(Common::String arg) { _vm->updateEvents(); // The event handler. _vm->_lucerna->_clock.update(); - _vm->_dropdown->updateMenu(); + _vm->_menu->update(); _vm->_celer->updateBackgroundSprites(); _vm->_animation->animLink(); _vm->_lucerna->checkClick(); diff --git a/engines/avalanche/celer.cpp b/engines/avalanche/celer.cpp index 6edb4d2bb4..61a45c7e26 100644 --- a/engines/avalanche/celer.cpp +++ b/engines/avalanche/celer.cpp @@ -54,7 +54,7 @@ Celer::~Celer() { * @remarks Originally called 'pics_link' */ void Celer::updateBackgroundSprites() { - if (_vm->_gyro->_dropdownActive) + if (_vm->_menu->isActive()) return; // No animation when the menus are up. switch (_vm->_gyro->_room) { diff --git a/engines/avalanche/dropdown.cpp b/engines/avalanche/dropdown.cpp deleted file mode 100644 index 8ae3af0db1..0000000000 --- a/engines/avalanche/dropdown.cpp +++ /dev/null @@ -1,789 +0,0 @@ -/* 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. - * - */ - -/* - * This code is based on the original source code of Lord Avalot d'Argent version 1.3. - * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman. - */ - - /* DROPDOWN A customised version of Oopmenu (qv). */ - -#include "avalanche/avalanche.h" - -#include "avalanche/dropdown.h" -#include "avalanche/lucerna.h" -#include "avalanche/gyro.h" -#include "avalanche/acci.h" -#include "avalanche/animation.h" - -#include "common/textconsole.h" - -namespace Avalanche { - -void HeadType::init(char trig, char altTrig, Common::String title, byte pos, DropdownFunc setupFunc, DropdownFunc chooseFunc, Dropdown *dr) { - _trigger = trig; - _altTrigger = altTrig; - _title = title; - _position = pos; - _xpos = _position * _dr->kSpacing + _dr->kIndent; - _xright = (_position + 1) * _dr->kSpacing + _dr->kIndent; - _setupFunc = setupFunc; - _chooseFunc = chooseFunc; - - _dr = dr; -} - -void HeadType::draw() { - CursorMan.showMouse(false); - _dr->drawMenuText(_xpos, 1, _trigger, _title, true, false); - CursorMan.showMouse(true); -} - -void HeadType::highlight() { - CursorMan.showMouse(false); - - //nosound(); - //setactivepage(cp); - warning("STUB: Dropdown::headytpe::highlight()"); - - _dr->drawMenuText(_xpos, 1, _trigger, _title, true, true); - - _dr->_activeMenuItem._left = _xpos; - _dr->_activeMenuItem._activeNow = true; - _dr->_vm->_gyro->_dropdownActive = true; - _dr->_activeMenuItem._activeNum = _position; - - _dr->_vm->_gyro->_currentMouse = 177; // Force redraw of cursor. -} - -bool HeadType::parseAltTrigger(char key) { - if (key != _altTrigger) - return true; - return false; -} - -void MenuItem::init(Dropdown *dr) { - _dr = dr; - _activeNow = false; - _dr->_vm->_gyro->_dropdownActive = false; - _activeNum = 1; -} - -void MenuItem::reset() { - _optionNum = 0; - _width = 0; - _firstlix = false; - _oldY = 0; - _highlightNum = 0; -} - -void MenuItem::setupOption(Common::String title, char trigger, Common::String shortcut, bool valid) { - uint16 width = (title + shortcut).size() + 3; - if (_width < width) - _width = width; - - _options[_optionNum]._title = title; - _options[_optionNum]._trigger = trigger; - _options[_optionNum]._shortcut = shortcut; - _options[_optionNum]._valid = valid; - _optionNum++; -} - -void MenuItem::displayOption(byte y, bool highlit) { - byte backgroundColor; - if (highlit) - backgroundColor = 0; - else - backgroundColor = 7; - _dr->_vm->_graphics->_surface.fillRect(Common::Rect((_flx1 + 1) * 8, 3 + (y + 1) * 10, (_flx2 + 1) * 8, 13 + (y + 1) * 10), backgroundColor); - - Common::String text = _options[y]._title; - while (text.size() + _options[y]._shortcut.size() < _width) - text += ' '; // Pad _options[y] with spaces. - text += _options[y]._shortcut; - - _dr->drawMenuText(_left, 4 + (y + 1) * 10, _options[y]._trigger, text, _options[y]._valid, highlit); -} - -void MenuItem::display() { - CursorMan.showMouse(false); - //setactivepage(cp); - //setvisualpage(cp); - //setfillstyle(1, menu_b); - //setcolor(menu_border); - _firstlix = true; - _flx1 = _left - 2; - _flx2 = _left + _width; - _fly = 15 + _optionNum * 10; - _activeNow = true; - _dr->_vm->_gyro->_dropdownActive = true; - - _dr->_vm->_graphics->_surface.fillRect(Common::Rect((_flx1 + 1) * 8, 12, (_flx2 + 1) * 8, _fly), _dr->kMenuBackgroundColor); - _dr->_vm->_graphics->_surface.frameRect(Common::Rect((_flx1 + 1) * 8 - 1, 11, (_flx2 + 1) * 8 + 1, _fly + 1), _dr->kMenuBorderColor); - - displayOption(0, true); - for (int y = 1; y < _optionNum; y++) - displayOption(y, false); - - _dr->_vm->_gyro->_defaultLed = 1; - _dr->_vm->_gyro->_currentMouse = 177; - //mousepage(cp); - CursorMan.showMouse(true); // 4 = fletch -} - -void MenuItem::wipe() { - //setactivepage(cp); - CursorMan.showMouse(false); - - _dr->drawMenuText(_dr->_menuBar._menuItems[_dr->_activeMenuItem._activeNum]._xpos, 1, _dr->_menuBar._menuItems[_dr->_activeMenuItem._activeNum]._trigger, _dr->_menuBar._menuItems[_dr->_activeMenuItem._activeNum]._title, true, false); - - _activeNow = false; - _dr->_vm->_gyro->_dropdownActive = false; - _firstlix = false; - _dr->_vm->_gyro->_defaultLed = 2; - - CursorMan.showMouse(true); -} - -void MenuItem::moveHighlight(int8 inc) { - if (inc != 0) { - int8 highlightNum = _highlightNum + inc; - if ((highlightNum < 0) || (highlightNum >= _optionNum)) - return; - _highlightNum = highlightNum; - } - //setactivepage(cp); - CursorMan.showMouse(false); - displayOption(_oldY, false); - displayOption(_highlightNum, true); - //setactivepage(1 - cp); - _oldY = _highlightNum; - CursorMan.showMouse(true); -} - -void MenuItem::lightUp(Common::Point cursorPos) { - if ((cursorPos.x < _flx1 * 8) || (cursorPos.x > _flx2 * 8) || (cursorPos.y <= 25) || (cursorPos.y > ((_fly - 3) * 2 + 1))) - return; - _highlightNum = (cursorPos.y - 26) / 20; - if (_highlightNum == _oldY) - return; - moveHighlight(0); -} - -void MenuItem::select(byte which) { - if (!_options[which]._valid) - return; - - _choiceNum = which; - wipe(); - - if (_choiceNum == _optionNum) - _choiceNum--; // Off the bottom. - if (_choiceNum > _optionNum) - _choiceNum = 0; // Off the top, I suppose. - - (_dr->*_dr->_menuBar._menuItems[_activeNum]._chooseFunc)(); -} - -void MenuItem::parseKey(char c) { - c = toupper(c); - bool found = false; - for (int i = 0; i < _optionNum; i++) { - if ((toupper(_options[i]._trigger) == c) && _options[i]._valid) { - select(i); - found = true; - } - } - if (!found) - _dr->_vm->_gyro->blip(); -} - -void MenuBar::init(Dropdown *dr) { - _dr = dr; - _menuNum = 0; -} - -void MenuBar::createMenuItem(char trig, Common::String title, char altTrig, DropdownFunc setupFunc, DropdownFunc chooseFunc) { - _menuItems[_menuNum].init(trig, altTrig, title, _menuNum, setupFunc, chooseFunc, _dr); - _menuNum++; -} - -void MenuBar::draw() { - //setactivepage(3); - - _dr->_vm->_graphics->_surface.fillRect(Common::Rect(0, 0, 640, 10), _dr->kMenuBackgroundColor); - - byte savecp = _dr->_vm->_gyro->_cp; - _dr->_vm->_gyro->_cp = 3; - - for (int i = 0; i < _menuNum; i++) - _menuItems[i].draw(); - - _dr->_vm->_gyro->_cp = savecp; -} - -void MenuBar::parseAltTrigger(char c) { - byte i = 0; - while ((i < _menuNum) && (_menuItems[i].parseAltTrigger(c))) - i++; - if (i == _menuNum) - return; - setupMenuItem(i); -} - -void MenuBar::setupMenuItem(byte which) { - if (_dr->_activeMenuItem._activeNow) { - _dr->_activeMenuItem.wipe(); // Get rid of menu. - if (_dr->_activeMenuItem._activeNum == _menuItems[which]._position) - return; // Clicked on own highlight. - } - _menuItems[which].highlight(); - (_dr->*_menuItems[which]._setupFunc)(); -} - -void MenuBar::chooseMenuItem(int16 x) { - for (int i = 0; i < _menuNum; i++) { - if ((x > _menuItems[i]._xpos * 8) && (x < _menuItems[i]._xright * 8)) { - setupMenuItem(i); - break; - } - } -} - -Dropdown::Dropdown(AvalancheEngine *vm) { - _vm = vm; - _activeMenuItem.init(this); - _menuBar.init(this); -} - -void Dropdown::findWhatYouCanDoWithIt() { - switch (_vm->_gyro->_thinks) { - case Gyro::kObjectWine: - case Gyro::kObjectPotion: - case Gyro::kObjectInk: - _vm->_gyro->_verbStr = Common::String(Acci::kVerbCodeExam) + Acci::kVerbCodeDrink; - break; - case Gyro::kObjectBell: - _vm->_gyro->_verbStr = Common::String(Acci::kVerbCodeExam) + Acci::kVerbCodeRing; - break; - case Gyro::kObjectChastity: - _vm->_gyro->_verbStr = Common::String(Acci::kVerbCodeExam) + Acci::kVerbCodeWear; - break; - case Gyro::kObjectLute: - _vm->_gyro->_verbStr = Common::String(Acci::kVerbCodeExam) + Acci::kVerbCodePlay; - break; - case Gyro::kObjectMushroom: - case Gyro::kObjectOnion: - _vm->_gyro->_verbStr = Common::String(Acci::kVerbCodeExam) + Acci::kVerbCodeEat; - break; - case Gyro::kObjectClothes: - _vm->_gyro->_verbStr = Common::String(Acci::kVerbCodeExam) + Acci::kVerbCodeWear; - break; - default: - _vm->_gyro->_verbStr = Acci::kVerbCodeExam; // Anything else. - } -} - -void Dropdown::drawMenuText(int16 x, int16 y, char trigger, Common::String text, bool valid, bool highlighted) { - byte fontColor; - byte backgroundColor; - if (highlighted) { - fontColor = kColorWhite; - backgroundColor = kColorBlack; - } else { - fontColor = kColorBlack; - backgroundColor = kColorLightgray; - } - - byte ander; - if (valid) - ander = 255; - else - ander = 170; - - FontType font; - for (uint i = 0; i < text.size(); i++) { - for (int j = 0; j < 8; j++) { - byte idx = text[i]; - font[idx][j] = _vm->_gyro->_font[idx][j] & ander; // Set the font. - // And set the background of the text to the desired color. - for (int k = 0; k < 8; k++) - *(byte *)_vm->_graphics->_surface.getBasePtr(x * 8 + i * 8 + k, y + j) = backgroundColor; - } - } - - _vm->_graphics->drawText(_vm->_graphics->_surface, text, font, 8, x * 8, y, fontColor); - - // Underline the selected character. - if ((trigger == 0) || !text.contains(trigger) ) - return; - else { - byte i; - for (i = 0; text[i] != trigger; i++) - ; // Search for the character in the string. - - byte pixel = ander; - for (int bit = 0; bit < 8; bit++) { - byte pixelBit = (pixel >> bit) & 1; - if (pixelBit) - *(byte *)_vm->_graphics->_surface.getBasePtr(x * 8 + i * 8 + 7 - bit, y + 8) = fontColor; - } - } - - _vm->_graphics->refreshScreen(); -} - -void Dropdown::bleep() { - warning("STUB: Dropdown::bleep()"); -} - -void Dropdown::parseKey(char r, char re) { - //switch (r) { - //case 0: - //case 224: { - // switch (re) { - // case 'K': - // if (_activeMenuItem._activeNum > 1) { - // _activeMenuItem.wipe(); - // _menuBar.setupMenuItem(_activeMenuItem._activeNum - 1); - // } else { - // // Get menu on the left-hand side. - // _activeMenuItem.wipe(); - // _menuBar.chooseMenuItem((_menuBar._menuNum - 1) * kSpacing + kIndent); - // } - // break; - // case 'M': - // if (_activeMenuItem._activeNum < _menuBar._menuNum) { - // _activeMenuItem.wipe(); - // _menuBar.setupMenuItem(_activeMenuItem._activeNum + 1); - // } else { - // // Get menu on the far right-hand side. - // _activeMenuItem.wipe(); - // _menuBar.chooseMenuItem(kIndent); - // } - // break; - // case 'H': - // _activeMenuItem.moveHighlight(-1); - // break; - // case 'P': - // _activeMenuItem.moveHighlight(1); - // break; - // default: - // _menuBar.parseAltTrigger(re); - // } - //} - //break; - //case 13: - // _activeMenuItem.select(_activeMenuItem._highlightNum); - // break; - //default: - // if (_activeMenuItem._activeNow) - // _activeMenuItem.parseKey(r); - //} - warning("STUB: Dropdown::parseKey()"); // To be implemented properly later! Don't remove the comment above! -} - -Common::String Dropdown::selectGender(byte x) { - if (x < 175) - return "im"; - else - return "er"; -} - -void Dropdown::setupMenuGame() { - _activeMenuItem.reset(); - _activeMenuItem.setupOption("Help...", 'H', "f1", true); - _activeMenuItem.setupOption("Boss Key", 'B', "alt-B", true); - _activeMenuItem.setupOption("Untrash screen", 'U', "ctrl-f7", true); - _activeMenuItem.setupOption("Score and rank", 'S', "f9", true); - _activeMenuItem.setupOption("About Avvy...", 'A', "shift-f10", true); - _activeMenuItem.display(); -} - -void Dropdown::setupMenuFile() { - _activeMenuItem.reset(); - _activeMenuItem.setupOption("New game", 'N', "f4", true); - _activeMenuItem.setupOption("Load...", 'L', "^f3", true); - _activeMenuItem.setupOption("Save", 'S', "^f2", _vm->_gyro->_alive); - _activeMenuItem.setupOption("Save As...", 'v', "", _vm->_gyro->_alive); - _activeMenuItem.setupOption("DOS Shell", 'D', _vm->_gyro->_atKey + '1', true); - _activeMenuItem.setupOption("Quit", 'Q', "alt-X", true); - _activeMenuItem.display(); -} - -void Dropdown::setupMenuAction() { - _activeMenuItem.reset(); - - Common::String f5Does = _vm->_gyro->f5Does(); - for (int i = 0; i < 2; i++) - if (!f5Does.empty()) - f5Does.deleteChar(0); - if (f5Does.empty()) - _activeMenuItem.setupOption("Do something", 'D', "f5", false); - else - _activeMenuItem.setupOption(f5Does, f5Does[0], "f5", true); - _activeMenuItem.setupOption("Pause game", 'P', "f6", true); - if (_vm->_gyro->_room == kRoomMap) - _activeMenuItem.setupOption("Journey thither", 'J', "f7", _vm->_animation->nearDoor()); - else - _activeMenuItem.setupOption("Open the door", 'O', "f7", _vm->_animation->nearDoor()); - _activeMenuItem.setupOption("Look around", 'L', "f8", true); - _activeMenuItem.setupOption("Inventory", 'I', "Tab", true); - if (_vm->_animation->_sprites[0]._speedX == _vm->_gyro->kWalk) - _activeMenuItem.setupOption("Run fast", 'R', "^R", true); - else - _activeMenuItem.setupOption("Walk slowly", 'W', "^W", true); - - _activeMenuItem.display(); -} - -void Dropdown::setupMenuPeople() { - if (!people.empty()) - people.clear(); - - _activeMenuItem.reset(); - - for (int i = 150; i <= 178; i++) { - if (_vm->_gyro->_whereIs[i - 150] == _vm->_gyro->_room) { - _activeMenuItem.setupOption(_vm->_gyro->getName(i), _vm->_gyro->getNameChar(i), "", true); - people += i; - } - } - - _activeMenuItem.display(); -} - -void Dropdown::setupMenuObjects() { - _activeMenuItem.reset(); - for (int i = 0; i < kObjectNum; i++) { - if (_vm->_gyro->_objects[i]) - _activeMenuItem.setupOption(_vm->_gyro->getThing(i + 1), _vm->_gyro->getThingChar(i + 1), "", true); - } - _activeMenuItem.display(); -} - -void Dropdown::setupMenuWith() { - _activeMenuItem.reset(); - - if (_vm->_gyro->_thinkThing) { - findWhatYouCanDoWithIt(); - - for (uint i = 0; i < _vm->_gyro->_verbStr.size(); i++) { - char vbchar; - Common::String verb; - - _vm->_acci->verbOpt(_vm->_gyro->_verbStr[i], verb, vbchar); - _activeMenuItem.setupOption(verb, vbchar, "", true); - } - - // We disable the "give" option if: (a), you haven't selected anybody, (b), the _person you've selected isn't in the room, - // or (c), the _person you've selected is YOU! - - if ((_vm->_gyro->_lastPerson == Gyro::kPeopleAvalot) || (_vm->_gyro->_lastPerson == _vm->_acci->kNothing) - || (_vm->_gyro->_whereIs[_vm->_gyro->_lastPerson - 150] != _vm->_gyro->_room)) - _activeMenuItem.setupOption("Give to...", 'G', "", false); // Not here. - else { - _activeMenuItem.setupOption(Common::String("Give to ") + _vm->_gyro->getName(_vm->_gyro->_lastPerson), 'G', "", true); - _vm->_gyro->_verbStr = _vm->_gyro->_verbStr + Acci::kVerbCodeGive; - } - } else { - _activeMenuItem.setupOption("Examine", 'x', "", true); - _activeMenuItem.setupOption(Common::String("Talk to h") + selectGender(_vm->_gyro->_thinks), 'T', "", true); - _vm->_gyro->_verbStr = Common::String(Acci::kVerbCodeExam) + Acci::kVerbCodeTalk; - switch (_vm->_gyro->_thinks) { - case Gyro::kPeopleGeida: - case Gyro::kPeopleArkata: - _activeMenuItem.setupOption("Kiss her", 'K', "", true); - _vm->_gyro->_verbStr = _vm->_gyro->_verbStr + Acci::kVerbCodeKiss; - break; - case Gyro::kPeopleDogfood: - _activeMenuItem.setupOption("Play his game", 'P', "", !_vm->_gyro->_wonNim); // True if you HAVEN'T won. - _vm->_gyro->_verbStr = _vm->_gyro->_verbStr + Acci::kVerbCodePlay; - break; - case Gyro::kPeopleMalagauche: { - bool isSober = !_vm->_gyro->_teetotal; - _activeMenuItem.setupOption("Buy some wine", 'w', "", !_vm->_gyro->_objects[Gyro::kObjectWine - 1]); - _activeMenuItem.setupOption("Buy some beer", 'b', "", isSober); - _activeMenuItem.setupOption("Buy some whisky", 'h', "", isSober); - _activeMenuItem.setupOption("Buy some cider", 'c', "", isSober); - _activeMenuItem.setupOption("Buy some mead", 'm', "", isSober); - _vm->_gyro->_verbStr = _vm->_gyro->_verbStr + 101 + 100 + 102 + 103 + 104; - } - break; - case Gyro::kPeopleTrader: - _activeMenuItem.setupOption("Buy an onion", 'o', "", !_vm->_gyro->_objects[Gyro::kObjectOnion - 1]); - _vm->_gyro->_verbStr = _vm->_gyro->_verbStr + 105; - break; - } - } - _activeMenuItem.display(); -} - -void Dropdown::runMenuGame() { - // Help, boss, untrash screen. - switch (_activeMenuItem._choiceNum) { - case 0: - _vm->_lucerna->callVerb(Acci::kVerbCodeHelp); - break; - case 1: - _vm->_lucerna->callVerb(Acci::kVerbCodeBoss); - break; - case 2: - _vm->_lucerna->majorRedraw(); - break; - case 3: - _vm->_lucerna->callVerb(Acci::kVerbCodeScore); - break; - case 4: - _vm->_lucerna->callVerb(Acci::kVerbCodeInfo); - break; - } -} - -void Dropdown::runMenuFile() { - // New game, load, save, save as, DOS shell, about, quit. - switch (_activeMenuItem._choiceNum) { - case 0: - _vm->_lucerna->callVerb(Acci::kVerbCodeRestart); - break; - case 1: - if (!_vm->_acci->_realWords[1].empty()) - _vm->_acci->_realWords[1].clear(); - _vm->_lucerna->callVerb(Acci::kVerbCodeLoad); - break; - case 2: - if (!_vm->_acci->_realWords[1].empty()) - _vm->_acci->_realWords[1].clear(); - _vm->_lucerna->callVerb(Acci::kVerbCodeSave); - break; - case 3: - //_vm->_basher->filename_edit(); - warning("STUB: Dropdown::runMenuFile()"); - break; - case 4: - //_vm->_enid->backToBootstrap(2); TODO: Replace it with proper ScummVM-friendly function(s)! Do not remove until then! - break; - case 5: - _vm->_lucerna->callVerb(Acci::kVerbCodeQuit); - break; - } -} - -void Dropdown::runMenuAction() { - Common::String f5Does; - // Get up, pause game, open door, look, inventory, walk/run. - switch (_activeMenuItem._choiceNum) { - case 0: - _vm->_acci->_person = _vm->_acci->kPardon; - _vm->_acci->_thing = _vm->_acci->kPardon; - f5Does = _vm->_gyro->f5Does(); - _vm->_lucerna->callVerb(f5Does[0]); - break; - case 1: - _vm->_acci->_thing = _vm->_acci->kPardon; - _vm->_lucerna->callVerb(Acci::kVerbCodePause); - break; - case 2: - _vm->_lucerna->callVerb(Acci::kVerbCodeOpen); - break; - case 3: - _vm->_acci->_thing = _vm->_acci->kPardon; - _vm->_lucerna->callVerb(Acci::kVerbCodeLook); - break; - case 4: - _vm->_lucerna->callVerb(Acci::kVerbCodeInv); - break; - case 5: { - AnimationType *avvy = &_vm->_animation->_sprites[0]; - if (avvy->_speedX == _vm->_gyro->kWalk) - avvy->_speedX = _vm->_gyro->kRun; - else - avvy->_speedX = _vm->_gyro->kWalk; - _vm->_animation->updateSpeed(); - } - break; - } -} - -void Dropdown::runMenuObjects() { - _vm->_lucerna->thinkAbout(_vm->_gyro->_objectList[_activeMenuItem._choiceNum], Gyro::kThing); -} - -void Dropdown::runMenuPeople() { - _vm->_lucerna->thinkAbout(people[_activeMenuItem._choiceNum], Gyro::kPerson); - _vm->_gyro->_lastPerson = people[_activeMenuItem._choiceNum]; -} - -void Dropdown::runMenuWith() { - _vm->_acci->_thing = _vm->_gyro->_thinks; - - if (_vm->_gyro->_thinkThing) { - _vm->_acci->_thing += 49; - - if (_vm->_gyro->_verbStr[_activeMenuItem._choiceNum] == Acci::kVerbCodeGive) - _vm->_acci->_person = _vm->_gyro->_lastPerson; - else - _vm->_acci->_person = Acci::kPardon; - } else { - switch (_vm->_gyro->_verbStr[_activeMenuItem._choiceNum]) { - case 100: // Beer - _vm->_acci->_thing = 100; - _vm->_lucerna->callVerb(Acci::kVerbCodeBuy); - return; - case 101: // Wine - _vm->_acci->_thing = 50; - _vm->_lucerna->callVerb(Acci::kVerbCodeBuy); - return; - case 102: // Whisky - _vm->_acci->_thing = 102; - _vm->_lucerna->callVerb(Acci::kVerbCodeBuy); - return; - case 103: // Cider - _vm->_acci->_thing = 103; - _vm->_lucerna->callVerb(Acci::kVerbCodeBuy); - return; - case 104: // Mead - _vm->_acci->_thing = 107; - _vm->_lucerna->callVerb(Acci::kVerbCodeBuy); - return; - case 105: // Onion (trader) - _vm->_acci->_thing = 67; - _vm->_lucerna->callVerb(Acci::kVerbCodeBuy); - return; - default: - _vm->_acci->_person = _vm->_acci->_thing; - _vm->_acci->_thing = Acci::kPardon; - _vm->_gyro->_subjectNum = 0; - } - } - _vm->_lucerna->callVerb(_vm->_gyro->_verbStr[_activeMenuItem._choiceNum]); -} - -void Dropdown::setupMenu() { - _menuBar.init(this); - _activeMenuItem.init(this); - - _menuBar.createMenuItem('F', "File", '!', &Avalanche::Dropdown::setupMenuFile, &Avalanche::Dropdown::runMenuFile); - _menuBar.createMenuItem('G', "Game", 34, &Avalanche::Dropdown::setupMenuGame, &Avalanche::Dropdown::runMenuGame); - _menuBar.createMenuItem('A', "Action", 30, &Avalanche::Dropdown::setupMenuAction, &Avalanche::Dropdown::runMenuAction); - _menuBar.createMenuItem('O', "Objects", 24, &Avalanche::Dropdown::setupMenuObjects, &Avalanche::Dropdown::runMenuObjects); - _menuBar.createMenuItem('P', "People", 25, &Avalanche::Dropdown::setupMenuPeople, &Avalanche::Dropdown::runMenuPeople); - _menuBar.createMenuItem('W', "With", 17, &Avalanche::Dropdown::setupMenuWith, &Avalanche::Dropdown::runMenuWith); - - _menuBar.draw(); -} - -void Dropdown::updateMenu() { // TODO: Optimize it ASAP!!! It really needs it... - Common::Point cursorPos = _vm->getMousePos(); - ::Graphics::Surface backup; - backup.copyFrom(_vm->_graphics->_surface); - - while (!_activeMenuItem._activeNow && (cursorPos.y <= 21) && _vm->_lucerna->_holdLeftMouse) { - _menuBar.chooseMenuItem(cursorPos.x); - do - _vm->updateEvents(); - while (_vm->_lucerna->_holdLeftMouse); - - - while (!_vm->shouldQuit()) { - do { - _vm->updateEvents(); - - // We updadte the cursor's picture. - cursorPos = _vm->getMousePos(); - // Change arrow... - if ((0 <= cursorPos.y) && (cursorPos.y <= 21)) - _vm->_gyro->newMouse(1); // Up arrow - else if ((22 <= cursorPos.y) && (cursorPos.y <= 339)) { - if ((cursorPos.x >= _activeMenuItem._flx1 * 8) && (cursorPos.x <= _activeMenuItem._flx2 * 8) && (cursorPos.y > 21) && (cursorPos.y <= _activeMenuItem._fly * 2 + 1)) - _vm->_gyro->newMouse(3); // Right-arrow - else - _vm->_gyro->newMouse(4); // Fletch - } else if ((340 <= cursorPos.y) && (cursorPos.y <= 399)) - _vm->_gyro->newMouse(2); // Screwdriver - - _activeMenuItem.lightUp(cursorPos); - - _vm->_graphics->refreshScreen(); - } while (!_vm->_lucerna->_holdLeftMouse); - - if (_vm->_lucerna->_holdLeftMouse) { - if (cursorPos.y > 21) { - if (!((_activeMenuItem._firstlix) && ((cursorPos.x >= _activeMenuItem._flx1 * 8) && (cursorPos.x <= _activeMenuItem._flx2 * 8) - && (cursorPos.y >= 24) && (cursorPos.y <= (_activeMenuItem._fly * 2 + 1))))) { - // Clicked OUTSIDE the menu. - if (_activeMenuItem._activeNow) { - _activeMenuItem.wipe(); - _vm->_lucerna->_holdLeftMouse = false; - backup.free(); - return; - } // No "else"- clicking on menu has no effect (only releasing). - } - } else { - // Clicked on menu bar. - if (_activeMenuItem._activeNow) { - _activeMenuItem.wipe(); - _vm->_graphics->_surface.copyFrom(backup); - _vm->_graphics->refreshScreen(); - - if (((_activeMenuItem._left * 8) <= cursorPos.x) && (cursorPos.x <= (_activeMenuItem._left * 8 + 80))) { // 80: the width of one menu item on the bar in pixels. - // If we clicked on the same menu item (the one that is already active) on the bar... - _vm->_lucerna->_holdLeftMouse = false; - backup.free(); - return; - } else { - _vm->_lucerna->_holdLeftMouse = true; - break; - } - } - } - - // NOT clicked button... - if ((_activeMenuItem._firstlix) && ((cursorPos.x >= _activeMenuItem._flx1 * 8) && (cursorPos.x <= _activeMenuItem._flx2 * 8) - && (cursorPos.y >= 12) && (cursorPos.y <= (_activeMenuItem._fly * 2 + 1)))) { - - // We act only if the button is released over a menu item. - while (!_vm->shouldQuit()) { - cursorPos = _vm->getMousePos(); - _activeMenuItem.lightUp(cursorPos); - _vm->_graphics->refreshScreen(); - - _vm->updateEvents(); - if (!_vm->_lucerna->_holdLeftMouse) - break; - } - - uint16 which = (cursorPos.y - 26) / 20; - _activeMenuItem.select(which); - if (_activeMenuItem._options[which]._valid) { // If the menu item wasn't active, we do nothing. - backup.free(); - return; - } - } - } - } - } - - backup.free(); -} - -} // End of namespace Avalanche. diff --git a/engines/avalanche/dropdown.h b/engines/avalanche/dropdown.h deleted file mode 100644 index b14f4cb196..0000000000 --- a/engines/avalanche/dropdown.h +++ /dev/null @@ -1,167 +0,0 @@ -/* 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. - * - */ - -/* - * This code is based on the original source code of Lord Avalot d'Argent version 1.3. - * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman. - */ - -/* DROPDOWN A customised version of Oopmenu (qv). */ - -#ifndef AVALANCHE_DROPDOWN2_H -#define AVALANCHE_DROPDOWN2_H - -#include "avalanche/color.h" - -#include "common/scummsys.h" -#include "common/str.h" - - - -namespace Avalanche { -class AvalancheEngine; - -class Dropdown; - -typedef void (Dropdown::*DropdownFunc)(); - -class HeadType { -public: - Common::String _title; - char _trigger, _altTrigger; - byte _position; - int16 _xpos, _xright; - DropdownFunc _setupFunc, _chooseFunc; - - void init(char trig, char alTtrig, Common::String title, byte pos, DropdownFunc setupFunc, DropdownFunc chooseFunc, Dropdown *dr); - void draw(); - void highlight(); - bool parseAltTrigger(char key); - -private: - Dropdown *_dr; -}; - -struct OptionType { - Common::String _title; - byte _trigger; - Common::String _shortcut; - bool _valid; -}; - -class MenuItem { -public: - OptionType _options[12]; - byte _optionNum; - uint16 _width, _left; - bool _firstlix; - int16 _flx1, _flx2, _fly; - byte _oldY; // used by lightUp */ - bool _activeNow; // Is there an active option now? - byte _activeNum; // And if so, which is it? - byte _choiceNum; // Your choice? - byte _highlightNum; - - void init(Dropdown *dr); - void reset(); - void setupOption(Common::String title, char trigger, Common::String shortcut, bool valid); - void display(); - void wipe(); - void lightUp(Common::Point cursorPos); // This makes the menu highlight follow the mouse. - void displayOption(byte y, bool highlit); - void moveHighlight(int8 inc); - void select(byte which); // Choose which one you want. - void parseKey(char c); - -private: - Dropdown *_dr; -}; - -class MenuBar { -public: - HeadType _menuItems[8]; - byte _menuNum; - - void init(Dropdown *dr); - void createMenuItem(char trig, Common::String title, char altTrig, DropdownFunc setupFunc, DropdownFunc chooseFunc); - void draw(); - void parseAltTrigger(char c); - void setupMenuItem(byte which); - void chooseMenuItem(int16 x); - -private: - Dropdown *_dr; -}; - -class Dropdown { -public: - friend class HeadType; - friend class MenuItem; - friend class MenuBar; - - MenuItem _activeMenuItem; - MenuBar _menuBar; - - Common::String people; - - Dropdown(AvalancheEngine *vm); - - void parseKey(char r, char re); - void updateMenu(); - void setupMenu(); // Standard menu bar. - -private: - static const byte kIndent = 5; - static const byte kSpacing = 10; - - static const byte kMenuBackgroundColor = kColorLightgray; - static const byte kMenuFontColor = kColorBlack; - static const byte kMenuBorderColor = kColorBlack; - static const byte kHighlightBackgroundColor = kColorBlack; - static const byte kHighlightFontColor = kColorWhite; - static const byte kDisabledColor = kColorDarkgray; - - AvalancheEngine *_vm; - - Common::String selectGender(byte x); // Returns "im" for boys, and "er" for girls. - void findWhatYouCanDoWithIt(); - void drawMenuText(int16 x, int16 y, char trigger, Common::String text, bool valid, bool highlighted); - void bleep(); - - void setupMenuGame(); - void setupMenuFile(); - void setupMenuAction(); - void setupMenuPeople(); - void setupMenuObjects(); - void setupMenuWith(); - - void runMenuGame(); - void runMenuFile(); - void runMenuAction(); - void runMenuObjects(); - void runMenuPeople(); - void runMenuWith(); -}; - -} // End of namespace Avalanche. - -#endif // AVALANCHE_DROPDOWN2_H diff --git a/engines/avalanche/gyro.cpp b/engines/avalanche/gyro.cpp index 2cb9d0e6e8..ec695947bf 100644 --- a/engines/avalanche/gyro.cpp +++ b/engines/avalanche/gyro.cpp @@ -356,7 +356,7 @@ void Gyro::newGame() { _vm->_lucerna->enterRoom(1, 1); avvy->_visible = false; _vm->_lucerna->drawScore(); - _vm->_dropdown->setupMenu(); + _vm->_menu->setup(); _vm->_lucerna->_clock.update(); _vm->_lucerna->spriteRun(); } diff --git a/engines/avalanche/gyro.h b/engines/avalanche/gyro.h index 977a2e79ae..b01f3e1a06 100644 --- a/engines/avalanche/gyro.h +++ b/engines/avalanche/gyro.h @@ -348,7 +348,6 @@ public: byte _buffer[2000]; uint16 _bufSize; int16 _underScroll; // Y-coord of just under the scroll text. - bool _dropdownActive; // Kludge so we don't have to keep referring to Dropdown Common::String _roomnName; // Name of actual room Common::String _subject; // What you're talking to them about. byte _subjectNum; // The same thing. diff --git a/engines/avalanche/lucerna.cpp b/engines/avalanche/lucerna.cpp index 2b75d5abcc..336c686a6f 100644 --- a/engines/avalanche/lucerna.cpp +++ b/engines/avalanche/lucerna.cpp @@ -380,7 +380,7 @@ void Lucerna::exitRoom(byte x) { * @remarks Originally called 'new_town' */ void Lucerna::enterNewTown() { - _vm->_dropdown->setupMenu(); + _vm->_menu->setup(); switch (_vm->_gyro->_room) { case kRoomOutsideNottsPub: // Entry into Nottingham. @@ -1080,7 +1080,7 @@ void Lucerna::checkClick() { _vm->_gyro->newMouse(8); //I-beam else if ((340 <= cursorPos.y) && (cursorPos.y <= 399)) _vm->_gyro->newMouse(2); // screwdriver - else if (!_vm->_gyro->_dropdownActive) { // Dropdown can handle its own pointers. + else if (!_vm->_menu->isActive()) { // Dropdown can handle its own pointers. if (_holdLeftMouse) { _vm->_gyro->newMouse(7); // Mark's crosshairs guideAvvy(cursorPos); // Normally, if you click on the picture, you're guiding Avvy around. @@ -1091,7 +1091,7 @@ void Lucerna::checkClick() { if (_holdLeftMouse) { if ((0 <= cursorPos.y) && (cursorPos.y <= 21)) { // Click on the dropdown menu. if (_vm->_gyro->_dropsOk) - _vm->_dropdown->updateMenu(); + _vm->_menu->update(); } else if ((317 <= cursorPos.y) && (cursorPos.y <= 339)) { // Click on the command line. _vm->_parser->_inputTextPos = (cursorPos.x - 23) / 8; if (_vm->_parser->_inputTextPos > _vm->_parser->_inputText.size() + 1) diff --git a/engines/avalanche/menu.cpp b/engines/avalanche/menu.cpp new file mode 100644 index 0000000000..69267da55c --- /dev/null +++ b/engines/avalanche/menu.cpp @@ -0,0 +1,799 @@ +/* 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. + * + */ + +/* + * This code is based on the original source code of Lord Avalot d'Argent version 1.3. + * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman. + */ + + /* DROPDOWN A customised version of Oopmenu (qv). */ + +#include "avalanche/avalanche.h" +#include "avalanche/menu.h" +#include "avalanche/lucerna.h" +#include "avalanche/gyro.h" +#include "avalanche/acci.h" +#include "avalanche/animation.h" + +#include "common/textconsole.h" + +namespace Avalanche { + +void HeadType::init(char trig, char altTrig, Common::String title, byte pos, MenuFunc setupFunc, MenuFunc chooseFunc, Menu *dr) { + _trigger = trig; + _altTrigger = altTrig; + _title = title; + _position = pos; + _xpos = _position * _dr->kSpacing + _dr->kIndent; + _xright = (_position + 1) * _dr->kSpacing + _dr->kIndent; + _setupFunc = setupFunc; + _chooseFunc = chooseFunc; + + _dr = dr; +} + +void HeadType::draw() { + CursorMan.showMouse(false); + _dr->drawMenuText(_xpos, 1, _trigger, _title, true, false); + CursorMan.showMouse(true); +} + +void HeadType::highlight() { + CursorMan.showMouse(false); + + //nosound(); + //setactivepage(cp); + warning("STUB: Dropdown::headytpe::highlight()"); + + _dr->drawMenuText(_xpos, 1, _trigger, _title, true, true); + + _dr->_activeMenuItem._left = _xpos; + _dr->_activeMenuItem._activeNow = true; + _dr->_activeMenuItem._activeNum = _position; + _dr->_menuActive = true; + + _dr->_vm->_gyro->_currentMouse = 177; // Force redraw of cursor. +} + +bool HeadType::parseAltTrigger(char key) { + if (key != _altTrigger) + return true; + return false; +} + +void MenuItem::init(Menu *dr) { + _dr = dr; + + _activeNow = false; + _activeNum = 1; + _dr->_menuActive = false; +} + +void MenuItem::reset() { + _optionNum = 0; + _width = 0; + _firstlix = false; + _oldY = 0; + _highlightNum = 0; +} + +void MenuItem::setupOption(Common::String title, char trigger, Common::String shortcut, bool valid) { + uint16 width = (title + shortcut).size() + 3; + if (_width < width) + _width = width; + + _options[_optionNum]._title = title; + _options[_optionNum]._trigger = trigger; + _options[_optionNum]._shortcut = shortcut; + _options[_optionNum]._valid = valid; + _optionNum++; +} + +void MenuItem::displayOption(byte y, bool highlit) { + byte backgroundColor; + if (highlit) + backgroundColor = 0; + else + backgroundColor = 7; + _dr->_vm->_graphics->_surface.fillRect(Common::Rect((_flx1 + 1) * 8, 3 + (y + 1) * 10, (_flx2 + 1) * 8, 13 + (y + 1) * 10), backgroundColor); + + Common::String text = _options[y]._title; + while (text.size() + _options[y]._shortcut.size() < _width) + text += ' '; // Pad _options[y] with spaces. + text += _options[y]._shortcut; + + _dr->drawMenuText(_left, 4 + (y + 1) * 10, _options[y]._trigger, text, _options[y]._valid, highlit); +} + +void MenuItem::display() { + CursorMan.showMouse(false); + //setactivepage(cp); + //setvisualpage(cp); + //setfillstyle(1, menu_b); + //setcolor(menu_border); + _firstlix = true; + _flx1 = _left - 2; + _flx2 = _left + _width; + _fly = 15 + _optionNum * 10; + _activeNow = true; + _dr->_menuActive = true; + + _dr->_vm->_graphics->_surface.fillRect(Common::Rect((_flx1 + 1) * 8, 12, (_flx2 + 1) * 8, _fly), _dr->kMenuBackgroundColor); + _dr->_vm->_graphics->_surface.frameRect(Common::Rect((_flx1 + 1) * 8 - 1, 11, (_flx2 + 1) * 8 + 1, _fly + 1), _dr->kMenuBorderColor); + + displayOption(0, true); + for (int y = 1; y < _optionNum; y++) + displayOption(y, false); + + _dr->_vm->_gyro->_defaultLed = 1; + _dr->_vm->_gyro->_currentMouse = 177; + //mousepage(cp); + CursorMan.showMouse(true); // 4 = fletch +} + +void MenuItem::wipe() { + //setactivepage(cp); + CursorMan.showMouse(false); + + _dr->drawMenuText(_dr->_menuBar._menuItems[_dr->_activeMenuItem._activeNum]._xpos, 1, _dr->_menuBar._menuItems[_dr->_activeMenuItem._activeNum]._trigger, _dr->_menuBar._menuItems[_dr->_activeMenuItem._activeNum]._title, true, false); + + _activeNow = false; + _dr->_menuActive = false; + _firstlix = false; + _dr->_vm->_gyro->_defaultLed = 2; + + CursorMan.showMouse(true); +} + +void MenuItem::moveHighlight(int8 inc) { + if (inc != 0) { + int8 highlightNum = _highlightNum + inc; + if ((highlightNum < 0) || (highlightNum >= _optionNum)) + return; + _highlightNum = highlightNum; + } + //setactivepage(cp); + CursorMan.showMouse(false); + displayOption(_oldY, false); + displayOption(_highlightNum, true); + //setactivepage(1 - cp); + _oldY = _highlightNum; + CursorMan.showMouse(true); +} + +void MenuItem::lightUp(Common::Point cursorPos) { + if ((cursorPos.x < _flx1 * 8) || (cursorPos.x > _flx2 * 8) || (cursorPos.y <= 25) || (cursorPos.y > ((_fly - 3) * 2 + 1))) + return; + _highlightNum = (cursorPos.y - 26) / 20; + if (_highlightNum == _oldY) + return; + moveHighlight(0); +} + +void MenuItem::select(byte which) { + if (!_options[which]._valid) + return; + + _choiceNum = which; + wipe(); + + if (_choiceNum == _optionNum) + _choiceNum--; // Off the bottom. + if (_choiceNum > _optionNum) + _choiceNum = 0; // Off the top, I suppose. + + (_dr->*_dr->_menuBar._menuItems[_activeNum]._chooseFunc)(); +} + +void MenuItem::parseKey(char c) { + c = toupper(c); + bool found = false; + for (int i = 0; i < _optionNum; i++) { + if ((toupper(_options[i]._trigger) == c) && _options[i]._valid) { + select(i); + found = true; + } + } + if (!found) + _dr->_vm->_gyro->blip(); +} + +void MenuBar::init(Menu *dr) { + _dr = dr; + _menuNum = 0; +} + +void MenuBar::createMenuItem(char trig, Common::String title, char altTrig, MenuFunc setupFunc, MenuFunc chooseFunc) { + _menuItems[_menuNum].init(trig, altTrig, title, _menuNum, setupFunc, chooseFunc, _dr); + _menuNum++; +} + +void MenuBar::draw() { + //setactivepage(3); + + _dr->_vm->_graphics->_surface.fillRect(Common::Rect(0, 0, 640, 10), _dr->kMenuBackgroundColor); + + byte savecp = _dr->_vm->_gyro->_cp; + _dr->_vm->_gyro->_cp = 3; + + for (int i = 0; i < _menuNum; i++) + _menuItems[i].draw(); + + _dr->_vm->_gyro->_cp = savecp; +} + +void MenuBar::parseAltTrigger(char c) { + byte i = 0; + while ((i < _menuNum) && (_menuItems[i].parseAltTrigger(c))) + i++; + if (i == _menuNum) + return; + setupMenuItem(i); +} + +void MenuBar::setupMenuItem(byte which) { + if (_dr->_activeMenuItem._activeNow) { + _dr->_activeMenuItem.wipe(); // Get rid of menu. + if (_dr->_activeMenuItem._activeNum == _menuItems[which]._position) + return; // Clicked on own highlight. + } + _menuItems[which].highlight(); + (_dr->*_menuItems[which]._setupFunc)(); +} + +void MenuBar::chooseMenuItem(int16 x) { + for (int i = 0; i < _menuNum; i++) { + if ((x > _menuItems[i]._xpos * 8) && (x < _menuItems[i]._xright * 8)) { + setupMenuItem(i); + break; + } + } +} + +Menu::Menu(AvalancheEngine *vm) { + _vm = vm; + _activeMenuItem.init(this); + _menuBar.init(this); +} + +void Menu::findWhatYouCanDoWithIt() { + switch (_vm->_gyro->_thinks) { + case Gyro::kObjectWine: + case Gyro::kObjectPotion: + case Gyro::kObjectInk: + _vm->_gyro->_verbStr = Common::String(Acci::kVerbCodeExam) + Acci::kVerbCodeDrink; + break; + case Gyro::kObjectBell: + _vm->_gyro->_verbStr = Common::String(Acci::kVerbCodeExam) + Acci::kVerbCodeRing; + break; + case Gyro::kObjectChastity: + _vm->_gyro->_verbStr = Common::String(Acci::kVerbCodeExam) + Acci::kVerbCodeWear; + break; + case Gyro::kObjectLute: + _vm->_gyro->_verbStr = Common::String(Acci::kVerbCodeExam) + Acci::kVerbCodePlay; + break; + case Gyro::kObjectMushroom: + case Gyro::kObjectOnion: + _vm->_gyro->_verbStr = Common::String(Acci::kVerbCodeExam) + Acci::kVerbCodeEat; + break; + case Gyro::kObjectClothes: + _vm->_gyro->_verbStr = Common::String(Acci::kVerbCodeExam) + Acci::kVerbCodeWear; + break; + default: + _vm->_gyro->_verbStr = Acci::kVerbCodeExam; // Anything else. + } +} + +void Menu::drawMenuText(int16 x, int16 y, char trigger, Common::String text, bool valid, bool highlighted) { + byte fontColor; + byte backgroundColor; + if (highlighted) { + fontColor = kColorWhite; + backgroundColor = kColorBlack; + } else { + fontColor = kColorBlack; + backgroundColor = kColorLightgray; + } + + byte ander; + if (valid) + ander = 255; + else + ander = 170; + + FontType font; + for (uint i = 0; i < text.size(); i++) { + for (int j = 0; j < 8; j++) { + byte idx = text[i]; + font[idx][j] = _vm->_gyro->_font[idx][j] & ander; // Set the font. + // And set the background of the text to the desired color. + for (int k = 0; k < 8; k++) + *(byte *)_vm->_graphics->_surface.getBasePtr(x * 8 + i * 8 + k, y + j) = backgroundColor; + } + } + + _vm->_graphics->drawText(_vm->_graphics->_surface, text, font, 8, x * 8, y, fontColor); + + // Underline the selected character. + if ((trigger == 0) || !text.contains(trigger) ) + return; + else { + byte i; + for (i = 0; text[i] != trigger; i++) + ; // Search for the character in the string. + + byte pixel = ander; + for (int bit = 0; bit < 8; bit++) { + byte pixelBit = (pixel >> bit) & 1; + if (pixelBit) + *(byte *)_vm->_graphics->_surface.getBasePtr(x * 8 + i * 8 + 7 - bit, y + 8) = fontColor; + } + } + + _vm->_graphics->refreshScreen(); +} + +void Menu::bleep() { + warning("STUB: Dropdown::bleep()"); +} + +void Menu::parseKey(char r, char re) { +#if 0 + switch (r) { + case 0: + case 224: { + switch (re) { + case 'K': + if (_activeMenuItem._activeNum > 1) { + _activeMenuItem.wipe(); + _menuBar.setupMenuItem(_activeMenuItem._activeNum - 1); + } else { + // Get menu on the left-hand side. + _activeMenuItem.wipe(); + _menuBar.chooseMenuItem((_menuBar._menuNum - 1) * kSpacing + kIndent); + } + break; + case 'M': + if (_activeMenuItem._activeNum < _menuBar._menuNum) { + _activeMenuItem.wipe(); + _menuBar.setupMenuItem(_activeMenuItem._activeNum + 1); + } else { + // Get menu on the far right-hand side. + _activeMenuItem.wipe(); + _menuBar.chooseMenuItem(kIndent); + } + break; + case 'H': + _activeMenuItem.moveHighlight(-1); + break; + case 'P': + _activeMenuItem.moveHighlight(1); + break; + default: + _menuBar.parseAltTrigger(re); + } + } + break; + case 13: + _activeMenuItem.select(_activeMenuItem._highlightNum); + break; + default: + if (_activeMenuItem._activeNow) + _activeMenuItem.parseKey(r); + } +#endif + + warning("STUB: Dropdown::parseKey()"); // To be implemented properly later! Don't remove the comment above! +} + +Common::String Menu::selectGender(byte x) { + if (x < 175) + return "im"; + else + return "er"; +} + +void Menu::setupMenuGame() { + _activeMenuItem.reset(); + _activeMenuItem.setupOption("Help...", 'H', "f1", true); + _activeMenuItem.setupOption("Boss Key", 'B', "alt-B", true); + _activeMenuItem.setupOption("Untrash screen", 'U', "ctrl-f7", true); + _activeMenuItem.setupOption("Score and rank", 'S', "f9", true); + _activeMenuItem.setupOption("About Avvy...", 'A', "shift-f10", true); + _activeMenuItem.display(); +} + +void Menu::setupMenuFile() { + _activeMenuItem.reset(); + _activeMenuItem.setupOption("New game", 'N', "f4", true); + _activeMenuItem.setupOption("Load...", 'L', "^f3", true); + _activeMenuItem.setupOption("Save", 'S', "^f2", _vm->_gyro->_alive); + _activeMenuItem.setupOption("Save As...", 'v', "", _vm->_gyro->_alive); + _activeMenuItem.setupOption("DOS Shell", 'D', _vm->_gyro->_atKey + '1', true); + _activeMenuItem.setupOption("Quit", 'Q', "alt-X", true); + _activeMenuItem.display(); +} + +void Menu::setupMenuAction() { + _activeMenuItem.reset(); + + Common::String f5Does = _vm->_gyro->f5Does(); + for (int i = 0; i < 2; i++) + if (!f5Does.empty()) + f5Does.deleteChar(0); + if (f5Does.empty()) + _activeMenuItem.setupOption("Do something", 'D', "f5", false); + else + _activeMenuItem.setupOption(f5Does, f5Does[0], "f5", true); + _activeMenuItem.setupOption("Pause game", 'P', "f6", true); + if (_vm->_gyro->_room == kRoomMap) + _activeMenuItem.setupOption("Journey thither", 'J', "f7", _vm->_animation->nearDoor()); + else + _activeMenuItem.setupOption("Open the door", 'O', "f7", _vm->_animation->nearDoor()); + _activeMenuItem.setupOption("Look around", 'L', "f8", true); + _activeMenuItem.setupOption("Inventory", 'I', "Tab", true); + if (_vm->_animation->_sprites[0]._speedX == _vm->_gyro->kWalk) + _activeMenuItem.setupOption("Run fast", 'R', "^R", true); + else + _activeMenuItem.setupOption("Walk slowly", 'W', "^W", true); + + _activeMenuItem.display(); +} + +void Menu::setupMenuPeople() { + if (!people.empty()) + people.clear(); + + _activeMenuItem.reset(); + + for (int i = 150; i <= 178; i++) { + if (_vm->_gyro->_whereIs[i - 150] == _vm->_gyro->_room) { + _activeMenuItem.setupOption(_vm->_gyro->getName(i), _vm->_gyro->getNameChar(i), "", true); + people += i; + } + } + + _activeMenuItem.display(); +} + +void Menu::setupMenuObjects() { + _activeMenuItem.reset(); + for (int i = 0; i < kObjectNum; i++) { + if (_vm->_gyro->_objects[i]) + _activeMenuItem.setupOption(_vm->_gyro->getThing(i + 1), _vm->_gyro->getThingChar(i + 1), "", true); + } + _activeMenuItem.display(); +} + +void Menu::setupMenuWith() { + _activeMenuItem.reset(); + + if (_vm->_gyro->_thinkThing) { + findWhatYouCanDoWithIt(); + + for (uint i = 0; i < _vm->_gyro->_verbStr.size(); i++) { + char vbchar; + Common::String verb; + + _vm->_acci->verbOpt(_vm->_gyro->_verbStr[i], verb, vbchar); + _activeMenuItem.setupOption(verb, vbchar, "", true); + } + + // We disable the "give" option if: (a), you haven't selected anybody, (b), the _person you've selected isn't in the room, + // or (c), the _person you've selected is YOU! + + if ((_vm->_gyro->_lastPerson == Gyro::kPeopleAvalot) || (_vm->_gyro->_lastPerson == _vm->_acci->kNothing) + || (_vm->_gyro->_whereIs[_vm->_gyro->_lastPerson - 150] != _vm->_gyro->_room)) + _activeMenuItem.setupOption("Give to...", 'G', "", false); // Not here. + else { + _activeMenuItem.setupOption(Common::String("Give to ") + _vm->_gyro->getName(_vm->_gyro->_lastPerson), 'G', "", true); + _vm->_gyro->_verbStr = _vm->_gyro->_verbStr + Acci::kVerbCodeGive; + } + } else { + _activeMenuItem.setupOption("Examine", 'x', "", true); + _activeMenuItem.setupOption(Common::String("Talk to h") + selectGender(_vm->_gyro->_thinks), 'T', "", true); + _vm->_gyro->_verbStr = Common::String(Acci::kVerbCodeExam) + Acci::kVerbCodeTalk; + switch (_vm->_gyro->_thinks) { + case Gyro::kPeopleGeida: + case Gyro::kPeopleArkata: + _activeMenuItem.setupOption("Kiss her", 'K', "", true); + _vm->_gyro->_verbStr = _vm->_gyro->_verbStr + Acci::kVerbCodeKiss; + break; + case Gyro::kPeopleDogfood: + _activeMenuItem.setupOption("Play his game", 'P', "", !_vm->_gyro->_wonNim); // True if you HAVEN'T won. + _vm->_gyro->_verbStr = _vm->_gyro->_verbStr + Acci::kVerbCodePlay; + break; + case Gyro::kPeopleMalagauche: { + bool isSober = !_vm->_gyro->_teetotal; + _activeMenuItem.setupOption("Buy some wine", 'w', "", !_vm->_gyro->_objects[Gyro::kObjectWine - 1]); + _activeMenuItem.setupOption("Buy some beer", 'b', "", isSober); + _activeMenuItem.setupOption("Buy some whisky", 'h', "", isSober); + _activeMenuItem.setupOption("Buy some cider", 'c', "", isSober); + _activeMenuItem.setupOption("Buy some mead", 'm', "", isSober); + _vm->_gyro->_verbStr = _vm->_gyro->_verbStr + 101 + 100 + 102 + 103 + 104; + } + break; + case Gyro::kPeopleTrader: + _activeMenuItem.setupOption("Buy an onion", 'o', "", !_vm->_gyro->_objects[Gyro::kObjectOnion - 1]); + _vm->_gyro->_verbStr = _vm->_gyro->_verbStr + 105; + break; + } + } + _activeMenuItem.display(); +} + +void Menu::runMenuGame() { + // Help, boss, untrash screen. + switch (_activeMenuItem._choiceNum) { + case 0: + _vm->_lucerna->callVerb(Acci::kVerbCodeHelp); + break; + case 1: + _vm->_lucerna->callVerb(Acci::kVerbCodeBoss); + break; + case 2: + _vm->_lucerna->majorRedraw(); + break; + case 3: + _vm->_lucerna->callVerb(Acci::kVerbCodeScore); + break; + case 4: + _vm->_lucerna->callVerb(Acci::kVerbCodeInfo); + break; + } +} + +void Menu::runMenuFile() { + // New game, load, save, save as, DOS shell, about, quit. + switch (_activeMenuItem._choiceNum) { + case 0: + _vm->_lucerna->callVerb(Acci::kVerbCodeRestart); + break; + case 1: + if (!_vm->_acci->_realWords[1].empty()) + _vm->_acci->_realWords[1].clear(); + _vm->_lucerna->callVerb(Acci::kVerbCodeLoad); + break; + case 2: + if (!_vm->_acci->_realWords[1].empty()) + _vm->_acci->_realWords[1].clear(); + _vm->_lucerna->callVerb(Acci::kVerbCodeSave); + break; + case 3: + //_vm->_basher->filename_edit(); + warning("STUB: Dropdown::runMenuFile()"); + break; + case 4: + //_vm->_enid->backToBootstrap(2); TODO: Replace it with proper ScummVM-friendly function(s)! Do not remove until then! + break; + case 5: + _vm->_lucerna->callVerb(Acci::kVerbCodeQuit); + break; + } +} + +void Menu::runMenuAction() { + Common::String f5Does; + // Get up, pause game, open door, look, inventory, walk/run. + switch (_activeMenuItem._choiceNum) { + case 0: + _vm->_acci->_person = _vm->_acci->kPardon; + _vm->_acci->_thing = _vm->_acci->kPardon; + f5Does = _vm->_gyro->f5Does(); + _vm->_lucerna->callVerb(f5Does[0]); + break; + case 1: + _vm->_acci->_thing = _vm->_acci->kPardon; + _vm->_lucerna->callVerb(Acci::kVerbCodePause); + break; + case 2: + _vm->_lucerna->callVerb(Acci::kVerbCodeOpen); + break; + case 3: + _vm->_acci->_thing = _vm->_acci->kPardon; + _vm->_lucerna->callVerb(Acci::kVerbCodeLook); + break; + case 4: + _vm->_lucerna->callVerb(Acci::kVerbCodeInv); + break; + case 5: { + AnimationType *avvy = &_vm->_animation->_sprites[0]; + if (avvy->_speedX == _vm->_gyro->kWalk) + avvy->_speedX = _vm->_gyro->kRun; + else + avvy->_speedX = _vm->_gyro->kWalk; + _vm->_animation->updateSpeed(); + } + break; + } +} + +void Menu::runMenuObjects() { + _vm->_lucerna->thinkAbout(_vm->_gyro->_objectList[_activeMenuItem._choiceNum], Gyro::kThing); +} + +void Menu::runMenuPeople() { + _vm->_lucerna->thinkAbout(people[_activeMenuItem._choiceNum], Gyro::kPerson); + _vm->_gyro->_lastPerson = people[_activeMenuItem._choiceNum]; +} + +void Menu::runMenuWith() { + _vm->_acci->_thing = _vm->_gyro->_thinks; + + if (_vm->_gyro->_thinkThing) { + _vm->_acci->_thing += 49; + + if (_vm->_gyro->_verbStr[_activeMenuItem._choiceNum] == Acci::kVerbCodeGive) + _vm->_acci->_person = _vm->_gyro->_lastPerson; + else + _vm->_acci->_person = Acci::kPardon; + } else { + switch (_vm->_gyro->_verbStr[_activeMenuItem._choiceNum]) { + case 100: // Beer + _vm->_acci->_thing = 100; + _vm->_lucerna->callVerb(Acci::kVerbCodeBuy); + return; + case 101: // Wine + _vm->_acci->_thing = 50; + _vm->_lucerna->callVerb(Acci::kVerbCodeBuy); + return; + case 102: // Whisky + _vm->_acci->_thing = 102; + _vm->_lucerna->callVerb(Acci::kVerbCodeBuy); + return; + case 103: // Cider + _vm->_acci->_thing = 103; + _vm->_lucerna->callVerb(Acci::kVerbCodeBuy); + return; + case 104: // Mead + _vm->_acci->_thing = 107; + _vm->_lucerna->callVerb(Acci::kVerbCodeBuy); + return; + case 105: // Onion (trader) + _vm->_acci->_thing = 67; + _vm->_lucerna->callVerb(Acci::kVerbCodeBuy); + return; + default: + _vm->_acci->_person = _vm->_acci->_thing; + _vm->_acci->_thing = Acci::kPardon; + _vm->_gyro->_subjectNum = 0; + } + } + _vm->_lucerna->callVerb(_vm->_gyro->_verbStr[_activeMenuItem._choiceNum]); +} + +void Menu::setup() { + _menuBar.init(this); + _activeMenuItem.init(this); + + _menuBar.createMenuItem('F', "File", '!', &Avalanche::Menu::setupMenuFile, &Avalanche::Menu::runMenuFile); + _menuBar.createMenuItem('G', "Game", 34, &Avalanche::Menu::setupMenuGame, &Avalanche::Menu::runMenuGame); + _menuBar.createMenuItem('A', "Action", 30, &Avalanche::Menu::setupMenuAction, &Avalanche::Menu::runMenuAction); + _menuBar.createMenuItem('O', "Objects", 24, &Avalanche::Menu::setupMenuObjects, &Avalanche::Menu::runMenuObjects); + _menuBar.createMenuItem('P', "People", 25, &Avalanche::Menu::setupMenuPeople, &Avalanche::Menu::runMenuPeople); + _menuBar.createMenuItem('W', "With", 17, &Avalanche::Menu::setupMenuWith, &Avalanche::Menu::runMenuWith); + + _menuBar.draw(); +} + +void Menu::update() { // TODO: Optimize it ASAP!!! It really needs it... + Common::Point cursorPos = _vm->getMousePos(); + ::Graphics::Surface backup; + backup.copyFrom(_vm->_graphics->_surface); + + while (!_activeMenuItem._activeNow && (cursorPos.y <= 21) && _vm->_lucerna->_holdLeftMouse) { + _menuBar.chooseMenuItem(cursorPos.x); + do + _vm->updateEvents(); + while (_vm->_lucerna->_holdLeftMouse); + + + while (!_vm->shouldQuit()) { + do { + _vm->updateEvents(); + + // We updadte the cursor's picture. + cursorPos = _vm->getMousePos(); + // Change arrow... + if ((0 <= cursorPos.y) && (cursorPos.y <= 21)) + _vm->_gyro->newMouse(1); // Up arrow + else if ((22 <= cursorPos.y) && (cursorPos.y <= 339)) { + if ((cursorPos.x >= _activeMenuItem._flx1 * 8) && (cursorPos.x <= _activeMenuItem._flx2 * 8) && (cursorPos.y > 21) && (cursorPos.y <= _activeMenuItem._fly * 2 + 1)) + _vm->_gyro->newMouse(3); // Right-arrow + else + _vm->_gyro->newMouse(4); // Fletch + } else if ((340 <= cursorPos.y) && (cursorPos.y <= 399)) + _vm->_gyro->newMouse(2); // Screwdriver + + _activeMenuItem.lightUp(cursorPos); + + _vm->_graphics->refreshScreen(); + } while (!_vm->_lucerna->_holdLeftMouse); + + if (_vm->_lucerna->_holdLeftMouse) { + if (cursorPos.y > 21) { + if (!((_activeMenuItem._firstlix) && ((cursorPos.x >= _activeMenuItem._flx1 * 8) && (cursorPos.x <= _activeMenuItem._flx2 * 8) + && (cursorPos.y >= 24) && (cursorPos.y <= (_activeMenuItem._fly * 2 + 1))))) { + // Clicked OUTSIDE the menu. + if (_activeMenuItem._activeNow) { + _activeMenuItem.wipe(); + _vm->_lucerna->_holdLeftMouse = false; + backup.free(); + return; + } // No "else"- clicking on menu has no effect (only releasing). + } + } else { + // Clicked on menu bar. + if (_activeMenuItem._activeNow) { + _activeMenuItem.wipe(); + _vm->_graphics->_surface.copyFrom(backup); + _vm->_graphics->refreshScreen(); + + if (((_activeMenuItem._left * 8) <= cursorPos.x) && (cursorPos.x <= (_activeMenuItem._left * 8 + 80))) { // 80: the width of one menu item on the bar in pixels. + // If we clicked on the same menu item (the one that is already active) on the bar... + _vm->_lucerna->_holdLeftMouse = false; + backup.free(); + return; + } else { + _vm->_lucerna->_holdLeftMouse = true; + break; + } + } + } + + // NOT clicked button... + if ((_activeMenuItem._firstlix) && ((cursorPos.x >= _activeMenuItem._flx1 * 8) && (cursorPos.x <= _activeMenuItem._flx2 * 8) + && (cursorPos.y >= 12) && (cursorPos.y <= (_activeMenuItem._fly * 2 + 1)))) { + + // We act only if the button is released over a menu item. + while (!_vm->shouldQuit()) { + cursorPos = _vm->getMousePos(); + _activeMenuItem.lightUp(cursorPos); + _vm->_graphics->refreshScreen(); + + _vm->updateEvents(); + if (!_vm->_lucerna->_holdLeftMouse) + break; + } + + uint16 which = (cursorPos.y - 26) / 20; + _activeMenuItem.select(which); + if (_activeMenuItem._options[which]._valid) { // If the menu item wasn't active, we do nothing. + backup.free(); + return; + } + } + } + } + } + + backup.free(); +} + +bool Menu::isActive() { + return _menuActive; +} + +void Menu::init() { + _menuActive = false; +} +} // End of namespace Avalanche. diff --git a/engines/avalanche/menu.h b/engines/avalanche/menu.h new file mode 100644 index 0000000000..ad0821e932 --- /dev/null +++ b/engines/avalanche/menu.h @@ -0,0 +1,168 @@ +/* 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. + * + */ + +/* + * This code is based on the original source code of Lord Avalot d'Argent version 1.3. + * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman. + */ + +/* DROPDOWN A customised version of Oopmenu (qv). */ + +#ifndef AVALANCHE_DROPDOWN2_H +#define AVALANCHE_DROPDOWN2_H + +#include "avalanche/color.h" +#include "common/scummsys.h" +#include "common/str.h" + +namespace Avalanche { +class AvalancheEngine; + +class Menu; + +typedef void (Menu::*MenuFunc)(); + +class HeadType { +public: + Common::String _title; + char _trigger, _altTrigger; + byte _position; + int16 _xpos, _xright; + MenuFunc _setupFunc, _chooseFunc; + + void init(char trig, char alTtrig, Common::String title, byte pos, MenuFunc setupFunc, MenuFunc chooseFunc, Menu *dr); + void draw(); + void highlight(); + bool parseAltTrigger(char key); + +private: + Menu *_dr; +}; + +struct OptionType { + Common::String _title; + byte _trigger; + Common::String _shortcut; + bool _valid; +}; + +class MenuItem { +public: + OptionType _options[12]; + byte _optionNum; + uint16 _width, _left; + bool _firstlix; + int16 _flx1, _flx2, _fly; + byte _oldY; // used by lightUp */ + bool _activeNow; // Is there an active option now? + byte _activeNum; // And if so, which is it? + byte _choiceNum; // Your choice? + byte _highlightNum; + + void init(Menu *dr); + void reset(); + void setupOption(Common::String title, char trigger, Common::String shortcut, bool valid); + void display(); + void wipe(); + void lightUp(Common::Point cursorPos); // This makes the menu highlight follow the mouse. + void displayOption(byte y, bool highlit); + void moveHighlight(int8 inc); + void select(byte which); // Choose which one you want. + void parseKey(char c); + +private: + Menu *_dr; +}; + +class MenuBar { +public: + HeadType _menuItems[8]; + byte _menuNum; + + void init(Menu *dr); + void createMenuItem(char trig, Common::String title, char altTrig, MenuFunc setupFunc, MenuFunc chooseFunc); + void draw(); + void parseAltTrigger(char c); + void setupMenuItem(byte which); + void chooseMenuItem(int16 x); + +private: + Menu *_dr; +}; + +class Menu { +public: + friend class HeadType; + friend class MenuItem; + friend class MenuBar; + + MenuItem _activeMenuItem; + MenuBar _menuBar; + + Common::String people; + + Menu(AvalancheEngine *vm); + + void parseKey(char r, char re); + void update(); + void setup(); // Standard menu bar. + bool isActive(); + void init(); + +private: + static const byte kIndent = 5; + static const byte kSpacing = 10; + + static const byte kMenuBackgroundColor = kColorLightgray; + static const byte kMenuFontColor = kColorBlack; + static const byte kMenuBorderColor = kColorBlack; + static const byte kHighlightBackgroundColor = kColorBlack; + static const byte kHighlightFontColor = kColorWhite; + static const byte kDisabledColor = kColorDarkgray; + + bool _menuActive; // Kludge so we don't have to keep referring to Dropdown + + AvalancheEngine *_vm; + + Common::String selectGender(byte x); // Returns "im" for boys, and "er" for girls. + void findWhatYouCanDoWithIt(); + void drawMenuText(int16 x, int16 y, char trigger, Common::String text, bool valid, bool highlighted); + void bleep(); + + void setupMenuGame(); + void setupMenuFile(); + void setupMenuAction(); + void setupMenuPeople(); + void setupMenuObjects(); + void setupMenuWith(); + + void runMenuGame(); + void runMenuFile(); + void runMenuAction(); + void runMenuObjects(); + void runMenuPeople(); + void runMenuWith(); +}; + +} // End of namespace Avalanche. + +#endif // AVALANCHE_DROPDOWN2_H diff --git a/engines/avalanche/module.mk b/engines/avalanche/module.mk index 0da172cf9f..4a0c7034b6 100644 --- a/engines/avalanche/module.mk +++ b/engines/avalanche/module.mk @@ -16,7 +16,7 @@ MODULE_OBJS = \ timer.o \ animation.o \ acci.o \ - dropdown.o \ + menu.o \ closing.o # This module can be built as a plugin diff --git a/engines/avalanche/parser.cpp b/engines/avalanche/parser.cpp index 4bf05884f7..903a01b796 100644 --- a/engines/avalanche/parser.cpp +++ b/engines/avalanche/parser.cpp @@ -65,7 +65,7 @@ void Parser::handleInputText(const Common::Event &event) { } void Parser::handleBackspace() { - if (!_vm->_dropdown->_activeMenuItem._activeNow) { + if (!_vm->_menu->_activeMenuItem._activeNow) { if (_inputTextPos > _leftMargin) { _inputTextPos--; if ((_inputText[_inputTextPos] == '"') || (_inputText[_inputTextPos] == '`')) @@ -78,7 +78,7 @@ void Parser::handleBackspace() { } void Parser::handleReturn() { - if (_vm->_dropdown->_activeMenuItem._activeNow) + if (_vm->_menu->_activeMenuItem._activeNow) _vm->_parser->tryDropdown(); else if (!_inputText.empty()) { _inputTextBackup = _inputText; diff --git a/engines/avalanche/timer.cpp b/engines/avalanche/timer.cpp index ebace781e2..8038f01bf1 100644 --- a/engines/avalanche/timer.cpp +++ b/engines/avalanche/timer.cpp @@ -80,7 +80,7 @@ void Timer::addTimer(int32 duration, byte action, byte reason) { * @remarks Originally called 'one_tick' */ void Timer::updateTimer() { - if (_vm->_gyro->_dropdownActive) + if (_vm->_menu->isActive()) return; for (int i = 0; i < 7; i++) { -- cgit v1.2.3