aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorPaul Gilbert2010-03-23 12:02:23 +0000
committerPaul Gilbert2010-03-23 12:02:23 +0000
commitb46a2b4e100e3018d604da240cecf936c629e8a0 (patch)
treec9cd258d0e9181a2cbaea51611971ee94d58b6b6 /engines
parent9571c817c7b7f30ed33ff5d4a07d80b8cea4f8c1 (diff)
downloadscummvm-rg350-b46a2b4e100e3018d604da240cecf936c629e8a0.tar.gz
scummvm-rg350-b46a2b4e100e3018d604da240cecf936c629e8a0.tar.bz2
scummvm-rg350-b46a2b4e100e3018d604da240cecf936c629e8a0.zip
Added further code for the game dialog framework
svn-id: r48368
Diffstat (limited to 'engines')
-rw-r--r--engines/m4/mads_menus.cpp179
-rw-r--r--engines/m4/mads_menus.h22
-rw-r--r--engines/m4/mads_scene.cpp25
-rw-r--r--engines/m4/mads_scene.h4
-rw-r--r--engines/m4/viewmgr.cpp66
-rw-r--r--engines/m4/viewmgr.h66
6 files changed, 316 insertions, 46 deletions
diff --git a/engines/m4/mads_menus.cpp b/engines/m4/mads_menus.cpp
index 353b41c9a9..c9cd1b129a 100644
--- a/engines/m4/mads_menus.cpp
+++ b/engines/m4/mads_menus.cpp
@@ -586,22 +586,32 @@ void DragonMainMenuView::handleAction(MadsGameAction action) {
*--------------------------------------------------------------------------
*/
-RexDialogView::RexDialogView(): View(_madsVm, Common::Rect(0, 0, _madsVm->_screen->width(), _madsVm->_screen->height())) {
+RexDialogView::RexDialogView(): MadsView(_madsVm, Common::Rect(0, 0, _madsVm->_screen->width(), _madsVm->_screen->height())) {
_screenType = VIEWID_MENU;
- _initialised = false;
+ // Store the previously active scene
+ _priorSceneId = _madsVm->_scene->getCurrentScene();
+
+ // Load necessary quotes
+ _madsVm->globals()->loadQuoteRange(1, 48);
+
+ initialiseLines();
+ initialiseGraphics();
+}
+
+void RexDialogView::initialiseLines() {
// Set up a list of blank entries for use in the various dialogs
for (int i = 0; i < DIALOG_LINES_SIZE; ++i) {
DialogTextEntry rec;
+ rec.in_use = false;
_dialogText.push_back(rec);
}
_totalTextEntries = 0;
- // Store the previously active scene
- _priorSceneId = _madsVm->_scene->getCurrentScene();
-
- // Load necessary quotes
- _madsVm->globals()->loadQuoteRange(1, 48);
+ // Set up a default sprite slot entry
+ _spriteSlotsStart = 1;
+ _spriteSlots[0].spriteId = -2;
+ _spriteSlots[0].timerIndex = -1;
}
void RexDialogView::initialiseGraphics() {
@@ -620,20 +630,16 @@ void RexDialogView::initialiseGraphics() {
// Set the current cursor
_madsVm->_mouse->setCursorNum(CURSOR_ARROW);
-
- _initialised = true;
}
RexDialogView::~RexDialogView() {
- if (_initialised) {
- _madsVm->_palette->deleteRange(_bgPalData);
- delete _bgPalData;
- delete _backgroundSurface;
- _madsVm->_palette->deleteRange(_spritesPalData);
- delete _spritesPalData;
- delete _menuSprites;
- }
+ _madsVm->_palette->deleteRange(_bgPalData);
+ delete _bgPalData;
+ delete _backgroundSurface;
+ _madsVm->_palette->deleteRange(_spritesPalData);
+ delete _spritesPalData;
+ delete _menuSprites;
}
void RexDialogView::loadBackground() {
@@ -683,9 +689,6 @@ void RexDialogView::loadMenuSprites() {
void RexDialogView::updateState() {
- if (!_initialised) {
- initialiseGraphics();
- }
}
void RexDialogView::onRefresh(RectList *rects, M4Surface *destSurface) {
@@ -701,11 +704,147 @@ void RexDialogView::onRefresh(RectList *rects, M4Surface *destSurface) {
View::onRefresh(rects, destSurface);
}
+void RexDialogView::setFrame(int frameNumber, int depth) {
+ int slotIndex = getSpriteSlotsIndex();
+ _spriteSlots[slotIndex].spriteId = 1;
+ _spriteSlots[slotIndex].timerIndex = 1;
+ _spriteSlots[slotIndex].spriteListIndex = 0; //_menuSpritesIndex;
+ _spriteSlots[slotIndex].frameNumber = frameNumber;
+ M4Sprite *spr = _menuSprites->getFrame(0);
+ _spriteSlots[slotIndex].width = spr->width();
+ _spriteSlots[slotIndex].height = spr->height();
+ _spriteSlots[slotIndex].depth = depth;
+ _spriteSlots[slotIndex].scale = 100;
+}
+
+void RexDialogView::initVars() {
+ _word_8502C = -1;
+ _selectedLine = -1;
+ _lineIndex = 0;
+ _enterFlag = false;
+ _textLines.clear();
+}
+
+void RexDialogView::addLine(const char *msg_p, Font *font, MadsTextAlignment alignment, int left, int top) {
+ DialogTextEntry *rec = NULL;
+
+ if (_lineIndex < _totalTextEntries) {
+ if (strcmp(msg_p, _dialogText[_lineIndex].text) == 0) {
+ rec = &_dialogText[_lineIndex];
+ if (rec->textDisplay_index != 0) {
+ MadsTextDisplayEntry &tdEntry = _textDisplay[rec->textDisplay_index];
+ if (tdEntry.active) {
+ if (_textLines.size() < 20) {
+ // Add entry to line list
+ _textLines.push_back(tdEntry.msg);
+ tdEntry.msg = _textLines[_textLines.size() - 1].c_str();
+ }
+ }
+ }
+ }
+ } else {
+ if (_lineIndex < DIALOG_LINES_SIZE) {
+ rec = &_dialogText[_lineIndex];
+ _totalTextEntries = _lineIndex + 1;
+ }
+ }
+
+ // Handling for if a line needs to be added
+ if (rec) {
+ strcpy(rec->text, msg_p);
+ rec->font = font;
+ rec->field_2 = 0;
+ rec->pos.y = top;
+ rec->widthAdjust = -1;
+ rec->in_use = true;
+ rec->textDisplay_index = -1;
+
+ switch (alignment) {
+ case ALIGN_CENTER:
+ // Center text
+ rec->pos.x = (width() - font->getWidth(rec->text)) / 2;
+ break;
+
+ case ALIGN_CHAR_CENTER: {
+ // Text is center aligned on the '@' character within the string
+ char *p = strchr(rec->text, '@');
+
+ if (p) {
+ // '@' string handling
+ // Get length of string up to the '@' character
+ *p = '\0';
+ int strWidth = font->getWidth(rec->text, rec->widthAdjust);
+ // Remove the character from the string. strcpy isn't used here because it's unsafe for
+ // copying within the same string
+ while ((*p == *(p + 1)) != '\0') ++p;
+
+ rec->pos.x = (width() / 2) - strWidth;
+ } else {
+ rec->pos.x = left;
+ }
+ break;
+ }
+
+ case RIGHT_ALIGN:
+ // Right align (moving left from given passed left)
+ rec->pos.x = left - font->getWidth(rec->text);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ ++_lineIndex;
+}
+
+/**
+ * Adds a line consisting of either a single quote, or the combination of two quote Ids
+ */
+void RexDialogView::addQuote(Font *font, MadsTextAlignment alignment, int left, int top, int id1, int id2) {
+ char buffer[80];
+
+ // Copy the first quote string into the buffer
+ const char *quoteStr = _madsVm->globals()->getQuote(id1);
+ strcpy(buffer, quoteStr);
+
+ // Handle the optional second quote Id
+ if (id2 != 0) {
+ quoteStr = _madsVm->globals()->getQuote(id2);
+ strcat(buffer, " ");
+ strcat(buffer, quoteStr);
+ }
+
+ // Add in the generated line
+ addLine(buffer, font, alignment, left, top);
+}
+
/*--------------------------------------------------------------------------
* RexDialogView is the Rex Nebular Game Menu dialog
*--------------------------------------------------------------------------
*/
+RexGameMenuDialog::RexGameMenuDialog(): RexDialogView() {
+ setFrame(1, 2);
+ initVars();
+
+ _vm->_font->setFont(FONT_CONVERSATION_MADS);
+ addLines();
+}
+
+void RexGameMenuDialog::addLines() {
+ // Add the title
+ int top = -((_vm->_font->getHeight() + 1) * 12 - 78);
+ addQuote(_vm->_font, ALIGN_CENTER, 0, top, 10);
+
+ // Loop for adding the option lines of the dialog
+ top += 6;
+ for (int idx = 0; idx < 5; ++idx) {
+ top += _vm->_font->getHeight() + 1;
+ addQuote(_vm->_font, ALIGN_CENTER, 0, top, 11 + idx);
+ }
+}
+
void RexGameMenuDialog::onRefresh(RectList *rects, M4Surface *destSurface) {
RexDialogView::onRefresh(rects, destSurface);
}
diff --git a/engines/m4/mads_menus.h b/engines/m4/mads_menus.h
index 0fad0cfb76..5d3258ab46 100644
--- a/engines/m4/mads_menus.h
+++ b/engines/m4/mads_menus.h
@@ -104,15 +104,29 @@ public:
#define DIALOG_LINES_SIZE 20
-class RexDialogView: public View {
+enum MadsTextAlignment { ALIGN_CENTER = -1, ALIGN_CHAR_CENTER = -2, RIGHT_ALIGN = -3 };
+
+
+class RexDialogView: public MadsView {
private:
int _priorSceneId;
- bool _initialised;
+ void initialiseLines();
void initialiseGraphics();
void loadBackground();
void loadMenuSprites();
protected:
+ int _word_8502C;
+ int _selectedLine;
+ int _lineIndex;
+ bool _enterFlag;
+ Common::StringArray _textLines;
+
+ void setFrame(int frameNumber, int depth);
+ void initVars();
+ void addLine(const char *msg_p, Font *font, MadsTextAlignment alignment, int left, int top);
+ void addQuote(Font *font, MadsTextAlignment alignment, int left, int top, int id1, int id2 = 0);
+protected:
M4Surface *_backgroundSurface;
RGBList *_bgPalData;
SpriteAsset *_menuSprites;
@@ -131,8 +145,10 @@ public:
};
class RexGameMenuDialog: public RexDialogView {
+private:
+ void addLines();
public:
- RexGameMenuDialog(): RexDialogView() {};
+ RexGameMenuDialog();
virtual void onRefresh(RectList *rects, M4Surface *destSurface);
};
diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp
index df5e6ba220..53f232472d 100644
--- a/engines/m4/mads_scene.cpp
+++ b/engines/m4/mads_scene.cpp
@@ -688,7 +688,7 @@ void MadsSceneResources::load(int sId) {
/*--------------------------------------------------------------------------*/
MadsScreenText::MadsScreenText() {
- for (int i = 0; i < TEXT_DISPLAY_SIZE; ++i)
+ for (int i = 0; i < OLD_TEXT_DISPLAY_SIZE; ++i)
_textDisplay[i].active = false;
for (int i = 0; i < TIMED_TEXT_SIZE; ++i)
_timedText[i].flags = 0;
@@ -701,9 +701,9 @@ MadsScreenText::MadsScreenText() {
int MadsScreenText::add(const Common::Point &destPos, uint fontColours, int widthAdjust, const char *msg, Font *font) {
// Find a free slot
int idx = 0;
- while ((idx < TEXT_DISPLAY_SIZE) && _textDisplay[idx].active)
+ while ((idx < OLD_TEXT_DISPLAY_SIZE) && _textDisplay[idx].active)
++idx;
- if (idx == TEXT_DISPLAY_SIZE)
+ if (idx == OLD_TEXT_DISPLAY_SIZE)
error("Ran out of text display slots");
// Set up the entry values
@@ -766,27 +766,10 @@ int MadsScreenText::addTimed(const Common::Point &destPos, uint fontColours, uin
* Draws any text display entries to the screen
*/
void MadsScreenText::draw(M4Surface *surface) {
- for (int idx = 0; idx < TEXT_DISPLAY_SIZE; ++idx) {
- if (_textDisplay[idx].active && (_textDisplay[idx].active2 >= 0)) {
- _textDisplay[idx].font->setColours(_textDisplay[idx].colour1, 0xFF,
- (_textDisplay[idx].colour2 == 0) ? _textDisplay[idx].colour1 : _textDisplay[idx].colour2);
- _textDisplay[idx].font->writeString(surface, _textDisplay[idx].message,
- _textDisplay[idx].bounds.left, _textDisplay[idx].bounds.top, _textDisplay[idx].bounds.width(),
- _textDisplay[idx].spacing);
- }
- }
-
- // Clear up any now inactive text display entries
- for (int idx = 0; idx < TEXT_DISPLAY_SIZE; ++idx) {
- if (_textDisplay[idx].active2 < 0) {
- _textDisplay[idx].active = false;
- _textDisplay[idx].active2 = 0;
- }
- }
}
void MadsScreenText::timedDisplay() {
- for (int idx = 0; !_abortTimedText && (idx < TEXT_DISPLAY_SIZE); ++idx) {
+ for (int idx = 0; !_abortTimedText && (idx < OLD_TEXT_DISPLAY_SIZE); ++idx) {
if (((_timedText[idx].flags & TEXTFLAG_ACTIVE) != 0) &&
(_timedText[idx].frameTimer <= g_system->getMillis()))
// Add the specified entry
diff --git a/engines/m4/mads_scene.h b/engines/m4/mads_scene.h
index d5d3a5a477..b4cdbafd80 100644
--- a/engines/m4/mads_scene.h
+++ b/engines/m4/mads_scene.h
@@ -66,7 +66,7 @@ public:
};
#define TIMED_TEXT_SIZE 10
-#define TEXT_DISPLAY_SIZE 40
+#define OLD_TEXT_DISPLAY_SIZE 40
#define TEXT_4A_SIZE 30
enum TalkTextFlags {TEXTFLAG_2 = 2, TEXTFLAG_4 = 4, TEXTFLAG_8 = 8, TEXTFLAG_40 = 0x40,
@@ -104,7 +104,7 @@ struct Text4A {
class MadsScreenText {
private:
- TextDisplay _textDisplay[TEXT_DISPLAY_SIZE];
+ TextDisplay _textDisplay[OLD_TEXT_DISPLAY_SIZE];
TimedText _timedText[TIMED_TEXT_SIZE];
Text4A _text4A[TEXT_4A_SIZE];
bool _abortTimedText;
diff --git a/engines/m4/viewmgr.cpp b/engines/m4/viewmgr.cpp
index 46b4b5af9d..a1e9c3e584 100644
--- a/engines/m4/viewmgr.cpp
+++ b/engines/m4/viewmgr.cpp
@@ -194,6 +194,72 @@ void View::onRefresh(RectList *rects, M4Surface *destSurface) {
//--------------------------------------------------------------------------
+MadsTextDisplay::MadsTextDisplay() {
+ for (int i = 0; i < TEXT_DISPLAY_SIZE; ++i)
+ _entries[i].active = false;
+}
+
+int MadsTextDisplay::add(int xp, int yp, uint fontColour, int charSpacing, const char *msg, Font *font) {
+ int usedSlot = -1;
+
+ for (int idx = 0; idx < TEXT_DISPLAY_SIZE; ++idx) {
+ if (!_entries[idx].active) {
+ usedSlot = idx;
+
+ _entries[idx].bounds.left = xp;
+ _entries[idx].bounds.top = yp;
+ _entries[idx].font = font;
+ _entries[idx].msg = msg;
+ _entries[idx].bounds.setWidth(font->getWidth(msg, charSpacing));
+ _entries[idx].bounds.setHeight(font->getHeight());
+ _entries[idx].colour1 = fontColour & 0xff;
+ _entries[idx].colour2 = fontColour >> 8;
+ _entries[idx].spacing = charSpacing;
+ _entries[idx].active2 = 1;
+ _entries[idx].active = true;
+ break;
+ }
+ }
+
+ return usedSlot;
+}
+
+void MadsTextDisplay::draw(View *view) {
+ for (int idx = 0; idx < OLD_TEXT_DISPLAY_SIZE; ++idx) {
+ if (_entries[idx].active && (_entries[idx].active2 >= 0)) {
+ _entries[idx].font->setColours(_entries[idx].colour1, 0xFF,
+ (_entries[idx].colour2 == 0) ? _entries[idx].colour1 : _entries[idx].colour2);
+ _entries[idx].font->writeString(view, _entries[idx].msg,
+ _entries[idx].bounds.left, _entries[idx].bounds.top, _entries[idx].bounds.width(),
+ _entries[idx].spacing);
+ }
+ }
+
+ // Clear up any now inactive text display entries
+ for (int idx = 0; idx < OLD_TEXT_DISPLAY_SIZE; ++idx) {
+ if (_entries[idx].active2 < 0) {
+ _entries[idx].active = false;
+ _entries[idx].active2 = 0;
+ }
+ }
+}
+
+//--------------------------------------------------------------------------
+
+MadsView::MadsView(MadsM4Engine *vm, const Common::Rect &viewBounds, bool transparent): View(vm, viewBounds, transparent) {
+ _spriteSlotsStart = 0;
+}
+
+MadsView::MadsView(MadsM4Engine *vm, int x, int y, bool transparent): View(vm, x, y, transparent) {
+ _spriteSlotsStart = 0;
+}
+
+int MadsView::getSpriteSlotsIndex() {
+ return _spriteSlotsStart++;
+}
+
+//--------------------------------------------------------------------------
+
ViewManager::ViewManager(MadsM4Engine *vm): _systemHotkeys(HotkeyList(NULL)), _vm(vm) {
_captureScreen = NULL;
_captureEvents = false;
diff --git a/engines/m4/viewmgr.h b/engines/m4/viewmgr.h
index dccfffb8aa..308240645d 100644
--- a/engines/m4/viewmgr.h
+++ b/engines/m4/viewmgr.h
@@ -32,6 +32,7 @@
#include "common/events.h"
#include "common/rect.h"
+#include "m4/font.h"
#include "m4/globals.h"
#include "m4/events.h"
#include "m4/graphics.h"
@@ -147,6 +148,71 @@ protected:
bool _transparent;
};
+class MadsSpriteSlot {
+public:
+ int spriteId;
+ int timerIndex;
+ int spriteListIndex;
+ int frameNumber;
+ int width;
+ int height;
+ int depth;
+ int scale;
+
+ MadsSpriteSlot() { };
+};
+
+#define SPRITE_SLOTS_SIZE 50
+
+class MadsTextDisplayEntry {
+public:
+ bool active;
+ int spacing;
+ Common::Rect bounds;
+ int active2;
+ uint8 colour1;
+ uint8 colour2;
+ Font *font;
+ const char *msg;
+
+ MadsTextDisplayEntry() { active = false; }
+};
+
+#define TEXT_DISPLAY_SIZE 40
+
+class MadsTextDisplay {
+private:
+ MadsTextDisplayEntry _entries[TEXT_DISPLAY_SIZE];
+public:
+ MadsTextDisplay();
+
+ MadsTextDisplayEntry &operator[](int idx) {
+ assert(idx < TEXT_DISPLAY_SIZE);
+ return _entries[idx];
+ }
+
+ int setActive2(int idx) {
+ assert(idx < TEXT_DISPLAY_SIZE);
+ _entries[idx].active2 = -1;
+ }
+
+ int add(int xp, int yp, uint fontColour, int charSpacing, const char *msg, Font *font);
+ void draw(View *view);
+};
+
+class MadsView: public View {
+protected:
+ MadsSpriteSlot _spriteSlots[SPRITE_SLOTS_SIZE];
+ MadsTextDisplay _textDisplay;
+ int _spriteSlotsStart;
+
+ int getSpriteSlotsIndex();
+public:
+ MadsView(MadsM4Engine *vm, const Common::Rect &viewBounds, bool transparent = false);
+ MadsView(MadsM4Engine *vm, int x = 0, int y = 0, bool transparent = false);
+
+};
+
class ViewManager {
private:
MadsM4Engine *_vm;