added walkthrough

svn-id: r15835
This commit is contained in:
Paweł Kołodziejski 2004-11-19 19:50:22 +00:00
parent c4a8b3c8b5
commit 20e9cf6f20
16 changed files with 388 additions and 3 deletions

View File

@ -47,6 +47,8 @@ Engine::Engine(OSystem *syst)
g_debugLevel = ConfMan.getInt("debuglevel");
_saveFileMan = _system->getSavefileManager();
_walkthroughDialog = new GUI::WalkthroughDialog(1.0, 1.0);
}
Engine::~Engine() {
@ -54,8 +56,9 @@ Engine::~Engine() {
delete _mixer;
delete _saveFileMan;
delete _walkthroughDialog;
g_engine = 0;
g_engine = NULL;
}
const char *Engine::getSavePath() const {

View File

@ -25,6 +25,8 @@
#include "common/str.h"
#include "common/system.h"
#include "gui/walkthrough.h"
class SoundMixer;
class Timer;
@ -37,6 +39,7 @@ public:
protected:
const Common::String _gameDataPath;
SaveFileManager *_saveFileMan;
GUI::WalkthroughDialog *_walkthroughDialog;
public:
Engine(OSystem *syst);

View File

@ -16,6 +16,7 @@ MODULE_OBJS := \
gui/PopUpWidget.o \
gui/ScrollBarWidget.o \
gui/TabWidget.o \
gui/walkthrough.o \
gui/widget.o
MODULE_DIRS += \

247
gui/walkthrough.cpp Normal file
View File

@ -0,0 +1,247 @@
/* ScummVM - Scumm Interpreter
* Copyright (C) 2002-2004 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header$
*/
#include "stdafx.h"
#include "common/file.h"
#include "graphics/font.h"
#include "gui/walkthrough.h"
#include "gui/ScrollBarWidget.h"
namespace GUI {
extern const Graphics::NewFont g_consolefont;
#define kConsoleCharWidth (g_consolefont.getMaxCharWidth())
#define kConsoleLineHeight (g_consolefont.getFontHeight() + 2)
WalkthroughDialog::WalkthroughDialog(float widthPercent, float heightPercent)
: Dialog(0, 0, 1, 1),
_initialized(false), _widthPercent(widthPercent), _heightPercent(heightPercent) {
}
WalkthroughDialog::~WalkthroughDialog() {
destroy();
}
static int getNextWordLength(byte *src, int maxLength) {
int l;
for (l = 0; l < maxLength; l++) {
byte tmp = src[l];
if ((tmp >= 0) && (tmp <= ' '))
break;
}
return l;
}
bool WalkthroughDialog::loadWalkthroughText(const char *gameName) {
char filename[MAX_PATH];
File file;
sprintf(filename, "%s.wkt", gameName);
file.open(filename);
if (!file.isOpen())
return false;
int bufferSize = file.size();
byte *buffer = (byte *)malloc(bufferSize);
file.read(buffer, bufferSize);
file.close();
int currentLinePos = 0;
byte *currentBuffer = buffer;
byte *lineBuffer = (byte *)malloc(_lineWidth + 1);
lineBuffer[0] = 0;
for (;;) {
if ((currentBuffer - buffer) >= bufferSize)
break;
int wordLength = getNextWordLength(currentBuffer, _lineWidth);
if (((currentLinePos + wordLength) < _lineWidth) &&
((*currentBuffer != 0x0a) && (*currentBuffer != 0x0d))) {
if ((*currentBuffer >= 0) && (*currentBuffer <= ' ')) {
lineBuffer[currentLinePos++] = ' ';
currentBuffer++;
} else {
memcpy(lineBuffer + currentLinePos, currentBuffer, wordLength);
currentLinePos += wordLength;
currentBuffer += wordLength;
if ((currentLinePos + 1) < _lineWidth) {
lineBuffer[currentLinePos] = ' ';
currentLinePos++;
}
}
} else {
if (*currentBuffer == 0x0d) {
currentBuffer++;
if ((*currentBuffer == 0x0a) && ((currentBuffer - buffer) < bufferSize)) {
currentBuffer++;
}
} else if (*currentBuffer == 0x0a) {
currentBuffer++;
}
lineBuffer[currentLinePos] = 0;
Entry line;
line.text = String((char *)lineBuffer);
_linesArray.push_back(line);
lineBuffer[0] = 0;
currentLinePos = 0;
}
}
free(buffer);
free(lineBuffer);
return true;
}
void WalkthroughDialog::create(const char *gameName) {
// Setup basic layout/dialog size
reflowLayout();
// Add scrollbar
_scrollBar = new ScrollBarWidget(this, _w - kScrollBarWidth - 1, 0, kScrollBarWidth, _h);
_scrollBar->setTarget(this);
_currentPos = 0;
_scrollLine = _linesPerPage - 1;
loadWalkthroughText(gameName);
_initialized = true;
}
void WalkthroughDialog::destroy() {
if (!_initialized)
return;
_linesArray.clear();
_initialized = false;
}
void WalkthroughDialog::reflowLayout() {
// Calculate the real width/height (rounded to char/line multiples)
_w = (uint16)(_widthPercent * g_system->getOverlayWidth());
_h = (uint16)((_heightPercent * g_system->getOverlayHeight() - 2) / kConsoleLineHeight);
_h = _h * kConsoleLineHeight + 2;
// Calculate depending values
_lineWidth = (_w - kScrollBarWidth - 2) / kConsoleCharWidth;
_linesPerPage = (_h - 2) / kConsoleLineHeight;
}
void WalkthroughDialog::open() {
Dialog::open();
}
void WalkthroughDialog::drawDialog() {
// Blend over the background
g_gui.fillRect(_x, _y, _w, _h, g_gui._bgcolor);
// Draw a border
g_gui.hLine(_x, _y + _h - 1, _x + _w - 1, g_gui._color);
// Draw text
int y = _y + 2;
for (int line = 0; (line < _linesPerPage) && ((_currentPos + line) < (int)_linesArray.size()); line++) {
const char *text = _linesArray[line + _currentPos].text.c_str();
int textLen = strlen(text);
int x = _x + 1;
for (int column = 0; (column < _lineWidth) && (column < textLen); column++) {
byte c = text[column];
g_gui.drawChar(c, x, y, g_gui._textcolor, &g_consolefont);
x += kConsoleCharWidth;
}
y += kConsoleLineHeight;
}
// Draw the scrollbar
_scrollBar->_numEntries = _linesArray.size();
_scrollBar->_currentPos = _currentPos;
_scrollBar->_entriesPerPage = _linesPerPage;
_scrollBar->recalc();
_scrollBar->draw();
// Finally blit it all to the screen
g_gui.addDirtyRect(_x, _y, _w, _h);
}
void WalkthroughDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
switch (cmd) {
case kSetPositionCmd:
_currentPos = _scrollBar->_currentPos;
drawDialog();
break;
default:
return;
}
}
void WalkthroughDialog::handleMouseWheel(int x, int y, int direction) {
_scrollBar->handleMouseWheel(x, y, direction);
}
void WalkthroughDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
if ((modifiers == OSystem::KBD_CTRL) && (keycode == 'w')) {
close();
return;
}
switch (keycode) {
case 256 + 17: // up arrow
_currentPos--;
break;
case 256 + 18: // down arrow
_currentPos++;
break;
case 256 + 22: // home
_currentPos = 0;
break;
case 256 + 23: // end
_currentPos = _linesArray.size() - _linesPerPage;
break;
case 256 + 24: // page up
_currentPos -= _linesPerPage;
break;
case 256 + 25: // page down
_currentPos += _linesPerPage;
break;
default:
return;
}
if (_currentPos < 0) {
_currentPos = 0;
}
if ((_currentPos + _linesPerPage) >= (int)_linesArray.size()) {
_currentPos = _linesArray.size() - _linesPerPage;
}
drawDialog();
}
} // End of namespace GUI

76
gui/walkthrough.h Normal file
View File

@ -0,0 +1,76 @@
/* ScummVM - Scumm Interpreter
* Copyright (C) 2002-2004 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header$
*/
#ifndef WALKTHROUGH_DIALOG_H
#define WALKTHROUGH_DIALOG_H
#include "common/array.h"
#include "common/str.h"
#include "gui/dialog.h"
#include "gui/newgui.h"
#include <stdarg.h>
namespace GUI {
class ScrollBarWidget;
class WalkthroughDialog : public Dialog {
private:
bool _initialized;
int _lineWidth;
int _linesPerPage;
int _currentPos;
int _scrollLine;
int _firstLineInBuffer;
typedef Common::String String;
struct Entry {
String text;
};
typedef Common::Array<Entry> EntryList;
EntryList _linesArray;
ScrollBarWidget *_scrollBar;
float _widthPercent, _heightPercent;
void reflowLayout();
bool loadWalkthroughText(const char *gameName);
public:
WalkthroughDialog(float widthPercent, float heightPercent);
~WalkthroughDialog();
void create(const char *gameName);
void destroy();
void open();
void drawDialog();
void handleMouseWheel(int x, int y, int direction);
void handleKeyDown(uint16 ascii, int keycode, int modifiers);
void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
};
} // End of namespace GUI
#endif

View File

@ -169,6 +169,9 @@ KyraEngine::KyraEngine(GameDetector *detector, OSystem *syst)
assert(_npcScript);
assert(_currentScript);
_walkthroughDialog->setGameName(detector->_game.name);
_walkthroughDialog->create();
}
KyraEngine::~KyraEngine() {
@ -179,6 +182,8 @@ KyraEngine::~KyraEngine() {
delete _npcScript;
delete _currentScript;
delete _font;
_walkthroughDialog->destroy();
}
void KyraEngine::errorString(const char *buf1, char *buf2) {

View File

@ -20,9 +20,11 @@
*/
#include "stdafx.h"
#include "queen/input.h"
#include "common/system.h"
#include "queen/input.h"
namespace Queen {
const char *Input::_commandKeys[LANGUAGE_COUNT] = {
@ -102,6 +104,8 @@ void Input::delay(uint amount) {
_debugger = true;
} else if (event.kbd.keycode == 'f') {
_fastMode = !_fastMode;
} else if (event.kbd.keycode == 'w') {
// _walkthroughDialog->runModal(); // FIXME
}
} else {
_inKey = event.kbd.keycode;

View File

@ -91,6 +91,7 @@ namespace Queen {
QueenEngine::QueenEngine(GameDetector *detector, OSystem *syst)
: Engine(syst) {
_walkthroughDialog->setGameName(detector->_game.name);
}
QueenEngine::~QueenEngine() {
@ -107,6 +108,8 @@ QueenEngine::~QueenEngine() {
delete _music;
delete _sound;
delete _walk;
_walkthroughDialog->destroy();
}
void QueenEngine::registerDefaultSettings() {

View File

@ -42,6 +42,8 @@ int SagaEngine::processInput() {
switch (event.event_code) {
case OSystem::EVENT_KEYDOWN:
if (event.kbd.keycode == 'w')
_walkthroughDialog->runModal();
if (_vm->_console->isActive()) {
in_char = event.kbd.ascii;
switch (event.kbd.keycode) {

View File

@ -115,9 +115,12 @@ SagaEngine::SagaEngine(GameDetector *detector, OSystem *syst)
_mixer->setVolume(ConfMan.getInt("sfx_volume") * ConfMan.getInt("master_volume") / 255);
_vm = this;
_walkthroughDialog->setGameName(detector->_game.name);
}
SagaEngine::~SagaEngine() {
_walkthroughDialog->destroy();
}
void SagaEngine::errorString(const char *buf1, char *buf2) {

View File

@ -65,6 +65,8 @@ void ScummEngine::parseEvents() {
_debugger->attach();
else if (event.kbd.keycode == 's')
resourceStats();
else if (event.kbd.keycode == 'w')
_walkthroughDialog->runModal();
else
_keyPressed = event.kbd.ascii; // Normal key press, pass on to the game.
} else if (event.kbd.flags & OSystem::KBD_ALT) {

View File

@ -897,6 +897,8 @@ ScummEngine::ScummEngine(GameDetector *detector, OSystem *syst, const ScummGameS
}
_midi = gs.midi;
_walkthroughDialog->setGameName(detector->_game.name);
}
ScummEngine::~ScummEngine() {
@ -943,6 +945,8 @@ ScummEngine::~ScummEngine() {
free(_languageIndex);
delete _debugger;
_walkthroughDialog->destroy();
}
ScummEngine_v6::ScummEngine_v6(GameDetector *detector, OSystem *syst, const ScummGameSettings &gs, uint8 md5sum[16])
@ -986,6 +990,8 @@ void ScummEngine::mainInit() {
// Initialize backend
_system->initSize(_screenWidth, _screenHeight);
_walkthroughDialog->create();
int cd_num = ConfMan.getInt("cdrom");
if (cd_num >= 0 && (_features & GF_AUDIOTRACKS))
_system->openCD(cd_num);

View File

@ -718,6 +718,9 @@ SimonEngine::SimonEngine(GameDetector *detector, OSystem *syst)
// FIXME Use auto dirty rects cleanup code to reduce CPU usage
g_system->setFeatureState(OSystem::kFeatureAutoComputeDirtyRects, true);
_walkthroughDialog->setGameName(detector->_game.name);
_walkthroughDialog->create();
}
SimonEngine::~SimonEngine() {
@ -729,6 +732,8 @@ SimonEngine::~SimonEngine() {
delete _sound;
delete _debugger;
_walkthroughDialog->destroy();
}
void SimonEngine::errorString(const char *buf1, char *buf2) {
@ -4848,6 +4853,8 @@ void SimonEngine::delay(uint amount) {
_aboutDialog->runModal();
} else if (event.kbd.keycode == 'f')
_fast_mode ^= 1;
else if (event.kbd.keycode == 'w')
_walkthroughDialog->runModal();
else if (event.kbd.keycode == 'd')
_debugger->attach();
}

View File

@ -116,6 +116,8 @@ SystemVars SkyEngine::_systemVars = {0, 0, 0, 0, 4316, 0, 0, false, false };
SkyEngine::SkyEngine(GameDetector *detector, OSystem *syst)
: Engine(syst), _fastMode(0) {
_walkthroughDialog->setGameName(detector->_game.name);
_walkthroughDialog->create();
}
SkyEngine::~SkyEngine() {
@ -127,6 +129,8 @@ SkyEngine::~SkyEngine() {
delete _skyMouse;
delete _skyScreen;
delete _debugger;
_walkthroughDialog->destroy();
}
void SkyEngine::errorString(const char *buf1, char *buf2) {
@ -461,6 +465,9 @@ void SkyEngine::delay(uint amount) {
if (event.kbd.keycode == 'd') {
_debugger->attach();
}
if (event.kbd.keycode == 'w') {
_walkthroughDialog->runModal();
}
}
// Make sure backspace works right (this fixes a small issue on OS X)

View File

@ -109,6 +109,8 @@ SwordEngine::SwordEngine(GameDetector *detector, OSystem *syst)
if (!_mixer->isReady())
warning("Sound initialization failed");
_walkthroughDialog->setGameName(detector->_game.name);
}
SwordEngine::~SwordEngine() {
@ -121,6 +123,8 @@ SwordEngine::~SwordEngine() {
delete _mouse;
delete _objectMan;
delete _resMan;
_walkthroughDialog->destroy();
}
void SwordEngine::initialize(void) {
@ -198,6 +202,8 @@ void SwordEngine::initialize(void) {
_objectMan->initialize();
_mouse->initialize();
_control = new Control(_saveFileMan, _resMan, _objectMan, _system, _mouse, _sound, _music, getSavePath());
_walkthroughDialog->create();
}
void SwordEngine::reinitialize(void) {
@ -1283,6 +1289,8 @@ void SwordEngine::delay(uint amount) { //copied and mutilated from sky.cpp
_keyPressed = 8;
else
_keyPressed = (uint8)event.kbd.ascii;
if (event.kbd.keycode == 'w')
_walkthroughDialog->runModal();
break;
case OSystem::EVENT_MOUSEMOVE:
_mouseX = event.mouse.x;

View File

@ -180,6 +180,8 @@ Sword2Engine::Sword2Engine(GameDetector *detector, OSystem *syst) : Engine(syst)
_gameCycle = 0;
_quit = false;
_walkthroughDialog->setGameName(detector->_game.name);
}
Sword2Engine::~Sword2Engine() {
@ -193,6 +195,8 @@ Sword2Engine::~Sword2Engine() {
delete _logic;
delete _resman;
delete _memory;
_walkthroughDialog->destroy();
}
void Sword2Engine::errorString(const char *buf1, char *buf2) {
@ -296,6 +300,8 @@ void Sword2Engine::mainInit() {
startGame();
_graphics->initialiseRenderCycle();
_walkthroughDialog->create();
}
void Sword2Engine::mainRun() {
@ -315,6 +321,8 @@ void Sword2Engine::mainRun() {
if (ke) {
if ((ke->modifiers == OSystem::KBD_CTRL && ke->keycode == 'd') || ke->ascii == '#' || ke->ascii == '~') {
_debugger->attach();
} else if ((ke->modifiers == OSystem::KBD_SHIFT) && (ke->keycode == 'w')) {
_walkthroughDialog->runModal();
} else if (ke->modifiers == 0 || ke->modifiers == OSystem::KBD_SHIFT) {
switch (ke->keycode) {
case 'p':
@ -511,7 +519,7 @@ void Sword2Engine::startGame() {
// script #1, but with different ScreenManager objects depending on
// if it's the demo or the full game, or if we're using a boot param.
int screen_manager_id;
int screen_manager_id = 0;
debug(5, "startGame() STARTING:");