From 76bfcf834d73a9578164842ed5ab8e1eff2814e8 Mon Sep 17 00:00:00 2001 From: athrxx Date: Wed, 16 Nov 2011 19:16:19 +0100 Subject: KYRA: (EOB) - some refactoring --- engines/kyra/gui_v1.cpp | 630 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 630 insertions(+) create mode 100644 engines/kyra/gui_v1.cpp (limited to 'engines/kyra/gui_v1.cpp') diff --git a/engines/kyra/gui_v1.cpp b/engines/kyra/gui_v1.cpp new file mode 100644 index 0000000000..c38c828ff0 --- /dev/null +++ b/engines/kyra/gui_v1.cpp @@ -0,0 +1,630 @@ +/* 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 "kyra/gui_v1.h" + +#include "kyra/text.h" +#include "kyra/wsamovie.h" + +#include "common/savefile.h" +#include "common/system.h" + +namespace Kyra { + +GUI_v1::GUI_v1(KyraEngine_v1 *kyra) : GUI(kyra), _text(kyra->text()) { + _menuButtonList = 0; + + _redrawButtonFunctor = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::redrawButtonCallback); + _redrawShadedButtonFunctor = BUTTON_FUNCTOR(GUI_v1, this, &GUI_v1::redrawShadedButtonCallback); +} + +Button *GUI_v1::addButtonToList(Button *list, Button *newButton) { + if (!newButton) + return list; + + newButton->nextButton = 0; + + if (list) { + Button *cur = list; + while (cur->nextButton) + cur = cur->nextButton; + cur->nextButton = newButton; + } else { + list = newButton; + } + + return list; +} + +void GUI_v1::initMenuLayout(Menu &menu) { + if (menu.x == -1) + menu.x = (320 - menu.width) >> 1; + if (menu.y == -1) + menu.y = (200 - menu.height) >> 1; + + for (int i = 0; i < menu.numberOfItems; ++i) { + if (menu.item[i].x == -1) + menu.item[i].x = (menu.width - menu.item[i].width) >> 1; + } +} + +void GUI_v1::initMenu(Menu &menu) { + _menuButtonList = 0; + + _screen->hideMouse(); + + int textX; + int textY; + + int menu_x2 = menu.width + menu.x - 1; + int menu_y2 = menu.height + menu.y - 1; + + _screen->fillRect(menu.x + 2, menu.y + 2, menu_x2 - 2, menu_y2 - 2, menu.bkgdColor); + _screen->drawShadedBox(menu.x, menu.y, menu_x2, menu_y2, menu.color1, menu.color2); + + if (menu.titleX != -1) + textX = menu.titleX; + else + textX = getMenuCenterStringX(getMenuTitle(menu), menu.x, menu_x2); + + textY = menu.y + menu.titleY; + + if (_vm->game() == GI_LOL) { + printMenuText(getMenuTitle(menu), textX, textY, menu.textColor, 0, 9); + } else { + if (_vm->gameFlags().platform != Common::kPlatformAmiga) + printMenuText(getMenuTitle(menu), textX - 1, textY + 1, defaultColor1(), defaultColor2(), 0); + printMenuText(getMenuTitle(menu), textX, textY, menu.textColor, 0, 0); + } + + int x1, y1, x2, y2; + for (int i = 0; i < menu.numberOfItems; ++i) { + if (!menu.item[i].enabled) + continue; + + x1 = menu.x + menu.item[i].x; + y1 = menu.y + menu.item[i].y; + + x2 = x1 + menu.item[i].width - 1; + y2 = y1 + menu.item[i].height - 1; + + if (i < 7) { + Button *menuButtonData = getButtonListData() + i; + menuButtonData->nextButton = 0; + menuButtonData->x = x1; + menuButtonData->y = y1; + menuButtonData->width = menu.item[i].width - 1; + menuButtonData->height = menu.item[i].height - 1; + menuButtonData->buttonCallback = menu.item[i].callback; + menuButtonData->keyCode = menu.item[i].keyCode; + menuButtonData->keyCode2 = 0; + menuButtonData->arg = menu.item[i].itemId; + + _menuButtonList = addButtonToList(_menuButtonList, menuButtonData); + } + + _screen->fillRect(x1, y1, x2, y2, menu.item[i].bkgdColor); + _screen->drawShadedBox(x1, y1, x2, y2, menu.item[i].color1, menu.item[i].color2); + + if (getMenuItemTitle(menu.item[i])) { + if (menu.item[i].titleX != -1) + textX = x1 + menu.item[i].titleX + 3; + else + textX = getMenuCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2); + + textY = y1 + 2; + if (_vm->game() == GI_LOL) { + textY++; + if (i == menu.highlightedItem) + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 8); + else + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 8); + } else { + Screen::FontId of = _screen->_currentFont; + if (menu.item[i].saveSlot > 0) + _screen->setFont(Screen::FID_8_FNT); + + if (_vm->gameFlags().platform != Common::kPlatformAmiga) + printMenuText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0); + + if (i == menu.highlightedItem) + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 0); + else + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 0); + + _screen->setFont(of); + } + } + } + + for (int i = 0; i < menu.numberOfItems; ++i) { + if (getMenuItemLabel(menu.item[i])) { + if (_vm->game() == GI_LOL) { + menu.item[i].labelX = menu.item[i].x - 1; + menu.item[i].labelY = menu.item[i].y + 3; + printMenuText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX, menu.y + menu.item[i].labelY, menu.item[i].textColor, 0, 10); + } else { + if (_vm->gameFlags().platform != Common::kPlatformAmiga) + printMenuText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX - 1, menu.y + menu.item[i].labelY + 1, defaultColor1(), 0, 0); + printMenuText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX, menu.y + menu.item[i].labelY, menu.item[i].textColor, 0, 0); + } + } + } + + if (menu.scrollUpButtonX != -1) { + Button *scrollUpButton = getScrollUpButton(); + scrollUpButton->x = menu.scrollUpButtonX + menu.x; + scrollUpButton->y = menu.scrollUpButtonY + menu.y; + scrollUpButton->buttonCallback = getScrollUpButtonHandler(); + scrollUpButton->nextButton = 0; + scrollUpButton->mouseWheel = -1; + + _menuButtonList = addButtonToList(_menuButtonList, scrollUpButton); + updateMenuButton(scrollUpButton); + + Button *scrollDownButton = getScrollDownButton(); + scrollDownButton->x = menu.scrollDownButtonX + menu.x; + scrollDownButton->y = menu.scrollDownButtonY + menu.y; + scrollDownButton->buttonCallback = getScrollDownButtonHandler(); + scrollDownButton->nextButton = 0; + scrollDownButton->mouseWheel = 1; + + _menuButtonList = addButtonToList(_menuButtonList, scrollDownButton); + updateMenuButton(scrollDownButton); + } + + _screen->showMouse(); + _screen->updateScreen(); +} + +void GUI_v1::processHighlights(Menu &menu) { + int x1, y1, x2, y2; + Common::Point p = _vm->getMousePos(); + int mouseX = p.x; + int mouseY = p.y; + + if (_vm->game() == GI_LOL && menu.highlightedItem != 255) { + // LoL doesnt't have default highlighted items. + // We use a highlightedItem value of 255 for this. + + // With LoL no highlighting should take place unless the + // mouse cursor moves over a button. The highlighting should end + // when the mouse cursor leaves the button. + if (menu.item[menu.highlightedItem].enabled) + redrawText(menu); + } + + for (int i = 0; i < menu.numberOfItems; ++i) { + if (!menu.item[i].enabled) + continue; + + x1 = menu.x + menu.item[i].x; + y1 = menu.y + menu.item[i].y; + + x2 = x1 + menu.item[i].width; + y2 = y1 + menu.item[i].height; + + if (mouseX > x1 && mouseX < x2 && + mouseY > y1 && mouseY < y2) { + + if (menu.highlightedItem != i || _vm->game() == GI_LOL) { + if (_vm->game() != GI_LOL) { + if (menu.item[menu.highlightedItem].enabled) + redrawText(menu); + } + + menu.highlightedItem = i; + redrawHighlight(menu); + } + } + } + + _screen->updateScreen(); +} + +void GUI_v1::redrawText(const Menu &menu) { + int textX; + int i = menu.highlightedItem; + + int x1 = menu.x + menu.item[i].x; + int y1 = menu.y + menu.item[i].y; + + int x2 = x1 + menu.item[i].width - 1; + + if (menu.item[i].titleX >= 0) + textX = x1 + menu.item[i].titleX + 3; + else + textX = getMenuCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2); + + int textY = y1 + 2; + if (_vm->game() == GI_LOL) { + textY++; + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 8); + } else { + Screen::FontId of = _screen->_currentFont; + if (menu.item[i].saveSlot > 0) + _screen->setFont(Screen::FID_8_FNT); + if (_vm->gameFlags().platform != Common::kPlatformAmiga) + printMenuText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0); + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 0); + _screen->setFont(of); + } +} + +void GUI_v1::redrawHighlight(const Menu &menu) { + int textX; + int i = menu.highlightedItem; + + int x1 = menu.x + menu.item[i].x; + int y1 = menu.y + menu.item[i].y; + + int x2 = x1 + menu.item[i].width - 1; + + if (menu.item[i].titleX != -1) + textX = x1 + menu.item[i].titleX + 3; + else + textX = getMenuCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2); + + int textY = y1 + 2; + + if (_vm->game() == GI_LOL) { + textY++; + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 8); + } else { + Screen::FontId of = _screen->_currentFont; + if (menu.item[i].saveSlot > 0) + _screen->setFont(Screen::FID_8_FNT); + if (_vm->gameFlags().platform != Common::kPlatformAmiga) + printMenuText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0); + printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 0); + _screen->setFont(of); + } +} + +void GUI_v1::updateAllMenuButtons() { + for (Button *cur = _menuButtonList; cur; cur = cur->nextButton) + updateMenuButton(cur); +} + +void GUI_v1::updateMenuButton(Button *button) { + if (!_displayMenu) + return; + + _screen->hideMouse(); + updateButton(button); + _screen->updateScreen(); + _screen->showMouse(); +} + +void GUI_v1::updateButton(Button *button) { + if (!button || (button->flags & 8)) + return; + + if (button->flags2 & 1) + button->flags2 &= 0xFFF7; + else + button->flags2 |= 8; + + button->flags2 &= 0xFFFC; + + if (button->flags2 & 4) + button->flags2 |= 0x10; + else + button->flags2 &= 0xEEEF; + + button->flags2 &= 0xFFFB; + + processButton(button); +} + +int GUI_v1::redrawButtonCallback(Button *button) { + if (!_displayMenu) + return 0; + + _screen->hideMouse(); + if (_vm->gameFlags().platform == Common::kPlatformAmiga) + _screen->drawBox(button->x + 1, button->y + 1, button->x + button->width - 1, button->y + button->height - 1, 17); + else + _screen->drawBox(button->x + 1, button->y + 1, button->x + button->width - 1, button->y + button->height - 1, 0xF8); + _screen->showMouse(); + + return 0; +} + +int GUI_v1::redrawShadedButtonCallback(Button *button) { + if (!_displayMenu) + return 0; + + _screen->hideMouse(); + if (_vm->gameFlags().platform == Common::kPlatformAmiga) + _screen->drawShadedBox(button->x, button->y, button->x + button->width, button->y + button->height, 31, 18); + else + _screen->drawShadedBox(button->x, button->y, button->x + button->width, button->y + button->height, 0xF9, 0xFA); + _screen->showMouse(); + + return 0; +} + +void GUI_v1::checkTextfieldInput() { + Common::Event event; + + uint32 now = _vm->_system->getMillis(); + + bool running = true; + int keys = 0; + while (_vm->_eventMan->pollEvent(event) && running) { + switch (event.type) { + case Common::EVENT_KEYDOWN: + if (event.kbd.keycode == Common::KEYCODE_q && event.kbd.hasFlags(Common::KBD_CTRL)) + _vm->quitGame(); + else + _keyPressed = event.kbd; + running = false; + break; + + case Common::EVENT_LBUTTONDOWN: + case Common::EVENT_LBUTTONUP: { + Common::Point pos = _vm->getMousePos(); + _vm->_mouseX = pos.x; + _vm->_mouseY = pos.y; + keys = event.type == Common::EVENT_LBUTTONDOWN ? 199 : (200 | 0x800); + running = false; + } break; + + case Common::EVENT_MOUSEMOVE: { + Common::Point pos = _vm->getMousePos(); + _vm->_mouseX = pos.x; + _vm->_mouseY = pos.y; + + _vm->_system->updateScreen(); + _lastScreenUpdate = now; + } break; + + default: + break; + } + } + + if (now - _lastScreenUpdate > 50) { + _vm->_system->updateScreen(); + _lastScreenUpdate = now; + } + + processButtonList(_menuButtonList, keys | 0x8000, 0); + _vm->_system->delayMillis(3); +} + +void GUI_v1::printMenuText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 c2) { + _text->printText(str, x, y, c0, c1, c2); +} + +int GUI_v1::getMenuCenterStringX(const char *str, int x1, int x2) { + return _text->getCenterStringX(str, x1, x2); +} + +#pragma mark - + +MainMenu::MainMenu(KyraEngine_v1 *vm) : _vm(vm), _screen(0) { + _screen = _vm->screen(); + _nextUpdate = 0; + _system = g_system; +} + +void MainMenu::init(StaticData data, Animation anim) { + _static = data; + _anim = anim; + _animIntern.curFrame = _anim.startFrame; + _animIntern.direction = 1; +} + +void MainMenu::updateAnimation() { + if (_anim.anim) { + uint32 now = _system->getMillis(); + if (now > _nextUpdate) { + _nextUpdate = now + _anim.delay * _vm->tickLength(); + + _anim.anim->displayFrame(_animIntern.curFrame, 0, 0, 0, 0, 0, 0); + _animIntern.curFrame += _animIntern.direction; + if (_animIntern.curFrame < _anim.startFrame) { + _animIntern.curFrame = _anim.startFrame; + _animIntern.direction = 1; + } else if (_animIntern.curFrame > _anim.endFrame) { + _animIntern.curFrame = _anim.endFrame; + _animIntern.direction = -1; + } + } + } + + _screen->updateScreen(); +} + +bool MainMenu::getInput() { + Common::Event event; + Common::EventManager *eventMan = _vm->getEventManager(); + + bool updateScreen = false; + + while (eventMan->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_LBUTTONUP: + return true; + + case Common::EVENT_MOUSEMOVE: + updateScreen = true; + break; + + default: + break; + } + } + + if (updateScreen) + _system->updateScreen(); + return false; +} + +int MainMenu::handle(int dim) { + int command = -1; + + uint8 colorMap[16]; + memset(colorMap, 0, sizeof(colorMap)); + _screen->setTextColorMap(colorMap); + + Screen::FontId oldFont = _screen->setFont(_static.font); + int charWidthBackUp = _screen->_charWidth; + + if (_vm->game() != GI_LOL) + _screen->_charWidth = -2; + _screen->setScreenDim(dim); + + int backUpX = _screen->_curDim->sx; + int backUpY = _screen->_curDim->sy; + int backUpWidth = _screen->_curDim->w; + int backUpHeight = _screen->_curDim->h; + _screen->copyRegion(backUpX, backUpY, backUpX, backUpY, backUpWidth, backUpHeight, 0, 3); + + int x = _screen->_curDim->sx << 3; + int y = _screen->_curDim->sy; + int width = _screen->_curDim->w << 3; + int height = _screen->_curDim->h; + + drawBox(x, y, width, height, 1); + drawBox(x + 1, y + 1, width - 2, height - 2, 0); + + int selected = 0; + + draw(selected); + + while (!_screen->isMouseVisible()) + _screen->showMouse(); + + int fh = _screen->getFontHeight(); + if (_vm->gameFlags().lang == Common::JA_JPN) + fh++; + + int textPos = ((_screen->_curDim->w >> 1) + _screen->_curDim->sx) << 3; + + Common::Rect menuRect(x + 16, y + 4, x + width - 16, y + 4 + fh * _static.menuTable[3]); + + while (!_vm->shouldQuit()) { + updateAnimation(); + bool mousePressed = getInput(); + + Common::Point mouse = _vm->getMousePos(); + if (menuRect.contains(mouse)) { + int item = (mouse.y - menuRect.top) / fh; + + if (item != selected) { + printString("%s", textPos, menuRect.top + selected * fh, _static.menuTable[5], 0, 5, _static.strings[selected]); + printString("%s", textPos, menuRect.top + item * fh, _static.menuTable[6], 0, 5, _static.strings[item]); + + selected = item; + } + + if (mousePressed) { + for (int i = 0; i < 3; i++) { + printString("%s", textPos, menuRect.top + selected * fh, _static.menuTable[5], 0, 5, _static.strings[selected]); + _screen->updateScreen(); + _system->delayMillis(50); + printString("%s", textPos, menuRect.top + selected * fh, _static.menuTable[6], 0, 5, _static.strings[selected]); + _screen->updateScreen(); + _system->delayMillis(50); + } + command = item; + break; + } + } + _system->delayMillis(10); + } + + if (_vm->shouldQuit()) + command = -1; + + _screen->copyRegion(backUpX, backUpY, backUpX, backUpY, backUpWidth, backUpHeight, 3, 0); + _screen->_charWidth = charWidthBackUp; + _screen->setFont(oldFont); + + return command; +} + +void MainMenu::draw(int select) { + int top = _screen->_curDim->sy; + top += _static.menuTable[1]; + int fh = _screen->getFontHeight(); + if (_vm->gameFlags().lang == Common::JA_JPN) + fh++; + + for (int i = 0; i < _static.menuTable[3]; ++i) { + int curY = top + i * fh; + int color = (i == select) ? _static.menuTable[6] : _static.menuTable[5]; + printString("%s", ((_screen->_curDim->w >> 1) + _screen->_curDim->sx) << 3, curY, color, 0, 5, _static.strings[i]); + } +} + +void MainMenu::drawBox(int x, int y, int w, int h, int fill) { + --w; --h; + + if (fill) + _screen->fillRect(x, y, x+w, y+h, _static.colorTable[0]); + + _screen->drawClippedLine(x, y+h, x+w, y+h, _static.colorTable[1]); + _screen->drawClippedLine(x+w, y, x+w, y+h, _static.colorTable[1]); + _screen->drawClippedLine(x, y, x+w, y, _static.colorTable[2]); + _screen->drawClippedLine(x, y, x, y+h, _static.colorTable[2]); + + _screen->setPagePixel(_screen->_curPage, x, y+h, _static.colorTable[3]); + _screen->setPagePixel(_screen->_curPage, x+w, y, _static.colorTable[3]); +} + +void MainMenu::printString(const char *format, int x, int y, int col1, int col2, int flags, ...) { + if (!format) + return; + + va_list vaList; + va_start(vaList, flags); + Common::String string = Common::String::vformat(format, vaList); + va_end(vaList); + + if (flags & 1) + x -= _screen->getTextWidth(string.c_str()) >> 1; + + if (flags & 2) + x -= _screen->getTextWidth(string.c_str()); + + if (_vm->gameFlags().use16ColorMode) + flags &= 3; + + if (flags & 4) { + _screen->printText(string.c_str(), x - 1, y, _static.altColor, col2); + _screen->printText(string.c_str(), x, y + 1, _static.altColor, col2); + } + + if (flags & 8) { + _screen->printText(string.c_str(), x - 1, y, 227, col2); + _screen->printText(string.c_str(), x, y + 1, 227, col2); + } + + _screen->printText(string.c_str(), x, y, col1, col2); +} + +} // End of namespace Kyra + -- cgit v1.2.3