ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

gui-manager.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "common/events.h"
00024 #include "common/system.h"
00025 #include "common/util.h"
00026 #include "common/config-manager.h"
00027 #include "common/algorithm.h"
00028 #include "common/rect.h"
00029 #include "common/textconsole.h"
00030 #include "common/translation.h"
00031 #include "gui/EventRecorder.h"
00032 
00033 #include "backends/keymapper/action.h"
00034 #include "backends/keymapper/keymap.h"
00035 #include "backends/keymapper/keymapper.h"
00036 #include "backends/keymapper/standard-actions.h"
00037 
00038 #include "gui/gui-manager.h"
00039 #include "gui/dialog.h"
00040 #include "gui/ThemeEngine.h"
00041 #include "gui/ThemeEval.h"
00042 #include "gui/Tooltip.h"
00043 #include "gui/widget.h"
00044 
00045 #include "graphics/cursorman.h"
00046 
00047 namespace Common {
00048 DECLARE_SINGLETON(GUI::GuiManager);
00049 }
00050 
00051 namespace GUI {
00052 
00053 enum {
00054     kDoubleClickDelay = 500, // milliseconds
00055     kCursorAnimateDelay = 250,
00056     kTooltipDelay = 1250
00057 };
00058 
00059 // Constructor
00060 GuiManager::GuiManager() : _redrawStatus(kRedrawDisabled), _stateIsSaved(false),
00061     _cursorAnimateCounter(0), _cursorAnimateTimer(0) {
00062     _theme = nullptr;
00063     _useStdCursor = false;
00064 
00065     _system = g_system;
00066     _lastScreenChangeID = _system->getScreenChangeID();
00067     _width = _system->getOverlayWidth();
00068     _height = _system->getOverlayHeight();
00069 
00070     _launched = false;
00071 
00072     // Clear the cursor
00073     memset(_cursor, 0xFF, sizeof(_cursor));
00074 
00075 #ifdef USE_TRANSLATION
00076     // Enable translation
00077     TransMan.setLanguage(ConfMan.get("gui_language").c_str());
00078 #endif // USE_TRANSLATION
00079 
00080 #ifdef USE_TTS
00081     initTextToSpeech();
00082 #endif // USE_TTS
00083 
00084     ConfMan.registerDefault("gui_theme", "modern");
00085     Common::String themefile(ConfMan.get("gui_theme"));
00086 
00087     ConfMan.registerDefault("gui_renderer", ThemeEngine::findModeConfigName(ThemeEngine::_defaultRendererMode));
00088     ThemeEngine::GraphicsMode gfxMode = (ThemeEngine::GraphicsMode)ThemeEngine::findMode(ConfMan.get("gui_renderer"));
00089 
00090 #ifdef __DS__
00091     // Searching for the theme file takes ~10 seconds on the DS.
00092     // Disable this search here because external themes are not supported.
00093     if (!loadNewTheme("builtin", gfxMode)) {
00094         // Loading the built-in theme failed as well. Bail out
00095         error("Failed to load any GUI theme, aborting");
00096     }
00097 #else
00098     // Try to load the theme
00099     if (!loadNewTheme(themefile, gfxMode)) {
00100         // Loading the theme failed, try to load the built-in theme
00101         if (!loadNewTheme("builtin", gfxMode)) {
00102             // Loading the built-in theme failed as well. Bail out
00103             error("Failed to load any GUI theme, aborting");
00104         }
00105     }
00106 #endif
00107 }
00108 
00109 GuiManager::~GuiManager() {
00110     delete _theme;
00111 }
00112 
00113 Common::Keymap *GuiManager::getKeymap() const {
00114     using namespace Common;
00115 
00116     Keymap *guiMap = new Keymap(Keymap::kKeymapTypeGui, kGuiKeymapName, _("GUI"));
00117 
00118     Action *act;
00119 
00120     act = new Action(Common::kStandardActionInteract, _("Interact"));
00121     act->addDefaultInputMapping("JOY_A");
00122     act->setLeftClickEvent();
00123     guiMap->addAction(act);
00124 
00125     act = new Action("CLOS", _("Close"));
00126     act->addDefaultInputMapping("ESCAPE");
00127     act->addDefaultInputMapping("JOY_Y");
00128     act->setKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE, 0));
00129     guiMap->addAction(act);
00130 
00131     act = new Action(kStandardActionMoveUp, _("Up"));
00132     act->setKeyEvent(KEYCODE_UP);
00133     act->addDefaultInputMapping("JOY_UP");
00134     guiMap->addAction(act);
00135 
00136     act = new Action(kStandardActionMoveDown, _("Down"));
00137     act->setKeyEvent(KEYCODE_DOWN);
00138     act->addDefaultInputMapping("JOY_DOWN");
00139     guiMap->addAction(act);
00140 
00141     act = new Action(kStandardActionMoveLeft, _("Left"));
00142     act->setKeyEvent(KEYCODE_LEFT);
00143     act->addDefaultInputMapping("JOY_LEFT");
00144     guiMap->addAction(act);
00145 
00146     act = new Action(kStandardActionMoveRight, _("Right"));
00147     act->setKeyEvent(KEYCODE_RIGHT);
00148     act->addDefaultInputMapping("JOY_RIGHT");
00149     guiMap->addAction(act);
00150 
00151     return guiMap;
00152 }
00153 
00154 void GuiManager::initKeymap() {
00155     using namespace Common;
00156 
00157     Keymapper *mapper = _system->getEventManager()->getKeymapper();
00158 
00159     // Do not try to recreate same keymap over again
00160     if (mapper->getKeymap(kGuiKeymapName) != 0)
00161         return;
00162 
00163     Keymap *guiMap = getKeymap();
00164     mapper->addGlobalKeymap(guiMap);
00165 }
00166 
00167 void GuiManager::enableKeymap(bool enabled) {
00168     Common::Keymapper *keymapper = _system->getEventManager()->getKeymapper();
00169     keymapper->setEnabledKeymapType(enabled ? Common::Keymap::kKeymapTypeGui : Common::Keymap::kKeymapTypeGame);
00170 }
00171 
00172 bool GuiManager::loadNewTheme(Common::String id, ThemeEngine::GraphicsMode gfx, bool forced) {
00173     // If we are asked to reload the currently active theme, just do nothing
00174     // FIXME: Actually, why? It might be desirable at times to force a theme reload...
00175     if (!forced)
00176         if (_theme && id == _theme->getThemeId() && gfx == _theme->getGraphicsMode())
00177             return true;
00178 
00179     ThemeEngine *newTheme = nullptr;
00180 
00181     if (gfx == ThemeEngine::kGfxDisabled)
00182         gfx = ThemeEngine::_defaultRendererMode;
00183 
00184     // Try to load the new theme
00185     newTheme = new ThemeEngine(id, gfx);
00186     assert(newTheme);
00187 
00188     if (!newTheme->init())
00189         return false;
00190 
00191     //
00192     // Disable and delete the old theme
00193     //
00194     if (_theme)
00195         _theme->disable();
00196     delete _theme;
00197 
00198     if (_useStdCursor) {
00199         CursorMan.popCursorPalette();
00200         CursorMan.popCursor();
00201     }
00202 
00203     //
00204     // Enable the new theme
00205     //
00206     _theme = newTheme;
00207     _useStdCursor = !_theme->ownCursor();
00208 
00209     // If _stateIsSaved is set, we know that a Theme is already initialized,
00210     // thus we initialize the new theme properly
00211     if (_stateIsSaved) {
00212         _theme->enable();
00213 
00214         if (_useStdCursor)
00215             setupCursor();
00216     }
00217 
00218     // refresh all dialogs
00219     for (DialogStack::size_type i = 0; i < _dialogStack.size(); ++i)
00220         _dialogStack[i]->reflowLayout();
00221 
00222     // We need to redraw immediately. Otherwise
00223     // some other event may cause a widget to be
00224     // redrawn before redraw() has been called.
00225     _redrawStatus = kRedrawFull;
00226     redraw();
00227     _system->updateScreen();
00228 
00229     return true;
00230 }
00231 
00232 void GuiManager::redrawFull() {
00233     _redrawStatus = kRedrawFull;
00234     redraw();
00235     _system->updateScreen();
00236 }
00237 
00238 void GuiManager::redraw() {
00239     ThemeEngine::ShadingStyle shading;
00240 
00241     if (_dialogStack.empty())
00242         return;
00243 
00244     shading = (ThemeEngine::ShadingStyle)xmlEval()->getVar("Dialog." + _dialogStack.top()->_name + ".Shading", 0);
00245 
00246     // Tanoku: Do not apply shading more than once when opening many dialogs
00247     // on top of each other. Screen ends up being too dark and it's a
00248     // performance hog.
00249     if (_redrawStatus == kRedrawOpenDialog && _dialogStack.size() > 3)
00250         shading = ThemeEngine::kShadingNone;
00251 
00252     switch (_redrawStatus) {
00253         case kRedrawCloseDialog:
00254         case kRedrawFull:
00255         case kRedrawTopDialog:
00256             _theme->clearAll();
00257             _theme->drawToBackbuffer();
00258 
00259             for (DialogStack::size_type i = 0; i < _dialogStack.size() - 1; i++) {
00260                 _dialogStack[i]->drawDialog(kDrawLayerBackground);
00261                 _dialogStack[i]->drawDialog(kDrawLayerForeground);
00262             }
00263 
00264             // fall through
00265 
00266         case kRedrawOpenDialog:
00267             // This case is an optimization to avoid redrawing the whole dialog
00268             // stack when opening a new dialog.
00269 
00270             _theme->drawToBackbuffer();
00271 
00272             if (_redrawStatus == kRedrawOpenDialog && _dialogStack.size() > 1) {
00273                 Dialog *previousDialog = _dialogStack[_dialogStack.size() - 2];
00274                 previousDialog->drawDialog(kDrawLayerForeground);
00275             }
00276 
00277             _theme->applyScreenShading(shading);
00278             _dialogStack.top()->drawDialog(kDrawLayerBackground);
00279 
00280             _theme->drawToScreen();
00281             _theme->copyBackBufferToScreen();
00282 
00283             _dialogStack.top()->drawDialog(kDrawLayerForeground);
00284             break;
00285 
00286         default:
00287             break;
00288     }
00289 
00290     // Redraw the widgets that are marked as dirty
00291     _theme->drawToScreen();
00292     _dialogStack.top()->drawWidgets();
00293 
00294     _theme->updateScreen();
00295     _redrawStatus = kRedrawDisabled;
00296 }
00297 
00298 Dialog *GuiManager::getTopDialog() const {
00299     if (_dialogStack.empty())
00300         return nullptr;
00301     return _dialogStack.top();
00302 }
00303 
00304 void GuiManager::addToTrash(GuiObject* object, Dialog* parent) {
00305     debug(7, "Adding Gui Object %p to trash", (void *)object);
00306     GuiObjectTrashItem t;
00307     t.object = object;
00308     t.parent = nullptr;
00309     // If a dialog was provided, check it is in the dialog stack
00310     if (parent != nullptr) {
00311         for (uint i = 0 ; i < _dialogStack.size() ; ++i) {
00312             if (_dialogStack[i] == parent) {
00313                 t.parent = parent;
00314                 break;
00315             }
00316         }
00317     }
00318     _guiObjectTrash.push_back(t);
00319 }
00320 
00321 void GuiManager::runLoop() {
00322     Dialog * const activeDialog = getTopDialog();
00323     bool didSaveState = false;
00324 
00325     if (activeDialog == nullptr)
00326         return;
00327 
00328 #ifdef ENABLE_EVENTRECORDER
00329     // Suspend recording while GUI is shown
00330     g_eventRec.suspendRecording();
00331 #endif
00332 
00333     if (!_stateIsSaved) {
00334         saveState();
00335         _theme->enable();
00336         didSaveState = true;
00337 
00338         _useStdCursor = !_theme->ownCursor();
00339         if (_useStdCursor)
00340             setupCursor();
00341 
00342 //      _theme->refresh();
00343 
00344         _redrawStatus = kRedrawFull;
00345         redraw();
00346     }
00347 
00348     Common::EventManager *eventMan = _system->getEventManager();
00349     const uint32 targetFrameDuration = 1000 / 60;
00350 
00351     while (!_dialogStack.empty() && activeDialog == getTopDialog() && !eventMan->shouldQuit()) {
00352         uint32 frameStartTime = _system->getMillis(true);
00353 
00354         // Don't "tickle" the dialog until the theme has had a chance
00355         // to re-allocate buffers in case of a scaler change.
00356 
00357         activeDialog->handleTickle();
00358 
00359         if (_useStdCursor)
00360             animateCursor();
00361 
00362         Common::Event event;
00363 
00364         while (eventMan->pollEvent(event)) {
00365             // We will need to check whether the screen changed while polling
00366             // for an event here. While we do send EVENT_SCREEN_CHANGED
00367             // whenever this happens we still cannot be sure that we get such
00368             // an event immediately. For example, we might have an mouse move
00369             // event queued before an screen changed event. In some rare cases
00370             // this would make the GUI redraw (with the code a few lines
00371             // below) when it is not yet updated for new overlay dimensions.
00372             // As a result ScummVM would crash because it tries to copy data
00373             // outside the actual overlay screen.
00374             if (event.type != Common::EVENT_SCREEN_CHANGED) {
00375                 checkScreenChange();
00376             }
00377 
00378             // The top dialog can change during the event loop. In that case, flush all the
00379             // dialog-related events since they were probably generated while the old dialog
00380             // was still visible, and therefore not intended for the new one.
00381             //
00382             // This hopefully fixes strange behavior/crashes with pop-up widgets. (Most easily
00383             // triggered in 3x mode or when running ScummVM under Valgrind.)
00384             if (activeDialog != getTopDialog() && event.type != Common::EVENT_SCREEN_CHANGED) {
00385                 processEvent(event, getTopDialog());
00386                 continue;
00387             }
00388 
00389             processEvent(event, activeDialog);
00390         }
00391 
00392         // Delete GuiObject that have been added to the trash for a delayed deletion
00393         Common::List<GuiObjectTrashItem>::iterator it = _guiObjectTrash.begin();
00394         while (it != _guiObjectTrash.end()) {
00395             if ((*it).parent == nullptr || (*it).parent == activeDialog) {
00396                 debug(7, "Delayed deletion of Gui Object %p", (void *)(*it).object);
00397                 delete (*it).object;
00398                 it = _guiObjectTrash.erase(it);
00399             } else
00400                 ++it;
00401         }
00402 
00403         if (_lastMousePosition.time + kTooltipDelay < _system->getMillis(true)) {
00404             Widget *wdg = activeDialog->findWidget(_lastMousePosition.x, _lastMousePosition.y);
00405             if (wdg && wdg->hasTooltip() && !(wdg->getFlags() & WIDGET_PRESSED)) {
00406                 Tooltip *tooltip = new Tooltip();
00407                 tooltip->setup(activeDialog, wdg, _lastMousePosition.x, _lastMousePosition.y);
00408                 tooltip->runModal();
00409                 delete tooltip;
00410             }
00411         }
00412 
00413         redraw();
00414 
00415         // Delay until the allocated frame time is elapsed to match the target frame rate
00416         uint32 actualFrameDuration = _system->getMillis(true) - frameStartTime;
00417         if (actualFrameDuration < targetFrameDuration) {
00418             _system->delayMillis(targetFrameDuration - actualFrameDuration);
00419         }
00420         _system->updateScreen();
00421     }
00422 
00423     // WORKAROUND: When quitting we might not properly close the dialogs on
00424     // the dialog stack, thus we do this here to avoid any problems.
00425     // This is most noticable in bug #3481395 "LAUNCHER: Can't quit from unsupported game dialog".
00426     // It seems that Dialog::runModal never removes the dialog from the dialog
00427     // stack, thus if the dialog does not call Dialog::close to close itself
00428     // it will never be removed. Since we can have multiple run loops being
00429     // called we cannot rely on catching EVENT_QUIT in the event loop above,
00430     // since it would only catch it for the top run loop.
00431     if (eventMan->shouldQuit() && activeDialog == getTopDialog())
00432         getTopDialog()->close();
00433 
00434     if (didSaveState) {
00435         _theme->disable();
00436         restoreState();
00437         _useStdCursor = false;
00438     }
00439 
00440 #ifdef ENABLE_EVENTRECORDER
00441     // Resume recording once GUI is shown
00442     g_eventRec.resumeRecording();
00443 #endif
00444 }
00445 
00446 #pragma mark -
00447 
00448 void GuiManager::saveState() {
00449     initKeymap();
00450     enableKeymap(true);
00451 
00452     // Backup old cursor
00453     _lastClick.x = _lastClick.y = 0;
00454     _lastClick.time = 0;
00455     _lastClick.count = 0;
00456 
00457     _stateIsSaved = true;
00458 }
00459 
00460 void GuiManager::restoreState() {
00461     enableKeymap(false);
00462 
00463     if (_useStdCursor) {
00464         CursorMan.popCursor();
00465         CursorMan.popCursorPalette();
00466     }
00467 
00468     _system->updateScreen();
00469 
00470     _stateIsSaved = false;
00471 }
00472 
00473 void GuiManager::openDialog(Dialog *dialog) {
00474     giveFocusToDialog(dialog);
00475 
00476     if (!_dialogStack.empty())
00477         getTopDialog()->lostFocus();
00478 
00479     _dialogStack.push(dialog);
00480     if (_redrawStatus != kRedrawFull)
00481         _redrawStatus = kRedrawOpenDialog;
00482 
00483     // We reflow the dialog just before opening it. If the screen changed
00484     // since the last time we looked, also refresh the loaded theme,
00485     // and reflow all other open dialogs, too.
00486     if (!checkScreenChange())
00487         dialog->reflowLayout();
00488 }
00489 
00490 void GuiManager::closeTopDialog() {
00491     // Don't do anything if no dialog is open
00492     if (_dialogStack.empty())
00493         return;
00494 
00495     // Remove the dialog from the stack
00496     _dialogStack.pop()->lostFocus();
00497 
00498     if (!_dialogStack.empty()) {
00499         Dialog *dialog = getTopDialog();
00500         giveFocusToDialog(dialog);
00501     }
00502 
00503     if (_redrawStatus != kRedrawFull)
00504         _redrawStatus = kRedrawCloseDialog;
00505 
00506     redraw();
00507 }
00508 
00509 void GuiManager::setupCursor() {
00510     const byte palette[] = {
00511         255, 255, 255,
00512         255, 255, 255,
00513         171, 171, 171,
00514          87,  87,  87
00515     };
00516 
00517     CursorMan.pushCursorPalette(palette, 0, 4);
00518     CursorMan.pushCursor(nullptr, 0, 0, 0, 0, 0);
00519     CursorMan.showMouse(true);
00520 }
00521 
00522 // Draw the mouse cursor (animated). This is pretty much the same as in old
00523 // SCUMM games, but the code no longer resembles what we have in cursor.cpp
00524 // very much. We could plug in a different cursor here if we like to.
00525 
00526 void GuiManager::animateCursor() {
00527     int time = _system->getMillis(true);
00528     if (time > _cursorAnimateTimer + kCursorAnimateDelay) {
00529         for (int i = 0; i < 15; i++) {
00530             if ((i < 6) || (i > 8)) {
00531                 _cursor[16 * 7 + i] = _cursorAnimateCounter;
00532                 _cursor[16 * i + 7] = _cursorAnimateCounter;
00533             }
00534         }
00535 
00536         CursorMan.replaceCursor(_cursor, 16, 16, 7, 7, 255);
00537 
00538         _cursorAnimateTimer = time;
00539         _cursorAnimateCounter = (_cursorAnimateCounter + 1) % 4;
00540     }
00541 }
00542 
00543 bool GuiManager::checkScreenChange() {
00544     int tmpScreenChangeID = _system->getScreenChangeID();
00545     if (_lastScreenChangeID != tmpScreenChangeID) {
00546         screenChange();
00547         return true;
00548     }
00549     return false;
00550 }
00551 
00552 void GuiManager::screenChange() {
00553     _lastScreenChangeID = _system->getScreenChangeID();
00554     _width = _system->getOverlayWidth();
00555     _height = _system->getOverlayHeight();
00556 
00557     // reinit the whole theme
00558     _theme->refresh();
00559 
00560     // refresh all dialogs
00561     for (DialogStack::size_type i = 0; i < _dialogStack.size(); ++i) {
00562         _dialogStack[i]->reflowLayout();
00563     }
00564     // We need to redraw immediately. Otherwise
00565     // some other event may cause a widget to be
00566     // redrawn before redraw() has been called.
00567     _redrawStatus = kRedrawFull;
00568     redraw();
00569     _system->updateScreen();
00570 }
00571 
00572 void GuiManager::processEvent(const Common::Event &event, Dialog *const activeDialog) {
00573     if (activeDialog == nullptr)
00574         return;
00575     int button;
00576     uint32 time;
00577     Common::Point mouse(event.mouse.x - activeDialog->_x, event.mouse.y - activeDialog->_y);
00578 
00579     switch (event.type) {
00580     case Common::EVENT_KEYDOWN:
00581         activeDialog->handleKeyDown(event.kbd);
00582         break;
00583     case Common::EVENT_KEYUP:
00584         activeDialog->handleKeyUp(event.kbd);
00585         break;
00586     case Common::EVENT_MOUSEMOVE:
00587         _globalMousePosition.x = event.mouse.x;
00588         _globalMousePosition.y = event.mouse.y;
00589         activeDialog->handleMouseMoved(mouse.x, mouse.y, 0);
00590 
00591         if (mouse.x != _lastMousePosition.x || mouse.y != _lastMousePosition.y) {
00592             setLastMousePos(mouse.x, mouse.y);
00593         }
00594 
00595         break;
00596         // We don't distinguish between mousebuttons (for now at least)
00597     case Common::EVENT_LBUTTONDOWN:
00598     case Common::EVENT_RBUTTONDOWN:
00599         button = (event.type == Common::EVENT_LBUTTONDOWN ? 1 : 2);
00600         time = _system->getMillis(true);
00601         if (_lastClick.count && (time < _lastClick.time + kDoubleClickDelay)
00602             && ABS(_lastClick.x - event.mouse.x) < 3
00603             && ABS(_lastClick.y - event.mouse.y) < 3) {
00604                 _lastClick.count++;
00605         } else {
00606             _lastClick.x = event.mouse.x;
00607             _lastClick.y = event.mouse.y;
00608             _lastClick.count = 1;
00609         }
00610         _lastClick.time = time;
00611         activeDialog->handleMouseDown(mouse.x, mouse.y, button, _lastClick.count);
00612         break;
00613     case Common::EVENT_LBUTTONUP:
00614     case Common::EVENT_RBUTTONUP:
00615         button = (event.type == Common::EVENT_LBUTTONUP ? 1 : 2);
00616         activeDialog->handleMouseUp(mouse.x, mouse.y, button, _lastClick.count);
00617         break;
00618     case Common::EVENT_WHEELUP:
00619         activeDialog->handleMouseWheel(mouse.x, mouse.y, -1);
00620         break;
00621     case Common::EVENT_WHEELDOWN:
00622         activeDialog->handleMouseWheel(mouse.x, mouse.y, 1);
00623         break;
00624     case Common::EVENT_SCREEN_CHANGED:
00625         screenChange();
00626         break;
00627     default:
00628         activeDialog->handleOtherEvent(event);
00629         break;
00630     }
00631 }
00632 
00633 void GuiManager::scheduleTopDialogRedraw() {
00634     _redrawStatus = kRedrawTopDialog;
00635 }
00636 
00637 void GuiManager::giveFocusToDialog(Dialog *dialog) {
00638     int16 dialogX = _globalMousePosition.x - dialog->_x;
00639     int16 dialogY = _globalMousePosition.y - dialog->_y;
00640     dialog->receivedFocus(dialogX, dialogY);
00641     setLastMousePos(dialogX, dialogY);
00642 }
00643 
00644 void GuiManager::setLastMousePos(int16 x, int16 y) {
00645     _lastMousePosition.x = x;
00646     _lastMousePosition.y = y;
00647     _lastMousePosition.time = _system->getMillis(true);
00648 }
00649 
00650 #ifdef USE_TTS
00651 void GuiManager::initTextToSpeech() {
00652     Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
00653     if (ttsMan == nullptr)
00654         return;
00655 #ifdef USE_TRANSLATION
00656     Common::String currentLanguage = TransMan.getCurrentLanguage();
00657     if (currentLanguage == "C")
00658         currentLanguage = "en";
00659     ttsMan->setLanguage(currentLanguage);
00660 #endif
00661     int volume = (ConfMan.getInt("speech_volume", "residualvm") * 100) / 256;
00662     if (ConfMan.hasKey("mute", "residualvm") && ConfMan.getBool("mute", "residualvm"))
00663         volume = 0;
00664     ttsMan->setVolume(volume);
00665 
00666     unsigned voice;
00667     if(ConfMan.hasKey("tts_voice"))
00668         voice = ConfMan.getInt("tts_voice", "residualvm");
00669     else
00670         voice = 0;
00671     if (voice >= ttsMan->getVoicesArray().size())
00672         voice = 0;
00673     ttsMan->setVoice(voice);
00674 }
00675 #endif
00676 
00677 } // End of namespace GUI


Generated on Sat May 30 2020 05:01:05 for ResidualVM by doxygen 1.7.1
curved edge   curved edge