[Scummvm-git-logs] scummvm master -> 0c963e8ed4542cf5306e6ae969b4d38ce4d589f9

sev- noreply at scummvm.org
Thu Jun 19 21:38:32 UTC 2025


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

Summary:
caa23d3db5 GRAPHICS: MACGUI: Add text-to-speech (TTS) to submenus and dialog buttons
0c963e8ed4 WAGE: Add text-to-speech (TTS)


Commit: caa23d3db53f34424ce244263d014e28e642caeb
    https://github.com/scummvm/scummvm/commit/caa23d3db53f34424ce244263d014e28e642caeb
Author: ellm135 (ellm13531 at gmail.com)
Date: 2025-06-19T23:38:28+02:00

Commit Message:
GRAPHICS: MACGUI: Add text-to-speech (TTS) to submenus and dialog buttons

Changed paths:
    graphics/macgui/macdialog.cpp
    graphics/macgui/macdialog.h
    graphics/macgui/macmenu.cpp
    graphics/macgui/macmenu.h
    graphics/macgui/macwindowmanager.cpp
    graphics/macgui/macwindowmanager.h


diff --git a/graphics/macgui/macdialog.cpp b/graphics/macgui/macdialog.cpp
index 0f7885f749a..264f439c3c8 100644
--- a/graphics/macgui/macdialog.cpp
+++ b/graphics/macgui/macdialog.cpp
@@ -78,6 +78,7 @@ MacDialog::MacDialog(ManagedSurface *screen, MacWindowManager *wm, int width, Ma
 	_bbox.bottom = (_screen->h + height) / 2;
 
 	_pressedButton = -1;
+	_mouseOverButton = -1;
 
 	_mouseOverPressedButton = false;
 
@@ -220,9 +221,9 @@ int MacDialog::matchButton(int x, int y) {
 }
 
 void MacDialog::mouseMove(int x, int y) {
-	if (_pressedButton != -1) {
-		int match = matchButton(x, y);
+	int match = matchButton(x, y);
 
+	if (_pressedButton != -1) {
 		if (_mouseOverPressedButton && match != _pressedButton) {
 			_mouseOverPressedButton = false;
 			_needsRedraw = true;
@@ -231,6 +232,13 @@ void MacDialog::mouseMove(int x, int y) {
 			_needsRedraw = true;
 		}
 	}
+
+	if (_mouseOverButton != match) {
+		_mouseOverButton = match;
+		if (match != -1) {
+			_wm->sayText(_buttons->operator[](match)->text);
+		}
+	}
 }
 
 void MacDialog::mouseClick(int x, int y) {
diff --git a/graphics/macgui/macdialog.h b/graphics/macgui/macdialog.h
index a51df659ba6..389d33a67eb 100644
--- a/graphics/macgui/macdialog.h
+++ b/graphics/macgui/macdialog.h
@@ -97,6 +97,7 @@ private:
 	MacDialogButtonArray *_buttons;
 	uint _defaultButton;
 	bool _mouseOverPressedButton;
+	int _mouseOverButton;
 
 public:
 	int _pressedButton;
diff --git a/graphics/macgui/macmenu.cpp b/graphics/macgui/macmenu.cpp
index 7d334f5b3aa..7dc551f622c 100644
--- a/graphics/macgui/macmenu.cpp
+++ b/graphics/macgui/macmenu.cpp
@@ -119,6 +119,7 @@ MacMenu::MacMenu(int id, const Common::Rect &bounds, MacWindowManager *wm)
 	_activeSubItem = -1;
 	_lastActiveItem = -1;
 	_lastActiveSubItem = -1;
+	_selectedItem = -1;
 
 	_ccallback = NULL;
 	_unicodeccallback = NULL;
@@ -798,6 +799,16 @@ const Font *MacMenu::getMenuFont(int slant) {
 	return _wm->_fontMan->getFont(Graphics::MacFont(kMacFontSystem, 12, slant));
 }
 
+Common::CodePage MacMenu::getMenuEncoding() const {
+#ifdef USE_FREETYPE2
+	if (_wm->_mode & kWMModeWin95 && !(_wm->_mode & kWMModeForceMacFontsInWin95)) {
+		return Common::CodePage::kUtf8;
+	}
+#endif
+
+	return _wm->_fontMan->getFontEncoding(kMacFontSystem);
+}
+
 const Common::String MacMenu::getAcceleratorString(MacMenuItem *item, const char *prefix) {
 	if (item->shortcut == 0)
 		return Common::String();
@@ -1175,6 +1186,14 @@ void MacMenu::renderSubmenu(MacMenuSubMenu *menu, bool recursive) {
 			Common::Rect trect(r->left, y - (_wm->_fontMan->hasBuiltInFonts() ? 1 : 0), r->right, y + _font->getFontHeight());
 
 			_screen.fillRect(trect, _wm->_colorBlack);
+
+			if (_selectedItem != i) {
+				if (menu->items[i]->unicode) {
+					_wm->sayText(menu->items[i]->unicodeText);
+				} else {
+					_wm->sayText(Common::U32String(menu->items[i]->text, getMenuEncoding()));
+				}
+			}
 		}
 
 		if (!text.empty() || !unicodeText.empty()) {
@@ -1237,6 +1256,8 @@ void MacMenu::renderSubmenu(MacMenuSubMenu *menu, bool recursive) {
 		y += _menuDropdownItemHeight;
 	}
 
+	_selectedItem = menu->highlight;
+
 	if (recursive && topMenuEnabled && menu->highlight != -1 && menu->items[menu->highlight]->enabled && menu->items[menu->highlight]->submenu != nullptr)
 		renderSubmenu(menu->items[menu->highlight]->submenu, false);
 
@@ -1356,6 +1377,7 @@ bool MacMenu::mouseClick(int x, int y) {
 
 				_activeItem = i;
 				_activeSubItem = -1;
+				_selectedItem = -1;
 				if (_items[_activeItem]->submenu != nullptr) {
 					_menustack.push_back(_items[_activeItem]->submenu);
 					_items[_activeItem]->submenu->highlight = -1;
@@ -1564,6 +1586,7 @@ void MacMenu::closeMenu() {
 
 	_activeItem = -1;
 	_activeSubItem = -1;
+	_selectedItem = -1;
 	_menustack.clear();
 
 	_wm->setFullRefresh(true);
diff --git a/graphics/macgui/macmenu.h b/graphics/macgui/macmenu.h
index 5f3cd0aa099..1c00a31264a 100644
--- a/graphics/macgui/macmenu.h
+++ b/graphics/macgui/macmenu.h
@@ -203,6 +203,7 @@ private:
 private:
 	bool checkCallback(bool unicode = false);
 	const Font *getMenuFont(int slant = kMacFontRegular);
+	Common::CodePage getMenuEncoding() const;
 	const Common::String getAcceleratorString(MacMenuItem *item, const char *prefix);
 	void processTabs();
 	void processSubmenuTabs(MacMenuSubMenu *submenu);
@@ -230,6 +231,8 @@ private:
 	int _lastActiveItem;
 	int _lastActiveSubItem;
 
+	int _selectedItem;
+
 	bool _scrollTimerActive;
 	int _scrollDirection;
 
diff --git a/graphics/macgui/macwindowmanager.cpp b/graphics/macgui/macwindowmanager.cpp
index c27d02c1707..6429ba4f0ba 100644
--- a/graphics/macgui/macwindowmanager.cpp
+++ b/graphics/macgui/macwindowmanager.cpp
@@ -21,6 +21,7 @@
 #include "common/array.h"
 #include "common/list.h"
 #include "common/system.h"
+#include "common/text-to-speech.h"
 
 #include "graphics/cursorman.h"
 #include "graphics/managed_surface.h"
@@ -247,6 +248,8 @@ MacWindowManager::MacWindowManager(uint32 mode, MacPatterns *patterns, Common::L
 		CursorMan.showMouse(true);
 	}
 
+	_ttsEnabled = false;
+
 	loadDataBundle();
 	setDesktopMode(mode);
 }
@@ -1531,5 +1534,16 @@ const Common::U32String::value_type *readHex(uint16 *res, const Common::U32Strin
 	return s;
 }
 
+void MacWindowManager::sayText(const Common::U32String &text) const {
+	Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
+	if (ttsMan && _ttsEnabled) {
+		ttsMan->say(text, Common::TextToSpeechManager::INTERRUPT);
+	}
+}
+
+void MacWindowManager::setTTSEnabled(bool enabled) {
+	_ttsEnabled = enabled;
+}
+
 
 } // End of namespace Graphics
diff --git a/graphics/macgui/macwindowmanager.h b/graphics/macgui/macwindowmanager.h
index 5a81733b2c3..f272f235510 100644
--- a/graphics/macgui/macwindowmanager.h
+++ b/graphics/macgui/macwindowmanager.h
@@ -394,6 +394,9 @@ public:
 	MacMenu *getMenu();
 	MacMenu *getMenu(int id);
 
+	void sayText(const Common::U32String &text) const;
+	void setTTSEnabled(bool enabled);
+
 public:
 	MacFontManager *_fontMan;
 	uint32 _mode;
@@ -484,6 +487,8 @@ private:
 	Common::Archive *_dataBundle;
 
 	Common::U32String _clipboard;
+
+	bool _ttsEnabled;
 };
 
 const Common::U32String::value_type *readHex(uint16 *res, const Common::U32String::value_type *s, int len);


Commit: 0c963e8ed4542cf5306e6ae969b4d38ce4d589f9
    https://github.com/scummvm/scummvm/commit/0c963e8ed4542cf5306e6ae969b4d38ce4d589f9
Author: InfinityColme1 (mauricio.lavady at gmail.com)
Date: 2025-06-19T23:38:28+02:00

Commit Message:
WAGE: Add text-to-speech (TTS)

Changed paths:
  A engines/wage/detection.h
    engines/wage/POTFILES
    engines/wage/detection.cpp
    engines/wage/gui.cpp
    engines/wage/gui.h
    engines/wage/metaengine.cpp
    engines/wage/saveload.cpp
    engines/wage/wage.cpp
    engines/wage/wage.h


diff --git a/engines/wage/POTFILES b/engines/wage/POTFILES
index 1c60aabe9ab..9f6fa128682 100644
--- a/engines/wage/POTFILES
+++ b/engines/wage/POTFILES
@@ -1 +1,2 @@
 engines/wage/saveload.cpp
+engines/wage/metaengine.cpp
diff --git a/engines/wage/detection.cpp b/engines/wage/detection.cpp
index a0c99c9d357..30bbabc2b49 100644
--- a/engines/wage/detection.cpp
+++ b/engines/wage/detection.cpp
@@ -38,12 +38,13 @@ static const PlainGameDescriptor wageGames[] = {
 };
 
 #include "wage/detection_tables.h"
+#include "wage/detection.h"
 
 class WageMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
 public:
 	WageMetaEngineDetection() : AdvancedMetaEngineDetection(Wage::gameDescriptions, wageGames) {
 		_md5Bytes = 2 * 1024 * 1024;
-		_guiOptions = GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI);
+		_guiOptions = GUIO3(GUIO_NOSPEECH, GUIO_NOMIDI, GAMEOPTION_TTS);
 	}
 
 	const char *getName() const override {
diff --git a/engines/wage/detection.h b/engines/wage/detection.h
new file mode 100644
index 00000000000..b145fef6d02
--- /dev/null
+++ b/engines/wage/detection.h
@@ -0,0 +1,27 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef WAGE_DETECTION_H
+#define WAGE_DETECTION_H
+
+#define GAMEOPTION_TTS                    GUIO_GAMEOPTIONS1
+
+#endif // WAGE_DETECTION_H
diff --git a/engines/wage/gui.cpp b/engines/wage/gui.cpp
index fe3ddef01de..16e98c24ca4 100644
--- a/engines/wage/gui.cpp
+++ b/engines/wage/gui.cpp
@@ -133,6 +133,8 @@ Gui::Gui(WageEngine *engine) {
 	_consoleWindow = _wm->addTextWindow(font, kColorBlack, kColorWhite, maxWidth, Graphics::kTextAlignLeft, _menu);
 	_consoleWindow->setEditable(true);
 
+	_selectedMenuItem = -1;
+
 	loadBorders();
 }
 
@@ -252,6 +254,27 @@ bool Gui::processEvent(Common::Event &event) {
 		_menu->enableCommand(kMenuEdit, kMenuActionPaste, true);
 	}
 
+	if (event.type == Common::EVENT_MOUSEMOVE) {
+		bool mouseOnItem = false;
+		for (int i = 0; i < _menu->numberOfMenus(); i++) {
+			Graphics::MacMenuItem *menuItem = _menu->getMenuItem(i);
+
+			if (menuItem->enabled && menuItem->bbox.contains(event.mouse.x, event.mouse.y)) {
+				if (_selectedMenuItem != i) {
+					_engine->sayText(menuItem->text, Common::TextToSpeechManager::INTERRUPT);
+					_selectedMenuItem = i;
+				}
+				
+				mouseOnItem = true;
+				break;
+			}
+		}
+
+		if (!mouseOnItem) {
+			_selectedMenuItem = -1;
+		}
+	}
+
 	return _wm->processEvent(event);
 }
 
@@ -326,6 +349,8 @@ void Gui::executeMenuCommand(int action, Common::String &text) {
 			_engine->_inputText = text;
 			Common::String inp = text + '\n';
 
+			_engine->sayText(text, Common::TextToSpeechManager::QUEUE);
+
 			appendText(inp.c_str());
 
 			_consoleWindow->clearInput();
diff --git a/engines/wage/gui.h b/engines/wage/gui.h
index b939c7a68c4..a2a78d6f7c4 100644
--- a/engines/wage/gui.h
+++ b/engines/wage/gui.h
@@ -171,6 +171,8 @@ private:
 
 	int _commandsMenuId;
 	int _weaponsMenuId;
+
+	int _selectedMenuItem;
 };
 
 } // End of namespace Wage
diff --git a/engines/wage/metaengine.cpp b/engines/wage/metaengine.cpp
index 5ced1e261ac..68739ce9500 100644
--- a/engines/wage/metaengine.cpp
+++ b/engines/wage/metaengine.cpp
@@ -23,10 +23,12 @@
 
 #include "common/system.h"
 #include "common/savefile.h"
+#include "common/translation.h"
 
 #include "engines/advancedDetector.h"
 
 #include "wage/wage.h"
+#include "wage/detection.h"
 
 namespace Wage {
 
@@ -40,12 +42,38 @@ const char *WageEngine::getGameFile() const {
 
 } // End of namespace Wage
 
+#ifdef USE_TTS
+
+static const ADExtraGuiOptionsMap optionsList[] = {
+	{
+		GAMEOPTION_TTS,
+		{
+			_s("Enable Text to Speech"),
+			_s("Use TTS to read the descriptions (if TTS is available)"),
+			"tts_enabled",
+			false,
+			0,
+			0
+		}
+	},
+	
+	AD_EXTRA_GUI_OPTIONS_TERMINATOR
+};
+
+#endif
+
 class WageMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
 public:
 	const char *getName() const override {
 		return "wage";
 	}
 
+#ifdef USE_TTS
+	const ADExtraGuiOptionsMap *getAdvancedExtraGuiOptions() const override {
+		return optionsList;
+	}
+#endif
+
 	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
 
 	bool hasFeature(MetaEngineFeature f) const override;
diff --git a/engines/wage/saveload.cpp b/engines/wage/saveload.cpp
index f81c6c31e8e..80307b794ff 100644
--- a/engines/wage/saveload.cpp
+++ b/engines/wage/saveload.cpp
@@ -709,6 +709,8 @@ Common::Error WageEngine::loadGameState(int slot) {
 			_gui->enableSave();
 		}
 
+		sayText(_world->_player->_currentScene->_name, Common::TextToSpeechManager::QUEUE);
+
 		return Common::kNoError;
 	} else {
 		return Common::kUnknownError;
diff --git a/engines/wage/wage.cpp b/engines/wage/wage.cpp
index 646101bd6d5..d14b2fe2aad 100644
--- a/engines/wage/wage.cpp
+++ b/engines/wage/wage.cpp
@@ -50,6 +50,7 @@
 #include "common/events.h"
 #include "common/punycode.h"
 #include "common/system.h"
+#include "common/text-to-speech.h"
 
 #include "engines/engine.h"
 #include "engines/util.h"
@@ -147,6 +148,13 @@ Common::Error WageEngine::run() {
 
 	_gui->_consoleWindow->setTextWindowFont(_world->_player->_currentScene->getFont());
 
+	Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
+	if (ttsMan) {
+		ttsMan->setLanguage(ConfMan.get("language"));
+		ttsMan->enable(ConfMan.getBool("tts_enabled"));
+		_gui->_wm->setTTSEnabled(ConfMan.getBool("tts_enabled"));
+	}
+
 	Common::String input("look");
 	processTurn(&input, NULL);
 	_temporarilyHidden = false;
@@ -233,6 +241,8 @@ void WageEngine::processEvents() {
 					_inputText = Common::convertFromU32String(_gui->_consoleWindow->getInput());
 					Common::String inp = _inputText + '\n';
 
+					sayText(_gui->_consoleWindow->getInput(), Common::TextToSpeechManager::INTERRUPT);
+
 					_gui->appendText(inp.c_str());
 
 					_gui->_consoleWindow->clearInput();
@@ -270,11 +280,23 @@ void WageEngine::appendText(const char *str) {
 		s += '\n';
 
 		_gui->appendText(s.c_str());
+		sayText(s, Common::TextToSpeechManager::QUEUE);
 	}
 
 	_inputText.clear();
 }
 
+void WageEngine::sayText(const Common::U32String &str, Common::TextToSpeechManager::Action action) const {
+	Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
+	if (ttsMan && ConfMan.getBool("tts_enabled")) {
+		ttsMan->say(str, action);
+	}
+}
+
+void WageEngine::sayText(const Common::String &str, Common::TextToSpeechManager::Action action) const {
+	sayText(Common::U32String(str, Common::CodePage::kMacRoman), action);
+}
+
 void WageEngine::gameOver() {
 	Graphics::MacDialogButtonArray buttons;
 
@@ -285,6 +307,8 @@ void WageEngine::gameOver() {
 	Graphics::MacText gameOverMessage(*_world->_gameOverMessage, _gui->_wm, &font, Graphics::kColorBlack,
 									  Graphics::kColorWhite, 199, Graphics::kTextAlignCenter);
 
+	sayText(*_world->_gameOverMessage, Common::TextToSpeechManager::QUEUE);
+
 	Graphics::MacDialog gameOverDialog(&_gui->_screen, _gui->_wm,  199, &gameOverMessage, 199, &buttons, 0);
 
 	int button = gameOverDialog.run();
@@ -310,6 +334,8 @@ bool WageEngine::saveDialog() {
 	Graphics::MacText saveBeforeCloseMessage(*_world->_saveBeforeCloseMessage, _gui->_wm, &font, Graphics::kColorBlack,
 									  Graphics::kColorWhite, 291, Graphics::kTextAlignCenter);
 
+	sayText(*_world->_saveBeforeCloseMessage);
+
 	Graphics::MacDialog save(&_gui->_screen, _gui->_wm, 291, &saveBeforeCloseMessage, 291, &buttons, 1);
 
 	int button = save.run();
@@ -336,6 +362,9 @@ void WageEngine::aboutDialog() {
 
 	Common::U32String disclaimer("\n\n\n\nThis adventure was produced with World Builder\xAA\nthe adventure game creation system.\n© Copyright 1986 by William C. Appleton, All Right Reserved\nPublished by Silicon Beach Software, Inc.");
 
+	sayText(_world->_aboutMessage);
+	sayText(disclaimer, Common::TextToSpeechManager::QUEUE);
+
 	aboutMessage.appendText(disclaimer, 3, 9, 0, false);
 
 	Graphics::MacDialog about(&_gui->_screen, _gui->_wm, 450, &aboutMessage, 400, &buttons, 0);
@@ -411,6 +440,8 @@ void WageEngine::performInitialSetup() {
 		_world->move(_world->_player, _world->getRandomScene());
 	}
 
+	sayText(_world->_player->_currentScene->_name);
+
 	// Set the console window's dimensions early here because
 	// flowText() that needs them gets called before they're set
 	_gui->_consoleWindow->setDimensions(*_world->_player->_currentScene->_textBounds);
@@ -539,6 +570,7 @@ void WageEngine::processTurnInternal(Common::String *textInput, Designed *clickI
 		_gui->clearOutput();
 		_gui->_consoleWindow->setTextWindowFont(_world->_player->_currentScene->getFont());
 		regen();
+		sayText(playerScene->_name, Common::TextToSpeechManager::QUEUE);
 		Common::String input("look");
 		processTurnInternal(&input, NULL);
 
diff --git a/engines/wage/wage.h b/engines/wage/wage.h
index 4a765ec8dec..1c371b89754 100644
--- a/engines/wage/wage.h
+++ b/engines/wage/wage.h
@@ -55,6 +55,7 @@
 #include "common/macresman.h"
 #include "common/random.h"
 #include "common/timer.h"
+#include "common/text-to-speech.h"
 
 #include "wage/debugger.h"
 
@@ -219,6 +220,8 @@ public:
 	void updateSoundTimerForScene(Scene *scene, bool firstTime);
 	void setMenu(Common::String soundName);
 	void appendText(const char *str);
+	void sayText(const Common::U32String &str, Common::TextToSpeechManager::Action action = Common::TextToSpeechManager::INTERRUPT_NO_REPEAT) const;
+	void sayText(const Common::String &str, Common::TextToSpeechManager::Action action = Common::TextToSpeechManager::INTERRUPT_NO_REPEAT) const;
 	void gameOver();
 	bool saveDialog();
 	void aboutDialog();




More information about the Scummvm-git-logs mailing list