[Scummvm-git-logs] scummvm master -> b28a106ff59009370735647483bdb5a7f0f9965b

criezy criezy at scummvm.org
Tue Jun 8 17:23:47 UTC 2021


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
b28a106ff5 GRIFFON: Add Text To Speech support


Commit: b28a106ff59009370735647483bdb5a7f0f9965b
    https://github.com/scummvm/scummvm/commit/b28a106ff59009370735647483bdb5a7f0f9965b
Author: Twan (77198777+taylorzhancher at users.noreply.github.com)
Date: 2021-06-08T18:23:44+01:00

Commit Message:
GRIFFON: Add Text To Speech support

Changed paths:
    engines/griffon/cutscenes.cpp
    engines/griffon/detection.cpp
    engines/griffon/dialogs.cpp
    engines/griffon/griffon.cpp


diff --git a/engines/griffon/cutscenes.cpp b/engines/griffon/cutscenes.cpp
index 9de5f70b04..b43dceb3a4 100644
--- a/engines/griffon/cutscenes.cpp
+++ b/engines/griffon/cutscenes.cpp
@@ -38,6 +38,9 @@
 
 #include "griffon/griffon.h"
 
+#include "common/config-manager.h"
+#include "common/text-to-speech.h"
+
 namespace Griffon {
 
 #define POLL_AND_CHECK_QUIT() 		if (g_system->getEventManager()->pollEvent(_event)) { \
@@ -133,6 +136,23 @@ const char *story2[27] = {
 	"and I am free to die as I please."
 };
 
+int textToSpeech(int nextparagraph, const char *storyVariable[], int arraysize) {
+	Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
+	if (ttsMan != nullptr && ConfMan.getBool("tts_enabled") && storyVariable[nextparagraph][0] != 0) {
+		Common::String paragraph;
+		while (nextparagraph < arraysize && storyVariable[nextparagraph][0] != ' ') {
+			if (!paragraph.empty())
+				paragraph += " ";
+			paragraph += storyVariable[nextparagraph++];
+		}
+		while (nextparagraph < arraysize && storyVariable[nextparagraph][0] == ' ') {
+			nextparagraph += 1;
+		}
+		ttsMan->say(paragraph, Common::TextToSpeechManager::QUEUE_NO_REPEAT);
+	}
+	return nextparagraph;
+}
+
 void GriffonEngine::showLogos() {
 	_ticks = g_system->getMillis();
 	int ticks1 = _ticks;
@@ -202,11 +222,15 @@ void GriffonEngine::intro() {
 	_secsInGame = 0;
 	_secStart = 0;
 
+	Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
+
 	bool ldStop = false;
 	bool speedUp = false;
 	int cnt = 0;
 	float xofs = 0.0;
 	float ld = 0.0;
+	int nextparagraph = 0;
+
 	do {
 		Common::Rect rc;
 
@@ -234,15 +258,21 @@ void GriffonEngine::intro() {
 			y--;
 		}
 
-		for (int i = 0; i <= 37; i++) {
+		for (int i = 0; i < ARRAYSIZE(story); i++) {
 			int yy = y + i * 10;
+
+			if (i == nextparagraph)
+				nextparagraph = textToSpeech(nextparagraph, story, ARRAYSIZE(story));
+
 			if (yy > -8 && yy < 240) {
 				int x = 160 - strlen(story[i]) * 4;
 				drawString(_videoBuffer, story[i], x, yy, 4);
 			}
 
-			if (yy < 10 && i == 37)
-				return;
+			if (yy < 10 && i == ARRAYSIZE(story) - 1) {
+				if (ttsMan == nullptr || ttsMan->isSpeaking() == false)
+					return;
+			}
 		}
 
 		g_system->copyRectToScreen(_videoBuffer->getPixels(), _videoBuffer->pitch, 0, 0, _videoBuffer->w, _videoBuffer->h);
@@ -274,11 +304,15 @@ void GriffonEngine::intro() {
 					speedUp = true;
 					cnt = 6;
 				}
-				else if (_event.customType == kGriffonMenu)
+				else if (_event.customType == kGriffonMenu) {
+					if (ttsMan != nullptr)
+						ttsMan->stop();
 					return;
+				}
 			} else if (_event.type == Common::EVENT_CUSTOM_ENGINE_ACTION_END) {
-				if (_event.customType == kGriffonCutsceneSpeedUp)
+				if (_event.customType == kGriffonCutsceneSpeedUp) {
 					speedUp = false;
+				}
 			}
 
 			CHECK_QUIT();
@@ -306,6 +340,9 @@ void GriffonEngine::endOfGame() {
 
 	float ld = 0;
 	bool ldstop = false; // CHECKME: Check if actually used
+	int nextparagraph = 0;
+
+	Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
 
 	do {
 		ld += 4 * _fpsr;
@@ -367,15 +404,22 @@ void GriffonEngine::endOfGame() {
 		_titleImg->blit(*_videoBuffer, rc.left, rc.top);
 
 		y = y - spd * _fpsr;
-		for (int i = 0; i <= 26; i++) {
+
+		for (int i = 0; i < ARRAYSIZE(story2); i++) {
 			int yy = y + i * 10;
+
+			if (i == nextparagraph)
+				nextparagraph = textToSpeech(nextparagraph, story2, ARRAYSIZE(story2));
+
 			if (yy > -8 && yy < 240) {
 				int x = 160 - strlen(story2[i]) * 4;
 				drawString(_videoBuffer, story2[i], x, yy, 4);
 			}
 
-			if (yy < 10 && i == 25)
-				break;
+			if (yy < 10 && i == ARRAYSIZE(story2)-1) {
+				if (ttsMan == nullptr || ttsMan->isSpeaking() == false)
+					break;
+			}
 		}
 
 		ya = 255;
@@ -411,8 +455,11 @@ void GriffonEngine::endOfGame() {
 			if (_event.type == Common::EVENT_CUSTOM_ENGINE_ACTION_START) {
 				if (_event.customType == kGriffonCutsceneSpeedUp)
 					spd = 1.0f;
-				else if (_event.customType == kGriffonMenu)
+				else if (_event.customType == kGriffonMenu) {
+					if (ttsMan != nullptr)
+						ttsMan->stop();
 					break;
+				}
 			} else if (_event.type == Common::EVENT_CUSTOM_ENGINE_ACTION_END) {
 				if (_event.customType == kGriffonCutsceneSpeedUp)
 					spd = 0.2f;
diff --git a/engines/griffon/detection.cpp b/engines/griffon/detection.cpp
index 8e326e1e76..87c1650b85 100644
--- a/engines/griffon/detection.cpp
+++ b/engines/griffon/detection.cpp
@@ -23,11 +23,29 @@
 #include "base/plugins.h"
 #include "engines/advancedDetector.h"
 
+#include "common/text-to-speech.h"
+#include "common/translation.h"
+
 static const PlainGameDescriptor griffonGames[] = {
 	{"griffon", "The Griffon Legend"},
 	{NULL, NULL}
 };
 
+#define GAMEOPTION_TTS_NARRATOR 	GUIO_GAMEOPTIONS1
+
+static const ADExtraGuiOptionsMap optionsList[] = {
+	{
+		GAMEOPTION_TTS_NARRATOR,
+		{
+			_s("Enable Text to Speech"),
+			_s("Use TTS to read the descriptions (if TTS is available)"),
+			"tts_enabled",
+			false
+		}
+	},
+	AD_EXTRA_GUI_OPTIONS_TERMINATOR
+};
+
 namespace Griffon {
 
 static const ADGameDescription gameDescriptions[] = {
@@ -38,7 +56,11 @@ static const ADGameDescription gameDescriptions[] = {
 		Common::EN_ANY,
 		Common::kPlatformWindows,
 		ADGF_DROPPLATFORM,
+#ifdef USE_TTS
+		GUIO2(GUIO_NOMIDI, GAMEOPTION_TTS_NARRATOR)
+#else
 		GUIO1(GUIO_NOMIDI)
+#endif
 	},
 
 	AD_TABLE_END_MARKER
@@ -48,7 +70,11 @@ static const ADGameDescription gameDescriptions[] = {
 
 class GriffonMetaEngineDetection: public AdvancedMetaEngineDetection {
 public:
-	GriffonMetaEngineDetection() : AdvancedMetaEngineDetection(Griffon::gameDescriptions, sizeof(ADGameDescription), griffonGames) {
+	GriffonMetaEngineDetection() : AdvancedMetaEngineDetection(Griffon::gameDescriptions, sizeof(ADGameDescription), griffonGames
+#ifdef USE_TTS
+			, optionsList
+#endif
+			) {
 	}
 
 	const char *getEngineId() const override {
diff --git a/engines/griffon/dialogs.cpp b/engines/griffon/dialogs.cpp
index c76354e5ec..646c9cdc48 100644
--- a/engines/griffon/dialogs.cpp
+++ b/engines/griffon/dialogs.cpp
@@ -39,14 +39,25 @@
 
 #include "griffon/griffon.h"
 
+#include "common/text-to-speech.h"
+
 namespace Griffon {
 
 #define MINCURSEL 7
-#define MAXCURSEL 14
-#define SY 22
+#define MAXCURSEL 16
+#define SY 25
 #define PI 3.141593
 
 void GriffonEngine::title(int mode) {
+	const char *optionTitles[4] = {
+		"new game/save/load",
+		"options",
+		"quit game",
+		"return"
+	};
+
+	Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
+
 	float xofs = 0;
 	_itemyloc = 0;
 	bool exitTitle = false;
@@ -109,12 +120,12 @@ void GriffonEngine::title(int mode) {
 		int y = 172;
 		int x = 160 - 14 * 4;
 
-		drawString(_videoBuffer, "new game/save/load", x, y, 4);
-		drawString(_videoBuffer, "options", x, y + 16, 4);
-		drawString(_videoBuffer, "quit game", x, y + 32, 4);
+		drawString(_videoBuffer, optionTitles[0], x, y, 4);
+		drawString(_videoBuffer, optionTitles[1], x, y + 16, 4);
+		drawString(_videoBuffer, optionTitles[2], x, y + 32, 4);
 
 		if (mode == 1)
-			drawString(_videoBuffer, "return", x, y + 48, 4);
+			drawString(_videoBuffer, optionTitles[3], x, y + 48, 4);
 		else
 			drawString(_videoBuffer, "(c) 2005 by Daniel 'Syn9' Kennedy", 28, 224, 4);
 
@@ -164,6 +175,7 @@ void GriffonEngine::title(int mode) {
 				_shouldQuit = true;
 
 			if (_event.type == Common::EVENT_CUSTOM_ENGINE_ACTION_START) {
+
 				switch(_event.customType) {
 				case kGriffonMenu:
 					if (mode == 1)
@@ -173,13 +185,19 @@ void GriffonEngine::title(int mode) {
 					cursel--;
 					if (cursel < 0)
 						cursel = (mode == 1 ? 3 : 2);
+					if (ttsMan != nullptr && ConfMan.getBool("tts_enabled"))
+						ttsMan->say(optionTitles[cursel]);
 					break;
 				case kGriffonDown:
 					cursel++;
 					if (cursel >= (mode == 1 ? 4 : 3))
 						cursel = 0;
+					if (ttsMan != nullptr && ConfMan.getBool("tts_enabled"))
+						ttsMan->say(optionTitles[cursel]);
 					break;
 				case kGriffonConfirm:
+					if (ttsMan != nullptr)
+							ttsMan->stop();
 					switch(cursel) {
 					case 0:
 						_ticks = g_system->getMillis();
@@ -224,27 +242,59 @@ void GriffonEngine::title(int mode) {
 	}
 }
 
+static Common::String formatPercent(int val) {
+	val = val / 2.55;
+	return Common::String::format("%d percent", val - val % 10);
+}
+
+static void speakMenuItem(int mapTitles, int mapValues, const char *mapTitleText[], const char *mapValueText[]) {
+	Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
+	if (ttsMan != nullptr && ConfMan.getBool("tts_enabled")) {
+		Common::TextToSpeechManager::Action valueAction = Common::TextToSpeechManager::INTERRUPT;
+		if (mapTitles != 0) {
+			ttsMan->say(mapTitleText[mapTitles]);
+			valueAction = Common::TextToSpeechManager::QUEUE;
+		}
+		if (mapValues != 0)
+			ttsMan->say(mapValueText[mapValues], valueAction);
+	}
+}
+
 void GriffonEngine::configMenu() {
-	static const char *optionTitles[22] = {
+	static const char *optionTitles[25] = {
 		"", "",
 		"", "", "", "",
 		"", "", "",
 		"Music:", "", "",
 		"Sound Effects:", "", "",
+		"Text to Speech:", "", "",
 		"Music Volume:", "",
 		"Effects Volume:", "", "", "", ""
 	};
-	static const char *optionValues[22] = {
+	static const char *optionValues[25] = {
 		"", "",
 		"", "", "", "",
 		"", "", "",
 		"On", "Off", "",
 		"On", "Off", "",
+		"On", "Off", "",
 		"[----------]", "",
 		"[----------]", "",
 		"Exit + Save", "",
 		"Exit"
 	};
+	static const int curselMapTitles[MAXCURSEL+1] = {
+		0, 0, 0, 0, 0,
+		0, 0, 9, 9, 12,
+		12, 15, 15, 18, 20,
+		0, 0
+	};
+	static const int curselMapValues[MAXCURSEL+1] = {
+		0, 0, 0, 0, 0,
+		0, 0, 9, 10, 12,
+		13, 15, 16, 0, 0,
+		22, 24
+	};
 
 	int cursel = MINCURSEL;
 	bool exitMenu = false;
@@ -256,6 +306,7 @@ void GriffonEngine::configMenu() {
 
 	int ticks1 = _ticks;
 
+	Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
 
 	do {
 		_videoBuffer->fillRect(Common::Rect(0, 0, _videoBuffer->w, _videoBuffer->h), 0);
@@ -279,7 +330,7 @@ void GriffonEngine::configMenu() {
 
 		int sy = SY;
 
-		for (int i = 0; i <= 21; i++) {
+		for (int i = 0; i <= 24; i++) {
 			static char line[24];
 
 			int destColumn = 3;
@@ -291,14 +342,18 @@ void GriffonEngine::configMenu() {
 				destColumn = 0;
 			else if (i == 13 && !config.effects)
 				destColumn = 0;
-			else if (i == 15 || i == 17) {
-				int vol = (i == 15 ? config.musicVol : config.effectsVol) * 9 / 255;
+			else if (i == 15 && ConfMan.getBool("tts_enabled"))
+				destColumn = 0;
+			else if (i == 16 && !ConfMan.getBool("tts_enabled"))
+				destColumn = 0;
+			else if (i == 18|| i == 20) {
+				int vol = (i ==18 ? config.musicVol : config.effectsVol) * 9 / 255;
 				vol = CLIP(vol, 0, 9);
 
 				strcpy(line, "[----------]");
 				line[vol + 1] = 'X';
 				optionValues[i] = line;
-			} else if (i > 18)
+			} else if (i > 21)
 				destColumn = 0;
 
 			drawString(_videoBuffer, optionTitles[i], 156 - 8 * strlen(optionTitles[i]), sy + i * 8, 0);
@@ -310,12 +365,14 @@ void GriffonEngine::configMenu() {
 			curselt += 1;
 		if (cursel > 10)
 			curselt += 1;
-		if (cursel > 11)
-			curselt += 1;
 		if (cursel > 12)
 			curselt += 1;
 		if (cursel > 13)
 			curselt += 1;
+		if (cursel > 14)
+			curselt += 1;
+		if (cursel > 15)
+			curselt += 1;
 
 		Common::Rect rc;
 		rc.left = 148 + 3 * cos(2 * PI * _itemyloc / 16.0);
@@ -364,15 +421,20 @@ void GriffonEngine::configMenu() {
 					break;
 
 				case kGriffonLeft:
-					if (cursel == 11) {
+					if (cursel == 13) {
 						config.musicVol = CLIP(config.musicVol - 25, 0, 255);
 						setChannelVolume(_musicChannel, config.musicVol);
 						setChannelVolume(_menuChannel, config.musicVol);
-					} else if (cursel == 12) {
+						if (ttsMan != nullptr && ConfMan.getBool("tts_enabled"))
+							ttsMan->say(formatPercent(config.musicVol));
+					} else if (cursel == 14) {
 						config.effectsVol = CLIP(config.effectsVol - 25, 0, 255);
+
 						setChannelVolume(-1, config.effectsVol);
 						setChannelVolume(_musicChannel, config.musicVol);
 						setChannelVolume(_menuChannel, config.musicVol);
+						if (ttsMan != nullptr && ConfMan.getBool("tts_enabled"))
+							ttsMan->say(formatPercent(config.effectsVol));
 
 						if (config.effects) {
 							int snd = playSound(_sfx[kSndDoor]);
@@ -382,16 +444,19 @@ void GriffonEngine::configMenu() {
 					break;
 
 				case kGriffonRight:
-					if (cursel == 11) {
+					if (cursel == 13) {
 						config.musicVol = CLIP(config.musicVol + 25, 0, 255);
 						setChannelVolume(_musicChannel, config.musicVol);
 						setChannelVolume(_menuChannel, config.musicVol);
-					} else if (cursel == 12) {
+						if (ttsMan != nullptr && ConfMan.getBool("tts_enabled"))
+							ttsMan->say(formatPercent(config.musicVol));
+					} else if (cursel == 14) {
 						config.effectsVol = CLIP(config.effectsVol + 25, 0, 255);
-
 						setChannelVolume(-1, config.effectsVol);
 						setChannelVolume(_musicChannel, config.musicVol);
 						setChannelVolume(_menuChannel, config.musicVol);
+						if (ttsMan != nullptr && ConfMan.getBool("tts_enabled"))
+							ttsMan->say(formatPercent(config.effectsVol));
 
 						if (config.effects) {
 							int snd = playSound(_sfx[kSndDoor]);
@@ -404,12 +469,14 @@ void GriffonEngine::configMenu() {
 					cursel--;
 					if (cursel < MINCURSEL)
 						cursel = MAXCURSEL;
+					speakMenuItem(curselMapTitles[cursel], curselMapValues[cursel], optionTitles, optionValues);
 					break;
 
 				case kGriffonDown:
 					++cursel;
 					if (cursel > MAXCURSEL)
 						cursel = MINCURSEL;
+					speakMenuItem(curselMapTitles[cursel], curselMapValues[cursel], optionTitles, optionValues);
 					break;
 
 				case kGriffonConfirm:
@@ -439,10 +506,22 @@ void GriffonEngine::configMenu() {
 						if (config.effects)
 							config.effects = false;
 						break;
-					case 13:
+					case 11:
+						if (!ConfMan.getBool("tts_enabled")) {
+							ConfMan.setBool("tts_enabled", true);
+						}
+						break;
+					case 12:
+						if (ConfMan.getBool("tts_enabled")) {
+							ConfMan.setBool("tts_enabled", false);
+						}
+						break;
+					case 15:
 						saveConfig();
 						// fall through
-					case 14:
+					case 16:
+						if (ttsMan != nullptr)
+							ttsMan->stop();
 						exitMenu = true;
 						break;
 					default:
@@ -545,6 +624,10 @@ void GriffonEngine::renderSaveStates() {
 }
 
 void GriffonEngine::saveLoadNew() {
+	const char *optionTitles[4] = {
+		"new game", "", "load", "return",
+	};
+
 	float y = 0.0;
 
 	_cloudAngle = 0;
@@ -570,6 +653,8 @@ void GriffonEngine::saveLoadNew() {
 	}
 	_saveLoadImg->setAlpha(192, true);
 
+	Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
+
 	// Main menu loop
 	do {
 		_videoBuffer->fillRect(Common::Rect(0, 0, _videoBuffer->w, _videoBuffer->h), 0);
@@ -605,6 +690,8 @@ void GriffonEngine::saveLoadNew() {
 					if (curRow == 0) {
 						if (curCol == 0) {
 							// NEW GAME
+							if (ttsMan != nullptr)
+								ttsMan->stop();
 							_gameMode = kGameModeNewGame;
 
 							return;
@@ -619,6 +706,8 @@ void GriffonEngine::saveLoadNew() {
 							curRow = 1;
 							tickPause = _ticks + 125;
 						} else if (curCol == 3) {
+							if (ttsMan != nullptr)
+								ttsMan->stop();
 							// RETURN
 							return;
 						} else if (curCol == 4) {
@@ -681,6 +770,8 @@ void GriffonEngine::saveLoadNew() {
 
 						tickPause = _ticks + 125;
 					}
+					if (ttsMan != nullptr && ConfMan.getBool("tts_enabled"))
+						ttsMan -> say(optionTitles[curCol]);
 					break;
 
 				case kGriffonRight:
@@ -694,6 +785,8 @@ void GriffonEngine::saveLoadNew() {
 
 						tickPause = _ticks + 125;
 					}
+					if (ttsMan != nullptr && ConfMan.getBool("tts_enabled"))
+						ttsMan -> say(optionTitles[curCol]);
 					break;
 				default:
 					;
diff --git a/engines/griffon/griffon.cpp b/engines/griffon/griffon.cpp
index b92c47ff53..a5a5ff197f 100644
--- a/engines/griffon/griffon.cpp
+++ b/engines/griffon/griffon.cpp
@@ -43,6 +43,8 @@
 #include "common/translation.h"
 #include "graphics/pixelformat.h"
 
+#include "common/text-to-speech.h"
+
 #include "engines/util.h"
 
 #include "griffon/griffon.h"
@@ -129,6 +131,10 @@ void GriffonEngine::saveConfig() {
 }
 
 Common::Error GriffonEngine::run() {
+	Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
+	if (ttsMan != nullptr)
+		ttsMan->setLanguage("en");
+
 	initGraphics(320, 240, new Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0));
 
 	_mixer = g_system->getMixer();




More information about the Scummvm-git-logs mailing list