2007-05-30 21:56:52 +00:00
|
|
|
/* 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.
|
2003-07-28 01:44:38 +00:00
|
|
|
*
|
2007-05-31 20:28:29 +00:00
|
|
|
* Additional copyright for this file:
|
|
|
|
* Copyright (C) 1994-1998 Revolution Software Ltd.
|
|
|
|
*
|
2003-07-28 01:44:38 +00:00
|
|
|
* 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
|
2005-10-18 01:30:26 +00:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2003-07-28 01:44:38 +00:00
|
|
|
*
|
2006-02-09 15:12:44 +00:00
|
|
|
* $URL$
|
|
|
|
* $Id$
|
2003-07-28 01:44:38 +00:00
|
|
|
*/
|
|
|
|
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2007-06-21 19:33:05 +00:00
|
|
|
#include "common/events.h"
|
2004-02-05 14:19:07 +00:00
|
|
|
#include "common/rect.h"
|
2003-10-29 07:53:05 +00:00
|
|
|
#include "common/config-manager.h"
|
2005-01-10 22:06:49 +00:00
|
|
|
#include "common/system.h"
|
2005-02-19 14:02:16 +00:00
|
|
|
|
2003-10-28 19:51:30 +00:00
|
|
|
#include "sword2/sword2.h"
|
2003-11-16 14:18:29 +00:00
|
|
|
#include "sword2/defs.h"
|
2006-02-17 15:07:36 +00:00
|
|
|
#include "sword2/header.h"
|
2005-02-20 15:38:48 +00:00
|
|
|
#include "sword2/controls.h"
|
2005-02-19 14:02:16 +00:00
|
|
|
#include "sword2/mouse.h"
|
2004-02-05 14:19:07 +00:00
|
|
|
#include "sword2/resman.h"
|
2006-02-17 15:07:36 +00:00
|
|
|
#include "sword2/screen.h"
|
Began what I hope is the final major restructuring of the BS2 engine.
In this first step, I have moved all opcode functions into functions.cpp,
instead of having them scattered all over the place.
To get things to compile again, I had to rewrite the overly complicated
sound effects handling. It's much simpler now.
The next step will be to move any non-trivial code out of the opcode
functions and into the appropriate object. This, I hope, will make it
easier to create well-separated objects, instead of the current mess.
I also want to tear down the artificial boundary between the main directory
and the "driver" directory. We already have a cross-platform layer; there's
no need to have yet another one. (Actually, the rewriting of the sound
effects code took one first step in this direction.)
At the final stage, I'd like to get rid of the "drivers" directory
completely, but I'll probably need some help with that if I want to
preserve the CVS history of the code.
Things will probably be a bit bumpy along the way, but I seem to have
reached a point of relative stability again, which is why I'm commiting
this now.
svn-id: r16668
2005-01-28 16:33:14 +00:00
|
|
|
#include "sword2/sound.h"
|
2003-10-04 00:52:27 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
#define MAX_STRING_LEN 64 // 20 was too low; better to be safe ;)
|
|
|
|
#define CHARACTER_OVERLAP 2 // overlap characters by 3 pixels
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
// our fonts start on SPACE character (32)
|
2005-02-20 15:38:48 +00:00
|
|
|
#define SIZE_OF_CHAR_SET (256 - 32)
|
2003-11-16 14:18:29 +00:00
|
|
|
|
|
|
|
namespace Sword2 {
|
2003-10-03 06:54:44 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
static int baseSlot = 0;
|
2003-11-16 14:18:29 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
class Widget;
|
2003-09-08 06:38:16 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
/**
|
|
|
|
* Base class for all widgets.
|
|
|
|
*/
|
|
|
|
|
|
|
|
class Widget {
|
|
|
|
protected:
|
2005-02-20 15:38:48 +00:00
|
|
|
Sword2Engine *_vm;
|
2003-11-16 14:18:29 +00:00
|
|
|
Dialog *_parent;
|
|
|
|
|
2003-12-28 15:08:12 +00:00
|
|
|
SpriteInfo *_sprites;
|
2003-11-16 14:18:29 +00:00
|
|
|
|
|
|
|
struct WidgetSurface {
|
2004-04-23 07:02:11 +00:00
|
|
|
byte *_surface;
|
2003-11-16 14:18:29 +00:00
|
|
|
bool _original;
|
|
|
|
};
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
WidgetSurface *_surfaces;
|
|
|
|
int _numStates;
|
|
|
|
int _state;
|
|
|
|
|
|
|
|
Common::Rect _hitRect;
|
|
|
|
|
|
|
|
public:
|
|
|
|
Widget(Dialog *parent, int states);
|
|
|
|
|
|
|
|
virtual ~Widget();
|
|
|
|
|
|
|
|
void createSurfaceImage(int state, uint32 res, int x, int y, uint32 pc);
|
|
|
|
void linkSurfaceImage(Widget *from, int state, int x, int y);
|
|
|
|
|
|
|
|
void createSurfaceImages(uint32 res, int x, int y);
|
|
|
|
void linkSurfaceImages(Widget *from, int x, int y);
|
|
|
|
|
|
|
|
void setHitRect(int x, int y, int width, int height);
|
|
|
|
bool isHit(int16 x, int16 y);
|
|
|
|
|
|
|
|
void setState(int state);
|
|
|
|
int getState();
|
|
|
|
|
|
|
|
virtual void paint(Common::Rect *clipRect = NULL);
|
|
|
|
|
|
|
|
virtual void onMouseEnter() {}
|
|
|
|
virtual void onMouseExit() {}
|
|
|
|
virtual void onMouseMove(int x, int y) {}
|
|
|
|
virtual void onMouseDown(int x, int y) {}
|
|
|
|
virtual void onMouseUp(int x, int y) {}
|
2003-12-19 16:50:03 +00:00
|
|
|
virtual void onWheelUp(int x, int y) {}
|
|
|
|
virtual void onWheelDown(int x, int y) {}
|
2003-12-28 15:08:12 +00:00
|
|
|
virtual void onKey(KeyboardEvent *ke) {}
|
2003-11-16 14:18:29 +00:00
|
|
|
virtual void onTick() {}
|
|
|
|
|
|
|
|
virtual void releaseMouse(int x, int y) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This class is used to draw text in dialogs, buttons, etc.
|
|
|
|
*/
|
|
|
|
|
2003-10-07 07:06:50 +00:00
|
|
|
class FontRendererGui {
|
2003-09-08 06:38:16 +00:00
|
|
|
private:
|
2005-02-20 15:38:48 +00:00
|
|
|
Sword2Engine *_vm;
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
struct Glyph {
|
2004-04-23 07:02:11 +00:00
|
|
|
byte *_data;
|
2003-09-08 06:38:16 +00:00
|
|
|
int _width;
|
|
|
|
int _height;
|
2003-11-16 14:18:29 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
Glyph _glyph[SIZE_OF_CHAR_SET];
|
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
int _fontId;
|
|
|
|
|
|
|
|
public:
|
2003-11-16 14:18:29 +00:00
|
|
|
enum {
|
|
|
|
kAlignLeft,
|
|
|
|
kAlignRight,
|
|
|
|
kAlignCenter
|
|
|
|
};
|
2003-09-08 06:38:16 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
FontRendererGui(Sword2Engine *vm, int fontId);
|
2003-11-16 14:18:29 +00:00
|
|
|
~FontRendererGui();
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2004-04-23 07:02:11 +00:00
|
|
|
void fetchText(uint32 textId, byte *buf);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2004-04-23 07:02:11 +00:00
|
|
|
int getCharWidth(byte c);
|
|
|
|
int getCharHeight(byte c);
|
2004-02-21 08:30:10 +00:00
|
|
|
|
2004-04-23 07:02:11 +00:00
|
|
|
int getTextWidth(byte *text);
|
2004-03-04 08:03:32 +00:00
|
|
|
int getTextWidth(uint32 textId);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2004-04-23 07:02:11 +00:00
|
|
|
void drawText(byte *text, int x, int y, int alignment = kAlignLeft);
|
2004-03-04 08:03:32 +00:00
|
|
|
void drawText(uint32 textId, int x, int y, int alignment = kAlignLeft);
|
2003-11-16 14:18:29 +00:00
|
|
|
};
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
FontRendererGui::FontRendererGui(Sword2Engine *vm, int fontId)
|
|
|
|
: _vm(vm), _fontId(fontId) {
|
|
|
|
byte *font = _vm->_resman->openResource(fontId);
|
2003-12-28 15:08:12 +00:00
|
|
|
SpriteInfo sprite;
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
sprite.type = RDSPR_NOCOMPRESSION | RDSPR_TRANS;
|
|
|
|
|
|
|
|
for (int i = 0; i < SIZE_OF_CHAR_SET; i++) {
|
Applied my own patch #1341495, in an attempt to fix alignment issues
reported by Crilith.
To elaborate a bit, the engine no longer accesses resource data through
packed structs. Instead it uses memory streams and the READ/WRITE
functions.
If data is mainly read, not written, I have replaced the old struct with a
new one with a read() function to read the whole thing from memory into the
struct's variables, and a write() function to dump the struct's variables
to memory. In fact, most of these write() functions remain unused.
If data is both read and written, I have replaced the struct with a class
with individual get/set functions to replace the old variables. This
manipulates memory directly.
Since I'm fairly sure that these structs are frequently stored as local
variables for a script, all script variables (both local and global) are
stored as little-endian and accessed through the READ/WRITE functions,
rather than being treated as arrays of 32-bit integers.
On a positive note, the functions for doing endian conversion of resources
and save games have been removed, and some general cleanups have been made
to assist in the rewrite.
Initial reports indicate that this patch indeed fixes alignment issues, and
that I have not - surprisingly - broken the game on big-endian platforms.
At least not in any immediately obvious way. And there's still plenty of
time to fix regressions before 0.9.0, too.
svn-id: r19366
2005-10-29 21:24:54 +00:00
|
|
|
byte *frame = _vm->fetchFrameHeader(font, i);
|
|
|
|
|
|
|
|
FrameHeader frame_head;
|
|
|
|
|
|
|
|
frame_head.read(frame);
|
|
|
|
|
|
|
|
sprite.data = frame + FrameHeader::size();
|
|
|
|
sprite.w = frame_head.width;
|
|
|
|
sprite.h = frame_head.height;
|
2005-02-20 15:38:48 +00:00
|
|
|
_vm->_screen->createSurface(&sprite, &_glyph[i]._data);
|
Applied my own patch #1341495, in an attempt to fix alignment issues
reported by Crilith.
To elaborate a bit, the engine no longer accesses resource data through
packed structs. Instead it uses memory streams and the READ/WRITE
functions.
If data is mainly read, not written, I have replaced the old struct with a
new one with a read() function to read the whole thing from memory into the
struct's variables, and a write() function to dump the struct's variables
to memory. In fact, most of these write() functions remain unused.
If data is both read and written, I have replaced the struct with a class
with individual get/set functions to replace the old variables. This
manipulates memory directly.
Since I'm fairly sure that these structs are frequently stored as local
variables for a script, all script variables (both local and global) are
stored as little-endian and accessed through the READ/WRITE functions,
rather than being treated as arrays of 32-bit integers.
On a positive note, the functions for doing endian conversion of resources
and save games have been removed, and some general cleanups have been made
to assist in the rewrite.
Initial reports indicate that this patch indeed fixes alignment issues, and
that I have not - surprisingly - broken the game on big-endian platforms.
At least not in any immediately obvious way. And there's still plenty of
time to fix regressions before 0.9.0, too.
svn-id: r19366
2005-10-29 21:24:54 +00:00
|
|
|
_glyph[i]._width = frame_head.width;
|
|
|
|
_glyph[i]._height = frame_head.height;
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
_vm->_resman->closeResource(fontId);
|
2003-11-16 14:18:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
FontRendererGui::~FontRendererGui() {
|
|
|
|
for (int i = 0; i < SIZE_OF_CHAR_SET; i++)
|
2005-02-20 15:38:48 +00:00
|
|
|
_vm->_screen->deleteSurface(_glyph[i]._data);
|
2003-11-16 14:18:29 +00:00
|
|
|
}
|
|
|
|
|
2004-04-23 07:02:11 +00:00
|
|
|
void FontRendererGui::fetchText(uint32 textId, byte *buf) {
|
2005-02-20 15:38:48 +00:00
|
|
|
byte *data = _vm->fetchTextLine(_vm->_resman->openResource(textId / SIZE), textId & 0xffff);
|
2003-11-16 14:18:29 +00:00
|
|
|
int i;
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
for (i = 0; data[i + 2]; i++) {
|
|
|
|
if (buf)
|
|
|
|
buf[i] = data[i + 2];
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
buf[i] = 0;
|
2005-02-20 15:38:48 +00:00
|
|
|
_vm->_resman->closeResource(textId / SIZE);
|
2003-11-16 14:18:29 +00:00
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2004-04-23 07:02:11 +00:00
|
|
|
int FontRendererGui::getCharWidth(byte c) {
|
2004-02-21 08:30:10 +00:00
|
|
|
if (c < 32)
|
|
|
|
return 0;
|
|
|
|
return _glyph[c - 32]._width;
|
|
|
|
}
|
|
|
|
|
2004-04-23 07:02:11 +00:00
|
|
|
int FontRendererGui::getCharHeight(byte c) {
|
2004-02-21 08:30:10 +00:00
|
|
|
if (c < 32)
|
|
|
|
return 0;
|
|
|
|
return _glyph[c - 32]._height;
|
|
|
|
}
|
|
|
|
|
2004-04-23 07:02:11 +00:00
|
|
|
int FontRendererGui::getTextWidth(byte *text) {
|
2003-11-16 14:18:29 +00:00
|
|
|
int textWidth = 0;
|
|
|
|
|
|
|
|
for (int i = 0; text[i]; i++)
|
2004-02-21 08:30:10 +00:00
|
|
|
if (text[i] >= ' ')
|
|
|
|
textWidth += (getCharWidth(text[i]) - CHARACTER_OVERLAP);
|
2003-11-16 14:18:29 +00:00
|
|
|
return textWidth;
|
|
|
|
}
|
|
|
|
|
2004-03-04 08:03:32 +00:00
|
|
|
int FontRendererGui::getTextWidth(uint32 textId) {
|
2004-04-23 07:02:11 +00:00
|
|
|
byte text[MAX_STRING_LEN];
|
2003-11-16 14:18:29 +00:00
|
|
|
|
|
|
|
fetchText(textId, text);
|
|
|
|
return getTextWidth(text);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2004-04-23 07:02:11 +00:00
|
|
|
void FontRendererGui::drawText(byte *text, int x, int y, int alignment) {
|
2003-12-28 15:08:12 +00:00
|
|
|
SpriteInfo sprite;
|
2003-09-08 06:38:16 +00:00
|
|
|
int i;
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
if (alignment != kAlignLeft) {
|
|
|
|
int textWidth = getTextWidth(text);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
switch (alignment) {
|
2003-09-21 16:11:26 +00:00
|
|
|
case kAlignRight:
|
|
|
|
x -= textWidth;
|
|
|
|
break;
|
|
|
|
case kAlignCenter:
|
|
|
|
x -= (textWidth / 2);
|
|
|
|
break;
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
sprite.x = x;
|
|
|
|
sprite.y = y;
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
for (i = 0; text[i]; i++) {
|
2004-02-21 08:30:10 +00:00
|
|
|
if (text[i] >= ' ') {
|
|
|
|
sprite.w = getCharWidth(text[i]);
|
|
|
|
sprite.h = getCharHeight(text[i]);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
_vm->_screen->drawSurface(&sprite, _glyph[text[i] - 32]._data);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2004-02-21 08:30:10 +00:00
|
|
|
sprite.x += (getCharWidth(text[i]) - CHARACTER_OVERLAP);
|
|
|
|
}
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2004-03-04 08:03:32 +00:00
|
|
|
void FontRendererGui::drawText(uint32 textId, int x, int y, int alignment) {
|
2004-04-23 07:02:11 +00:00
|
|
|
byte text[MAX_STRING_LEN];
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
fetchText(textId, text);
|
|
|
|
drawText(text, x, y, alignment);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
//
|
|
|
|
// Dialog class functions
|
|
|
|
//
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
Dialog::Dialog(Sword2Engine *vm)
|
|
|
|
: _numWidgets(0), _finish(false), _result(0), _vm(vm) {
|
|
|
|
_vm->_screen->setFullPalette(CONTROL_PANEL_PALETTE);
|
|
|
|
_vm->_screen->clearScene();
|
2005-06-05 17:30:20 +00:00
|
|
|
_vm->_screen->updateDisplay();
|
2004-01-06 13:33:28 +00:00
|
|
|
|
2005-02-21 08:16:50 +00:00
|
|
|
// Usually the mouse pointer will already be "normal", but not always.
|
|
|
|
_vm->_mouse->setMouse(NORMAL_MOUSE_ID);
|
2009-04-07 19:52:46 +00:00
|
|
|
|
2009-05-24 15:17:42 +00:00
|
|
|
// Force mouse mode as system menu: normally not needed,
|
|
|
|
// but value is not correct in case of game start dialog
|
|
|
|
// (when asking to restart or load a game).
|
2009-04-07 19:52:46 +00:00
|
|
|
// This is forced to avoid GMM loading/saving being enabled
|
|
|
|
// during initial dialog.
|
|
|
|
_vm->_mouse->setMouseMode(MOUSE_system_menu);
|
2003-11-16 14:18:29 +00:00
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
Dialog::~Dialog() {
|
|
|
|
for (int i = 0; i < _numWidgets; i++)
|
|
|
|
delete _widgets[i];
|
2005-06-05 17:30:20 +00:00
|
|
|
_vm->_screen->clearScene();
|
|
|
|
_vm->_screen->updateDisplay();
|
2003-11-16 14:18:29 +00:00
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
void Dialog::registerWidget(Widget *widget) {
|
|
|
|
if (_numWidgets < MAX_WIDGETS)
|
|
|
|
_widgets[_numWidgets++] = widget;
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
void Dialog::paint() {
|
2005-02-20 15:38:48 +00:00
|
|
|
_vm->_screen->clearScene();
|
2003-11-16 14:18:29 +00:00
|
|
|
for (int i = 0; i < _numWidgets; i++)
|
|
|
|
_widgets[i]->paint();
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
void Dialog::setResult(int result) {
|
|
|
|
_result = result;
|
|
|
|
_finish = true;
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
int Dialog::runModal() {
|
2005-07-09 13:21:21 +00:00
|
|
|
uint32 oldFilter = _vm->setInputEventFilter(0);
|
2004-05-09 13:32:04 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
int i;
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
paint();
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-19 14:02:16 +00:00
|
|
|
int oldMouseX = -1;
|
|
|
|
int oldMouseY = -1;
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
while (!_finish) {
|
|
|
|
// So that the menu icons will reach their full size
|
2005-02-20 15:38:48 +00:00
|
|
|
_vm->_mouse->processMenu();
|
|
|
|
_vm->_screen->updateDisplay(false);
|
2005-02-19 14:02:16 +00:00
|
|
|
|
|
|
|
int newMouseX, newMouseY;
|
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
_vm->_mouse->getPos(newMouseX, newMouseY);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-19 14:02:16 +00:00
|
|
|
newMouseY += 40;
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
MouseEvent *me = _vm->mouseEvent();
|
|
|
|
KeyboardEvent *ke = _vm->keyboardEvent();
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2004-05-09 13:32:04 +00:00
|
|
|
if (ke) {
|
2007-06-22 23:03:12 +00:00
|
|
|
if (ke->kbd.keycode == Common::KEYCODE_ESCAPE)
|
2003-11-16 14:18:29 +00:00
|
|
|
setResult(0);
|
2007-06-22 23:03:12 +00:00
|
|
|
else if (ke->kbd.keycode == Common::KEYCODE_RETURN || ke->kbd.keycode == Common::KEYCODE_KP_ENTER)
|
2003-11-16 14:18:29 +00:00
|
|
|
setResult(1);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-12-19 16:50:03 +00:00
|
|
|
int oldHit = -1;
|
|
|
|
int newHit = -1;
|
|
|
|
|
|
|
|
// Find out which widget the mouse was over the last time, and
|
|
|
|
// which it is currently over. This assumes the widgets do not
|
|
|
|
// overlap.
|
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
for (i = 0; i < _numWidgets; i++) {
|
2003-12-19 16:50:03 +00:00
|
|
|
if (_widgets[i]->isHit(oldMouseX, oldMouseY))
|
|
|
|
oldHit = i;
|
|
|
|
if (_widgets[i]->isHit(newMouseX, newMouseY))
|
|
|
|
newHit = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Was the mouse inside a widget the last time?
|
|
|
|
|
|
|
|
if (oldHit >= 0) {
|
|
|
|
if (newHit != oldHit)
|
|
|
|
_widgets[oldHit]->onMouseExit();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Is the mouse currently in a widget?
|
|
|
|
|
|
|
|
if (newHit >= 0) {
|
|
|
|
if (newHit != oldHit)
|
|
|
|
_widgets[newHit]->onMouseEnter();
|
2003-11-16 14:18:29 +00:00
|
|
|
|
|
|
|
if (me) {
|
|
|
|
switch (me->buttons) {
|
|
|
|
case RD_LEFTBUTTONDOWN:
|
2003-12-19 16:50:03 +00:00
|
|
|
_widgets[newHit]->onMouseDown(newMouseX, newMouseY);
|
2003-11-16 14:18:29 +00:00
|
|
|
break;
|
|
|
|
case RD_LEFTBUTTONUP:
|
2003-12-19 16:50:03 +00:00
|
|
|
_widgets[newHit]->onMouseUp(newMouseX, newMouseY);
|
|
|
|
break;
|
|
|
|
case RD_WHEELUP:
|
|
|
|
_widgets[newHit]->onWheelUp(newMouseX, newMouseY);
|
|
|
|
break;
|
|
|
|
case RD_WHEELDOWN:
|
|
|
|
_widgets[newHit]->onWheelDown(newMouseX, newMouseY);
|
2003-11-16 14:18:29 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2003-12-19 16:50:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Some events are passed to the widgets regardless of where
|
|
|
|
// the mouse cursor is.
|
|
|
|
|
|
|
|
for (i = 0; i < _numWidgets; i++) {
|
|
|
|
if (me && me->buttons == RD_LEFTBUTTONUP) {
|
|
|
|
// So that slider widgets will know when the
|
|
|
|
// user releases the mouse button, even if the
|
|
|
|
// cursor is outside of the slider's hit area.
|
|
|
|
_widgets[i]->releaseMouse(newMouseX, newMouseY);
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is to make it easier to drag the slider widget
|
|
|
|
|
|
|
|
if (newMouseX != oldMouseX || newMouseY != oldMouseY)
|
|
|
|
_widgets[i]->onMouseMove(newMouseX, newMouseY);
|
2003-11-16 14:18:29 +00:00
|
|
|
|
2004-05-09 13:32:04 +00:00
|
|
|
if (ke)
|
|
|
|
_widgets[i]->onKey(ke);
|
2003-11-16 14:18:29 +00:00
|
|
|
|
|
|
|
_widgets[i]->onTick();
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
oldMouseX = newMouseX;
|
|
|
|
oldMouseY = newMouseY;
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
_vm->_system->delayMillis(20);
|
2004-01-09 07:54:16 +00:00
|
|
|
|
2008-09-30 12:27:38 +00:00
|
|
|
if (_vm->shouldQuit())
|
2004-01-09 07:54:16 +00:00
|
|
|
setResult(0);
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-07-09 13:21:21 +00:00
|
|
|
_vm->setInputEventFilter(oldFilter);
|
2003-11-16 14:18:29 +00:00
|
|
|
return _result;
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
//
|
|
|
|
// Widget functions
|
|
|
|
//
|
|
|
|
|
|
|
|
Widget::Widget(Dialog *parent, int states)
|
2005-02-20 15:38:48 +00:00
|
|
|
: _vm(parent->_vm), _parent(parent), _numStates(states), _state(0) {
|
2005-05-12 13:12:15 +00:00
|
|
|
_sprites = (SpriteInfo *)calloc(states, sizeof(SpriteInfo));
|
|
|
|
_surfaces = (WidgetSurface *)calloc(states, sizeof(WidgetSurface));
|
2003-11-16 14:18:29 +00:00
|
|
|
|
|
|
|
_hitRect.left = _hitRect.right = _hitRect.top = _hitRect.bottom = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Widget::~Widget() {
|
|
|
|
for (int i = 0; i < _numStates; i++) {
|
|
|
|
if (_surfaces[i]._original)
|
2005-02-20 15:38:48 +00:00
|
|
|
_vm->_screen->deleteSurface(_surfaces[i]._surface);
|
2003-11-16 14:18:29 +00:00
|
|
|
}
|
|
|
|
free(_sprites);
|
|
|
|
free(_surfaces);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-10-04 01:09:29 +00:00
|
|
|
void Widget::createSurfaceImage(int state, uint32 res, int x, int y, uint32 pc) {
|
2004-04-23 07:02:11 +00:00
|
|
|
byte *file, *colTablePtr = NULL;
|
Applied my own patch #1341495, in an attempt to fix alignment issues
reported by Crilith.
To elaborate a bit, the engine no longer accesses resource data through
packed structs. Instead it uses memory streams and the READ/WRITE
functions.
If data is mainly read, not written, I have replaced the old struct with a
new one with a read() function to read the whole thing from memory into the
struct's variables, and a write() function to dump the struct's variables
to memory. In fact, most of these write() functions remain unused.
If data is both read and written, I have replaced the struct with a class
with individual get/set functions to replace the old variables. This
manipulates memory directly.
Since I'm fairly sure that these structs are frequently stored as local
variables for a script, all script variables (both local and global) are
stored as little-endian and accessed through the READ/WRITE functions,
rather than being treated as arrays of 32-bit integers.
On a positive note, the functions for doing endian conversion of resources
and save games have been removed, and some general cleanups have been made
to assist in the rewrite.
Initial reports indicate that this patch indeed fixes alignment issues, and
that I have not - surprisingly - broken the game on big-endian platforms.
At least not in any immediately obvious way. And there's still plenty of
time to fix regressions before 0.9.0, too.
svn-id: r19366
2005-10-29 21:24:54 +00:00
|
|
|
AnimHeader anim_head;
|
|
|
|
FrameHeader frame_head;
|
|
|
|
CdtEntry cdt_entry;
|
2003-09-08 06:38:16 +00:00
|
|
|
uint32 spriteType = RDSPR_TRANS;
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
// open anim resource file, point to base
|
2005-02-20 15:38:48 +00:00
|
|
|
file = _vm->_resman->openResource(res);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
Applied my own patch #1341495, in an attempt to fix alignment issues
reported by Crilith.
To elaborate a bit, the engine no longer accesses resource data through
packed structs. Instead it uses memory streams and the READ/WRITE
functions.
If data is mainly read, not written, I have replaced the old struct with a
new one with a read() function to read the whole thing from memory into the
struct's variables, and a write() function to dump the struct's variables
to memory. In fact, most of these write() functions remain unused.
If data is both read and written, I have replaced the struct with a class
with individual get/set functions to replace the old variables. This
manipulates memory directly.
Since I'm fairly sure that these structs are frequently stored as local
variables for a script, all script variables (both local and global) are
stored as little-endian and accessed through the READ/WRITE functions,
rather than being treated as arrays of 32-bit integers.
On a positive note, the functions for doing endian conversion of resources
and save games have been removed, and some general cleanups have been made
to assist in the rewrite.
Initial reports indicate that this patch indeed fixes alignment issues, and
that I have not - surprisingly - broken the game on big-endian platforms.
At least not in any immediately obvious way. And there's still plenty of
time to fix regressions before 0.9.0, too.
svn-id: r19366
2005-10-29 21:24:54 +00:00
|
|
|
byte *frame = _vm->fetchFrameHeader(file, pc);
|
|
|
|
|
|
|
|
anim_head.read(_vm->fetchAnimHeader(file));
|
|
|
|
cdt_entry.read(_vm->fetchCdtEntry(file, pc));
|
|
|
|
frame_head.read(frame);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
// If the frame is flipped. (Only really applicable to frames using
|
|
|
|
// offsets.)
|
2003-07-28 01:44:38 +00:00
|
|
|
|
Applied my own patch #1341495, in an attempt to fix alignment issues
reported by Crilith.
To elaborate a bit, the engine no longer accesses resource data through
packed structs. Instead it uses memory streams and the READ/WRITE
functions.
If data is mainly read, not written, I have replaced the old struct with a
new one with a read() function to read the whole thing from memory into the
struct's variables, and a write() function to dump the struct's variables
to memory. In fact, most of these write() functions remain unused.
If data is both read and written, I have replaced the struct with a class
with individual get/set functions to replace the old variables. This
manipulates memory directly.
Since I'm fairly sure that these structs are frequently stored as local
variables for a script, all script variables (both local and global) are
stored as little-endian and accessed through the READ/WRITE functions,
rather than being treated as arrays of 32-bit integers.
On a positive note, the functions for doing endian conversion of resources
and save games have been removed, and some general cleanups have been made
to assist in the rewrite.
Initial reports indicate that this patch indeed fixes alignment issues, and
that I have not - surprisingly - broken the game on big-endian platforms.
At least not in any immediately obvious way. And there's still plenty of
time to fix regressions before 0.9.0, too.
svn-id: r19366
2005-10-29 21:24:54 +00:00
|
|
|
if (cdt_entry.frameType & FRAME_FLIPPED)
|
2003-09-08 06:38:16 +00:00
|
|
|
spriteType |= RDSPR_FLIP;
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
// Which compression was used?
|
2003-07-28 01:44:38 +00:00
|
|
|
|
Applied my own patch #1341495, in an attempt to fix alignment issues
reported by Crilith.
To elaborate a bit, the engine no longer accesses resource data through
packed structs. Instead it uses memory streams and the READ/WRITE
functions.
If data is mainly read, not written, I have replaced the old struct with a
new one with a read() function to read the whole thing from memory into the
struct's variables, and a write() function to dump the struct's variables
to memory. In fact, most of these write() functions remain unused.
If data is both read and written, I have replaced the struct with a class
with individual get/set functions to replace the old variables. This
manipulates memory directly.
Since I'm fairly sure that these structs are frequently stored as local
variables for a script, all script variables (both local and global) are
stored as little-endian and accessed through the READ/WRITE functions,
rather than being treated as arrays of 32-bit integers.
On a positive note, the functions for doing endian conversion of resources
and save games have been removed, and some general cleanups have been made
to assist in the rewrite.
Initial reports indicate that this patch indeed fixes alignment issues, and
that I have not - surprisingly - broken the game on big-endian platforms.
At least not in any immediately obvious way. And there's still plenty of
time to fix regressions before 0.9.0, too.
svn-id: r19366
2005-10-29 21:24:54 +00:00
|
|
|
switch (anim_head.runTimeComp) {
|
2003-09-21 16:11:26 +00:00
|
|
|
case NONE:
|
|
|
|
spriteType |= RDSPR_NOCOMPRESSION;
|
|
|
|
break;
|
|
|
|
case RLE256:
|
|
|
|
spriteType |= RDSPR_RLE256;
|
|
|
|
break;
|
|
|
|
case RLE16:
|
|
|
|
spriteType |= RDSPR_RLE256;
|
|
|
|
// Points to just after last cdt_entry, i.e. start of colour
|
|
|
|
// table
|
Applied my own patch #1341495, in an attempt to fix alignment issues
reported by Crilith.
To elaborate a bit, the engine no longer accesses resource data through
packed structs. Instead it uses memory streams and the READ/WRITE
functions.
If data is mainly read, not written, I have replaced the old struct with a
new one with a read() function to read the whole thing from memory into the
struct's variables, and a write() function to dump the struct's variables
to memory. In fact, most of these write() functions remain unused.
If data is both read and written, I have replaced the struct with a class
with individual get/set functions to replace the old variables. This
manipulates memory directly.
Since I'm fairly sure that these structs are frequently stored as local
variables for a script, all script variables (both local and global) are
stored as little-endian and accessed through the READ/WRITE functions,
rather than being treated as arrays of 32-bit integers.
On a positive note, the functions for doing endian conversion of resources
and save games have been removed, and some general cleanups have been made
to assist in the rewrite.
Initial reports indicate that this patch indeed fixes alignment issues, and
that I have not - surprisingly - broken the game on big-endian platforms.
At least not in any immediately obvious way. And there's still plenty of
time to fix regressions before 0.9.0, too.
svn-id: r19366
2005-10-29 21:24:54 +00:00
|
|
|
colTablePtr = _vm->fetchAnimHeader(file) + AnimHeader::size()
|
|
|
|
+ anim_head.noAnimFrames * CdtEntry::size();
|
2003-09-21 16:11:26 +00:00
|
|
|
break;
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
_sprites[state].x = x;
|
|
|
|
_sprites[state].y = y;
|
Applied my own patch #1341495, in an attempt to fix alignment issues
reported by Crilith.
To elaborate a bit, the engine no longer accesses resource data through
packed structs. Instead it uses memory streams and the READ/WRITE
functions.
If data is mainly read, not written, I have replaced the old struct with a
new one with a read() function to read the whole thing from memory into the
struct's variables, and a write() function to dump the struct's variables
to memory. In fact, most of these write() functions remain unused.
If data is both read and written, I have replaced the struct with a class
with individual get/set functions to replace the old variables. This
manipulates memory directly.
Since I'm fairly sure that these structs are frequently stored as local
variables for a script, all script variables (both local and global) are
stored as little-endian and accessed through the READ/WRITE functions,
rather than being treated as arrays of 32-bit integers.
On a positive note, the functions for doing endian conversion of resources
and save games have been removed, and some general cleanups have been made
to assist in the rewrite.
Initial reports indicate that this patch indeed fixes alignment issues, and
that I have not - surprisingly - broken the game on big-endian platforms.
At least not in any immediately obvious way. And there's still plenty of
time to fix regressions before 0.9.0, too.
svn-id: r19366
2005-10-29 21:24:54 +00:00
|
|
|
_sprites[state].w = frame_head.width;
|
|
|
|
_sprites[state].h = frame_head.height;
|
2003-09-08 06:38:16 +00:00
|
|
|
_sprites[state].scale = 0;
|
|
|
|
_sprites[state].type = spriteType;
|
Applied my own patch #1341495, in an attempt to fix alignment issues
reported by Crilith.
To elaborate a bit, the engine no longer accesses resource data through
packed structs. Instead it uses memory streams and the READ/WRITE
functions.
If data is mainly read, not written, I have replaced the old struct with a
new one with a read() function to read the whole thing from memory into the
struct's variables, and a write() function to dump the struct's variables
to memory. In fact, most of these write() functions remain unused.
If data is both read and written, I have replaced the struct with a class
with individual get/set functions to replace the old variables. This
manipulates memory directly.
Since I'm fairly sure that these structs are frequently stored as local
variables for a script, all script variables (both local and global) are
stored as little-endian and accessed through the READ/WRITE functions,
rather than being treated as arrays of 32-bit integers.
On a positive note, the functions for doing endian conversion of resources
and save games have been removed, and some general cleanups have been made
to assist in the rewrite.
Initial reports indicate that this patch indeed fixes alignment issues, and
that I have not - surprisingly - broken the game on big-endian platforms.
At least not in any immediately obvious way. And there's still plenty of
time to fix regressions before 0.9.0, too.
svn-id: r19366
2005-10-29 21:24:54 +00:00
|
|
|
_sprites[state].blend = anim_head.blend;
|
2003-09-08 06:38:16 +00:00
|
|
|
|
|
|
|
// Points to just after frame header, ie. start of sprite data
|
Applied my own patch #1341495, in an attempt to fix alignment issues
reported by Crilith.
To elaborate a bit, the engine no longer accesses resource data through
packed structs. Instead it uses memory streams and the READ/WRITE
functions.
If data is mainly read, not written, I have replaced the old struct with a
new one with a read() function to read the whole thing from memory into the
struct's variables, and a write() function to dump the struct's variables
to memory. In fact, most of these write() functions remain unused.
If data is both read and written, I have replaced the struct with a class
with individual get/set functions to replace the old variables. This
manipulates memory directly.
Since I'm fairly sure that these structs are frequently stored as local
variables for a script, all script variables (both local and global) are
stored as little-endian and accessed through the READ/WRITE functions,
rather than being treated as arrays of 32-bit integers.
On a positive note, the functions for doing endian conversion of resources
and save games have been removed, and some general cleanups have been made
to assist in the rewrite.
Initial reports indicate that this patch indeed fixes alignment issues, and
that I have not - surprisingly - broken the game on big-endian platforms.
At least not in any immediately obvious way. And there's still plenty of
time to fix regressions before 0.9.0, too.
svn-id: r19366
2005-10-29 21:24:54 +00:00
|
|
|
_sprites[state].data = frame + FrameHeader::size();
|
2003-09-08 06:38:16 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
_vm->_screen->createSurface(&_sprites[state], &_surfaces[state]._surface);
|
2003-09-08 06:38:16 +00:00
|
|
|
_surfaces[state]._original = true;
|
|
|
|
|
|
|
|
// Release the anim resource
|
2005-02-20 15:38:48 +00:00
|
|
|
_vm->_resman->closeResource(res);
|
2003-11-25 17:08:46 +00:00
|
|
|
}
|
2003-09-08 06:38:16 +00:00
|
|
|
|
2003-10-04 01:09:29 +00:00
|
|
|
void Widget::linkSurfaceImage(Widget *from, int state, int x, int y) {
|
2003-09-08 06:38:16 +00:00
|
|
|
_sprites[state].x = x;
|
|
|
|
_sprites[state].y = y;
|
|
|
|
_sprites[state].w = from->_sprites[state].w;
|
|
|
|
_sprites[state].h = from->_sprites[state].h;
|
|
|
|
_sprites[state].scale = from->_sprites[state].scale;
|
|
|
|
_sprites[state].type = from->_sprites[state].type;
|
|
|
|
_sprites[state].blend = from->_sprites[state].blend;
|
|
|
|
|
|
|
|
_surfaces[state]._surface = from->_surfaces[state]._surface;
|
|
|
|
_surfaces[state]._original = false;
|
2003-11-25 17:08:46 +00:00
|
|
|
}
|
2003-09-08 06:38:16 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
void Widget::createSurfaceImages(uint32 res, int x, int y) {
|
|
|
|
for (int i = 0; i < _numStates; i++)
|
|
|
|
createSurfaceImage(i, res, x, y, i);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
void Widget::linkSurfaceImages(Widget *from, int x, int y) {
|
|
|
|
for (int i = 0; i < from->_numStates; i++)
|
|
|
|
linkSurfaceImage(from, i, x, y);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
void Widget::setHitRect(int x, int y, int width, int height) {
|
|
|
|
_hitRect.left = x;
|
|
|
|
_hitRect.right = x + width;
|
|
|
|
_hitRect.top = y;
|
|
|
|
_hitRect.bottom = y + height;
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
bool Widget::isHit(int16 x, int16 y) {
|
|
|
|
return _hitRect.left >= 0 && _hitRect.contains(x, y);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
void Widget::setState(int state) {
|
|
|
|
if (state != _state) {
|
|
|
|
_state = state;
|
|
|
|
paint();
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
2003-11-16 14:18:29 +00:00
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
int Widget::getState() {
|
|
|
|
return _state;
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
void Widget::paint(Common::Rect *clipRect) {
|
2005-02-20 15:38:48 +00:00
|
|
|
_vm->_screen->drawSurface(&_sprites[_state], _surfaces[_state]._surface, clipRect);
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
/**
|
|
|
|
* Standard button class.
|
|
|
|
*/
|
|
|
|
|
2003-10-04 01:09:29 +00:00
|
|
|
class Button : public Widget {
|
2003-09-08 06:38:16 +00:00
|
|
|
public:
|
2003-11-16 14:18:29 +00:00
|
|
|
Button(Dialog *parent, int x, int y, int w, int h)
|
|
|
|
: Widget(parent, 2) {
|
2003-09-08 06:38:16 +00:00
|
|
|
setHitRect(x, y, w, h);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
virtual void onMouseExit() {
|
|
|
|
setState(0);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
virtual void onMouseDown(int x, int y) {
|
|
|
|
setState(1);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
virtual void onMouseUp(int x, int y) {
|
|
|
|
if (getState() != 0) {
|
|
|
|
setState(0);
|
|
|
|
_parent->onAction(this);
|
2003-07-28 01:44:38 +00:00
|
|
|
}
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
|
|
|
};
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
/**
|
|
|
|
* Scroll buttons are used to scroll the savegame list. The difference between
|
|
|
|
* this and a normal button is that we want this to repeat.
|
|
|
|
*/
|
|
|
|
|
2003-10-04 01:09:29 +00:00
|
|
|
class ScrollButton : public Widget {
|
2003-09-08 06:38:16 +00:00
|
|
|
private:
|
|
|
|
uint32 _holdCounter;
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
public:
|
2003-11-16 14:18:29 +00:00
|
|
|
ScrollButton(Dialog *parent, int x, int y, int w, int h)
|
|
|
|
: Widget(parent, 2), _holdCounter(0) {
|
2003-09-08 06:38:16 +00:00
|
|
|
setHitRect(x, y, w, h);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void onMouseExit() {
|
|
|
|
setState(0);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
virtual void onMouseDown(int x, int y) {
|
|
|
|
setState(1);
|
|
|
|
_parent->onAction(this);
|
|
|
|
_holdCounter = 0;
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
virtual void onMouseUp(int x, int y) {
|
|
|
|
setState(0);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
virtual void onTick() {
|
|
|
|
if (getState() != 0) {
|
|
|
|
_holdCounter++;
|
|
|
|
if (_holdCounter > 16 && (_holdCounter % 4) == 0)
|
|
|
|
_parent->onAction(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
/**
|
|
|
|
* A switch is a button that changes state when clicked, and keeps that state
|
|
|
|
* until clicked again.
|
|
|
|
*/
|
|
|
|
|
2003-10-04 01:09:29 +00:00
|
|
|
class Switch : public Widget {
|
2003-09-08 06:38:16 +00:00
|
|
|
private:
|
|
|
|
bool _holding, _value;
|
|
|
|
int _upState, _downState;
|
|
|
|
|
|
|
|
public:
|
2003-11-16 14:18:29 +00:00
|
|
|
Switch(Dialog *parent, int x, int y, int w, int h)
|
|
|
|
: Widget(parent, 2), _holding(false), _value(false),
|
|
|
|
_upState(0), _downState(1) {
|
2003-09-08 06:38:16 +00:00
|
|
|
setHitRect(x, y, w, h);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
// The sound mute switches have 0 as their "down" state and 1 as
|
|
|
|
// their "up" state, so this function is needed to get consistent
|
|
|
|
// behaviour.
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
void reverseStates() {
|
|
|
|
_upState = 1;
|
|
|
|
_downState = 0;
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
void setValue(bool value) {
|
|
|
|
_value = value;
|
|
|
|
if (_value)
|
|
|
|
setState(_downState);
|
|
|
|
else
|
|
|
|
setState(_upState);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
bool getValue() {
|
|
|
|
return _value;
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
virtual void onMouseExit() {
|
|
|
|
if (_holding && !_value)
|
|
|
|
setState(_upState);
|
|
|
|
_holding = false;
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
virtual void onMouseDown(int x, int y) {
|
|
|
|
_holding = true;
|
|
|
|
setState(_downState);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
virtual void onMouseUp(int x, int y) {
|
|
|
|
if (_holding) {
|
|
|
|
_holding = false;
|
|
|
|
_value = !_value;
|
|
|
|
if (_value)
|
|
|
|
setState(_downState);
|
2003-07-28 01:44:38 +00:00
|
|
|
else
|
2003-09-08 06:38:16 +00:00
|
|
|
setState(_upState);
|
|
|
|
_parent->onAction(this, getState());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
/**
|
|
|
|
* A slider is used to specify a value within a pre-defined range.
|
|
|
|
*/
|
|
|
|
|
2003-10-04 01:09:29 +00:00
|
|
|
class Slider : public Widget {
|
2003-09-08 06:38:16 +00:00
|
|
|
private:
|
2003-10-04 01:09:29 +00:00
|
|
|
Widget *_background;
|
2003-09-08 06:38:16 +00:00
|
|
|
bool _dragging;
|
|
|
|
int _value, _targetValue;
|
|
|
|
int _maxValue;
|
2005-01-25 07:27:14 +00:00
|
|
|
int _valueStep;
|
2003-09-08 06:38:16 +00:00
|
|
|
int _dragOffset;
|
|
|
|
|
|
|
|
int posFromValue(int value) {
|
|
|
|
return _hitRect.left + (value * (_hitRect.width() - 38)) / _maxValue;
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
int valueFromPos(int x) {
|
Applied my own patch #1341495, in an attempt to fix alignment issues
reported by Crilith.
To elaborate a bit, the engine no longer accesses resource data through
packed structs. Instead it uses memory streams and the READ/WRITE
functions.
If data is mainly read, not written, I have replaced the old struct with a
new one with a read() function to read the whole thing from memory into the
struct's variables, and a write() function to dump the struct's variables
to memory. In fact, most of these write() functions remain unused.
If data is both read and written, I have replaced the struct with a class
with individual get/set functions to replace the old variables. This
manipulates memory directly.
Since I'm fairly sure that these structs are frequently stored as local
variables for a script, all script variables (both local and global) are
stored as little-endian and accessed through the READ/WRITE functions,
rather than being treated as arrays of 32-bit integers.
On a positive note, the functions for doing endian conversion of resources
and save games have been removed, and some general cleanups have been made
to assist in the rewrite.
Initial reports indicate that this patch indeed fixes alignment issues, and
that I have not - surprisingly - broken the game on big-endian platforms.
At least not in any immediately obvious way. And there's still plenty of
time to fix regressions before 0.9.0, too.
svn-id: r19366
2005-10-29 21:24:54 +00:00
|
|
|
return (int)((double)(_maxValue * (x - _hitRect.left)) / (double)(_hitRect.width() - 38) + 0.5);
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
public:
|
2003-10-04 01:09:29 +00:00
|
|
|
Slider(Dialog *parent, Widget *background, int max,
|
2005-01-25 07:27:14 +00:00
|
|
|
int x, int y, int w, int h, int step, Widget *base = NULL)
|
2003-11-16 14:18:29 +00:00
|
|
|
: Widget(parent, 1), _background(background),
|
|
|
|
_dragging(false), _value(0), _targetValue(0),
|
2005-01-25 07:27:14 +00:00
|
|
|
_maxValue(max), _valueStep(step) {
|
2003-09-08 06:38:16 +00:00
|
|
|
setHitRect(x, y, w, h);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-01-25 07:27:14 +00:00
|
|
|
if (_valueStep <= 0)
|
|
|
|
_valueStep = 1;
|
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
if (base)
|
|
|
|
linkSurfaceImages(base, x, y);
|
|
|
|
else
|
|
|
|
createSurfaceImages(3406, x, y);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-10-02 17:43:02 +00:00
|
|
|
virtual void paint(Common::Rect *clipRect = NULL) {
|
2003-09-08 06:38:16 +00:00
|
|
|
// This will redraw a bit more than is strictly necessary,
|
|
|
|
// but I doubt that will make any noticeable difference.
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
_background->paint(&_hitRect);
|
2003-10-04 01:09:29 +00:00
|
|
|
Widget::paint(clipRect);
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
void setValue(int value) {
|
|
|
|
_value = value;
|
|
|
|
_targetValue = value;
|
|
|
|
_sprites[0].x = posFromValue(_value);
|
|
|
|
paint();
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
int getValue() {
|
|
|
|
return _value;
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
virtual void onMouseMove(int x, int y) {
|
|
|
|
if (_dragging) {
|
|
|
|
int newX = x - _dragOffset;
|
|
|
|
int newValue;
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
if (newX < _hitRect.left)
|
|
|
|
newX = _hitRect.left;
|
|
|
|
else if (newX + 38 > _hitRect.right)
|
|
|
|
newX = _hitRect.right - 38;
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
_sprites[0].x = newX;
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
newValue = valueFromPos(newX);
|
|
|
|
if (newValue != _value) {
|
|
|
|
_value = newValue;
|
|
|
|
_targetValue = newValue;
|
|
|
|
_parent->onAction(this, newValue);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
paint();
|
|
|
|
}
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
virtual void onMouseDown(int x, int y) {
|
|
|
|
if (x >= _sprites[0].x && x < _sprites[0].x + 38) {
|
|
|
|
_dragging = true;
|
|
|
|
_dragOffset = x - _sprites[0].x;
|
|
|
|
} else if (x < _sprites[0].x) {
|
2005-01-25 07:27:14 +00:00
|
|
|
if (_targetValue >= _valueStep)
|
|
|
|
_targetValue -= _valueStep;
|
|
|
|
else
|
|
|
|
_targetValue = 0;
|
2003-09-08 06:38:16 +00:00
|
|
|
} else {
|
2005-01-25 07:27:14 +00:00
|
|
|
if (_targetValue < _maxValue - _valueStep)
|
|
|
|
_targetValue += _valueStep;
|
|
|
|
else
|
|
|
|
_targetValue = _maxValue;
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
virtual void releaseMouse(int x, int y) {
|
|
|
|
if (_dragging)
|
|
|
|
_dragging = false;
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
virtual void onTick() {
|
|
|
|
if (!_dragging) {
|
|
|
|
int target = posFromValue(_targetValue);
|
|
|
|
|
|
|
|
if (target != _sprites[0].x) {
|
|
|
|
if (target < _sprites[0].x) {
|
|
|
|
_sprites[0].x -= 4;
|
|
|
|
if (_sprites[0].x < target)
|
|
|
|
_sprites[0].x = target;
|
|
|
|
} else if (target > _sprites[0].x) {
|
|
|
|
_sprites[0].x += 4;
|
|
|
|
if (_sprites[0].x > target)
|
|
|
|
_sprites[0].x = target;
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
int newValue = valueFromPos(_sprites[0].x);
|
|
|
|
if (newValue != _value) {
|
|
|
|
_value = newValue;
|
|
|
|
_parent->onAction(this, newValue);
|
2003-07-28 01:44:38 +00:00
|
|
|
}
|
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
paint();
|
2003-07-28 01:44:38 +00:00
|
|
|
}
|
|
|
|
}
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
|
|
|
};
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
/**
|
2005-02-20 15:38:48 +00:00
|
|
|
* The "mini" dialog.
|
2003-11-16 14:18:29 +00:00
|
|
|
*/
|
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
MiniDialog::MiniDialog(Sword2Engine *vm, uint32 headerTextId, uint32 okTextId, uint32 cancelTextId) : Dialog(vm) {
|
|
|
|
_headerTextId = headerTextId;
|
|
|
|
_okTextId = okTextId;
|
|
|
|
_cancelTextId = cancelTextId;
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
_fr = new FontRendererGui(_vm, _vm->_controlsFontId);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
_panel = new Widget(this, 1);
|
|
|
|
_panel->createSurfaceImages(1996, 203, 104);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
_okButton = new Button(this, 243, 214, 24, 24);
|
|
|
|
_okButton->createSurfaceImages(2002, 243, 214);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
_cancelButton = new Button(this, 243, 276, 24, 24);
|
|
|
|
_cancelButton->linkSurfaceImages(_okButton, 243, 276);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
registerWidget(_panel);
|
|
|
|
registerWidget(_okButton);
|
|
|
|
registerWidget(_cancelButton);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
MiniDialog::~MiniDialog() {
|
|
|
|
delete _fr;
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
void MiniDialog::paint() {
|
|
|
|
Dialog::paint();
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
if (_headerTextId)
|
|
|
|
_fr->drawText(_headerTextId, 310, 134, FontRendererGui::kAlignCenter);
|
|
|
|
_fr->drawText(_okTextId, 270, 214);
|
|
|
|
_fr->drawText(_cancelTextId, 270, 276);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
void MiniDialog::onAction(Widget *widget, int result) {
|
|
|
|
if (widget == _okButton)
|
|
|
|
setResult(1);
|
|
|
|
else if (widget == _cancelButton)
|
|
|
|
setResult(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
StartDialog::StartDialog(Sword2Engine *vm) : MiniDialog(vm, 0) {}
|
|
|
|
|
|
|
|
int StartDialog::runModal() {
|
|
|
|
while (1) {
|
|
|
|
MiniDialog startDialog(_vm, 0, TEXT_RESTART, TEXT_RESTORE);
|
|
|
|
|
|
|
|
if (startDialog.runModal())
|
|
|
|
return 1;
|
|
|
|
|
2008-09-30 12:27:38 +00:00
|
|
|
if (_vm->shouldQuit())
|
2005-02-20 15:38:48 +00:00
|
|
|
return 0;
|
|
|
|
|
2005-02-21 08:16:50 +00:00
|
|
|
RestoreDialog restoreDialog(_vm);
|
2005-02-20 15:38:48 +00:00
|
|
|
|
2005-02-21 08:16:50 +00:00
|
|
|
if (restoreDialog.runModal())
|
2005-02-20 15:38:48 +00:00
|
|
|
return 0;
|
|
|
|
|
2008-09-30 12:27:38 +00:00
|
|
|
if (_vm->shouldQuit())
|
2005-02-20 15:38:48 +00:00
|
|
|
return 0;
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
2005-02-20 15:38:48 +00:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
2003-09-08 06:38:16 +00:00
|
|
|
|
2003-11-16 14:18:29 +00:00
|
|
|
/**
|
2005-02-20 15:38:48 +00:00
|
|
|
* The restart dialog.
|
2003-11-16 14:18:29 +00:00
|
|
|
*/
|
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
RestartDialog::RestartDialog(Sword2Engine *vm) : MiniDialog(vm, TEXT_RESTART) {}
|
2003-09-08 06:38:16 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
int RestartDialog::runModal() {
|
|
|
|
int result = MiniDialog::runModal();
|
|
|
|
|
|
|
|
if (result)
|
|
|
|
_vm->restartGame();
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The quit dialog.
|
|
|
|
*/
|
|
|
|
|
|
|
|
QuitDialog::QuitDialog(Sword2Engine *vm) : MiniDialog(vm, TEXT_QUIT) {}
|
|
|
|
|
|
|
|
int QuitDialog::runModal() {
|
|
|
|
int result = MiniDialog::runModal();
|
|
|
|
|
|
|
|
if (result)
|
2008-07-13 22:00:39 +00:00
|
|
|
_vm->quitGame();
|
2005-02-20 15:38:48 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The game settings dialog.
|
|
|
|
*/
|
|
|
|
|
|
|
|
OptionsDialog::OptionsDialog(Sword2Engine *vm) : Dialog(vm) {
|
|
|
|
_fr = new FontRendererGui(_vm, _vm->_controlsFontId);
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
_mixer = _vm->_mixer;
|
|
|
|
|
|
|
|
_panel = new Widget(this, 1);
|
|
|
|
_panel->createSurfaceImages(3405, 0, 40);
|
|
|
|
|
|
|
|
_objectLabelsSwitch = new Switch(this, 304, 100, 53, 32);
|
|
|
|
_objectLabelsSwitch->createSurfaceImages(3687, 304, 100);
|
|
|
|
|
|
|
|
_subtitlesSwitch = new Switch(this, 510, 100, 53, 32);
|
|
|
|
_subtitlesSwitch->linkSurfaceImages(_objectLabelsSwitch, 510, 100);
|
|
|
|
|
|
|
|
_reverseStereoSwitch = new Switch(this, 304, 293, 53, 32);
|
|
|
|
_reverseStereoSwitch->linkSurfaceImages(_objectLabelsSwitch, 304, 293);
|
|
|
|
|
|
|
|
_musicSwitch = new Switch(this, 516, 157, 40, 32);
|
|
|
|
_musicSwitch->createSurfaceImages(3315, 516, 157);
|
|
|
|
_musicSwitch->reverseStates();
|
|
|
|
|
|
|
|
_speechSwitch = new Switch(this, 516, 205, 40, 32);
|
|
|
|
_speechSwitch->linkSurfaceImages(_musicSwitch, 516, 205);
|
|
|
|
_speechSwitch->reverseStates();
|
|
|
|
|
|
|
|
_fxSwitch = new Switch(this, 516, 250, 40, 32);
|
|
|
|
_fxSwitch->linkSurfaceImages(_musicSwitch, 516, 250);
|
|
|
|
_fxSwitch->reverseStates();
|
|
|
|
|
2005-05-10 23:48:48 +00:00
|
|
|
int volStep = Audio::Mixer::kMaxMixerVolume / 10;
|
2005-02-20 15:38:48 +00:00
|
|
|
|
2005-05-10 23:48:48 +00:00
|
|
|
_musicSlider = new Slider(this, _panel, Audio::Mixer::kMaxMixerVolume, 309, 161, 170, 27, volStep);
|
|
|
|
_speechSlider = new Slider(this, _panel, Audio::Mixer::kMaxMixerVolume, 309, 208, 170, 27, volStep, _musicSlider);
|
|
|
|
_fxSlider = new Slider(this, _panel, Audio::Mixer::kMaxMixerVolume, 309, 254, 170, 27, volStep, _musicSlider);
|
2005-02-20 15:38:48 +00:00
|
|
|
_gfxSlider = new Slider(this, _panel, 3, 309, 341, 170, 27, 1, _musicSlider);
|
|
|
|
|
|
|
|
_gfxPreview = new Widget(this, 4);
|
|
|
|
_gfxPreview->createSurfaceImages(256, 495, 310);
|
|
|
|
|
|
|
|
_okButton = new Button(this, 203, 382, 53, 32);
|
|
|
|
_okButton->createSurfaceImages(901, 203, 382);
|
|
|
|
|
|
|
|
_cancelButton = new Button(this, 395, 382, 53, 32);
|
|
|
|
_cancelButton->linkSurfaceImages(_okButton, 395, 382);
|
|
|
|
|
|
|
|
registerWidget(_panel);
|
|
|
|
registerWidget(_objectLabelsSwitch);
|
|
|
|
registerWidget(_subtitlesSwitch);
|
|
|
|
registerWidget(_reverseStereoSwitch);
|
|
|
|
registerWidget(_musicSwitch);
|
|
|
|
registerWidget(_speechSwitch);
|
|
|
|
registerWidget(_fxSwitch);
|
|
|
|
registerWidget(_musicSlider);
|
|
|
|
registerWidget(_speechSlider);
|
|
|
|
registerWidget(_fxSlider);
|
|
|
|
registerWidget(_gfxSlider);
|
|
|
|
registerWidget(_gfxPreview);
|
|
|
|
registerWidget(_okButton);
|
|
|
|
registerWidget(_cancelButton);
|
|
|
|
|
|
|
|
_objectLabelsSwitch->setValue(_vm->_mouse->getObjectLabels());
|
|
|
|
_subtitlesSwitch->setValue(_vm->getSubtitles());
|
|
|
|
_reverseStereoSwitch->setValue(_vm->_sound->isReverseStereo());
|
|
|
|
_musicSwitch->setValue(!_vm->_sound->isMusicMute());
|
|
|
|
_speechSwitch->setValue(!_vm->_sound->isSpeechMute());
|
|
|
|
_fxSwitch->setValue(!_vm->_sound->isFxMute());
|
|
|
|
|
2005-05-10 23:48:48 +00:00
|
|
|
_musicSlider->setValue(_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType));
|
|
|
|
_speechSlider->setValue(_mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType));
|
|
|
|
_fxSlider->setValue(_mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType));
|
2005-02-20 15:38:48 +00:00
|
|
|
|
|
|
|
_gfxSlider->setValue(_vm->_screen->getRenderLevel());
|
|
|
|
_gfxPreview->setState(_vm->_screen->getRenderLevel());
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
OptionsDialog::~OptionsDialog() {
|
|
|
|
delete _fr;
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
void OptionsDialog::paint() {
|
|
|
|
Dialog::paint();
|
2003-09-08 06:38:16 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
int maxWidth = 0;
|
|
|
|
int width;
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
uint32 alignTextIds[] = {
|
|
|
|
TEXT_OBJECT_LABELS,
|
|
|
|
TEXT_MUSIC_VOLUME,
|
|
|
|
TEXT_SPEECH_VOLUME,
|
|
|
|
TEXT_FX_VOLUME,
|
|
|
|
TEXT_GFX_QUALITY,
|
|
|
|
TEXT_REVERSE_STEREO
|
|
|
|
};
|
2003-09-08 06:38:16 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
for (int i = 0; i < ARRAYSIZE(alignTextIds); i++) {
|
|
|
|
width = _fr->getTextWidth(alignTextIds[i]);
|
|
|
|
if (width > maxWidth)
|
|
|
|
maxWidth = width;
|
|
|
|
}
|
|
|
|
|
|
|
|
_fr->drawText(TEXT_OPTIONS, 321, 55, FontRendererGui::kAlignCenter);
|
|
|
|
_fr->drawText(TEXT_SUBTITLES, 500, 103, FontRendererGui::kAlignRight);
|
|
|
|
_fr->drawText(TEXT_OBJECT_LABELS, 299 - maxWidth, 103);
|
|
|
|
_fr->drawText(TEXT_MUSIC_VOLUME, 299 - maxWidth, 161);
|
|
|
|
_fr->drawText(TEXT_SPEECH_VOLUME, 299 - maxWidth, 208);
|
|
|
|
_fr->drawText(TEXT_FX_VOLUME, 299 - maxWidth, 254);
|
|
|
|
_fr->drawText(TEXT_REVERSE_STEREO, 299 - maxWidth, 296);
|
|
|
|
_fr->drawText(TEXT_GFX_QUALITY, 299 - maxWidth, 341);
|
|
|
|
_fr->drawText(TEXT_OK, 193, 382, FontRendererGui::kAlignRight);
|
|
|
|
_fr->drawText(TEXT_CANCEL, 385, 382, FontRendererGui::kAlignRight);
|
|
|
|
}
|
2003-11-16 14:18:29 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
void OptionsDialog::onAction(Widget *widget, int result) {
|
|
|
|
// Since there is music playing while the dialog is displayed we need
|
|
|
|
// to update music volume immediately.
|
|
|
|
|
|
|
|
if (widget == _musicSwitch) {
|
|
|
|
_vm->_sound->muteMusic(result != 0);
|
|
|
|
} else if (widget == _musicSlider) {
|
2006-10-21 12:44:10 +00:00
|
|
|
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, result);
|
2005-02-20 15:38:48 +00:00
|
|
|
_vm->_sound->muteMusic(result == 0);
|
|
|
|
_musicSwitch->setValue(result != 0);
|
|
|
|
} else if (widget == _speechSlider) {
|
|
|
|
_speechSwitch->setValue(result != 0);
|
|
|
|
} else if (widget == _fxSlider) {
|
|
|
|
_fxSwitch->setValue(result != 0);
|
|
|
|
} else if (widget == _gfxSlider) {
|
|
|
|
_gfxPreview->setState(result);
|
|
|
|
_vm->_screen->setRenderLevel(result);
|
|
|
|
} else if (widget == _okButton) {
|
|
|
|
// Apply the changes
|
|
|
|
_vm->setSubtitles(_subtitlesSwitch->getValue());
|
|
|
|
_vm->_mouse->setObjectLabels(_objectLabelsSwitch->getValue());
|
|
|
|
_vm->_sound->muteMusic(!_musicSwitch->getValue());
|
|
|
|
_vm->_sound->muteSpeech(!_speechSwitch->getValue());
|
|
|
|
_vm->_sound->muteFx(!_fxSwitch->getValue());
|
|
|
|
_vm->_sound->setReverseStereo(_reverseStereoSwitch->getValue());
|
2005-05-10 23:48:48 +00:00
|
|
|
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, _musicSlider->getValue());
|
|
|
|
_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, _speechSlider->getValue());
|
|
|
|
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, _fxSlider->getValue());
|
2005-02-20 15:38:48 +00:00
|
|
|
_vm->_screen->setRenderLevel(_gfxSlider->getValue());
|
|
|
|
|
|
|
|
_vm->writeSettings();
|
|
|
|
setResult(1);
|
|
|
|
} else if (widget == _cancelButton) {
|
|
|
|
// Revert the changes
|
|
|
|
_vm->readSettings();
|
|
|
|
setResult(0);
|
|
|
|
}
|
|
|
|
}
|
2003-09-08 06:38:16 +00:00
|
|
|
|
2003-12-19 16:50:03 +00:00
|
|
|
// Slot button actions. Note that keyboard input generates positive actions
|
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
enum {
|
|
|
|
kSelectSlot = -1,
|
|
|
|
kDeselectSlot = -2,
|
2003-12-19 16:50:03 +00:00
|
|
|
kWheelDown = -3,
|
|
|
|
kWheelUp = -4,
|
|
|
|
kStartEditing = -5,
|
|
|
|
kCursorTick = -6
|
2003-09-08 06:38:16 +00:00
|
|
|
};
|
|
|
|
|
2003-10-04 01:09:29 +00:00
|
|
|
class Slot : public Widget {
|
2003-09-08 06:38:16 +00:00
|
|
|
private:
|
|
|
|
int _mode;
|
2003-10-07 07:06:50 +00:00
|
|
|
FontRendererGui *_fr;
|
2004-04-23 07:02:11 +00:00
|
|
|
byte _text[SAVE_DESCRIPTION_LEN];
|
2003-09-08 06:38:16 +00:00
|
|
|
bool _clickable;
|
|
|
|
bool _editable;
|
|
|
|
|
|
|
|
public:
|
2003-11-16 14:18:29 +00:00
|
|
|
Slot(Dialog *parent, int x, int y, int w, int h)
|
|
|
|
: Widget(parent, 2), _clickable(false), _editable(false) {
|
2003-09-08 06:38:16 +00:00
|
|
|
setHitRect(x, y, w, h);
|
|
|
|
_text[0] = 0;
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
void setMode(int mode) {
|
|
|
|
_mode = mode;
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
void setClickable(bool clickable) {
|
|
|
|
_clickable = clickable;
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
void setEditable(bool editable) {
|
|
|
|
_editable = editable;
|
2005-10-15 15:46:12 +00:00
|
|
|
_vm->_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, editable);
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
bool isEditable() {
|
|
|
|
return _editable;
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2004-04-23 07:02:11 +00:00
|
|
|
void setText(FontRendererGui *fr, int slot, byte *text) {
|
2003-09-08 06:38:16 +00:00
|
|
|
_fr = fr;
|
|
|
|
if (text)
|
2005-05-12 13:12:15 +00:00
|
|
|
sprintf((char *)_text, "%d. %s", slot, text);
|
2003-09-08 06:38:16 +00:00
|
|
|
else
|
2005-05-12 13:12:15 +00:00
|
|
|
sprintf((char *)_text, "%d. ", slot);
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2004-04-23 07:02:11 +00:00
|
|
|
byte *getText() {
|
2003-09-08 06:38:16 +00:00
|
|
|
return &_text[0];
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-10-02 17:43:02 +00:00
|
|
|
virtual void paint(Common::Rect *clipRect = NULL) {
|
2003-10-04 01:09:29 +00:00
|
|
|
Widget::paint();
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
// HACK: The main dialog is responsible for drawing the text
|
|
|
|
// when in editing mode.
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
if (!_editable)
|
|
|
|
_fr->drawText(_text, _sprites[0].x + 16, _sprites[0].y + 4 + 2 * getState());
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
virtual void onMouseDown(int x, int y) {
|
|
|
|
if (_clickable) {
|
|
|
|
if (getState() == 0) {
|
|
|
|
setState(1);
|
|
|
|
_parent->onAction(this, kSelectSlot);
|
|
|
|
if (_mode == kSaveDialog)
|
|
|
|
_parent->onAction(this, kStartEditing);
|
2005-02-21 08:16:50 +00:00
|
|
|
} else if (_mode == kRestoreDialog) {
|
2003-09-08 06:38:16 +00:00
|
|
|
setState(0);
|
|
|
|
_parent->onAction(this, kDeselectSlot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-12-19 16:50:03 +00:00
|
|
|
virtual void onWheelUp(int x, int y) {
|
|
|
|
_parent->onAction(this, kWheelUp);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void onWheelDown(int x, int y) {
|
|
|
|
_parent->onAction(this, kWheelDown);
|
|
|
|
}
|
|
|
|
|
2003-12-28 15:08:12 +00:00
|
|
|
virtual void onKey(KeyboardEvent *ke) {
|
2003-09-23 15:59:52 +00:00
|
|
|
if (_editable) {
|
2007-06-22 23:03:12 +00:00
|
|
|
if (ke->kbd.keycode == Common::KEYCODE_BACKSPACE)
|
2007-06-21 19:33:05 +00:00
|
|
|
_parent->onAction(this, Common::KEYCODE_BACKSPACE);
|
2007-06-22 23:03:12 +00:00
|
|
|
else if (ke->kbd.ascii >= ' ' && ke->kbd.ascii <= 255) {
|
2004-02-21 08:30:10 +00:00
|
|
|
// Accept the character if the font renderer
|
|
|
|
// has what looks like a valid glyph for it.
|
2007-06-22 23:03:12 +00:00
|
|
|
if (_fr->getCharWidth(ke->kbd.ascii))
|
|
|
|
_parent->onAction(this, ke->kbd.ascii);
|
2004-02-21 08:30:10 +00:00
|
|
|
}
|
2003-09-23 15:59:52 +00:00
|
|
|
}
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
virtual void onTick() {
|
|
|
|
if (_editable)
|
|
|
|
_parent->onAction(this, kCursorTick);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
void setY(int y) {
|
|
|
|
for (int i = 0; i < _numStates; i++)
|
|
|
|
_sprites[i].y = y;
|
|
|
|
setHitRect(_hitRect.left, y, _hitRect.width(), _hitRect.height());
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2003-09-08 06:38:16 +00:00
|
|
|
int getY() {
|
|
|
|
return _sprites[0].y;
|
|
|
|
}
|
|
|
|
};
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-21 08:16:50 +00:00
|
|
|
SaveRestoreDialog::SaveRestoreDialog(Sword2Engine *vm, int mode) : Dialog(vm) {
|
2005-02-20 15:38:48 +00:00
|
|
|
int i;
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
_mode = mode;
|
|
|
|
_selectedSlot = -1;
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
// FIXME: The "control font" and the "red font" are currently always
|
|
|
|
// the same font, so one should be eliminated.
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
_fr1 = new FontRendererGui(_vm, _vm->_controlsFontId);
|
|
|
|
_fr2 = new FontRendererGui(_vm, _vm->_redFontId);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
_panel = new Widget(this, 1);
|
|
|
|
_panel->createSurfaceImages(2016, 0, 40);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
_slotButton[i] = new Slot(this, 114, 0, 384, 36);
|
|
|
|
_slotButton[i]->createSurfaceImages(2006 + i, 114, 0);
|
|
|
|
_slotButton[i]->setMode(mode);
|
|
|
|
_slotButton[i + 4] = new Slot(this, 114, 0, 384, 36);
|
|
|
|
_slotButton[i + 4]->linkSurfaceImages(_slotButton[i], 114, 0);
|
|
|
|
_slotButton[i + 4]->setMode(mode);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
updateSlots();
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
_zupButton = new ScrollButton(this, 516, 65, 17, 17);
|
|
|
|
_zupButton->createSurfaceImages(1982, 516, 65);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
_upButton = new ScrollButton(this, 516, 85, 17, 17);
|
|
|
|
_upButton->createSurfaceImages(2067, 516, 85);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
_downButton = new ScrollButton(this, 516, 329, 17, 17);
|
|
|
|
_downButton->createSurfaceImages(1986, 516, 329);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
_zdownButton = new ScrollButton(this, 516, 350, 17, 17);
|
|
|
|
_zdownButton->createSurfaceImages(1988, 516, 350);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
_okButton = new Button(this, 130, 377, 24, 24);
|
|
|
|
_okButton->createSurfaceImages(2002, 130, 377);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
_cancelButton = new Button(this, 350, 377, 24, 24);
|
|
|
|
_cancelButton->linkSurfaceImages(_okButton, 350, 377);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
registerWidget(_panel);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
for (i = 0; i < 8; i++)
|
|
|
|
registerWidget(_slotButton[i]);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
registerWidget(_zupButton);
|
|
|
|
registerWidget(_upButton);
|
|
|
|
registerWidget(_downButton);
|
|
|
|
registerWidget(_zdownButton);
|
|
|
|
registerWidget(_okButton);
|
|
|
|
registerWidget(_cancelButton);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-21 08:16:50 +00:00
|
|
|
SaveRestoreDialog::~SaveRestoreDialog() {
|
2005-02-20 15:38:48 +00:00
|
|
|
delete _fr1;
|
|
|
|
delete _fr2;
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
// There aren't really a hundred different button objects of course, there are
|
|
|
|
// only eight. Re-arrange them to simulate scrolling.
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-21 08:16:50 +00:00
|
|
|
void SaveRestoreDialog::updateSlots() {
|
2005-02-20 15:38:48 +00:00
|
|
|
for (int i = 0; i < 8; i++) {
|
|
|
|
Slot *slot = _slotButton[(baseSlot + i) % 8];
|
|
|
|
FontRendererGui *fr;
|
|
|
|
byte description[SAVE_DESCRIPTION_LEN];
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
slot->setY(72 + i * 36);
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
if (baseSlot + i == _selectedSlot) {
|
|
|
|
slot->setEditable(_mode == kSaveDialog);
|
|
|
|
slot->setState(1);
|
|
|
|
fr = _fr2;
|
2003-09-08 06:38:16 +00:00
|
|
|
} else {
|
2005-02-20 15:38:48 +00:00
|
|
|
slot->setEditable(false);
|
|
|
|
slot->setState(0);
|
|
|
|
fr = _fr1;
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
if (_vm->getSaveDescription(baseSlot + i, description) == SR_OK) {
|
|
|
|
slot->setText(fr, baseSlot + i, description);
|
|
|
|
slot->setClickable(true);
|
2003-09-08 06:38:16 +00:00
|
|
|
} else {
|
2005-02-20 15:38:48 +00:00
|
|
|
slot->setText(fr, baseSlot + i, NULL);
|
|
|
|
slot->setClickable(_mode == kSaveDialog);
|
2003-07-28 01:44:38 +00:00
|
|
|
}
|
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
if (slot->isEditable())
|
|
|
|
drawEditBuffer(slot);
|
|
|
|
else
|
|
|
|
slot->paint();
|
|
|
|
}
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-21 08:16:50 +00:00
|
|
|
void SaveRestoreDialog::drawEditBuffer(Slot *slot) {
|
2005-02-20 15:38:48 +00:00
|
|
|
if (_selectedSlot == -1)
|
|
|
|
return;
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
// This will redraw a bit more than is strictly necessary, but I doubt
|
|
|
|
// that will make any noticeable difference.
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
slot->paint();
|
|
|
|
_fr2->drawText(_editBuffer, 130, 78 + (_selectedSlot - baseSlot) * 36);
|
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-21 08:16:50 +00:00
|
|
|
void SaveRestoreDialog::onAction(Widget *widget, int result) {
|
2005-02-20 15:38:48 +00:00
|
|
|
if (widget == _zupButton) {
|
|
|
|
if (baseSlot > 0) {
|
|
|
|
if (baseSlot >= 8)
|
|
|
|
baseSlot -= 8;
|
|
|
|
else
|
|
|
|
baseSlot = 0;
|
|
|
|
updateSlots();
|
|
|
|
}
|
|
|
|
} else if (widget == _upButton) {
|
|
|
|
if (baseSlot > 0) {
|
|
|
|
baseSlot--;
|
|
|
|
updateSlots();
|
|
|
|
}
|
|
|
|
} else if (widget == _downButton) {
|
|
|
|
if (baseSlot < 92) {
|
|
|
|
baseSlot++;
|
|
|
|
updateSlots();
|
|
|
|
}
|
|
|
|
} else if (widget == _zdownButton) {
|
|
|
|
if (baseSlot < 92) {
|
|
|
|
if (baseSlot <= 84)
|
|
|
|
baseSlot += 8;
|
|
|
|
else
|
|
|
|
baseSlot = 92;
|
|
|
|
updateSlots();
|
|
|
|
}
|
|
|
|
} else if (widget == _okButton) {
|
|
|
|
setResult(1);
|
|
|
|
} else if (widget == _cancelButton) {
|
|
|
|
setResult(0);
|
|
|
|
} else {
|
2005-05-12 13:12:15 +00:00
|
|
|
Slot *slot = (Slot *)widget;
|
2005-02-20 15:38:48 +00:00
|
|
|
int textWidth;
|
|
|
|
byte tmp;
|
|
|
|
int i;
|
|
|
|
int j;
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
switch (result) {
|
|
|
|
case kWheelUp:
|
|
|
|
onAction(_upButton);
|
|
|
|
break;
|
|
|
|
case kWheelDown:
|
|
|
|
onAction(_downButton);
|
|
|
|
break;
|
|
|
|
case kSelectSlot:
|
|
|
|
case kDeselectSlot:
|
|
|
|
if (result == kSelectSlot)
|
|
|
|
_selectedSlot = baseSlot + (slot->getY() - 72) / 35;
|
|
|
|
else if (result == kDeselectSlot)
|
|
|
|
_selectedSlot = -1;
|
|
|
|
|
|
|
|
for (i = 0; i < 8; i++)
|
|
|
|
if (widget == _slotButton[i])
|
2003-09-21 16:11:26 +00:00
|
|
|
break;
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
for (j = 0; j < 8; j++) {
|
|
|
|
if (j != i) {
|
|
|
|
_slotButton[j]->setEditable(false);
|
|
|
|
_slotButton[j]->setState(0);
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
2005-02-20 15:38:48 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case kStartEditing:
|
|
|
|
if (_selectedSlot >= 10)
|
|
|
|
_firstPos = 5;
|
|
|
|
else
|
|
|
|
_firstPos = 4;
|
|
|
|
|
2005-05-12 13:12:15 +00:00
|
|
|
strcpy((char *)_editBuffer, (char *)slot->getText());
|
|
|
|
_editPos = strlen((char *)_editBuffer);
|
2005-02-20 15:38:48 +00:00
|
|
|
_cursorTick = 0;
|
|
|
|
_editBuffer[_editPos] = '_';
|
|
|
|
_editBuffer[_editPos + 1] = 0;
|
|
|
|
slot->setEditable(true);
|
|
|
|
drawEditBuffer(slot);
|
|
|
|
break;
|
|
|
|
case kCursorTick:
|
|
|
|
_cursorTick++;
|
|
|
|
if (_cursorTick == 7) {
|
|
|
|
_editBuffer[_editPos] = ' ';
|
|
|
|
drawEditBuffer(slot);
|
|
|
|
} else if (_cursorTick == 14) {
|
|
|
|
_cursorTick = 0;
|
|
|
|
_editBuffer[_editPos] = '_';
|
|
|
|
drawEditBuffer(slot);
|
|
|
|
}
|
|
|
|
break;
|
2007-06-21 19:33:05 +00:00
|
|
|
case Common::KEYCODE_BACKSPACE:
|
2005-02-20 15:38:48 +00:00
|
|
|
if (_editPos > _firstPos) {
|
|
|
|
_editBuffer[_editPos - 1] = _editBuffer[_editPos];
|
|
|
|
_editBuffer[_editPos--] = 0;
|
|
|
|
drawEditBuffer(slot);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
tmp = _editBuffer[_editPos];
|
|
|
|
_editBuffer[_editPos] = 0;
|
|
|
|
textWidth = _fr2->getTextWidth(_editBuffer);
|
|
|
|
_editBuffer[_editPos] = tmp;
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
if (textWidth < 340 && _editPos < SAVE_DESCRIPTION_LEN - 2) {
|
|
|
|
_editBuffer[_editPos + 1] = _editBuffer[_editPos];
|
|
|
|
_editBuffer[_editPos + 2] = 0;
|
|
|
|
_editBuffer[_editPos++] = result;
|
|
|
|
drawEditBuffer(slot);
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
2005-02-20 15:38:48 +00:00
|
|
|
break;
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
|
|
|
}
|
2003-10-29 07:53:05 +00:00
|
|
|
}
|
|
|
|
|
2005-02-21 08:16:50 +00:00
|
|
|
void SaveRestoreDialog::paint() {
|
2005-02-20 15:38:48 +00:00
|
|
|
Dialog::paint();
|
2003-11-01 18:12:04 +00:00
|
|
|
|
2005-02-21 08:16:50 +00:00
|
|
|
_fr1->drawText((_mode == kRestoreDialog) ? TEXT_RESTORE : TEXT_SAVE, 165, 377);
|
2005-02-20 15:38:48 +00:00
|
|
|
_fr1->drawText(TEXT_CANCEL, 382, 377);
|
2003-10-29 07:53:05 +00:00
|
|
|
}
|
|
|
|
|
2005-02-21 08:16:50 +00:00
|
|
|
void SaveRestoreDialog::setResult(int result) {
|
2005-02-20 15:38:48 +00:00
|
|
|
if (result) {
|
|
|
|
if (_selectedSlot == -1)
|
|
|
|
return;
|
2004-03-04 08:03:32 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
if (_mode == kSaveDialog) {
|
|
|
|
if (_editPos <= _firstPos)
|
|
|
|
return;
|
|
|
|
}
|
2004-03-04 08:03:32 +00:00
|
|
|
}
|
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
Dialog::setResult(result);
|
2003-09-08 06:38:16 +00:00
|
|
|
}
|
2003-07-28 01:44:38 +00:00
|
|
|
|
2005-02-21 08:16:50 +00:00
|
|
|
int SaveRestoreDialog::runModal() {
|
2005-02-20 15:38:48 +00:00
|
|
|
int result = Dialog::runModal();
|
2003-10-29 07:53:05 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
if (result) {
|
|
|
|
switch (_mode) {
|
|
|
|
case kSaveDialog:
|
2005-10-16 13:53:15 +00:00
|
|
|
// Remove the cursor character from the savegame name
|
|
|
|
_editBuffer[_editPos] = 0;
|
|
|
|
|
2005-05-12 13:12:15 +00:00
|
|
|
if (_vm->saveGame(_selectedSlot, (byte *)&_editBuffer[_firstPos]) != SR_OK)
|
2005-02-20 15:38:48 +00:00
|
|
|
result = 0;
|
|
|
|
break;
|
2005-02-21 08:16:50 +00:00
|
|
|
case kRestoreDialog:
|
2005-02-20 15:38:48 +00:00
|
|
|
if (_vm->restoreGame(_selectedSlot) != SR_OK)
|
|
|
|
result = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2003-08-26 06:53:00 +00:00
|
|
|
|
2005-02-20 15:38:48 +00:00
|
|
|
return result;
|
2003-07-28 01:44:38 +00:00
|
|
|
}
|
2003-10-04 00:52:27 +00:00
|
|
|
|
|
|
|
} // End of namespace Sword2
|