MADS: Beginnings of dialog class hierarchy

This commit is contained in:
Paul Gilbert 2014-02-22 08:39:44 -05:00
parent 9f1416c6a3
commit 54c4515232
6 changed files with 347 additions and 215 deletions

200
engines/mads/dialogs.cpp Normal file
View File

@ -0,0 +1,200 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "common/scummsys.h"
#include "common/config-manager.h"
#include "mads/mads.h"
#include "mads/graphics.h"
#include "mads/msurface.h"
#include "mads/nebular/dialogs_nebular.h"
namespace MADS {
Dialog::Dialog(MADSEngine *vm): _vm(vm), _savedSurface(nullptr),
_position(Common::Point(-1, -1)), _width(0), _height(0) {
}
Dialog::~Dialog() {
delete _savedSurface;
}
void Dialog::save(MSurface *s) {
_savedSurface = MSurface::init(_width, _height);
s->copyTo(_savedSurface,
Common::Rect(_position.x, _position.y, _position.x + _width, _position.y + _height),
Common::Point());
}
void Dialog::restore(MSurface *s) {
_savedSurface->copyTo(s, _position);
delete _savedSurface;
_savedSurface = nullptr;
}
/*------------------------------------------------------------------------*/
TextDialog::TextDialog(MADSEngine *vm, const Common::String &fontName,
const Common::Point &pos, int maxChars):
Dialog(vm) {
_vm = vm;
_fontName = fontName;
_position = pos;
_vm->_font->setFont(FONT_INTERFACE);
_vm->_font->setColors(TEXTDIALOG_FONT, TEXTDIALOG_FONT, TEXTDIALOG_FONT, TEXTDIALOG_FONT);
_innerWidth = (_vm->_font->maxWidth() + 1) * maxChars;
_width = _innerWidth + 10;
_lineSize = maxChars * 2;
_lineWidth = 0;
_currentX = 0;
_numLines = 0;
Common::fill(&_lineXp[0], &_lineXp[TEXT_DIALOG_MAX_LINES], 0);
Common::copy(&_vm->_palette->_mainPalette[TEXTDIALOG_F8 * 3],
&_vm->_palette->_mainPalette[TEXTDIALOG_F8 * 3 + 8 * 3],
&_savedPalette[0]);
Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_F8, 2, 0x24, 0x20);
Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_FA, 2, 0x27, 0x1C);
Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_FC, 2, 0x24, 0x20);
Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_FE, 1, 0x37, 0x37);
_vm->_palette->setPalette(_vm->_palette->_mainPalette + (TEXTDIALOG_F8 * 3),
TEXTDIALOG_F8, 8);
}
TextDialog::~TextDialog() {
}
void TextDialog::addLine(const Common::String &line, bool underline) {
if (_lineWidth > 0 || _currentX > 0)
incNumLines();
int stringWidth = _vm->_font->getWidth(line);
if (stringWidth >= _innerWidth || (int)line.size() >= _lineSize) {
wordWrap(line);
} else {
_lineXp[_numLines] = (_innerWidth / 2) - (stringWidth / 2);
_lines[_numLines] = line;
if (underline)
underlineLine();
}
incNumLines();
}
void TextDialog::underlineLine() {
_lineXp[_numLines] |= 0x80;
}
void TextDialog::incNumLines() {
_lineWidth = 0;
_currentX = 0;
if (++_numLines == TEXT_DIALOG_MAX_LINES)
error("Exceeded text dialog line max");
}
void TextDialog::wordWrap(const Common::String &line) {
Common::String tempLine;
if (!line.empty()) {
const char *srcP = line.c_str();
do {
tempLine = "";
bool endWord = false;
bool newLine = false;
bool continueFlag = true;
do {
if (!*srcP) {
continueFlag = false;
} else {
tempLine += *srcP;
if (*srcP == 10) {
continueFlag = false;
newLine = true;
++srcP;
tempLine.deleteLastChar();
} else if (*srcP == ' ') {
++srcP;
endWord = true;
} else if (!endWord) {
++srcP;
} else {
tempLine.deleteLastChar();
continueFlag = false;
}
}
} while (continueFlag);
if (tempLine.hasSuffix(" "))
tempLine.deleteLastChar();
Common::String tempLine2;
if (_currentX > 0)
tempLine2 += ' ';
tempLine2 += tempLine;
int lineWidth = _vm->_font->getWidth(tempLine2, 1);
if (((_currentX + (int)tempLine2.size()) > _lineSize) ||
((_lineWidth + lineWidth) > _innerWidth)) {
incNumLines();
appendLine(tempLine);
} else {
appendLine(tempLine2);
}
if (newLine)
incNumLines();
} while (*srcP);
}
}
void TextDialog::appendLine(const Common::String &line) {
_currentX += line.size();
_lineWidth += _vm->_font->getWidth(line, 1);
_lines[_numLines] += line;
}
/*------------------------------------------------------------------------*/
MessageDialog::MessageDialog(MADSEngine *vm, int maxChars, ...):
TextDialog(vm, FONT_INTERFACE, Common::Point(-1, -1), maxChars) {
// Add in passed line list
va_list va;
va_start(va, maxChars);
const char *line = va_arg(va, const char *);
while (line) {
addLine(line);
line = va_arg(va, const char *);
}
va_end(va);
// TODO
}
} // End of namespace MADS

137
engines/mads/dialogs.h Normal file
View File

@ -0,0 +1,137 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef MADS_DIALOGS_H
#define MADS_DIALOGS_H
#include "common/scummsys.h"
#include "mads/game.h"
#include "mads/msurface.h"
namespace MADS {
class Dialog {
protected:
MADSEngine *_vm;
MSurface *_savedSurface;
Common::Point _position;
int _width;
int _height;
/**
* Save the section of the passed surface the dialog will cover.
* @param s Screen surface to save
*/
void save(MSurface *s);
/**
* Restore saved dialog surface
* @param s Screen surface to restore to.
*/
void restore(MSurface *s);
public:
/**
* Constructor
*/
Dialog(MADSEngine *vm);
/**
* Destructor
*/
~Dialog();
};
enum {
TEXTDIALOG_F8 = 0XF8,
TEXTDIALOG_F9 = 0XF8,
TEXTDIALOG_FA = 0XF8,
TEXTDIALOG_FB = 0XF8,
TEXTDIALOG_FC = 0XF8,
TEXTDIALOG_FD = 0XF8,
TEXTDIALOG_FE = 0XF8,
TEXTDIALOG_FONT = 0
};
#define TEXT_DIALOG_MAX_LINES 20
class TextDialog: protected Dialog {
private:
/**
* Increments the number of text lines the text dialog uses
*/
void incNumLines();
/**
* Flags the previously added line to be underlined
*/
void underlineLine();
/**
* Append text to the currently end line.
*/
void appendLine(const Common::String &line);
protected:
Common::String _fontName;
int _innerWidth;
int _lineWidth;
int _currentX;
int _numLines;
int _lineSize;
Common::String _lines[TEXT_DIALOG_MAX_LINES];
int _lineXp[TEXT_DIALOG_MAX_LINES];
byte _savedPalette[8 * 3];
/**
* Add a new line to the dialog
*/
void addLine(const Common::String &line, bool underline = false);
/**
* Adds one or more lines, word wrapping the passed text
*/
void wordWrap(const Common::String &line);
public:
/**
* Constructor
* @param vm Engine reference
* @param fontName Font to use for display
* @param pos Position for window top-left
* @param maxChars Horizontal width of window in characters
*/
TextDialog(MADSEngine *vm, const Common::String &fontName, const Common::Point &pos,
int maxChars);
/**
* Destructor
*/
~TextDialog();
};
class MessageDialog: protected TextDialog {
public:
MessageDialog(MADSEngine *vm, int lines, ...);
};
} // End of namespace MADS
#endif /* MADS_DIALOGS_H */

View File

@ -30,23 +30,13 @@
namespace MADS {
#define FONT_MENU "fontmenu.fnt"
#define FONT_INTERFACE "fontintr.fnt"
#define FONT_TINY "small.fnt"
#define FONT_SMALL "small.fnt"
#define FONT_MEDIUM "medium.fnt"
#define FONT_LINE "fontline.fnt"
#define FONT_CONVERSATION "fontconv.fnt"
#define FONT_4X6 "4x6pp.fnt"
#define FONT_5X6 "5x6pp.fnt"
#define FONT_CONVERSATION_MADS "fontconv.ff"
#define FONT_INTERFACE_MADS "fontintr.ff"
#define FONT_MAIN_MADS "fontmain.ff"
#define FONT_MENU_MADS "fontmenu.ff" // Not in Rex (uses bitmap files for menu strings)
#define FONT_MISC_MADS "fontmisc.ff"
#define FONT_TELE_MADS "fonttele.ff" // Not in Phantom
#define FONT_PHAN_MADS "fontphan.ff" // Phantom only
#define FONT_CONVERSATION "fontconv.ff"
#define FONT_INTERFACE "fontintr.ff"
#define FONT_MAIN "fontmain.ff"
#define FONT_MENU "fontmenu.ff" // Not in Rex (uses bitmap files for menu strings)
#define FONT_MISC "fontmisc.ff"
#define FONT_TELE "fonttele.ff" // Not in Phantom
#define FONT_PHAN "fontphan.ff" // Phantom only
class MADSEngine;

View File

@ -6,6 +6,7 @@ MODULE_OBJS := \
nebular/sound_nebular.o \
compression.o \
detection.o \
dialogs.o \
events.o \
font.o \
game.o \

View File

@ -31,133 +31,6 @@ namespace MADS {
namespace Nebular {
TextDialog::TextDialog(MADSEngine *vm, const Common::String &fontName,
const Common::Point &pos, int maxChars) {
_vm = vm;
_fontName = fontName;
_position = pos;
_vm->_font->setFont(FONT_INTERFACE);
_vm->_font->setColors(TEXTDIALOG_FONT, TEXTDIALOG_FONT, TEXTDIALOG_FONT, TEXTDIALOG_FONT);
_innerWidth = (_vm->_font->maxWidth() + 1) * maxChars;
_width = _innerWidth + 10;
_lineSize = maxChars * 2;
_lineWidth = 0;
_currentX = 0;
_numLines = 0;
Common::fill(&_lineXp[0], &_lineXp[TEXT_DIALOG_MAX_LINES], 0);
Common::copy(&_vm->_palette->_mainPalette[TEXTDIALOG_F8 * 3],
&_vm->_palette->_mainPalette[TEXTDIALOG_F8 * 3 + 8 * 3],
&_savedPalette[0]);
Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_F8, 2, 0x24, 0x20);
Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_FA, 2, 0x27, 0x1C);
Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_FC, 2, 0x24, 0x20);
Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_FE, 1, 0x37, 0x37);
_vm->_palette->setPalette(_vm->_palette->_mainPalette + (TEXTDIALOG_F8 * 3),
TEXTDIALOG_F8, 8);
}
TextDialog::~TextDialog() {
}
void TextDialog::addLine(const Common::String &line, bool underline) {
if (_lineWidth > 0 || _currentX > 0)
incNumLines();
int stringWidth = _vm->_font->getWidth(line);
if (stringWidth >= _innerWidth || (int)line.size() >= _lineSize) {
wordWrap(line);
} else {
_lineXp[_numLines] = (_innerWidth / 2) - (stringWidth / 2);
_lines[_numLines] = line;
if (underline)
underlineLine();
}
incNumLines();
}
void TextDialog::underlineLine() {
_lineXp[_numLines] |= 0x80;
}
void TextDialog::incNumLines() {
_lineWidth = 0;
_currentX = 0;
if (++_numLines == TEXT_DIALOG_MAX_LINES)
error("Exceeded text dialog line max");
}
void TextDialog::wordWrap(const Common::String &line) {
Common::String tempLine;
if (!line.empty()) {
const char *srcP = line.c_str();
do {
tempLine = "";
bool endWord = false;
bool newLine = false;
bool continueFlag = true;
do {
if (!*srcP) {
continueFlag = false;
} else {
tempLine += *srcP;
if (*srcP == 10) {
continueFlag = false;
newLine = true;
++srcP;
tempLine.deleteLastChar();
} else if (*srcP == ' ') {
++srcP;
endWord = true;
} else if (!endWord) {
++srcP;
} else {
tempLine.deleteLastChar();
continueFlag = false;
}
}
} while (continueFlag);
if (tempLine.hasSuffix(" "))
tempLine.deleteLastChar();
Common::String tempLine2;
if (_currentX > 0)
tempLine2 += ' ';
tempLine2 += tempLine;
int lineWidth = _vm->_font->getWidth(tempLine2, 1);
if (((_currentX + (int)tempLine2.size()) > _lineSize) ||
((_lineWidth + lineWidth) > _innerWidth)) {
incNumLines();
appendLine(tempLine);
} else {
appendLine(tempLine2);
}
if (newLine)
incNumLines();
} while (*srcP);
}
}
void TextDialog::appendLine(const Common::String &line) {
_currentX += line.size();
_lineWidth += _vm->_font->getWidth(line, 1);
_lines[_numLines] += line;
}
/*------------------------------------------------------------------------*/
bool CopyProtectionDialog::show(MADSEngine *vm) {
CopyProtectionDialog *dlg = new CopyProtectionDialog(vm, false);
@ -166,7 +39,7 @@ bool CopyProtectionDialog::show(MADSEngine *vm) {
}
CopyProtectionDialog::CopyProtectionDialog(MADSEngine *vm, bool priorAnswerWrong):
TextDialog(vm, FONT_INTERFACE_MADS, Common::Point(-1, -1), 32) {
TextDialog(vm, FONT_INTERFACE, Common::Point(-1, -1), 32) {
getHogAnusEntry(_hogEntry);
if (priorAnswerWrong) {

View File

@ -25,81 +25,12 @@
#include "common/scummsys.h"
#include "mads/game.h"
#include "mads/dialogs.h"
namespace MADS {
namespace Nebular {
enum {
TEXTDIALOG_F8 = 0XF8,
TEXTDIALOG_F9 = 0XF8,
TEXTDIALOG_FA = 0XF8,
TEXTDIALOG_FB = 0XF8,
TEXTDIALOG_FC = 0XF8,
TEXTDIALOG_FD = 0XF8,
TEXTDIALOG_FE = 0XF8,
TEXTDIALOG_FONT = 0
};
#define TEXT_DIALOG_MAX_LINES 20
class TextDialog {
private:
/**
* Increments the number of text lines the text dialog uses
*/
void incNumLines();
/**
* Flags the previously added line to be underlined
*/
void underlineLine();
/**
* Append text to the currently end line.
*/
void appendLine(const Common::String &line);
protected:
MADSEngine *_vm;
Common::Point _position;
Common::String _fontName;
int _width;
int _innerWidth;
int _lineWidth;
int _currentX;
int _numLines;
int _lineSize;
Common::String _lines[TEXT_DIALOG_MAX_LINES];
int _lineXp[TEXT_DIALOG_MAX_LINES];
byte _savedPalette[8 * 3];
/**
* Add a new line to the dialog
*/
void addLine(const Common::String &line, bool underline = false);
/**
* Adds one or more lines, word wrapping the passed text
*/
void wordWrap(const Common::String &line);
public:
/**
* Constructor
* @param vm Engine reference
* @param fontName Font to use for display
* @param pos Position for window top-left
* @param maxChars Horizontal width of window in characters
*/
TextDialog(MADSEngine *vm, const Common::String &fontName, const Common::Point &pos,
int maxChars);
/**
* Destructor
*/
~TextDialog();
};
struct HOGANUS {
int _bookId;
int _pageNum;