aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorPaul Gilbert2006-02-19 04:08:41 +0000
committerPaul Gilbert2006-02-19 04:08:41 +0000
commitb55cf4b0ffcfbbc7a300549a478f9d5c03f01dbd (patch)
tree5e429b168ed5d4792a335fdd207299d527a66919 /engines
parent7ce5441ad65b68d870fe2fb91d8f7c20b75cbfd9 (diff)
downloadscummvm-rg350-b55cf4b0ffcfbbc7a300549a478f9d5c03f01dbd.tar.gz
scummvm-rg350-b55cf4b0ffcfbbc7a300549a478f9d5c03f01dbd.tar.bz2
scummvm-rg350-b55cf4b0ffcfbbc7a300549a478f9d5c03f01dbd.zip
Added new class for displaying conversation talk dialogs
svn-id: r20760
Diffstat (limited to 'engines')
-rw-r--r--engines/lure/surface.cpp147
-rw-r--r--engines/lure/surface.h15
2 files changed, 137 insertions, 25 deletions
diff --git a/engines/lure/surface.cpp b/engines/lure/surface.cpp
index e254cfe501..ed64eab918 100644
--- a/engines/lure/surface.cpp
+++ b/engines/lure/surface.cpp
@@ -287,24 +287,13 @@ uint16 Surface::textWidth(const char *s, int numChars) {
return result;
}
-Surface *Surface::newDialog(uint16 width, uint8 numLines, char **lines, bool varLength, uint8 colour) {
- Surface *s = new Surface(width, (DIALOG_EDGE_SIZE + 3) * 2 +
- numLines * (FONT_HEIGHT - 1));
- s->createDialog();
-
- for (uint8 ctr = 0; ctr < numLines; ++ctr)
- s->writeString(DIALOG_EDGE_SIZE + 3, DIALOG_EDGE_SIZE + 3 +
- (ctr * (FONT_HEIGHT - 1)), lines[ctr], true, colour, varLength);
- return s;
-}
-
-Surface *Surface::newDialog(uint16 width, const char *line, uint8 colour) {
- uint8 numLines = 1;
+void Surface::wordWrap(char *text, uint16 width, char **&lines, uint8 &numLines) {
+ numLines = 1;
uint16 lineWidth = 0;
- char *s, *lineCopy;
+ char *s;
bool newLine;
- s = lineCopy = strdup(line);
+ s = text;
// Scan through the text and insert NULLs to break the line into allowable widths
@@ -320,20 +309,25 @@ Surface *Surface::newDialog(uint16 width, const char *line, uint8 colour) {
newLine = false;
}
- if (wordEnd) --wordEnd; // move back one to end of word
- else wordEnd = strchr(s, '\0') - 1;
+ if (wordEnd) {
+ if (!newLine) --wordEnd;
+ } else {
+ wordEnd = strchr(s, '\0') - 1;
+ }
uint16 wordSize = textWidth(s, (int) (wordEnd - s + 1));
- if (lineWidth + wordSize > width - (DIALOG_EDGE_SIZE + 3) * 2) {
+ if (lineWidth + wordSize > width) {
// Break word onto next line
*(wordStart - 1) = '\0';
++numLines;
- lineWidth = textWidth(wordStart, (int) (wordEnd - wordStart + 1));
+ if (newLine)
+ lineWidth = 0;
+ else
+ lineWidth = textWidth(wordStart, (int) (wordEnd - wordStart + 1));
} else if (newLine) {
// Break on newline
++numLines;
- ++wordEnd;
*wordEnd = '\0';
lineWidth = 0;
} else {
@@ -345,10 +339,29 @@ Surface *Surface::newDialog(uint16 width, const char *line, uint8 colour) {
}
// Set up a list for the start of each line
- char **lines = (char **) Memory::alloc(sizeof(char *) * numLines);
- lines[0] = lineCopy;
+ lines = (char **) Memory::alloc(sizeof(char *) * numLines);
+ lines[0] = text;
for (int ctr = 1; ctr < numLines; ++ctr)
lines[ctr] = strchr(lines[ctr-1], 0) + 1;
+}
+
+Surface *Surface::newDialog(uint16 width, uint8 numLines, char **lines, bool varLength, uint8 colour) {
+ Surface *s = new Surface(width, (DIALOG_EDGE_SIZE + 3) * 2 +
+ numLines * (FONT_HEIGHT - 1));
+ s->createDialog();
+
+ for (uint8 ctr = 0; ctr < numLines; ++ctr)
+ s->writeString(DIALOG_EDGE_SIZE + 3, DIALOG_EDGE_SIZE + 3 +
+ (ctr * (FONT_HEIGHT - 1)), lines[ctr], true, colour, varLength);
+ return s;
+}
+
+Surface *Surface::newDialog(uint16 width, const char *line, uint8 colour) {
+ char **lines;
+ char *lineCopy = strdup(line);
+ uint8 numLines;
+ wordWrap(lineCopy, width - (DIALOG_EDGE_SIZE + 3) * 2, lines, numLines);
+
// Create the dialog
Surface *result = newDialog(width, numLines, lines, true, colour);
@@ -387,12 +400,11 @@ void Dialog::show(const char *text) {
void Dialog::show(uint16 stringId) {
char buffer[MAX_DESC_SIZE];
+ Resources &res = Resources::getReference();
Room &r = Room::getReference();
StringData &sl = StringData::getReference();
- Action action = r.getCurrentAction();
-
- const char *actionName = (action == NONE) ? NULL : actionList[action];
+ const char *actionName = res.getCurrentActionStr();
char hotspotName[MAX_HOTSPOT_NAME_SIZE];
if (r.hotspotId() == 0)
strcpy(hotspotName, "");
@@ -453,4 +465,89 @@ void Dialog::showMessage(uint16 messageId, uint16 characterId) {
}
}
+/*--------------------------------------------------------------------------*/
+
+TalkDialog::TalkDialog(uint16 characterId, uint16 descId) {
+ StringData &strings = StringData::getReference();
+ Resources &res = Resources::getReference();
+ HotspotData *character = res.getHotspot(characterId);
+ char charName[MAX_DESC_SIZE];
+ strings.getString(character->nameId, charName, NULL, NULL);
+ strings.getString(descId, _desc, NULL, NULL);
+
+ // Apply word wrapping to figure out the needed size of the dialog
+ Surface::wordWrap(_desc, TALK_DIALOG_WIDTH - TALK_DIALOG_EDGE_SIZE * 2 - 2,
+ _lines, _numLines);
+
+ _surface = new Surface(TALK_DIALOG_WIDTH,
+ (_numLines + 1) * FONT_HEIGHT + TALK_DIALOG_EDGE_SIZE * 4);
+
+ // Draw the dialog
+ byte *pSrc = res.getTalkDialogData().data();
+ byte *pDest = _surface->data().data();
+ int xPos, yPos;
+
+ // Handle the dialog top
+ for (yPos = 0; yPos < TALK_DIALOG_EDGE_SIZE; ++yPos) {
+ *pDest++ = *pSrc++;
+ *pDest++ = *pSrc++;
+
+ for (xPos = 0; xPos < TALK_DIALOG_WIDTH - TALK_DIALOG_EDGE_SIZE - 2; ++xPos)
+ *pDest++ = *pSrc;
+ ++pSrc;
+
+ for (xPos = 0; xPos < TALK_DIALOG_EDGE_SIZE; ++xPos)
+ *pDest++ = *pSrc++;
+ }
+
+ // Handle the middle section
+ for (yPos = 0; yPos < _surface->height() - TALK_DIALOG_EDGE_SIZE * 2; ++yPos) {
+ byte *pSrcTemp = pSrc;
+
+ // Left edge
+ for (xPos = 0; xPos < TALK_DIALOG_EDGE_SIZE; ++xPos)
+ *pDest++ = *pSrcTemp++;
+
+ // Middle section
+ for (xPos = 0; xPos < _surface->width() - TALK_DIALOG_EDGE_SIZE * 2; ++xPos)
+ *pDest++ = *pSrcTemp;
+ ++pSrcTemp;
+
+ // Right edge
+ for (xPos = 0; xPos < TALK_DIALOG_EDGE_SIZE; ++xPos)
+ *pDest++ = *pSrcTemp++;
+ }
+
+ // Bottom section
+ pSrc += TALK_DIALOG_EDGE_SIZE * 2 + 1;
+ for (yPos = 0; yPos < TALK_DIALOG_EDGE_SIZE; ++yPos) {
+ for (xPos = 0; xPos < TALK_DIALOG_EDGE_SIZE; ++xPos)
+ *pDest++ = *pSrc++;
+
+ for (xPos = 0; xPos < TALK_DIALOG_WIDTH - TALK_DIALOG_EDGE_SIZE - 2; ++xPos)
+ *pDest++ = *pSrc;
+ ++pSrc;
+
+ *pDest++ = *pSrc++;
+ *pDest++ = *pSrc++;
+ }
+
+ // Write out the character name
+ uint16 charWidth = Surface::textWidth(charName);
+ _surface->writeString((TALK_DIALOG_WIDTH-charWidth)/2, TALK_DIALOG_EDGE_SIZE + 2,
+ charName, true, DIALOG_WHITE_COLOUR);
+
+ // TEMPORARY CODE - write out description. More properly, the text is meant to
+ // be displayed slowly, word by word
+ for (int lineCtr = 0; lineCtr < _numLines; ++lineCtr)
+ _surface->writeString(TALK_DIALOG_EDGE_SIZE + 2,
+ TALK_DIALOG_EDGE_SIZE + 4 + (lineCtr + 1) * FONT_HEIGHT,
+ _lines[lineCtr], true);
+}
+
+TalkDialog::~TalkDialog() {
+ delete _lines;
+ delete _surface;
+}
+
} // end of namespace Lure
diff --git a/engines/lure/surface.h b/engines/lure/surface.h
index 9febf542f5..730a824ac1 100644
--- a/engines/lure/surface.h
+++ b/engines/lure/surface.h
@@ -66,6 +66,7 @@ public:
void centerOnScreen();
static uint16 textWidth(const char *s, int numChars = 0);
+ static void wordWrap(char *text, uint16 width, char **&lines, uint8 &numLines);
static Surface *newDialog(uint16 width, uint8 numLines, char **lines, bool varLength = true, uint8 colour = DIALOG_TEXT_COLOUR);
static Surface *newDialog(uint16 width, const char *lines, uint8 colour = DIALOG_TEXT_COLOUR);
static Surface *getScreen(uint16 resourceId);
@@ -78,6 +79,20 @@ public:
static void showMessage(uint16 messageId, uint16 characterId);
};
+class TalkDialog {
+private:
+ Surface *_surface;
+ char _desc[MAX_DESC_SIZE];
+ char **_lines;
+ uint8 _numLines;
+public:
+ TalkDialog(uint16 characterId, uint16 descId);
+ ~TalkDialog();
+
+ char *desc() { return _desc; }
+ Surface &surface() { return *_surface; }
+};
+
} // End of namespace Lure
#endif