aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorThanasis Antoniou2019-03-09 20:01:29 +0200
committerThanasis Antoniou2019-03-09 20:01:29 +0200
commit90688204d2f7da59c67c9b34a793af43e3fb56fa (patch)
tree2344a84cedb018ff9c666052457ef82929d401c0 /engines
parent5102af631d0ee3d22a4fdc079ee78d089f5dcf4a (diff)
downloadscummvm-rg350-90688204d2f7da59c67c9b34a793af43e3fb56fa.tar.gz
scummvm-rg350-90688204d2f7da59c67c9b34a793af43e3fb56fa.tar.bz2
scummvm-rg350-90688204d2f7da59c67c9b34a793af43e3fb56fa.zip
BLADERUNNER: Subtitles code improvements
Allow for 4 lines of subtitles, but start from using 2 lines by default Also added debugger command to allow for immediate text testing for subtitles
Diffstat (limited to 'engines')
-rw-r--r--engines/bladerunner/actor.cpp4
-rw-r--r--engines/bladerunner/debugger.cpp32
-rw-r--r--engines/bladerunner/debugger.h1
-rw-r--r--engines/bladerunner/subtitles.cpp76
-rw-r--r--engines/bladerunner/subtitles.h18
5 files changed, 91 insertions, 40 deletions
diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index 44dd3a603e..e1a5f98066 100644
--- a/engines/bladerunner/actor.cpp
+++ b/engines/bladerunner/actor.cpp
@@ -592,10 +592,6 @@ bool Actor::tick(bool forceDraw, Common::Rect *screenRect) {
timeLeft = 0;
}
- if (!isSpeeching()) {
- _vm->_subtitles->hide();
- }
-
if (needsUpdate) {
int newAnimation = 0, newFrame = 0;
_vm->_aiScripts->updateAnimation(_id, &newAnimation, &newFrame);
diff --git a/engines/bladerunner/debugger.cpp b/engines/bladerunner/debugger.cpp
index f8101f63ec..08c26e3355 100644
--- a/engines/bladerunner/debugger.cpp
+++ b/engines/bladerunner/debugger.cpp
@@ -50,6 +50,7 @@
#include "bladerunner/waypoints.h"
#include "bladerunner/zbuffer.h"
#include "bladerunner/overlays.h"
+#include "bladerunner/subtitles.h"
#include "common/debug.h"
@@ -91,6 +92,7 @@ Debugger::Debugger(BladeRunnerEngine *vm) : GUI::Debugger() {
registerCmd("load", WRAP_METHOD(Debugger, cmdLoad));
registerCmd("save", WRAP_METHOD(Debugger, cmdSave));
registerCmd("overlay", WRAP_METHOD(Debugger, cmdOverlay));
+ registerCmd("subtitle", WRAP_METHOD(Debugger, cmdSubtitle));
}
Debugger::~Debugger() {
@@ -800,6 +802,36 @@ bool Debugger::cmdOverlay(int argc, const char **argv) {
return true;
}
+/**
+*
+* Show an explicitly specified string as a subtitle
+*/
+bool Debugger::cmdSubtitle(int argc, const char **argv) {
+ bool invalidSyntax = false;
+
+ if (argc != 2) {
+ invalidSyntax = true;
+ } else {
+ Common::String subtitleText = argv[1];
+ if (subtitleText == "reset") {
+ _vm->_subtitles->setGameSubsText("", false);
+ } else {
+ debugPrintf("Showing text: %s\n", subtitleText.c_str());
+ _vm->_subtitles->setGameSubsText(subtitleText, true);
+ _vm->_subtitles->show();
+ }
+ }
+
+ if (invalidSyntax) {
+ debugPrintf("Show specified text as subtitle or clear the current subtitle (with the reset option).\n");
+ debugPrintf("Use double quotes to encapsulate the text.\n");
+ debugPrintf("Usage: %s (\"<text_to_display>\" | reset)\n", argv[0]);
+ }
+ return true;
+
+}
+
+
void Debugger::drawDebuggerOverlay() {
if (_viewSceneObjects) drawSceneObjects();
if (_viewScreenEffects) drawScreenEffects();
diff --git a/engines/bladerunner/debugger.h b/engines/bladerunner/debugger.h
index f425543bad..5770ad71d9 100644
--- a/engines/bladerunner/debugger.h
+++ b/engines/bladerunner/debugger.h
@@ -74,6 +74,7 @@ public:
bool cmdLoad(int argc, const char **argv);
bool cmdSave(int argc, const char **argv);
bool cmdOverlay(int argc, const char **argv);
+ bool cmdSubtitle(int argc, const char **argv);
void drawDebuggerOverlay();
diff --git a/engines/bladerunner/subtitles.cpp b/engines/bladerunner/subtitles.cpp
index 1ef22cb759..4157d754ef 100644
--- a/engines/bladerunner/subtitles.cpp
+++ b/engines/bladerunner/subtitles.cpp
@@ -22,25 +22,24 @@
#include "bladerunner/subtitles.h"
-#include "bladerunner/bladerunner.h"
#include "bladerunner/font.h"
#include "bladerunner/text_resource.h"
#include "bladerunner/audio_speech.h"
-#include "common/debug.h"
+//#include "common/debug.h"
namespace BladeRunner {
/*
* Optional support for subtitles
+ *
* CHECK what happens in VQA where the audio plays separately (are the finales such VQAs ?)
- * TODO? Catch error for bad symbol in a quote (one that causes the font to crash) - this could happen with the corrupted internal font (TAHOMA18) -> font crash or bad font display / garbage character
- * TODO? Use another escape sequence to progressively display text in a line (like in SCUMM games) <-- this could be very useful with very long lines - might also need an extra manual time or ticks parameter to determine when during the display of the first segment we should switch to the second.
- * TODO? A more advanced subtitles system
- * TODO: subtitles could be independent from sound playing (but should disappear when switching between UI screens)
+ * TODO? Use another escape sequence to progressively display text in a line (like in SCUMM games) <-- this could be very useful with very long lines
+ * - might also need an extra manual time or ticks parameter to determine when during the display of the first segment we should switch to the second.
+ * TODO? A more advanced subtitles system:
+ * TODO: subtitles could be independent from sound playing (but probably should disappear when switching between UI screens)
* TODO?: Support for queuing subtitles when more than one subtitle should play for a spoken dialogue (due to a very long quote)
* TODO?: Predefine a minimum time for a subtitle to appear, before it is interrupted by the next one. (might need queuing)
* TODO?: If the subtitle is the last one then extend its duration to another predefined delay.
- * TODO?: A system to auto-split a dialogue after some max characters per both lines to a new dialogue set (delete previous 2 lines, start a new one(s) with the rest of the quote).
*
* DONE Removed support for internal font TAHOMA18 - this particular font is corrupted!
* DONE Create and Support proper external FON for subtitles.
@@ -150,7 +149,7 @@ void Subtitles::init(void) {
}
// Done - Loading text resources
//
- // Initializing/Loading Subtitles' Fonts
+ // Initializing/Loading Subtitles Fonts
_subsFont = new Font(_vm);
// Use TAHOMA18.FON (is corrupted in places)
// 10PT or TAHOMA24 or KIA6PT have all caps glyphs (and also are too big or too small) so they are not appropriate.
@@ -168,7 +167,7 @@ void Subtitles::init(void) {
// debug("Max height %d", _subsFont->getTextHeight(""));
if (_subsFontsLoaded) {
for (int i = 0; i < kMaxNumOfSubtitlesLines; ++i) {
- _subtitleLineScreenY[i] = 479 - ((kMaxNumOfSubtitlesLines - i) * (_subsFont->getTextHeight("") + 1));
+ _subtitleLineScreenY[i] = 479 - kSubtitlesBottomYOffsetPx - ((kMaxNumOfSubtitlesLines - i) * (_subsFont->getTextHeight("") + 1));
}
}
}
@@ -257,10 +256,11 @@ const char *Subtitles::getOuttakeSubsText(const Common::String &outtakesName, in
* Explicitly set the active subtitle text to be displayed
* Used for debug purposes mainly.
*/
-void Subtitles::setGameSubsText(Common::String dbgQuote) {
+void Subtitles::setGameSubsText(Common::String dbgQuote, bool forceShowWhenNoSpeech) {
if (_currentSubtitleTextFull != dbgQuote) {
_currentSubtitleTextFull = dbgQuote;
_subtitlesQuoteChanged = true;
+ _forceShowWhenNoSpeech = forceShowWhenNoSpeech; // overrides not showing subtitles when no one is speaking
}
}
@@ -309,14 +309,16 @@ bool Subtitles::isVisible() const {
* Tick method specific for outtakes (VQA videos)
*/
void Subtitles::tickOuttakes(Graphics::Surface &s) {
+ if (_subtitlesSystemInactive || !_vm->isSubtitlesEnabled()) {
+ return;
+ }
+
if (_currentSubtitleTextFull.empty()) {
_vm->_subtitles->hide();
} else {
_vm->_subtitles->show();
}
- if (_subtitlesSystemInactive || !_vm->isSubtitlesEnabled()) {
- return;
- }
+
if (!_isVisible) { // keep it as a separate if
return;
}
@@ -327,12 +329,14 @@ void Subtitles::tickOuttakes(Graphics::Surface &s) {
* Tick method for in-game subtitles -- Not for outtake cutscenes (VQA videos)
*/
void Subtitles::tick(Graphics::Surface &s) {
- if (!_vm->_audioSpeech->isPlaying()) {
- _vm->_subtitles->hide(); // TODO might need a better system. Don't call it always.
- }
if (_subtitlesSystemInactive || !_vm->isSubtitlesEnabled()) {
return;
}
+
+ if (!_vm->_audioSpeech->isPlaying() && !_forceShowWhenNoSpeech && _isVisible) {
+ _vm->_subtitles->hide(); // TODO might need a better system. Don't call it always.
+ }
+
if (!_isVisible) { // keep it as a separate if
return;
}
@@ -351,8 +355,20 @@ void Subtitles::draw(Graphics::Surface &s) {
_subtitlesQuoteChanged = false;
}
- for (int i = 0; i < _currentSubtitleLines; ++i) {
- _subsFont->draw(_subtitleLineQuote[i], s, _subtitleLineScreenX[i], _subtitleLineScreenY[i]);
+ // multi-line quotes appear from top to bottom
+ // ie. _subtitleLineQuote[0] is the top-most line
+ // The default available lines for drawing are:
+ // (kMaxNumOfSubtitlesLines - kStartFromSubtitleLineFromTop)
+ // And by default we prefer drawing starting from line: kStartFromSubtitleLineFromTop.
+ // However, if we have to draw more lines than the default available
+ // we should then override the default starting line and start from further up instead
+ int startingLineFromTop = kStartFromSubtitleLineFromTop;
+ if (_currentSubtitleLines > kMaxNumOfSubtitlesLines - kStartFromSubtitleLineFromTop) {
+ startingLineFromTop = kMaxNumOfSubtitlesLines - _currentSubtitleLines;
+ }
+
+ for (int i = 0, j = startingLineFromTop; i < _currentSubtitleLines; ++i, ++j) {
+ _subsFont->draw(_subtitleLineQuote[i], s, _subtitleLineScreenX[i], _subtitleLineScreenY[j]);
}
}
@@ -376,8 +392,8 @@ void Subtitles::draw(Graphics::Surface &s) {
* For the second case (auto-split), we don't account for the special case of a single word larger than max line length
* (no spaces), as practically this won't ever happen.
*
-* TODO; simplify this code
-* TODO: maybe calculate auto-split points based on quote pixel width and not character count
+* TODO: simplify this code
+* TODO: maybe calculate auto-split points taking into account on quote pixel width per character and not simply the character count
* TODO: somehow merge with graphics/font.cpp -> wordWrapTextImpl ?
*/
void Subtitles::calculatePosition() {
@@ -402,7 +418,10 @@ void Subtitles::calculatePosition() {
while (*textCharacters != 0) {
// check for new line explicit split case
- if (_currentSubtitleLines < kMaxNumOfSubtitlesLines && *textCharacters == '\n' && tmpCharIndex != 0 && _subtitleLineSplitAtCharIndex[_currentSubtitleLines - 1] == 0) {
+ if (_currentSubtitleLines < kMaxNumOfSubtitlesLines
+ && *textCharacters == '\n'
+ && tmpCharIndex != 0
+ && _subtitleLineSplitAtCharIndex[_currentSubtitleLines - 1] == 0) {
_subtitleLineSplitAtCharIndex[_currentSubtitleLines - 1] = tmpCharIndex;
_currentSubtitleLines += 1;
}
@@ -410,14 +429,14 @@ void Subtitles::calculatePosition() {
textCharacters += 1;
}
_subtitleLineSplitAtCharIndex[_currentSubtitleLines - 1] = tmpCharIndex;
- if (_currentSubtitleLines > 1) { // This means that split on new line characters is possible
+ if (_currentSubtitleLines > 1) { // This means that splitting on new line characters is possible
//
- int j = 0; // j iterates over subtitle lines.
- textCharacters = (const uint8 *)_currentSubtitleTextFull.c_str(); // reset pointer to the start of subtitle quote
- for (int i = 0; i < origQuoteNumOfChars ; ++i) { // i iterates over line characters
+ int j = 0; // j iterates over the subtitle line segments
+ textCharacters = (const uint8 *)_currentSubtitleTextFull.c_str(); // reset pointer to the start of the subtitle quote
+ for (int i = 0; i < origQuoteNumOfChars ; ++i) { // i iterates over characters in the quote
if (j < _currentSubtitleLines && i < _subtitleLineSplitAtCharIndex[j]) {
_subtitleLineQuote[j] += textCharacters[i];
- } else { // i is at split point
+ } else { // i is now at a split point of the quote
_subtitleLineQuote[j] += '\0';
j += 1; // start next line
}
@@ -432,9 +451,9 @@ void Subtitles::calculatePosition() {
}
} else {
// Here we initially have _currentSubtitleLines == 1
- // Check quote for auto-splitting
+ // We check quote for auto-splitting
// Auto splitting requires space characters in the quote string (which should be ok for the typical cases)
- if (wOrig > kMaxWidthPerLineToAutoSplitThresholdPx) { // kMaxWidthPerLineToAutoSplitThresholdPx is a practical chosen threshold for width for auto-splitting quotes purposes
+ if (wOrig > kMaxWidthPerLineToAutoSplitThresholdPx) { // kMaxWidthPerLineToAutoSplitThresholdPx is a practical chosen width threshold for auto-splitting quotes purposes
// Start by splitting in two lines. If the new parts are still too lengthy, re-try by splitting in three lines, etc.
for (int linesToSplitInto = 2; linesToSplitInto <= kMaxNumOfSubtitlesLines; ++linesToSplitInto) {
// find the first space after the middle
@@ -511,6 +530,7 @@ void Subtitles::calculatePosition() {
*/
void Subtitles::clear() {
_isVisible = false;
+ _forceShowWhenNoSpeech = false;
_currentSubtitleTextFull = "";
for (int i = 0; i < kMaxNumOfSubtitlesLines; ++i) {
_subtitleLineQuote[i] = "";
diff --git a/engines/bladerunner/subtitles.h b/engines/bladerunner/subtitles.h
index 208a8f39e2..2947ab5645 100644
--- a/engines/bladerunner/subtitles.h
+++ b/engines/bladerunner/subtitles.h
@@ -41,14 +41,16 @@ class TextResource;
class Font;
class Subtitles {
+ friend class Debugger;
//
// Subtitles could be in 6 possible languages are EN_ANY, DE_DEU, FR_FRA, IT_ITA, ES_ESP
// with corresponding _vm->_languageCode values: "E", "G", "F", "I", "R", "S"
- // TODO Maybe support 1 + 6 * 26 entries to support multiple language subtitles? Would that be useful?
- // TODO Or just support the current _vm->_languageCode ? [current implementation]
- static const int kMaxNumOfSubtitlesLines = 3;
- static const int kMaxWidthPerLineToAutoSplitThresholdPx = 610;
- static const int kMaxTextResourceEntries = 1 + 25; // Support in-game subs (1) and all possible VQAs (25) with spoken dialogue or translatable text!
+
+ static const int kMaxNumOfSubtitlesLines = 4; // At least one quote in the game requires 4 lines to be displayed correctly
+ static const int kStartFromSubtitleLineFromTop = 2; // Prefer drawing from this line (the top-most of available subtitle lines index is 0) by default
+ static const int kSubtitlesBottomYOffsetPx = 12; // In pixels. This is the bottom margin beneath the subtitles space
+ static const int kMaxWidthPerLineToAutoSplitThresholdPx = 610; // In pixels
+ static const int kMaxTextResourceEntries = 1 + 25; // Support in-game subs (1) and all possible VQAs (25) with spoken dialogue or translatable text!
static const char *SUBTITLES_FILENAME_PREFIXES[kMaxTextResourceEntries];
static const char *SUBTITLES_FONT_FILENAME_EXTERNAL;
@@ -59,6 +61,7 @@ class Subtitles {
Font *_subsFont;
bool _isVisible;
+ bool _forceShowWhenNoSpeech;
Common::String _currentSubtitleTextFull;
Common::String _subtitleLineQuote[kMaxNumOfSubtitlesLines];
int _subtitleLineScreenY[kMaxNumOfSubtitlesLines];
@@ -76,11 +79,11 @@ public:
~Subtitles();
void init();
- void setSubtitlesSystemInactive(bool flag); // disable subtitles system (possibly due to missing important resources like SUBTITLES.MIX file)
+ void setSubtitlesSystemInactive(bool flag); // disable subtitles system (possibly due to missing important resources like SUBTITLES.MIX file)
const char *getInGameSubsText(int actorId, int speech_id) ; // get the text for actorId, quoteId (in-game subs)
const char *getOuttakeSubsText(const Common::String &outtakesName, int frame); // get the text for this frame if any
- void setGameSubsText(Common::String dbgQuote); // for debugging - explicit set subs text
+ void setGameSubsText(Common::String dbgQuote, bool force); // for debugging - explicit set subs text
bool show();
bool hide();
bool isVisible() const;
@@ -89,7 +92,6 @@ public:
private:
void draw(Graphics::Surface &s);
- // bool showAt(int x, int y); // TODO maybe future use (?)
void calculatePosition();
int getIdxForSubsTreName(const Common::String &treName) const;