diff options
author | Max Horn | 2008-09-01 17:30:03 +0000 |
---|---|---|
committer | Max Horn | 2008-09-01 17:30:03 +0000 |
commit | 027ae0a6f6bd7e7dfbfe6f7df0824596894f51ae (patch) | |
tree | 205993ffb25dcb2311e62b1871431eb6cf62185e | |
parent | 2db5747642446bad3e1824afd0358f51c1965c20 (diff) | |
parent | 852bc9dbb750b9995d31e70f4158c97d3758c46f (diff) | |
download | scummvm-rg350-027ae0a6f6bd7e7dfbfe6f7df0824596894f51ae.tar.gz scummvm-rg350-027ae0a6f6bd7e7dfbfe6f7df0824596894f51ae.tar.bz2 scummvm-rg350-027ae0a6f6bd7e7dfbfe6f7df0824596894f51ae.zip |
First part of GSoC2008 RTL branch merge
svn-id: r34241
-rw-r--r-- | README | 125 | ||||
-rw-r--r-- | backends/events/default/default-events.cpp | 60 | ||||
-rw-r--r-- | backends/events/default/default-events.h | 4 | ||||
-rw-r--r-- | base/commandLine.cpp | 1 | ||||
-rw-r--r-- | base/main.cpp | 8 | ||||
-rw-r--r-- | common/events.h | 22 | ||||
-rw-r--r-- | engines/dialogs.cpp | 224 | ||||
-rw-r--r-- | engines/dialogs.h | 74 | ||||
-rw-r--r-- | engines/engine.cpp | 56 | ||||
-rw-r--r-- | engines/engine.h | 30 | ||||
-rw-r--r-- | engines/metaengine.h | 39 | ||||
-rw-r--r-- | engines/module.mk | 4 | ||||
-rw-r--r-- | gui/launcher.cpp | 221 | ||||
-rw-r--r-- | gui/launcher.h | 7 | ||||
-rw-r--r-- | gui/newgui.cpp | 6 | ||||
-rw-r--r-- | gui/theme-config.cpp | 33 | ||||
-rw-r--r-- | gui/themes/classic080.ini | 5 | ||||
-rw-r--r-- | gui/themes/modern.ini | 2 |
18 files changed, 885 insertions, 36 deletions
@@ -39,10 +39,12 @@ Table of Contents: * 5.1 Command Line Options * 5.2 Language Options * 5.3 Graphics Filters - * 5.4 Hotkeys + * 5.4 Global Menu + * 5.5 Hotkeys 6.0) Savegames * 6.1 Autosaves * 6.2 Converting savegames + * 6.3 Viewing/Loading savegames from the command line 7.0) Music and Sound * 7.1 Adlib emulation * 7.2 FluidSynth MIDI emulation @@ -781,6 +783,7 @@ arguments -- see the next section. -h, --help Display a brief help text and exit -z, --list-games Display list of supported games and exit -t, --list-targets Display list of configured targets and exit + --list-saves=TARGET Display a list of savegames for the game (TARGET) specified -c, --config=CONFIG Use alternate configuration file -p, --path=PATH Path to where the game is installed @@ -968,7 +971,38 @@ Likewise, games that originally were using 640x480 (such as COMI or Broken Sword will be scaled to 1280x960 and 1920x1440. -5.4) Hot Keys: +5.4) Global Menu: +---- ------------ + +The Global Menu is a general menu which is available to all of the game engines +by pressing F6. From this menu there are the following buttons: Resume, +Options, About, Return to Launcher, and Quit. Selecting 'Options' will display +a dialog where basic audio settings, such as volume levels, can be adjusted. +Selecting 'Return to Launcher' will close the current game and return the user +back to the ScummVM Launcher, where another game may be selected to play. + +Note: Returning to the Launcher is not supported by all of the engines, + and the button will be disabled in the Global Menu if it is not supported. + +Engines which currently support Returning to the Launcher are: + + AGI + AGOS + CINE + GOB + KYRA + LURE + PARALLACTION + QUEEN + SAGA + SCUMM + SKY + SWORD1 + SWORD2 + TOUCHE + + +5.5) Hot Keys: ---- --------- TODO TODO: Rework this section to clearly state which hotkeys are implemented in *all* @@ -982,7 +1016,8 @@ ScummVM supports various in-game hotkeys. They differ between SCUMM games and other games. Common: - Cmd-q - Quit (Mac OS X) + F6 - Displays the Global Menu + Cmd-q - Quit (Mac OS X) Ctrl-q - Quit (other unices including Linux) Ctrl-z OR Alt-x - Quit (other platforms) Ctrl-m - Toggle mouse capture @@ -1138,45 +1173,93 @@ The platforms that currently have a different default directory are: 6.1) Autosaves: ---- ---------- -For some games (namely "Beneath a Steel Sky", "Flight of the Amazon -Queen" and all SCUMM games), ScummVM will by default automatically -save the current state every five minutes (adjustable via the -"autosave_period" config setting). For the SCUMM engine, it will save -in Slot 0. This savestate can then be loaded again via Ctrl-0, or the -F5 menu. +For some games, (namely "Beneath a Steel Sky", "Flight of the Amazon Queen", +all AGI games, and all SCUMM games), ScummVM will by default automatically +save the current state every five minutes (adjustable via the "autosave_period" +config setting). For the AGI and SCUMM engines, it will save in Slot 0. For the +SCUMM engine, this savestate can then be loaded again via Ctrl-0, or the F5 +menu. 6.2) Converting Savegames: ----- ---------- -Using savegames from original versions, isn't supported by all game engines. Only -the following games, can use savedgames from their original versions. +---- --------------------- +Using savegames from original versions, isn't supported by all game engines. +Only the following games, can use savegames from their original versions. Elvira 1 - - Add 8 bytes (savedgame name) to the start of the savegame file - - Rename the savedgame to 'elvira1.xxx' + - Add 8 bytes (savegame name) to the start of the savegame file + - Rename the savegame to 'elvira1.xxx' Elvira 2 - - Add 8 bytes (savedgame name) to the start of the savegame file - - Rename the savedgame to 'elvira2-pc.xxx' (DOS version) or + - Add 8 bytes (savegame name) to the start of the savegame file + - Rename the savegame to 'elvira2-pc.xxx' (DOS version) or 'elvira2.xxx' (Other versions) Waxworks - - Add 8 bytes (savedgame name) to the start of the savegame file - - Rename the savedgame to 'waxworks-pc.xxx' (DOS version) or + - Add 8 bytes (savegame name) to the start of the savegame file + - Rename the savegame to 'waxworks-pc.xxx' (DOS version) or 'waxworks.xxx' (Other versions) Simon the Sorcerer 1 - - Rename the savedgame to 'simon1.xxx' + - Rename the savegame to 'simon1.xxx' Simon the Sorcerer 1 - - Rename the savedgame to 'simon2.xxx' + - Rename the savegame to 'simon2.xxx' The Feeble Files - - Rename the savedgame to 'feeble.xxx' + - Rename the savegame to 'feeble.xxx' Where 'xxx' is exact the saved game slot (ie 001) under ScummVM +6.3) Viewing/Loading savegames from the command line: +---- ------------------------------------------------ + +--list-saves: + + This switch may be used to display a list of the current savegames + of the specified target game and their corresponding save slots. + + Usage: --list-saves=[TARGET], where [TARGET] is the target game. + + Engines which currently support --list-saves are: + + AGI + AGOS + CINE + KYRA + LURE + PARALLACTION + QUEEN + SAGA + SCUMM + SKY + SWORD1 + SWORD2 + TOUCHE + +--save-slot/-x: + + This switch may be used to load a savegame directly from the command line. + + Usage: --save-slot[SLOT] or -x[SLOT], where [SLOT] is the save slot number. + + Engines which currently support --save-slot/-x are: + + AGI + CINE + KYRA + LURE + PARALLACTION + QUEEN + SAGA + SCUMM + SKY + SWORD1 + SWORD2 + TOUCHE + + 7.0) Music and Sound: ---- ---------------- diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp index 0caba25792..65b375605b 100644 --- a/backends/events/default/default-events.cpp +++ b/backends/events/default/default-events.cpp @@ -93,7 +93,8 @@ DefaultEventManager::DefaultEventManager(OSystem *boss) : _boss(boss), _buttonState(0), _modifierState(0), - _shouldQuit(false) { + _shouldQuit(false), + _shouldRTL(false) { assert(_boss); @@ -200,6 +201,9 @@ DefaultEventManager::~DefaultEventManager() { _boss->unlockMutex(_timeMutex); _boss->unlockMutex(_recorderMutex); + if (!artificialEventQueue.empty()) + artificialEventQueue.clear(); + if (_playbackFile != NULL) { delete _playbackFile; } @@ -349,7 +353,11 @@ bool DefaultEventManager::pollEvent(Common::Event &event) { uint32 time = _boss->getMillis(); bool result; - result = _boss->pollEvent(event); + if (!artificialEventQueue.empty()) { + event = artificialEventQueue.pop(); + result = true; + } else + result = _boss->pollEvent(event); if (_recordMode != kPassthrough) { @@ -375,7 +383,6 @@ bool DefaultEventManager::pollEvent(Common::Event &event) { switch (event.type) { case Common::EVENT_KEYDOWN: _modifierState = event.kbd.flags; - // init continuous event stream // not done on PalmOS because keyboard is emulated and keyup is not generated #if !defined(PALMOS_MODE) @@ -384,7 +391,27 @@ bool DefaultEventManager::pollEvent(Common::Event &event) { _currentKeyDown.flags = event.kbd.flags; _keyRepeatTime = time + kKeyRepeatInitialDelay; #endif + // Global Main Menu + // FIXME: F6 is not the best trigger, it conflicts with some games!!! + if (event.kbd.keycode == Common::KEYCODE_F6) + if (g_engine && !g_engine->isPaused()) { + Common::Event menuEvent; + menuEvent.type = Common::EVENT_MAINMENU; + + // FIXME: GSoC RTL branch passes the F6 key event to the + // engine, and also enqueues a EVENT_MAINMENU. For now, + // we just drop the key event and return an EVENT_MAINMENU + // instead. This way, we don't have to add special cases + // to engines (like it was the case for LURE in the RTL branch). + // + // However, this has other consequences, possibly negative ones. + // Like, what happens with key repeat for the trigger key? + + //pushEvent(menuEvent); + event = menuEvent; + } break; + case Common::EVENT_KEYUP: _modifierState = event.kbd.flags; if (event.kbd.keycode == _currentKeyDown.keycode) { @@ -401,6 +428,7 @@ bool DefaultEventManager::pollEvent(Common::Event &event) { _mousePos = event.mouse; _buttonState |= LBUTTON; break; + case Common::EVENT_LBUTTONUP: _mousePos = event.mouse; _buttonState &= ~LBUTTON; @@ -410,11 +438,26 @@ bool DefaultEventManager::pollEvent(Common::Event &event) { _mousePos = event.mouse; _buttonState |= RBUTTON; break; + case Common::EVENT_RBUTTONUP: _mousePos = event.mouse; _buttonState &= ~RBUTTON; break; + case Common::EVENT_MAINMENU: + if (g_engine && !g_engine->isPaused()) + g_engine->mainMenuDialog(); + + if (_shouldQuit) + event.type = Common::EVENT_QUIT; + else if (_shouldRTL) + event.type = Common::EVENT_RTL; + break; + + case Common::EVENT_RTL: + _shouldRTL = true; + break; + case Common::EVENT_QUIT: if (ConfMan.getBool("confirm_exit")) { if (g_engine) @@ -425,6 +468,7 @@ bool DefaultEventManager::pollEvent(Common::Event &event) { g_engine->pauseEngine(false); } else _shouldQuit = true; + break; default: @@ -447,4 +491,14 @@ bool DefaultEventManager::pollEvent(Common::Event &event) { return result; } +void DefaultEventManager::pushEvent(Common::Event event) { + + // If already received an EVENT_QUIT, don't add another one + if (event.type == Common::EVENT_QUIT) { + if (!_shouldQuit) + artificialEventQueue.push(event); + } else + artificialEventQueue.push(event); +} + #endif // !defined(DISABLE_DEFAULT_EVENTMANAGER) diff --git a/backends/events/default/default-events.h b/backends/events/default/default-events.h index 98dcd4b3de..b2cd1354cc 100644 --- a/backends/events/default/default-events.h +++ b/backends/events/default/default-events.h @@ -48,6 +48,7 @@ class DefaultEventManager : public Common::EventManager { int _buttonState; int _modifierState; bool _shouldQuit; + bool _shouldRTL; class RandomSourceRecord { public: @@ -107,6 +108,7 @@ public: ~DefaultEventManager(); virtual bool pollEvent(Common::Event &event); + virtual void pushEvent(Common::Event event); virtual void registerRandomSource(Common::RandomSource &rnd, const char *name); virtual void processMillis(uint32 &millis); @@ -114,6 +116,8 @@ public: virtual int getButtonState() const { return _buttonState; } virtual int getModifierState() const { return _modifierState; } virtual int shouldQuit() const { return _shouldQuit; } + virtual int shouldRTL() const { return _shouldRTL; } + virtual void resetRTL() { _shouldRTL = false; } }; #endif diff --git a/base/commandLine.cpp b/base/commandLine.cpp index f8ca8a90cd..47ba3cb9ed 100644 --- a/base/commandLine.cpp +++ b/base/commandLine.cpp @@ -56,6 +56,7 @@ static const char HELP_STRING[] = " -h, --help Display a brief help text and exit\n" " -z, --list-games Display list of supported games and exit\n" " -t, --list-targets Display list of configured targets and exit\n" + " --list-saves=TARGET Display a list of savegames for the game (TARGET) specified\n" "\n" " -c, --config=CONFIG Use alternate configuration file\n" " -p, --path=PATH Path to where the game is installed\n" diff --git a/base/main.cpp b/base/main.cpp index 115a920f36..4283b6cacf 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -38,6 +38,7 @@ #include "base/version.h" #include "common/config-manager.h" +#include "common/events.h" #include "common/file.h" #include "common/fs.h" #include "common/system.h" @@ -200,7 +201,8 @@ static int runGame(const EnginePlugin *plugin, OSystem &system, const Common::St // Reset the file/directory mappings Common::File::resetDefaultDirectories(); - return 0; + // If result=1 return to the launcher, else quit ScummVM + return result; } @@ -286,6 +288,10 @@ extern "C" int scummvm_main(int argc, char *argv[]) { // TODO: We should keep running if starting the selected game failed // (so instead of just quitting, show a nice error dialog to the // user and let him pick another game). + + // Reset RTL flag in case we want to load another engine + g_system->getEventManager()->resetRTL(); + if (result == 0) break; diff --git a/common/events.h b/common/events.h index d0cb740692..3e4fdbf5ef 100644 --- a/common/events.h +++ b/common/events.h @@ -27,6 +27,7 @@ #define COMMON_EVENTS_H #include "common/keyboard.h" +#include "common/queue.h" #include "common/rect.h" #include "common/system.h" #include "common/noncopyable.h" @@ -58,6 +59,9 @@ enum EventType { EVENT_MBUTTONDOWN = 13, EVENT_MBUTTONUP = 14, + EVENT_MAINMENU = 15, + EVENT_RTL = 16, + EVENT_QUIT = 10, EVENT_SCREEN_CHANGED = 11, /** @@ -142,6 +146,11 @@ public: */ virtual bool pollEvent(Common::Event &event) = 0; + /** + * Pushes a "fake" event of the specified type into the event queue + */ + virtual void pushEvent(Common::Event event) = 0; + /** Register random source so it can be serialized in game test purposes **/ virtual void registerRandomSource(Common::RandomSource &rnd, const char *name) = 0; @@ -166,6 +175,16 @@ public: */ virtual int shouldQuit() const = 0; + /** + * Should we return to the launcher? + */ + virtual int shouldRTL() const = 0; + + /** + * We have returned to the launcher, and the _shouldRTL should be reset to false + */ + virtual void resetRTL() = 0; + // Optional: check whether a given key is currently pressed ???? //virtual bool isKeyPressed(int keycode) = 0; @@ -173,6 +192,9 @@ public: // TODO: Consider removing OSystem::getScreenChangeID and // replacing it by a generic getScreenChangeID method here +protected: + + Common::Queue<Common::Event> artificialEventQueue; }; } // End of namespace Common diff --git a/engines/dialogs.cpp b/engines/dialogs.cpp new file mode 100644 index 0000000000..4f95b12143 --- /dev/null +++ b/engines/dialogs.cpp @@ -0,0 +1,224 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#include "base/version.h" + +#include "common/config-manager.h" +#include "common/savefile.h" +#include "common/system.h" +#include "common/events.h" + +#include "graphics/scaler.h" + +#include "gui/about.h" +#include "gui/eval.h" +#include "gui/newgui.h" +#include "gui/ListWidget.h" + +#include "engines/dialogs.h" +#include "engines/engine.h" +#include "engines/metaengine.h" + +#ifdef SMALL_SCREEN_DEVICE +#include "gui/KeysDialog.h" +#endif + +using GUI::CommandSender; +using GUI::StaticTextWidget; +using GUI::kButtonWidth; +using GUI::kButtonHeight; +using GUI::kBigButtonWidth; +using GUI::kBigButtonHeight; +using GUI::kCloseCmd; +using GUI::kTextAlignCenter; +using GUI::kTextAlignLeft; +using GUI::WIDGET_ENABLED; + +typedef GUI::OptionsDialog GUI_OptionsDialog; +typedef GUI::Dialog GUI_Dialog; + +GlobalDialog::GlobalDialog(String name) + : GUI::Dialog(name) { +_drawingHints |= GUI::THEME_HINT_SPECIAL_COLOR;} + +enum { + kSaveCmd = 'SAVE', + kLoadCmd = 'LOAD', + kPlayCmd = 'PLAY', + kOptionsCmd = 'OPTN', + kHelpCmd = 'HELP', + kAboutCmd = 'ABOU', + kQuitCmd = 'QUIT', + kRTLCmd = 'RTL', + kChooseCmd = 'CHOS' +}; + +MainMenuDialog::MainMenuDialog(Engine *engine) + : GlobalDialog("globalmain"), _engine(engine) { + + new StaticTextWidget(this, "global_title", "ScummVM"); + + new StaticTextWidget(this, "global_version", gScummVMVersionDate); + + new GUI::ButtonWidget(this, "globalmain_resume", "Resume", kPlayCmd, 'P'); + +// new GUI::ButtonWidget(this, "globalmain_load", "Load", kLoadCmd, 'L'); +// new GUI::ButtonWidget(this, "globalmain_save", "Save", kSaveCmd, 'S'); + + new GUI::ButtonWidget(this, "globalmain_options", "Options", kOptionsCmd, 'O'); + + new GUI::ButtonWidget(this, "globalmain_about", "About", kAboutCmd, 'A'); + + _rtlButton = new GUI::ButtonWidget(this, "globalmain_rtl", "Return to Launcher", kRTLCmd, 'R'); + // '0' corresponds to the kSupportsRTL MetaEngineFeature + _rtlButton->setEnabled(_engine->hasFeature(0)); + + + new GUI::ButtonWidget(this, "globalmain_quit", "Quit", kQuitCmd, 'Q'); + + _aboutDialog = new GUI::AboutDialog(); + _optionsDialog = new ConfigDialog(); +} + +MainMenuDialog::~MainMenuDialog() { + delete _aboutDialog; + delete _optionsDialog; +} + +void MainMenuDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { + switch (cmd) { + case kPlayCmd: + close(); + break; + case kOptionsCmd: + _optionsDialog->runModal(); + break; + case kAboutCmd: + _aboutDialog->runModal(); + break; + case kRTLCmd: { + Common::Event eventRTL; + eventRTL.type = Common::EVENT_RTL; + g_system->getEventManager()->pushEvent(eventRTL); + close(); + } + break; + case kQuitCmd: { + Common::Event eventQ; + eventQ.type = Common::EVENT_QUIT; + g_system->getEventManager()->pushEvent(eventQ); + close(); + } + break; + default: + GlobalDialog::handleCommand(sender, cmd, data); + } +} + +enum { + kOKCmd = 'ok ' +}; + +enum { + kKeysCmd = 'KEYS' +}; + +// FIXME: We use the empty string as domain name here. This tells the +// ConfigManager to use the 'default' domain for all its actions. We do that +// to get as close as possible to editing the 'active' settings. +// +// However, that requires bad & evil hacks in the ConfigManager code, +// and even then still doesn't work quite correctly. +// For example, if the transient domain contains 'false' for the 'fullscreen' +// flag, but the user used a hotkey to switch to windowed mode, then the dialog +// will display the wrong value anyway. +// +// Proposed solution consisting of multiple steps: +// 1) Add special code to the open() code that reads out everything stored +// in the transient domain that is controlled by this dialog, and updates +// the dialog accordingly. +// 2) Even more code is added to query the backend for current settings, like +// the fullscreen mode flag etc., and also updates the dialog accordingly. +// 3) The domain being edited is set to the active game domain. +// 4) If the dialog is closed with the "OK" button, then we remove everything +// stored in the transient domain (or at least everything corresponding to +// switches in this dialog. +// If OTOH the dialog is closed with "Cancel" we do no such thing. +// +// These changes will achieve two things at once: Allow us to get rid of using +// "" as value for the domain, and in fact provide a somewhat better user +// experience at the same time. +ConfigDialog::ConfigDialog() + : GUI::OptionsDialog("", "scummconfig") { + + // + // Sound controllers + // + + addVolumeControls(this, "scummconfig_"); + + // + // Some misc options + // + + // SCUMM has a talkspeed range of 0-9 + addSubtitleControls(this, "scummconfig_", 9); + + // + // Add the buttons + // + + new GUI::ButtonWidget(this, "scummconfig_ok", "OK", GUI::OptionsDialog::kOKCmd, 'O'); + new GUI::ButtonWidget(this, "scummconfig_cancel", "Cancel", kCloseCmd, 'C'); + +#ifdef SMALL_SCREEN_DEVICE + new GUI::ButtonWidget(this, "scummconfig_keys", "Keys", kKeysCmd, 'K'); + + // + // Create the sub dialog(s) + // + + _keysDialog = new GUI::KeysDialog(); +#endif +} + +ConfigDialog::~ConfigDialog() { +#ifdef SMALL_SCREEN_DEVICE + delete _keysDialog; +#endif +} + +void ConfigDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { + switch (cmd) { + case kKeysCmd: + +#ifdef SMALL_SCREEN_DEVICE + _keysDialog->runModal(); +#endif + break; + default: + GUI_OptionsDialog::handleCommand (sender, cmd, data); + } +} + diff --git a/engines/dialogs.h b/engines/dialogs.h new file mode 100644 index 0000000000..61c06006cb --- /dev/null +++ b/engines/dialogs.h @@ -0,0 +1,74 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#ifndef GLOBAL_DIALOGS_H +#define GLOBAL_DIALOGS_H + +#include "common/str.h" +#include "gui/dialog.h" +#include "gui/options.h" +#include "gui/widget.h" + +#include "engines/engine.h" + + +class GlobalDialog : public GUI::Dialog { +public: + GlobalDialog(Common::String name); + +protected: + typedef Common::String String; +}; + + +class MainMenuDialog : public GlobalDialog { +public: + MainMenuDialog(Engine *engine); + ~MainMenuDialog(); + + virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data); + +protected: + Engine *_engine; + + GUI::ButtonWidget *_rtlButton; + GUI::Dialog *_aboutDialog; + GUI::Dialog *_optionsDialog; + +}; + +class ConfigDialog : public GUI::OptionsDialog { +protected: +#ifdef SMALL_SCREEN_DEVICE + GUI::Dialog *_keysDialog; +#endif + +public: + ConfigDialog(); + ~ConfigDialog(); + + virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data); +}; + +#endif diff --git a/engines/engine.cpp b/engines/engine.cpp index 757a77f82b..4840b19838 100644 --- a/engines/engine.cpp +++ b/engines/engine.cpp @@ -36,7 +36,10 @@ #include "common/savefile.h" #include "common/system.h" #include "gui/message.h" +#include "gui/newgui.h" #include "sound/mixer.h" +#include "engines/dialogs.h" +#include "engines/metaengine.h" #ifdef _WIN32_WCE extern bool isSmartphone(void); @@ -54,7 +57,8 @@ Engine::Engine(OSystem *syst) _saveFileMan(_system->getSavefileManager()), _targetName(ConfMan.getActiveDomainName()), _gameDataPath(ConfMan.get("path")), - _pauseLevel(0) { + _pauseLevel(0), + _mainMenuDialog(NULL) { g_engine = this; _autosavePeriod = ConfMan.getInt("autosave_period"); @@ -72,7 +76,8 @@ Engine::Engine(OSystem *syst) Engine::~Engine() { _mixer->stopAll(); - + + delete _mainMenuDialog; g_engine = NULL; } @@ -210,3 +215,50 @@ void Engine::pauseEngineIntern(bool pause) { // By default, just (un)pause all digital sounds _mixer->pauseAll(pause); } + +void Engine::mainMenuDialog() { + if (!_mainMenuDialog) + _mainMenuDialog = new MainMenuDialog(this); + runDialog(*_mainMenuDialog); + syncSoundSettings(); +} + +int Engine::runDialog(Dialog &dialog) { + + pauseEngine(true); + + int result = dialog.runModal(); + + pauseEngine(false); + + return result; +} + +void Engine::syncSoundSettings() { + + // Sync the engine with the config manager + int soundVolumeMusic = ConfMan.getInt("music_volume"); + int soundVolumeSFX = ConfMan.getInt("sfx_volume"); + int soundVolumeSpeech = ConfMan.getInt("speech_volume"); + + _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, soundVolumeMusic); + _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, soundVolumeSFX); + _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, soundVolumeSpeech); +} + +void Engine::quitGame() { + Common::Event event; + + event.type = Common::EVENT_QUIT; + _eventMan->pushEvent(event); +} + +bool Engine::hasFeature(int f) { + const EnginePlugin *plugin = 0; + Common::String gameid = ConfMan.get("gameid"); + gameid.toLowercase(); + EngineMan.findGame(gameid, &plugin); + + return ( (*plugin)->hasFeature((MetaEngine::MetaEngineFeature)f) ); +} + diff --git a/engines/engine.h b/engines/engine.h index 73d529cc62..d2f0849b51 100644 --- a/engines/engine.h +++ b/engines/engine.h @@ -25,10 +25,12 @@ #ifndef ENGINES_ENGINE_H #define ENGINES_ENGINE_H +#include "common/events.h" #include "common/scummsys.h" #include "common/str.h" class OSystem; + namespace Audio { class Mixer; } @@ -39,8 +41,11 @@ namespace Common { } namespace GUI { class Debugger; + class Dialog; } +using GUI::Dialog; + class Engine { public: OSystem *_system; @@ -50,6 +55,9 @@ public: protected: Common::EventManager *_eventMan; Common::SaveFileManager *_saveFileMan; + + Dialog *_mainMenuDialog; + virtual int runDialog(Dialog &dialog); const Common::String _targetName; // target name for saves const Common::String _gameDataPath; @@ -109,10 +117,32 @@ public: void pauseEngine(bool pause); /** + * Quit the engine, sends a Quit event to the Event Manager + */ + void quitGame(); + + /** * Return whether the engine is currently paused or not. */ bool isPaused() const { return _pauseLevel != 0; } + /** + * Return whether or not the ENGINE should quit + */ + bool quit() const { return (_eventMan->shouldQuit() || _eventMan->shouldRTL()); } + + /** Run the Global Main Menu Dialog + */ + virtual void mainMenuDialog(); + + /** Sync the engine's sound settings with the config manager + */ + virtual void syncSoundSettings(); + + /** Determine whether the engine supports the specified MetaEngine feature + */ + virtual bool hasFeature(int f); + public: /** Setup the backend's graphics mode. */ diff --git a/engines/metaengine.h b/engines/metaengine.h index aef860e0f9..c911e1c2ae 100644 --- a/engines/metaengine.h +++ b/engines/metaengine.h @@ -91,6 +91,45 @@ public: virtual SaveStateList listSaves(const char *target) const { return SaveStateList(); } + + /** + * Remove the specified save state. + * + * For most engines this just involves a call removeSaveFile(). + * Engines which keep an index file will also update it accordingly. + * + * @param slot slot number of the save state to be removed + * @param saveNames a list of all the save state description names + */ + virtual void removeSaveState(int slot, Common::StringList saveNames) const {}; + + + /** @name MetaEngineFeature flags */ + //@{ + + /** + * A feature in this context means an ability of the engine which can be + * either on or off. Examples include: + * - Listing Save States (--list-saves) + * - Loading from the Launcher (-x) + * - Deleting Saves from the Launcher + * + * These determine whether the features will be available to the engine + * in the launcher. + */ + enum MetaEngineFeature { + kSupportsRTL = 0, + kSupportsListSaves = 1, + kSupportsDirectLoad = 2, + kSupportsDeleteSave = 3 + }; + + /** + * Determine whether the engine supports the specified MetaEngine feature + */ + virtual bool hasFeature(MetaEngineFeature f) const { return false; }; + + //@} }; diff --git a/engines/module.mk b/engines/module.mk index 6cfe9b36fa..f7dd71f403 100644 --- a/engines/module.mk +++ b/engines/module.mk @@ -1,7 +1,7 @@ MODULE := engines MODULE_OBJS := \ - engine.o - + engine.o \ + dialogs.o # Include common rules include $(srcdir)/rules.mk diff --git a/gui/launcher.cpp b/gui/launcher.cpp index 7cfe3943a7..40e0c3685e 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -29,6 +29,7 @@ #include "common/events.h" #include "common/fs.h" #include "common/util.h" +#include "common/savefile.h" #include "common/system.h" #include "gui/about.h" @@ -61,7 +62,10 @@ enum { kAddGameCmd = 'ADDG', kEditGameCmd = 'EDTG', kRemoveGameCmd = 'REMG', + kLoadGameCmd = 'LOAD', kQuitCmd = 'QUIT', + kChooseCmd = 'CHOS', + kDelCmd = 'DEL', kCmdGlobalGraphicsOverride = 'OGFX', @@ -468,6 +472,140 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat } } +class SaveLoadChooser : public GUI::Dialog { + typedef Common::String String; + typedef Common::StringList StringList; +protected: + bool _delSave; + bool _delSupport; + GUI::ListWidget *_list; + GUI::ButtonWidget *_chooseButton; + GUI::ButtonWidget *_deleteButton; + GUI::GraphicsWidget *_gfxWidget; + GUI::ContainerWidget *_container; + + uint8 _fillR, _fillG, _fillB; + + void updateInfos(bool redraw); +public: + SaveLoadChooser(const String &title, const String &buttonLabel); + ~SaveLoadChooser(); + + virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data); + const String &getResultString() const; + void setList(const StringList& list); + int runModal(bool delSupport); + + virtual void reflowLayout(); + + bool delSave() { return _delSave; }; +}; + +SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel) + : Dialog("scummsaveload"), _delSave(0), _delSupport(0), _list(0), _chooseButton(0), _deleteButton(0), _gfxWidget(0) { + + _drawingHints |= GUI::THEME_HINT_SPECIAL_COLOR; + + new StaticTextWidget(this, "scummsaveload_title", title); + + // Add choice list + _list = new GUI::ListWidget(this, "scummsaveload_list"); + _list->setNumberingMode(GUI::kListNumberingZero); + + _container = new GUI::ContainerWidget(this, 0, 0, 10, 10); + _container->setHints(GUI::THEME_HINT_USE_SHADOW); + + _gfxWidget = new GUI::GraphicsWidget(this, 0, 0, 10, 10); + + // Buttons + new GUI::ButtonWidget(this, "scummsaveload_cancel", "Cancel", kCloseCmd, 0); + _chooseButton = new GUI::ButtonWidget(this, "scummsaveload_choose", buttonLabel, kChooseCmd, 0); + _chooseButton->setEnabled(false); + + _deleteButton = new GUI::ButtonWidget(this, "scummsaveload_delete", "Delete", kDelCmd, 0); + _deleteButton->setEnabled(false); +} + +SaveLoadChooser::~SaveLoadChooser() { +} + +const Common::String &SaveLoadChooser::getResultString() const { + return _list->getSelectedString(); +} + +void SaveLoadChooser::setList(const StringList& list) { + _list->setList(list); +} + +int SaveLoadChooser::runModal(bool delSupport) { + if (_gfxWidget) + _gfxWidget->setGfx(0); + _delSave = false; + _delSupport = delSupport; + int ret = Dialog::runModal(); + return ret; +} + +void SaveLoadChooser::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { + int selItem = _list->getSelected(); + switch (cmd) { + case GUI::kListItemActivatedCmd: + case GUI::kListItemDoubleClickedCmd: + if (selItem >= 0) { + if (!getResultString().empty()) { + _list->endEditMode(); + setResult(selItem); + close(); + } + } + break; + case kChooseCmd: + _list->endEditMode(); + setResult(selItem); + close(); + break; + case GUI::kListSelectionChangedCmd: { + if (_gfxWidget) { + updateInfos(true); + } + + // Disable these buttons if nothing is selected, or if an empty + // list item is selected. + _chooseButton->setEnabled(selItem >= 0 && (!getResultString().empty())); + _chooseButton->draw(); + // Delete will always be disabled if the engine doesn't support it. + _deleteButton->setEnabled(_delSupport && (selItem >= 0) && (!getResultString().empty())); + _deleteButton->draw(); + } break; + case kDelCmd: + setResult(selItem); + _delSave = true; + + // Disable these buttons again after deleteing a selection + _chooseButton->setEnabled(false); + _deleteButton->setEnabled(false); + + close(); + break; + case kCloseCmd: + setResult(-1); + default: + Dialog::handleCommand(sender, cmd, data); + } +} + +void SaveLoadChooser::reflowLayout() { + _container->setFlags(GUI::WIDGET_INVISIBLE); + _gfxWidget->setFlags(GUI::WIDGET_INVISIBLE); + Dialog::reflowLayout(); +} + +void SaveLoadChooser::updateInfos(bool redraw) { + _gfxWidget->setGfx(-1, -1, _fillR, _fillG, _fillB); + if (redraw) + _gfxWidget->draw(); +} + #pragma mark - @@ -501,6 +639,8 @@ LauncherDialog::LauncherDialog() new ButtonWidget(this, "launcher_options_button", "Options", kOptionsCmd, 'O'); _startButton = new ButtonWidget(this, "launcher_start_button", "Start", kStartCmd, 'S'); + + new ButtonWidget(this, "launcher_loadGame_button", "Load", kLoadGameCmd, 'L'); // Above the lowest button rows: two more buttons (directly below the list box) _addButton = @@ -529,6 +669,9 @@ LauncherDialog::LauncherDialog() // Create file browser dialog _browser = new BrowserDialog("Select directory with game data", true); + + // Create Load dialog + _loadDialog = new SaveLoadChooser("Load game:", "Load"); } void LauncherDialog::selectGame(const String &name) { @@ -546,6 +689,7 @@ void LauncherDialog::selectGame(const String &name) { LauncherDialog::~LauncherDialog() { delete _browser; + delete _loadDialog; } void LauncherDialog::open() { @@ -795,6 +939,80 @@ void LauncherDialog::editGame(int item) { } } +void LauncherDialog::loadGame(int item) { + Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); + String gameId = ConfMan.get("gameid", _domains[item]); + if (gameId.empty()) + gameId = _domains[item]; + + const EnginePlugin *plugin = 0; + GameDescriptor game = EngineMan.findGame(gameId, &plugin); + + String description = _domains[item]; + description.toLowercase(); + + int idx; + if (plugin) { + bool delSupport = (*plugin)->hasFeature(MetaEngine::kSupportsDeleteSave); + + if ((*plugin)->hasFeature(MetaEngine::kSupportsListSaves) && + (*plugin)->hasFeature(MetaEngine::kSupportsDirectLoad)) + { + do { + Common::StringList saveNames = generateSavegameList(item, plugin); + _loadDialog->setList(saveNames); + SaveStateList saveList = (*plugin)->listSaves(description.c_str()); + idx = _loadDialog->runModal(delSupport); + if (idx >= 0) { + // Delete the savegame + if (_loadDialog->delSave()) { + String filename = saveList[idx].filename(); + //printf("Deleting file: %s\n", filename.c_str()); + MessageDialog alert("Do you really want to delete this savegame?", + "Yes", "No"); + if (alert.runModal() == GUI::kMessageOK) { + saveFileMan->removeSavefile(filename.c_str()); + if ((saveList.size() - 1) == 0) + ConfMan.setInt("save_slot", -1); + } + } + // Load the savegame + else { + int slot = atoi(saveList[idx].save_slot().c_str()); + //const char *file = saveList[idx].filename().c_str(); + //printf("Loading slot: %d\n", slot); + //printf("Loading file: %s\n", file); + ConfMan.setActiveDomain(_domains[item]); + ConfMan.setInt("save_slot", slot); + close(); + } + } + } + while (_loadDialog->delSave()); + } else { + MessageDialog dialog + ("Sorry, this game does not yet support loading games from the launcher.", "OK"); + dialog.runModal(); + } + } else { + MessageDialog dialog("ScummVM could not find any engine capable of running the selected game!", "OK"); + dialog.runModal(); + } +} + +Common::StringList LauncherDialog::generateSavegameList(int item, const EnginePlugin *plugin) { + String description = _domains[item]; + description.toLowercase(); + + StringList saveNames; + SaveStateList saveList = (*plugin)->listSaves(description.c_str()); + + for (SaveStateList::const_iterator x = saveList.begin(); x != saveList.end(); ++x) + saveNames.push_back(x->description().c_str()); + + return saveNames; +} + void LauncherDialog::handleKeyDown(Common::KeyState state) { Dialog::handleKeyDown(state); updateButtons(); @@ -818,6 +1036,9 @@ void LauncherDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat case kEditGameCmd: editGame(item); break; + case kLoadGameCmd: + loadGame(item); + break; case kOptionsCmd: { GlobalOptionsDialog options; options.runModal(); diff --git a/gui/launcher.h b/gui/launcher.h index a9d09bf109..a26651eef5 100644 --- a/gui/launcher.h +++ b/gui/launcher.h @@ -34,11 +34,10 @@ namespace GUI { class BrowserDialog; class ListWidget; class GraphicsWidget; - +class SaveLoadChooser; Common::String addGameToConf(const GameDescriptor &result); - class LauncherDialog : public Dialog { typedef Common::String String; typedef Common::StringList StringList; @@ -62,6 +61,7 @@ protected: #endif StringList _domains; BrowserDialog *_browser; + SaveLoadChooser *_loadDialog; virtual void reflowLayout(); @@ -73,6 +73,9 @@ protected: virtual void addGame(); void removeGame(int item); void editGame(int item); + void loadGame(int item); + + StringList generateSavegameList(int item, const EnginePlugin *plugin); void selectGame(const String &name); }; diff --git a/gui/newgui.cpp b/gui/newgui.cpp index 618c7bc873..b892fe076a 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -25,6 +25,7 @@ #include "common/events.h" #include "common/system.h" #include "common/util.h" +#include "engines/engine.h" #include "graphics/cursorman.h" #include "gui/newgui.h" #include "gui/dialog.h" @@ -255,7 +256,7 @@ void NewGui::runLoop() { Common::Event event; while (eventMan->pollEvent(event)) { - if (activeDialog != getTopDialog() && event.type != Common::EVENT_QUIT && event.type != Common::EVENT_SCREEN_CHANGED) + if (activeDialog != getTopDialog() && event.type != Common::EVENT_SCREEN_CHANGED) continue; Common::Point mouse(event.mouse.x - activeDialog->_x, event.mouse.y - activeDialog->_y); @@ -313,7 +314,8 @@ void NewGui::runLoop() { activeDialog->handleMouseWheel(mouse.x, mouse.y, 1); break; case Common::EVENT_QUIT: - _system->quit(); + if (!g_engine) + _system->quit(); return; case Common::EVENT_SCREEN_CHANGED: screenChange(); diff --git a/gui/theme-config.cpp b/gui/theme-config.cpp index 47f60d3d7b..9fc23c5e7d 100644 --- a/gui/theme-config.cpp +++ b/gui/theme-config.cpp @@ -95,6 +95,7 @@ const char *Theme::_defaultConfigINI = "scummsaveload_thumbnail=(parent.w - (kThumbnailWidth + 22)) 18\n" "scummsaveload_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n" "scummsaveload_choose=(prev.x2 + 10) prev.y prev.w prev.h\n" +"scummsaveload_delete=prev.x2 prev.y prev.w prev.h\n" "scummsaveload_extinfo.visible=false\n" "\n" "# MM NES resolution\n" @@ -118,6 +119,7 @@ const char *Theme::_defaultConfigINI = "def_aboutXOff=8\n" "def_aboutYOff=5\n" "def_aboutOuterBorder=80\n" +"def_globalmainHOffset=52\n" "def_scummmainHOffset=12\n" "def_scummmainVSpace=7\n" "def_scummmainVAddOff=3\n" @@ -171,10 +173,11 @@ const char *Theme::_defaultConfigINI = "launcher_options_button=(prev.x2 + space) prev.y prev.w prev.h\n" "launcher_start_button=(prev.x2 + space) prev.y prev.w prev.h\n" "top=(top - buttonHeight * 2)\n" -"numButtons=3\n" +"numButtons=4\n" "space=10\n" "butWidth=((w - 2 * hBorder - space * (numButtons - 1)) / numButtons)\n" -"launcher_addGame_button=hBorder top butWidth buttonHeight\n" +"launcher_loadGame_button=hBorder top butWidth buttonHeight\n" +"launcher_addGame_button=(prev.x2 + space) prev.y prev.w prev.h\n" "launcher_editGame_button=(prev.x2 + space) prev.y prev.w prev.h\n" "launcher_removeGame_button=(prev.x2 + space) prev.y prev.w prev.h\n" "launcher_list=hBorder (kLineHeight + 16) (w - 2 * hBorder) (top - kLineHeight - 20)\n" @@ -371,6 +374,7 @@ const char *Theme::_defaultConfigINI = "scummsaveload_thumbnail.fillB=0\n" "scummsaveload_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n" "scummsaveload_choose=(prev.x2 + 10) prev.y prev.w prev.h\n" +"scummsaveload_delete=prev.x (prev.y - 30) prev.w prev.h\n" "scummsaveload_extinfo.visible=true\n" "\n" "############################################\n" @@ -482,6 +486,31 @@ const char *Theme::_defaultConfigINI = "smH=(smY + scummmainVSpace)\n" "scummmain=((w - smW) / 2) ((h - smH) / 2) smW smH\n" "\n" +"#### Global Main Menu Dialog" +"[globalmain]\n" +"# note that globalmain size depends on overall height\n" +"hBorder=10\n" +"gmW=(scummmainButtonWidth + (2 * scummmainHOffset) + 80)\n" +"global_title=hBorder 8 (gmW - 2 * hBorder) kLineHeight\n" +"global_title.align=kTextAlignCenter\n" +"global_version=hBorder 25 (gmW - 2 * hBorder) kLineHeight\n" +"global_version.align=kTextAlignCenter\n" +"gmY=((scummmainVSpace * 7)+ scummmainVAddOff)\n" +"globalmain_resume=globalmainHOffset gmY scummmainButtonWidth scummmainButtonHeight\n" +"gmY=(gmY + scummmainButtonHeight + scummmainVAddOff)\n" +"gmY=(gmY + scummmainVSpace)\n" +"globalmain_options=prev.x gmY prev.w prev.h\n" +"gmY=(gmY + scummmainButtonHeight + scummmainVAddOff)\n" +"globalmain_about=prev.x gmY prev.w prev.h\n" +"gmY=(gmY + scummmainButtonHeight + scummmainVAddOff)\n" +"gmY=(gmY + scummmainVSpace)\n" +"globalmain_rtl=prev.x gmY prev.w prev.h\n" +"gmY=(gmY + scummmainButtonHeight + scummmainVAddOff)\n" +"globalmain_quit=prev.x gmY prev.w prev.h\n" +"gmY=(gmY + scummmainButtonHeight + scummmainVAddOff)\n" +"gmH=(gmY + scummmainVSpace)\n" +"globalmain=((w - gmW) / 2) ((h - gmH) / 2) gmW gmH\n" +"\n" "# PSP GUI\n" "[480x272]\n" "def_buttonWidth=100\n" diff --git a/gui/themes/classic080.ini b/gui/themes/classic080.ini index b5c911bada..766059ecb5 100644 --- a/gui/themes/classic080.ini +++ b/gui/themes/classic080.ini @@ -82,13 +82,14 @@ hBorder=10 launcher_version=hBorder 8 (w - 2 * hBorder) kLineHeight launcher_version.align=kTextAlignCenter top=(h - 8 - buttonHeight) -numButtons=4 +numButtons=3 space=8 butWidth=((w - 2 * hBorder - space * (numButtons - 1)) / numButtons) launcher_quit_button=hBorder top butWidth buttonHeight launcher_about_button=(prev.x2 + space) prev.y prev.w prev.h launcher_options_button=(prev.x2 + space) prev.y prev.w prev.h launcher_start_button=(prev.x2 + space) prev.y prev.w prev.h +launcher_loadGame_button=(prev.x2 + space) prev.y prev.w prev.h top=(top - buttonHeight * 2) numButtons=3 space=10 @@ -289,6 +290,7 @@ scummsaveload_thumbnail.fillG=0 scummsaveload_thumbnail.fillB=0 scummsaveload_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight scummsaveload_choose=(prev.x2 + 10) prev.y prev.w prev.h +scummsaveload_delete=prev.x (prev.y - 30) prev.w prev.h scummsaveload_extinfo.visible=true ############################################ @@ -441,6 +443,7 @@ scummsaveload_list=10 18 prev.w (parent.h - 17 - buttonHeight - 8 - self.y) scummsaveload_thumbnail=(parent.w - (kThumbnailWidth + 22)) 18 scummsaveload_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight scummsaveload_choose=(prev.x2 + 10) prev.y prev.w prev.h +scummsaveload_delete=prev.x (prev.y - 30) prev.w prev.h scummsaveload_extinfo.visible=false # MM NES resolution diff --git a/gui/themes/modern.ini b/gui/themes/modern.ini index 87ef0bcbb9..8dbe7331f8 100644 --- a/gui/themes/modern.ini +++ b/gui/themes/modern.ini @@ -250,6 +250,7 @@ space1=20 space2=5 launcher_list=insetX insetY insetW insetH launcher_start_button=(prev.x2 + 17) prev.y buttonWidth buttonHeight +launcher_loadGame_button=prev.x (prev.y2 + space2) prev.w prev.h launcher_addGame_button=prev.x (prev.y2 + space1) prev.w prev.h launcher_editGame_button=prev.x (prev.y2 + space2) prev.w prev.h launcher_removeGame_button=prev.x (prev.y2 + space2) prev.w prev.h @@ -456,6 +457,7 @@ scummsaveload_thumbnail.fillG=0 scummsaveload_thumbnail.fillB=0 scummsaveload_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight scummsaveload_choose=(prev.x2 + 10) prev.y prev.w prev.h +scummsaveload_delete=prev.x (prev.y - 30) prev.w prev.h scummsaveload_extinfo.visible=true ############################################ |