mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-22 09:49:11 +00:00
c0db9c0d25
svn-id: r31796
538 lines
14 KiB
C++
538 lines
14 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.
|
|
*
|
|
* $URL$
|
|
* $Id$
|
|
*
|
|
*/
|
|
|
|
#include "kyra/gui.h"
|
|
|
|
#include "kyra/screen.h"
|
|
#include "kyra/text.h"
|
|
#include "kyra/wsamovie.h"
|
|
|
|
#include "common/savefile.h"
|
|
|
|
namespace Kyra {
|
|
|
|
GUI::GUI(KyraEngine *kyra)
|
|
: _vm(kyra), _screen(kyra->screen()), _text(kyra->text()) {
|
|
_menuButtonList = 0;
|
|
_haveScrollButtons = false;
|
|
|
|
_redrawButtonFunctor = BUTTON_FUNCTOR(GUI, this, &GUI::redrawButtonCallback);
|
|
_redrawShadedButtonFunctor = BUTTON_FUNCTOR(GUI, this, &GUI::redrawShadedButtonCallback);
|
|
}
|
|
|
|
Button *GUI::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::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::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 = _text->getCenterStringX(getMenuTitle(menu), menu.x, menu_x2);
|
|
|
|
textY = menu.y + menu.titleY;
|
|
|
|
_text->printText(getMenuTitle(menu), textX - 1, textY + 1, defaultColor1(), defaultColor2(), 0);
|
|
_text->printText(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->unk6 = menu.item[i].unk1F;
|
|
menuButtonData->unk8 = 0;
|
|
|
|
_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 = _text->getCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2);
|
|
|
|
textY = y1 + 2;
|
|
_text->printText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0);
|
|
|
|
if (i == menu.highlightedItem)
|
|
_text->printText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 0);
|
|
else
|
|
_text->printText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 0);
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < menu.numberOfItems; ++i) {
|
|
if (getMenuItemLabel(menu.item[i])) {
|
|
_text->printText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX - 1, menu.y + menu.item[i].labelY + 1, defaultColor1(), 0, 0);
|
|
_text->printText(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) {
|
|
_haveScrollButtons = true;
|
|
|
|
Button *scrollUpButton = getScrollUpButton();
|
|
scrollUpButton->x = menu.scrollUpButtonX + menu.x;
|
|
scrollUpButton->y = menu.scrollUpButtonY + menu.y;
|
|
scrollUpButton->buttonCallback = getScrollUpButtonHandler();
|
|
scrollUpButton->nextButton = 0;
|
|
|
|
_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;
|
|
|
|
_menuButtonList = addButtonToList(_menuButtonList, scrollDownButton);
|
|
updateMenuButton(scrollDownButton);
|
|
} else {
|
|
_haveScrollButtons = false;
|
|
}
|
|
|
|
_screen->showMouse();
|
|
_screen->updateScreen();
|
|
}
|
|
|
|
void GUI::processHighlights(Menu &menu, int mouseX, int mouseY) {
|
|
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;
|
|
y2 = y1 + menu.item[i].height;
|
|
|
|
if (mouseX > x1 && mouseX < x2 &&
|
|
mouseY > y1 && mouseY < y2) {
|
|
|
|
if (menu.highlightedItem != i) {
|
|
if (menu.item[menu.highlightedItem].enabled)
|
|
redrawText(menu);
|
|
|
|
menu.highlightedItem = i;
|
|
redrawHighlight(menu);
|
|
_screen->updateScreen();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GUI::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 = _text->getCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2);
|
|
|
|
int textY = y1 + 2;
|
|
_text->printText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0);
|
|
_text->printText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 0);
|
|
}
|
|
|
|
void GUI::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 = _text->getCenterStringX(getMenuItemTitle(menu.item[i]), x1, x2);
|
|
|
|
int textY = y1 + 2;
|
|
_text->printText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0);
|
|
_text->printText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 0);
|
|
}
|
|
|
|
void GUI::updateAllMenuButtons() {
|
|
for (Button *cur = _menuButtonList; cur; cur = cur->nextButton)
|
|
updateMenuButton(cur);
|
|
}
|
|
|
|
void GUI::updateMenuButton(Button *button) {
|
|
if (!_displayMenu)
|
|
return;
|
|
|
|
_screen->hideMouse();
|
|
updateButton(button);
|
|
_screen->updateScreen();
|
|
_screen->showMouse();
|
|
}
|
|
|
|
void GUI::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::redrawButtonCallback(Button *button) {
|
|
if (!_displayMenu)
|
|
return 0;
|
|
|
|
_screen->hideMouse();
|
|
_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::redrawShadedButtonCallback(Button *button) {
|
|
if (!_displayMenu)
|
|
return 0;
|
|
|
|
_screen->hideMouse();
|
|
_screen->drawShadedBox(button->x, button->y, button->x + button->width, button->y + button->height, 0xF9, 0xFA);
|
|
_screen->showMouse();
|
|
|
|
return 0;
|
|
}
|
|
|
|
void GUI::updateSaveList() {
|
|
Common::String pattern = _vm->_targetName + ".???";
|
|
Common::StringList saveFileList = _vm->_saveFileMan->listSavefiles(pattern.c_str());
|
|
_saveSlots.clear();
|
|
|
|
for (Common::StringList::const_iterator i = saveFileList.begin(); i != saveFileList.end(); ++i) {
|
|
char s1 = 0, s2 = 0, s3 = 0;
|
|
s1 = (*i)[i->size()-3];
|
|
s2 = (*i)[i->size()-2];
|
|
s3 = (*i)[i->size()-1];
|
|
if (!isdigit(s1) || !isdigit(s2) || !isdigit(s3))
|
|
continue;
|
|
s1 -= '0';
|
|
s2 -= '0';
|
|
s3 -= '0';
|
|
_saveSlots.push_back(s1*100+s2*10+s3);
|
|
}
|
|
|
|
if (_saveSlots.begin() == _saveSlots.end())
|
|
return;
|
|
|
|
Common::sort(_saveSlots.begin(), _saveSlots.end(), Common::Less<int>());
|
|
if (_saveSlots.size() > 2)
|
|
Common::sort(_saveSlots.begin()+1, _saveSlots.end(), Common::Greater<int>());
|
|
}
|
|
|
|
int GUI::getNextSavegameSlot() {
|
|
Common::InSaveFile *in;
|
|
|
|
for (int i = 1; i < 990; i++) {
|
|
if ((in = _vm->_saveFileMan->openForLoading(_vm->getSavegameFilename(i))))
|
|
delete in;
|
|
else
|
|
return i;
|
|
}
|
|
warning("Didn't save: Ran out of saveGame filenames");
|
|
return 0;
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
MainMenu::MainMenu(KyraEngine *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);
|
|
_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;
|
|
|
|
while (_system->getEventManager()->pollEvent(event)) {
|
|
switch (event.type) {
|
|
case Common::EVENT_QUIT:
|
|
_quitFlag = true;
|
|
break;
|
|
case Common::EVENT_LBUTTONUP:
|
|
return true;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int MainMenu::handle(int dim) {
|
|
debugC(9, kDebugLevelMain, "MainMenu::handle(%d)", dim);
|
|
int command = -1;
|
|
_quitFlag = false;
|
|
|
|
uint8 colorMap[16];
|
|
memset(colorMap, 0, sizeof(colorMap));
|
|
_screen->setTextColorMap(colorMap);
|
|
|
|
Screen::FontId oldFont = _screen->setFont(Screen::FID_8_FNT);
|
|
int charWidthBackUp = _screen->_charWidth;
|
|
|
|
_screen->_charWidth = -2;
|
|
_screen->setScreenDim(dim);
|
|
|
|
while (!_screen->isMouseVisible())
|
|
_screen->showMouse();
|
|
|
|
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);
|
|
|
|
_screen->showMouse();
|
|
|
|
int fh = _screen->getFontHeight();
|
|
int textPos = ((_screen->_curDim->w >> 1) + _screen->_curDim->sx) << 3;
|
|
|
|
Common::Rect menuRect(x + 16, y + 4, x + width - 16, y + 4 + fh * 4);
|
|
|
|
while (!_quitFlag) {
|
|
updateAnimation();
|
|
bool mousePressed = getInput();
|
|
|
|
Common::Point mouse = _vm->getMousePos();
|
|
if (menuRect.contains(mouse)) {
|
|
int item = (mouse.y - menuRect.top) / fh;
|
|
|
|
if (item != selected) {
|
|
printString(_static.strings[selected], textPos, menuRect.top + selected * fh, _static.colorNormal, 0, 5);
|
|
printString(_static.strings[item], textPos, menuRect.top + item * fh, _static.colorFlash, 0, 5);
|
|
|
|
selected = item;
|
|
}
|
|
|
|
if (mousePressed) {
|
|
for (int i = 0; i < 3; i++) {
|
|
printString(_static.strings[selected], textPos, menuRect.top + selected * fh, _static.colorNormal, 0, 5);
|
|
_screen->updateScreen();
|
|
_system->delayMillis(50);
|
|
printString(_static.strings[selected], textPos, menuRect.top + selected * fh, _static.colorFlash, 0, 5);
|
|
_screen->updateScreen();
|
|
_system->delayMillis(50);
|
|
}
|
|
command = item;
|
|
break;
|
|
}
|
|
}
|
|
_system->delayMillis(10);
|
|
}
|
|
|
|
if (_quitFlag)
|
|
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) {
|
|
debugC(9, kDebugLevelMain, "MainMenu::draw(%d)", select);
|
|
int top = _screen->_curDim->sy;
|
|
top += _static.menuTable[1];
|
|
|
|
for (int i = 0; i < _static.menuTable[3]; ++i) {
|
|
int curY = top + i * _screen->getFontHeight();
|
|
int color = (i == select) ? _static.menuTable[6] : _static.menuTable[5];
|
|
printString(_static.strings[i], ((_screen->_curDim->w >> 1) + _screen->_curDim->sx) << 3, curY, color, 0, 5);
|
|
}
|
|
}
|
|
|
|
void MainMenu::drawBox(int x, int y, int w, int h, int fill) {
|
|
debugC(9, kDebugLevelMain, "MainMenu::drawBox(%d, %d, %d, %d, %d)", x, y, w, h, 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, ...) {
|
|
debugC(9, kDebugLevelMain, "MainMenu::printString('%s', %d, %d, %d, %d, %d, ...)", format, x, y, col1, col2, flags);
|
|
if (!format)
|
|
return;
|
|
|
|
char string[512];
|
|
va_list vaList;
|
|
va_start(vaList, flags);
|
|
vsprintf(string, format, vaList);
|
|
va_end(vaList);
|
|
|
|
if (flags & 1)
|
|
x -= _screen->getTextWidth(string) >> 1;
|
|
|
|
if (flags & 2)
|
|
x -= _screen->getTextWidth(string);
|
|
|
|
if (flags & 4) {
|
|
_screen->printText(string, x - 1, y, 240, col2);
|
|
_screen->printText(string, x, y + 1, 240, col2);
|
|
}
|
|
|
|
if (flags & 8) {
|
|
_screen->printText(string, x - 1, y, 227, col2);
|
|
_screen->printText(string, x, y + 1, 227, col2);
|
|
}
|
|
|
|
_screen->printText(string, x, y, col1, col2);
|
|
}
|
|
|
|
} // end of namespace Kyra
|
|
|