scummvm/gui/options.cpp
Vicent Marti 5f30b1f320 Merged several revisions from SVNMerge.
Fixed theme loading to use the new ArchiveMember class.

Original SVNMerge.py log:
=====================
Merged revisions 34686,34688-34689,34691-34698,34700-34705,34707-34713,34715-34722,34725-34727,34731-34732,34734-34738,34746 via svnmerge from 
https://tanoku@scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk

........
  r34686 | cyx | 2008-09-29 21:09:56 +0200 (Mon, 29 Sep 2008) | 1 line
  
  add constructor to SearchSet::Node for proper init of structure members with gcc 3.4.x (see tracker items #2120595, #2106292)
........
  r34688 | cyx | 2008-09-29 22:08:26 +0200 (Mon, 29 Sep 2008) | 1 line
  
  restrict _heXmapNum to HE versions, should fix #2135822
........
  r34689 | eriktorbjorn | 2008-09-29 22:40:58 +0200 (Mon, 29 Sep 2008) | 4 lines
  
  Since no one has come up with any better suggestion... this should fix #2123258
  ("COMI: Crash after video (SAN) play"). The eos() function won't return true
  until we've tried to read *past* the end of the stream.
........
  r34691 | tanoku | 2008-09-30 00:29:07 +0200 (Tue, 30 Sep 2008) | 1 line
  
  Ported ZipArchive::getAllNames() implementation from GUI branch.
........
  r34692 | fingolfin | 2008-09-30 11:07:03 +0200 (Tue, 30 Sep 2008) | 1 line
  
  Order alphabetically
........
  r34693 | fingolfin | 2008-09-30 11:08:17 +0200 (Tue, 30 Sep 2008) | 1 line
  
  SAGA: Removed patchesCount from SAGAGameDescription
........
  r34694 | fingolfin | 2008-09-30 11:09:39 +0200 (Tue, 30 Sep 2008) | 1 line
  
  SCUMM HE: Use FilesystemNode::openForReading() instead of 'new Common::File' (didn't cover all instances, though)
........
  r34695 | fingolfin | 2008-09-30 11:11:25 +0200 (Tue, 30 Sep 2008) | 1 line
  
  SAGA: Forgot to commit saga.h
........
  r34696 | fingolfin | 2008-09-30 11:12:02 +0200 (Tue, 30 Sep 2008) | 1 line
  
  Added multiple new open() methods to Common::File, which make it possible to use this class as a generic convenience wrapper around all kinds of SeekableReadStream; also renamed the name() method to the less confusing getName()
........
  r34697 | fingolfin | 2008-09-30 13:33:43 +0200 (Tue, 30 Sep 2008) | 1 line
  
  cleanup
........
  r34698 | tanoku | 2008-09-30 13:53:37 +0200 (Tue, 30 Sep 2008) | 1 line
  
  Fixed functionality of ZipArchive::getAllNames(). Now it expects a possibly non-empty string list and returns the amount of new filenames added to it.
........
  r34700 | fingolfin | 2008-09-30 14:27:38 +0200 (Tue, 30 Sep 2008) | 1 line
  
  Renamed Engine::quit to Engine::shouldQuit (previously, it was easily confused with Engine::quitGame); also cleaned up engine.h a bit
........
  r34701 | fingolfin | 2008-09-30 14:37:28 +0200 (Tue, 30 Sep 2008) | 1 line
  
  cleanup
........
  r34702 | fingolfin | 2008-09-30 14:38:44 +0200 (Tue, 30 Sep 2008) | 1 line
  
  AdvancedDetector: Do not (ab)use paths to keep track of files, rather, use FSNodes -- partial (?) fix for bug #2137680
........
  r34703 | fingolfin | 2008-09-30 14:58:27 +0200 (Tue, 30 Sep 2008) | 1 line
  
  SAGA: Some code cleanup
........
  r34704 | fingolfin | 2008-09-30 14:59:29 +0200 (Tue, 30 Sep 2008) | 1 line
  
  SKY: Fix detector to not (ab)use FSNode::getPath; if you want to open a FSNode, just pass it to File::open
........
  r34705 | thebluegr | 2008-09-30 15:19:14 +0200 (Tue, 30 Sep 2008) | 1 line
  
  Fixed crash when starting IHNM, a regression from commit #34693
........
  r34707 | fingolfin | 2008-09-30 17:42:19 +0200 (Tue, 30 Sep 2008) | 1 line
  
  Fixing ConfigManager::loadConfigFile
........
  r34708 | fingolfin | 2008-09-30 18:23:35 +0200 (Tue, 30 Sep 2008) | 1 line
  
  AGI: Another case where it is better to use FSNodes directly, instead of converting them to path strings
........
  r34709 | fingolfin | 2008-09-30 18:34:38 +0200 (Tue, 30 Sep 2008) | 1 line
  
  Modified FilePluginProvider to use FSNodes (instead of raw filenames / paths) in its API
........
  r34710 | fingolfin | 2008-09-30 18:38:46 +0200 (Tue, 30 Sep 2008) | 1 line
  
  AGI: Got rid of yet another unwarranted use of FSNode::getPath
........
  r34711 | fingolfin | 2008-09-30 18:53:04 +0200 (Tue, 30 Sep 2008) | 1 line
  
  AGI: Simplify WagFileParser by not reading data into a memory stream first (this was there to improve performance on systems with slow seeking; those systems should use another approach, see scummvm-devel)
........
  r34712 | thebluegr | 2008-09-30 18:55:10 +0200 (Tue, 30 Sep 2008) | 1 line
  
  Fix crash when starting ITE, a regression from commit #34705
........
  r34713 | fingolfin | 2008-09-30 19:09:41 +0200 (Tue, 30 Sep 2008) | 1 line
  
  Fix ThemeBrowser to use FSNodes, not getPath()
........
  r34715 | Kirben | 2008-10-02 16:41:50 +0200 (Thu, 02 Oct 2008) | 1 line
  
  Correct HE version for Putt-Putt Enters the Race (French/Windows).
........
  r34716 | fingolfin | 2008-10-02 18:58:59 +0200 (Thu, 02 Oct 2008) | 1 line
  
  Renamed FilesystemNode -> FSNode
........
  r34717 | fingolfin | 2008-10-02 19:08:15 +0200 (Thu, 02 Oct 2008) | 1 line
  
  cleanup
........
  r34718 | fingolfin | 2008-10-02 19:17:18 +0200 (Thu, 02 Oct 2008) | 1 line
  
  Ignore String::deleteLastChar when called on an empty string
........
  r34719 | fingolfin | 2008-10-02 19:20:21 +0200 (Thu, 02 Oct 2008) | 1 line
  
  Fix for bug #2142743: Assertion on clicking "Theme" in Options
........
  r34720 | fingolfin | 2008-10-02 19:48:01 +0200 (Thu, 02 Oct 2008) | 7 lines
  
  Engine class changed:
  - Moved initCommonGFX() && GUIErrorMessage() out of class Engine
  - got rid of the _autosavePeriod member (this prevented users from
    changing the autosave period during runtime)
  - Got rid of an evil 'using GUI::Dialog' statement
  - Clarified some Doxygen comments
........
  r34721 | fingolfin | 2008-10-02 19:52:29 +0200 (Thu, 02 Oct 2008) | 1 line
  
  Add the current dir to the global SearchSet, i.e. to SearchMan (this should fix the problems on Windows, and maybe other systems, see 'bug' #2137680)
........
  r34722 | fingolfin | 2008-10-02 19:55:08 +0200 (Thu, 02 Oct 2008) | 1 line
  
  Forgot to mention yet another Engine class change: mainMenuDialog -> openMainMenuDialog; and also forgot to commit this related file :/
........
  r34725 | fingolfin | 2008-10-02 20:11:40 +0200 (Thu, 02 Oct 2008) | 1 line
  
  typo
........
  r34726 | thebluegr | 2008-10-03 00:04:34 +0200 (Fri, 03 Oct 2008) | 1 line
  
  Merged loadHotSpotsMads() and loadHotSpotsM4()
........
  r34727 | lordhoto | 2008-10-03 02:16:21 +0200 (Fri, 03 Oct 2008) | 2 lines
  
  Fixed typos (thanks to Raziel^ for spotting them).
........
  r34731 | fingolfin | 2008-10-03 18:07:57 +0200 (Fri, 03 Oct 2008) | 1 line
  
  Fixed Engine::hasFeature to use proper types (i.e., MetaEngine::MetaEngineFeature instead of int)
........
  r34732 | fingolfin | 2008-10-03 18:14:12 +0200 (Fri, 03 Oct 2008) | 1 line
  
  SCUMM: Added french Monkey VGA variant, see bug #2129199
........
  r34734 | lordhoto | 2008-10-03 18:57:40 +0200 (Fri, 03 Oct 2008) | 2 lines
  
  Committed slightly modified patch #2034983 "Case-insensitivy and directory handling for engines".
........
  r34735 | lordhoto | 2008-10-03 20:18:42 +0200 (Fri, 03 Oct 2008) | 2 lines
  
  Check all 'kyra.dat' files in setup paths instead of only the first one found.
........
  r34736 | lordhoto | 2008-10-03 20:23:57 +0200 (Fri, 03 Oct 2008) | 2 lines
  
  Cleanup.
........
  r34737 | dreammaster | 2008-10-04 13:10:25 +0200 (Sat, 04 Oct 2008) | 1 line
  
  Bugfix to prevent NPC characters managing to walk beyond room exits without leaving the room, and thus getting stuck
........
  r34738 | fingolfin | 2008-10-04 15:09:01 +0200 (Sat, 04 Oct 2008) | 1 line
  
  Renamed some MetaEngine feature flags; removed explicit numbers from this feature flag list (nothing should rely on their specific values, anyway); added a note that Engine::hasFeature should become independant of MetaEngine::hasFeature
........
  r34746 | john_doe | 2008-10-04 23:40:14 +0200 (Sat, 04 Oct 2008) | 3 lines
  
  - Declared all stack functions as inline
  - Sleep some ms after 500 opcodes to reduce CPU load
  - Fixed odd bug in LGoP2 where text disappeared quickly without waiting for user input by returning 0x38 in sfShowPage
........

svn-id: r34749
2008-10-05 11:21:07 +00:00

952 lines
28 KiB
C++

/* 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 "gui/browser.h"
#include "gui/themebrowser.h"
#include "gui/chooser.h"
#include "gui/message.h"
#include "gui/newgui.h"
#include "gui/ThemeEval.h"
#include "gui/options.h"
#include "gui/PopUpWidget.h"
#include "gui/TabWidget.h"
#include "common/fs.h"
#include "common/config-manager.h"
#include "common/system.h"
#include "graphics/scaler.h"
#include "sound/mididrv.h"
#include "sound/mixer.h"
namespace GUI {
enum {
kMidiGainChanged = 'mgch',
kMusicVolumeChanged = 'muvc',
kSfxVolumeChanged = 'sfvc',
kSubtitleToggle = 'sttg',
kSubtitleSpeedChanged = 'stsc',
kSpeechVolumeChanged = 'vcvc',
kChooseSoundFontCmd = 'chsf',
kClearSoundFontCmd = 'clsf',
kChooseSaveDirCmd = 'chos',
kChooseThemeDirCmd = 'chth',
kChooseExtraDirCmd = 'chex',
kChoosePluginsDirCmd = 'chpl',
kChooseThemeCmd = 'chtf'
};
#ifdef SMALL_SCREEN_DEVICE
enum {
kChooseKeyMappingCmd = 'chma'
};
#endif
static const char *savePeriodLabels[] = { "Never", "every 5 mins", "every 10 mins", "every 15 mins", "every 30 mins", 0 };
static const int savePeriodValues[] = { 0, 5 * 60, 10 * 60, 15 * 60, 30 * 60, -1 };
static const char *outputRateLabels[] = { "<default>", "22 kHz", "8 kHz", "11kHz", "44 kHz", "48 kHz", 0 };
static const int outputRateValues[] = { 0, 22050, 8000, 11025, 44100, 48000, -1 };
OptionsDialog::OptionsDialog(const String &domain, int x, int y, int w, int h)
: Dialog(x, y, w, h), _domain(domain), _graphicsTabId(-1), _tabWidget(0) {
init();
}
OptionsDialog::OptionsDialog(const String &domain, const String &name)
: Dialog(name), _domain(domain), _graphicsTabId(-1), _tabWidget(0) {
init();
}
const char *OptionsDialog::_subModeDesc[] = {
"Speech Only",
"Speech and Subtitles",
"Subtitles Only"
};
const char *OptionsDialog::_lowresSubModeDesc[] = {
"Speech Only",
"Speech & Subs",
"Subtitles Only"
};
void OptionsDialog::init() {
_enableGraphicSettings = false;
_gfxPopUp = 0;
_renderModePopUp = 0;
_fullscreenCheckbox = 0;
_aspectCheckbox = 0;
_enableAudioSettings = false;
_midiPopUp = 0;
_outputRatePopUp = 0;
_enableMIDISettings = false;
_multiMidiCheckbox = 0;
_mt32Checkbox = 0;
_enableGSCheckbox = 0;
_enableVolumeSettings = false;
_musicVolumeDesc = 0;
_musicVolumeSlider = 0;
_musicVolumeLabel = 0;
_sfxVolumeDesc = 0;
_sfxVolumeSlider = 0;
_sfxVolumeLabel = 0;
_speechVolumeDesc = 0;
_speechVolumeSlider = 0;
_speechVolumeLabel = 0;
_subToggleDesc = 0;
_subToggleButton = 0;
_subSpeedDesc = 0;
_subSpeedSlider = 0;
_subSpeedLabel = 0;
}
void OptionsDialog::open() {
Dialog::open();
// Reset result value
setResult(0);
// Graphic options
if (_fullscreenCheckbox) {
_gfxPopUp->setSelected(0);
if (ConfMan.hasKey("gfx_mode", _domain)) {
const OSystem::GraphicsMode *gm = g_system->getSupportedGraphicsModes();
String gfxMode(ConfMan.get("gfx_mode", _domain));
int gfxCount = 1;
while (gm->name) {
gfxCount++;
if (scumm_stricmp(gm->name, gfxMode.c_str()) == 0)
_gfxPopUp->setSelected(gfxCount);
gm++;
}
}
_renderModePopUp->setSelected(0);
if (ConfMan.hasKey("render_mode", _domain)) {
const Common::RenderModeDescription *p = Common::g_renderModes;
const Common::RenderMode renderMode = Common::parseRenderMode(ConfMan.get("render_mode", _domain));
int sel = 0;
for (int i = 0; p->code; ++p, ++i) {
if (renderMode == p->id)
sel = i + 2;
}
_renderModePopUp->setSelected(sel);
}
#ifndef SMALL_SCREEN_DEVICE
// Fullscreen setting
_fullscreenCheckbox->setState(ConfMan.getBool("fullscreen", _domain));
// Aspect ratio setting
_aspectCheckbox->setState(ConfMan.getBool("aspect_ratio", _domain));
#endif
}
// Audio options
if (_midiPopUp) {
// Music driver
const MidiDriverDescription *md = MidiDriver::getAvailableMidiDrivers();
int i = 0;
const int midiDriver =
ConfMan.hasKey("music_driver", _domain)
? MidiDriver::parseMusicDriver(ConfMan.get("music_driver", _domain))
: MD_AUTO;
while (md->name && md->id != midiDriver) {
i++;
md++;
}
_midiPopUp->setSelected(md->name ? i : 0);
}
if (_outputRatePopUp) {
_outputRatePopUp->setSelected(1);
int value = ConfMan.getInt("output_rate", _domain);
for (int i = 0; outputRateLabels[i]; i++) {
if (value == outputRateValues[i])
_outputRatePopUp->setSelected(i);
}
}
if (_multiMidiCheckbox) {
// Multi midi setting
_multiMidiCheckbox->setState(ConfMan.getBool("multi_midi", _domain));
// Native mt32 setting
_mt32Checkbox->setState(ConfMan.getBool("native_mt32", _domain));
// GS extensions setting
_enableGSCheckbox->setState(ConfMan.getBool("enable_gs", _domain));
String soundFont(ConfMan.get("soundfont", _domain));
if (soundFont.empty() || !ConfMan.hasKey("soundfont", _domain)) {
_soundFont->setLabel("None");
_soundFontClearButton->setEnabled(false);
} else {
_soundFont->setLabel(soundFont);
_soundFontClearButton->setEnabled(true);
}
// MIDI gain setting
char buf[10];
_midiGainSlider->setValue(ConfMan.getInt("midi_gain", _domain));
sprintf(buf, "%.2f", (double)_midiGainSlider->getValue() / 100.0);
_midiGainLabel->setLabel(buf);
}
// Volume options
if (_musicVolumeSlider) {
int vol;
vol = ConfMan.getInt("music_volume", _domain);
_musicVolumeSlider->setValue(vol);
_musicVolumeLabel->setValue(vol);
vol = ConfMan.getInt("sfx_volume", _domain);
_sfxVolumeSlider->setValue(vol);
_sfxVolumeLabel->setValue(vol);
vol = ConfMan.getInt("speech_volume", _domain);
_speechVolumeSlider->setValue(vol);
_speechVolumeLabel->setValue(vol);
}
// Subtitle options
if (_subToggleButton) {
int speed;
int sliderMaxValue = _subSpeedSlider->getMaxValue();
_subMode = getSubtitleMode(ConfMan.getBool("subtitles", _domain), ConfMan.getBool("speech_mute", _domain));
_subToggleButton->setLabel(_subModeDesc[_subMode]);
// Engines that reuse the subtitle speed widget set their own max value.
// Scale the config value accordingly (see addSubtitleControls)
speed = (ConfMan.getInt("talkspeed", _domain) * sliderMaxValue + 255 / 2) / 255;
_subSpeedSlider->setValue(speed);
_subSpeedLabel->setValue(speed);
}
}
void OptionsDialog::close() {
if (getResult()) {
// Graphic options
if (_fullscreenCheckbox) {
if (_enableGraphicSettings) {
ConfMan.setBool("fullscreen", _fullscreenCheckbox->getState(), _domain);
ConfMan.setBool("aspect_ratio", _aspectCheckbox->getState(), _domain);
bool isSet = false;
if ((int32)_gfxPopUp->getSelectedTag() >= 0) {
const OSystem::GraphicsMode *gm = g_system->getSupportedGraphicsModes();
while (gm->name) {
if (gm->id == (int)_gfxPopUp->getSelectedTag()) {
ConfMan.set("gfx_mode", gm->name, _domain);
isSet = true;
break;
}
gm++;
}
}
if (!isSet)
ConfMan.removeKey("gfx_mode", _domain);
if ((int32)_renderModePopUp->getSelectedTag() >= 0)
ConfMan.set("render_mode", Common::getRenderModeCode((Common::RenderMode)_renderModePopUp->getSelectedTag()), _domain);
} else {
ConfMan.removeKey("fullscreen", _domain);
ConfMan.removeKey("aspect_ratio", _domain);
ConfMan.removeKey("gfx_mode", _domain);
ConfMan.removeKey("render_mode", _domain);
}
}
// Volume options
if (_musicVolumeSlider) {
if (_enableVolumeSettings) {
ConfMan.setInt("music_volume", _musicVolumeSlider->getValue(), _domain);
ConfMan.setInt("sfx_volume", _sfxVolumeSlider->getValue(), _domain);
ConfMan.setInt("speech_volume", _speechVolumeSlider->getValue(), _domain);
} else {
ConfMan.removeKey("music_volume", _domain);
ConfMan.removeKey("sfx_volume", _domain);
ConfMan.removeKey("speech_volume", _domain);
}
}
// Audio options
if (_midiPopUp) {
if (_enableAudioSettings) {
const MidiDriverDescription *md = MidiDriver::getAvailableMidiDrivers();
while (md->name && md->id != (int)_midiPopUp->getSelectedTag())
md++;
if (md->name)
ConfMan.set("music_driver", md->name, _domain);
else
ConfMan.removeKey("music_driver", _domain);
} else {
ConfMan.removeKey("music_driver", _domain);
}
}
if (_outputRatePopUp) {
if (_enableAudioSettings) {
if (_outputRatePopUp->getSelectedTag() != 0)
ConfMan.setInt("output_rate", _outputRatePopUp->getSelectedTag(), _domain);
else
ConfMan.removeKey("output_rate", _domain);
} else {
ConfMan.removeKey("output_rate", _domain);
}
}
// MIDI options
if (_multiMidiCheckbox) {
if (_enableMIDISettings) {
ConfMan.setBool("multi_midi", _multiMidiCheckbox->getState(), _domain);
ConfMan.setBool("native_mt32", _mt32Checkbox->getState(), _domain);
ConfMan.setBool("enable_gs", _enableGSCheckbox->getState(), _domain);
ConfMan.setInt("midi_gain", _midiGainSlider->getValue(), _domain);
String soundFont(_soundFont->getLabel());
if (!soundFont.empty() && (soundFont != "None"))
ConfMan.set("soundfont", soundFont, _domain);
else
ConfMan.removeKey("soundfont", _domain);
} else {
ConfMan.removeKey("multi_midi", _domain);
ConfMan.removeKey("native_mt32", _domain);
ConfMan.removeKey("enable_gs", _domain);
ConfMan.removeKey("midi_gain", _domain);
ConfMan.removeKey("soundfont", _domain);
}
}
// Subtitle options
if (_subToggleButton) {
if (_enableSubtitleSettings) {
bool subtitles, speech_mute;
int talkspeed;
int sliderMaxValue = _subSpeedSlider->getMaxValue();
switch (_subMode) {
case 0:
subtitles = speech_mute = false;
break;
case 1:
subtitles = true;
speech_mute = false;
break;
case 2:
default:
subtitles = speech_mute = true;
break;
}
ConfMan.setBool("subtitles", subtitles, _domain);
ConfMan.setBool("speech_mute", speech_mute, _domain);
// Engines that reuse the subtitle speed widget set their own max value.
// Scale the config value accordingly (see addSubtitleControls)
talkspeed = (_subSpeedSlider->getValue() * 255 + sliderMaxValue / 2) / sliderMaxValue;
ConfMan.setInt("talkspeed", talkspeed, _domain);
} else {
ConfMan.removeKey("subtitles", _domain);
ConfMan.removeKey("talkspeed", _domain);
ConfMan.removeKey("speech_mute", _domain);
}
}
// Save config file
ConfMan.flushToDisk();
}
Dialog::close();
}
void OptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
char buf[10];
switch (cmd) {
case kMidiGainChanged:
sprintf(buf, "%.2f", (double)_midiGainSlider->getValue() / 100.0);
_midiGainLabel->setLabel(buf);
_midiGainLabel->draw();
break;
case kMusicVolumeChanged:
_musicVolumeLabel->setValue(_musicVolumeSlider->getValue());
_musicVolumeLabel->draw();
break;
case kSfxVolumeChanged:
_sfxVolumeLabel->setValue(_sfxVolumeSlider->getValue());
_sfxVolumeLabel->draw();
break;
case kSpeechVolumeChanged:
_speechVolumeLabel->setValue(_speechVolumeSlider->getValue());
_speechVolumeLabel->draw();
break;
case kSubtitleToggle:
if (_subMode < 2)
_subMode++;
else
_subMode = 0;
_subToggleButton->setLabel(g_system->getOverlayWidth() > 320 ? _subModeDesc[_subMode] : _lowresSubModeDesc[_subMode]);
_subToggleButton->draw();
_subSpeedDesc->draw();
_subSpeedSlider->draw();
_subSpeedLabel->draw();
break;
case kSubtitleSpeedChanged:
_subSpeedLabel->setValue(_subSpeedSlider->getValue());
_subSpeedLabel->draw();
break;
case kOKCmd:
setResult(1);
close();
break;
default:
Dialog::handleCommand(sender, cmd, data);
}
}
void OptionsDialog::setGraphicSettingsState(bool enabled) {
_enableGraphicSettings = enabled;
_gfxPopUp->setEnabled(enabled);
_renderModePopUp->setEnabled(enabled);
#ifndef SMALL_SCREEN_DEVICE
_fullscreenCheckbox->setEnabled(enabled);
_aspectCheckbox->setEnabled(enabled);
#endif
}
void OptionsDialog::setAudioSettingsState(bool enabled) {
_enableAudioSettings = enabled;
_midiPopUp->setEnabled(enabled);
_outputRatePopUp->setEnabled(enabled);
}
void OptionsDialog::setMIDISettingsState(bool enabled) {
_enableMIDISettings = enabled;
_soundFontButton->setEnabled(enabled);
_soundFont->setEnabled(enabled);
if (enabled && !_soundFont->getLabel().empty() && (_soundFont->getLabel() != "None"))
_soundFontClearButton->setEnabled(enabled);
else
_soundFontClearButton->setEnabled(false);
_multiMidiCheckbox->setEnabled(enabled);
_mt32Checkbox->setEnabled(enabled);
_enableGSCheckbox->setEnabled(enabled);
_midiGainDesc->setEnabled(enabled);
_midiGainSlider->setEnabled(enabled);
_midiGainLabel->setEnabled(enabled);
}
void OptionsDialog::setVolumeSettingsState(bool enabled) {
_enableVolumeSettings = enabled;
_musicVolumeDesc->setEnabled(enabled);
_musicVolumeSlider->setEnabled(enabled);
_musicVolumeLabel->setEnabled(enabled);
_sfxVolumeDesc->setEnabled(enabled);
_sfxVolumeSlider->setEnabled(enabled);
_sfxVolumeLabel->setEnabled(enabled);
_speechVolumeDesc->setEnabled(enabled);
_speechVolumeSlider->setEnabled(enabled);
_speechVolumeLabel->setEnabled(enabled);
}
void OptionsDialog::setSubtitleSettingsState(bool enabled) {
_enableSubtitleSettings = enabled;
_subToggleButton->setEnabled(enabled);
_subToggleDesc->setEnabled(enabled);
_subSpeedDesc->setEnabled(enabled);
_subSpeedSlider->setEnabled(enabled);
_subSpeedLabel->setEnabled(enabled);
}
void OptionsDialog::addGraphicControls(GuiObject *boss, const String &prefix) {
const OSystem::GraphicsMode *gm = g_system->getSupportedGraphicsModes();
int labelWidth = g_gui.xmlEval()->getVar("Globals.TabLabelWidth");
// The GFX mode popup
_gfxPopUp = new PopUpWidget(boss, prefix + "grModePopup", "Graphics mode:", labelWidth);
_gfxPopUp->appendEntry("<default>");
_gfxPopUp->appendEntry("");
while (gm->name) {
_gfxPopUp->appendEntry(gm->description, gm->id);
gm++;
}
// RenderMode popup
_renderModePopUp = new PopUpWidget(boss, prefix + "grRenderPopup", "Render mode:", labelWidth);
_renderModePopUp->appendEntry("<default>", Common::kRenderDefault);
_renderModePopUp->appendEntry("");
const Common::RenderModeDescription *rm = Common::g_renderModes;
for (; rm->code; ++rm) {
_renderModePopUp->appendEntry(rm->description, rm->id);
}
// Fullscreen checkbox
_fullscreenCheckbox = new CheckboxWidget(boss, prefix + "grFullscreenCheckbox", "Fullscreen mode", 0, 0);
// Aspect ratio checkbox
_aspectCheckbox = new CheckboxWidget(boss, prefix + "grAspectCheckbox", "Aspect ratio correction", 0, 0);
#ifdef SMALL_SCREEN_DEVICE
_fullscreenCheckbox->setState(true);
_fullscreenCheckbox->setEnabled(false);
_aspectCheckbox->setEnabled(false);
#endif
_enableGraphicSettings = true;
}
void OptionsDialog::addAudioControls(GuiObject *boss, const String &prefix) {
int labelWidth = g_gui.xmlEval()->getVar("Globals.TabLabelWidth");
// The MIDI mode popup & a label
_midiPopUp = new PopUpWidget(boss, prefix + "auMidiPopup", "Music driver:", labelWidth);
// Populate it
const MidiDriverDescription *md = MidiDriver::getAvailableMidiDrivers();
while (md->name) {
_midiPopUp->appendEntry(md->description, md->id);
md++;
}
// Sample rate settings
_outputRatePopUp = new PopUpWidget(boss, prefix + "auSampleRatePopup", "Output rate:", labelWidth);
for (int i = 0; outputRateLabels[i]; i++) {
_outputRatePopUp->appendEntry(outputRateLabels[i], outputRateValues[i]);
}
_enableAudioSettings = true;
}
void OptionsDialog::addMIDIControls(GuiObject *boss, const String &prefix) {
// SoundFont
_soundFontButton = new ButtonWidget(boss, prefix + "mcFontButton", "SoundFont:", kChooseSoundFontCmd, 0);
_soundFont = new StaticTextWidget(boss, prefix + "mcFontPath", "None");
_soundFontClearButton = new ButtonWidget(boss, prefix + "mcFontClearButton", "C", kClearSoundFontCmd, 0);
// Multi midi setting
_multiMidiCheckbox = new CheckboxWidget(boss, prefix + "mcMixedCheckbox", "Mixed Adlib/MIDI mode", 0, 0);
// Native mt32 setting
_mt32Checkbox = new CheckboxWidget(boss, prefix + "mcMt32Checkbox", "True Roland MT-32 (disable GM emulation)", 0, 0);
// GS Extensions setting
_enableGSCheckbox = new CheckboxWidget(boss, prefix + "mcGSCheckbox", "Enable Roland GS Mode", 0, 0);
// MIDI gain setting (FluidSynth uses this)
_midiGainDesc = new StaticTextWidget(boss, prefix + "mcMidiGainText", "MIDI gain:");
_midiGainSlider = new SliderWidget(boss, prefix + "mcMidiGainSlider", kMidiGainChanged);
_midiGainSlider->setMinValue(0);
_midiGainSlider->setMaxValue(1000);
_midiGainLabel = new StaticTextWidget(boss, prefix + "mcMidiGainLabel", "1.00");
_enableMIDISettings = true;
}
// The function has an extra slider range parameter, since both the launcher and SCUMM engine
// make use of the widgets. The launcher range is 0-255. SCUMM's 0-9
void OptionsDialog::addSubtitleControls(GuiObject *boss, const String &prefix, int maxSliderVal) {
_subToggleDesc = new StaticTextWidget(boss, prefix + "subToggleDesc", "Text and Speech:");
_subToggleButton = new ButtonWidget(boss, prefix + "subToggleButton", "", kSubtitleToggle, 0);
// Subtitle speed
_subSpeedDesc = new StaticTextWidget(boss, prefix + "subSubtitleSpeedDesc", "Subtitle speed:");
_subSpeedSlider = new SliderWidget(boss, prefix + "subSubtitleSpeedSlider", kSubtitleSpeedChanged);
_subSpeedLabel = new StaticTextWidget(boss, prefix + "subSubtitleSpeedLabel", "100%");
_subSpeedSlider->setMinValue(0); _subSpeedSlider->setMaxValue(maxSliderVal);
_subSpeedLabel->setFlags(WIDGET_CLEARBG);
_enableSubtitleSettings = true;
}
void OptionsDialog::addVolumeControls(GuiObject *boss, const String &prefix) {
// Volume controllers
_musicVolumeDesc = new StaticTextWidget(boss, prefix + "vcMusicText", "Music volume:");
_musicVolumeSlider = new SliderWidget(boss, prefix + "vcMusicSlider", kMusicVolumeChanged);
_musicVolumeLabel = new StaticTextWidget(boss, prefix + "vcMusicLabel", "100%");
_musicVolumeSlider->setMinValue(0);
_musicVolumeSlider->setMaxValue(Audio::Mixer::kMaxMixerVolume);
_musicVolumeLabel->setFlags(WIDGET_CLEARBG);
_sfxVolumeDesc = new StaticTextWidget(boss, prefix + "vcSfxText", "SFX volume:");
_sfxVolumeSlider = new SliderWidget(boss, prefix + "vcSfxSlider", kSfxVolumeChanged);
_sfxVolumeLabel = new StaticTextWidget(boss, prefix + "vcSfxLabel", "100%");
_sfxVolumeSlider->setMinValue(0);
_sfxVolumeSlider->setMaxValue(Audio::Mixer::kMaxMixerVolume);
_sfxVolumeLabel->setFlags(WIDGET_CLEARBG);
_speechVolumeDesc = new StaticTextWidget(boss, prefix + "vcSpeechText" , "Speech volume:");
_speechVolumeSlider = new SliderWidget(boss, prefix + "vcSpeechSlider", kSpeechVolumeChanged);
_speechVolumeLabel = new StaticTextWidget(boss, prefix + "vcSpeechLabel", "100%");
_speechVolumeSlider->setMinValue(0);
_speechVolumeSlider->setMaxValue(Audio::Mixer::kMaxMixerVolume);
_speechVolumeLabel->setFlags(WIDGET_CLEARBG);
_enableVolumeSettings = true;
}
int OptionsDialog::getSubtitleMode(bool subtitles, bool speech_mute) {
if (!subtitles && !speech_mute) // Speech only
return 0;
else if (subtitles && !speech_mute) // Speech and subtitles
return 1;
else if (subtitles && speech_mute) // Subtitles only
return 2;
else
warning("Wrong configuration: Both subtitles and speech are off. Assuming subtitles only");
return 2;
}
void OptionsDialog::reflowLayout() {
Dialog::reflowLayout();
int labelWidth = g_gui.xmlEval()->getVar("Globals.TabLabelWidth");
if (_graphicsTabId != -1 && _tabWidget)
_tabWidget->setTabTitle(_graphicsTabId, g_system->getOverlayWidth() > 320 ? "Graphics" : "GFX");
if (_midiPopUp)
_midiPopUp->changeLabelWidth(labelWidth);
if (_outputRatePopUp)
_outputRatePopUp->changeLabelWidth(labelWidth);
if (_gfxPopUp)
_gfxPopUp->changeLabelWidth(labelWidth);
if (_renderModePopUp)
_renderModePopUp->changeLabelWidth(labelWidth);
}
#pragma mark -
GlobalOptionsDialog::GlobalOptionsDialog()
: OptionsDialog(Common::ConfigManager::kApplicationDomain, "GlobalOptions") {
// The tab widget
TabWidget *tab = new TabWidget(this, "GlobalOptions.TabWidget");
//
// 1) The graphics tab
//
_graphicsTabId = tab->addTab(g_system->getOverlayWidth() > 320 ? "Graphics" : "GFX");
addGraphicControls(tab, "GlobalOptions_Graphics.");
//
// 2) The audio tab
//
tab->addTab("Audio");
addAudioControls(tab, "GlobalOptions_Audio.");
addSubtitleControls(tab, "GlobalOptions_Audio.");
tab->addTab("Volume");
addVolumeControls(tab, "GlobalOptions_Volume.");
// TODO: cd drive setting
//
// 3) The MIDI tab
//
tab->addTab("MIDI");
addMIDIControls(tab, "GlobalOptions_MIDI.");
//
// 4) The miscellaneous tab
//
tab->addTab("Paths");
#if !( defined(__DC__) || defined(__GP32__) )
// These two buttons have to be extra wide, or the text will be
// truncated in the small version of the GUI.
// Save game path
new ButtonWidget(tab, "GlobalOptions_Paths.SaveButton", "Save Path: ", kChooseSaveDirCmd, 0);
_savePath = new StaticTextWidget(tab, "GlobalOptions_Paths.SavePath", "/foo/bar");
new ButtonWidget(tab, "GlobalOptions_Paths.ThemeButton", "Theme Path:", kChooseThemeDirCmd, 0);
_themePath = new StaticTextWidget(tab, "GlobalOptions_Paths.ThemePath", "None");
new ButtonWidget(tab, "GlobalOptions_Paths.ExtraButton", "Extra Path:", kChooseExtraDirCmd, 0);
_extraPath = new StaticTextWidget(tab, "GlobalOptions_Paths.ExtraPath", "None");
#ifdef DYNAMIC_MODULES
new ButtonWidget(tab, "GlobalOptions_Paths.PluginsButton", "Plugins Path:", kChoosePluginsDirCmd, 0);
_pluginsPath = new StaticTextWidget(tab, "GlobalOptions_Paths.PluginsPath", "None");
#endif
#endif
#ifdef SMALL_SCREEN_DEVICE
new ButtonWidget(tab, "GlobalOptions.KeysButton", "Keys", kChooseKeyMappingCmd, 0);
#endif
tab->addTab("Misc");
new ButtonWidget(tab, "GlobalOptions_Misc.ThemeButton", "Theme:", kChooseThemeCmd, 0);
_curTheme = new StaticTextWidget(tab, "GlobalOptions_Misc.CurTheme", g_gui.theme()->getThemeName());
int labelWidth = g_gui.xmlEval()->getVar("Globals.TabLabelWidth");
_rendererPopUp = new PopUpWidget(tab, "GlobalOptions_Misc.Renderer", "GUI Renderer:", labelWidth);
for (int i = 1; i < GUI::ThemeEngine::kGfxMAX; ++i) {
_rendererPopUp->appendEntry(GUI::ThemeEngine::rendererModeLabels[i], i);
}
_autosavePeriodPopUp = new PopUpWidget(tab, "GlobalOptions_Misc.AutosavePeriod", "Autosave:", labelWidth);
for (int i = 0; savePeriodLabels[i]; i++) {
_autosavePeriodPopUp->appendEntry(savePeriodLabels[i], savePeriodValues[i]);
}
// TODO: joystick setting
// Activate the first tab
tab->setActiveTab(0);
_tabWidget = tab;
// Add OK & Cancel buttons
new ButtonWidget(this, "GlobalOptions.Cancel", "Cancel", kCloseCmd, 0);
new ButtonWidget(this, "GlobalOptions.Ok", "OK", kOKCmd, 0);
#ifdef SMALL_SCREEN_DEVICE
_keysDialog = new KeysDialog();
#endif
}
GlobalOptionsDialog::~GlobalOptionsDialog() {
#ifdef SMALL_SCREEN_DEVICE
delete _keysDialog;
#endif
}
void GlobalOptionsDialog::open() {
OptionsDialog::open();
#if !( defined(__DC__) || defined(__GP32__) || defined(__PLAYSTATION2__) )
// Set _savePath to the current save path
Common::String savePath(ConfMan.get("savepath", _domain));
Common::String themePath(ConfMan.get("themepath", _domain));
Common::String extraPath(ConfMan.get("extrapath", _domain));
if (savePath.empty() || !ConfMan.hasKey("savepath", _domain)) {
_savePath->setLabel("None");
} else {
_savePath->setLabel(savePath);
}
if (themePath.empty() || !ConfMan.hasKey("themepath", _domain)) {
_themePath->setLabel("None");
} else {
_themePath->setLabel(themePath);
}
if (extraPath.empty() || !ConfMan.hasKey("extrapath", _domain)) {
_extraPath->setLabel("None");
} else {
_extraPath->setLabel(extraPath);
}
#ifdef DYNAMIC_MODULES
Common::String pluginsPath(ConfMan.get("pluginspath", _domain));
if (pluginsPath.empty() || !ConfMan.hasKey("pluginspath", _domain)) {
_pluginsPath->setLabel("None");
} else {
_pluginsPath->setLabel(pluginsPath);
}
#endif
#endif
// Misc Tab
_autosavePeriodPopUp->setSelected(1);
int value = ConfMan.getInt("autosave_period");
for (int i = 0; savePeriodLabels[i]; i++) {
if (value == savePeriodValues[i])
_autosavePeriodPopUp->setSelected(i);
}
_rendererPopUp->setSelected(ConfMan.getInt("gui_renderer") - 1);
}
void GlobalOptionsDialog::close() {
if (getResult()) {
String savePath(_savePath->getLabel());
if (!savePath.empty() && (savePath != "None"))
ConfMan.set("savepath", savePath, _domain);
String themePath(_themePath->getLabel());
if (!themePath.empty() && (themePath != "None"))
ConfMan.set("themepath", themePath, _domain);
else
ConfMan.removeKey("themepath", _domain);
String extraPath(_extraPath->getLabel());
if (!extraPath.empty() && (extraPath != "None"))
ConfMan.set("extrapath", extraPath, _domain);
else
ConfMan.removeKey("extrapath", _domain);
#ifdef DYNAMIC_MODULES
String pluginsPath(_pluginsPath->getLabel());
if (!pluginsPath.empty() && (pluginsPath != "None"))
ConfMan.set("pluginspath", pluginsPath, _domain);
else
ConfMan.removeKey("pluginspath", _domain);
#endif
ConfMan.setInt("autosave_period", _autosavePeriodPopUp->getSelectedTag(), _domain);
if ((int)_rendererPopUp->getSelectedTag() != ConfMan.getInt("gui_renderer")) {
g_gui.loadNewTheme(g_gui.theme()->getThemeFileName(), (GUI::ThemeEngine::GraphicsMode)_rendererPopUp->getSelectedTag());
ConfMan.setInt("gui_renderer", _rendererPopUp->getSelectedTag(), _domain);
}
}
OptionsDialog::close();
}
void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
switch (cmd) {
case kChooseSaveDirCmd: {
BrowserDialog browser("Select directory for savegames", true);
if (browser.runModal() > 0) {
// User made his choice...
Common::FSNode dir(browser.getResult());
if (dir.isWritable()) {
_savePath->setLabel(dir.getPath());
} else {
MessageDialog error("The chosen directory cannot be written to. Please select another one.");
error.runModal();
return;
}
draw();
}
break;
}
case kChooseThemeDirCmd: {
BrowserDialog browser("Select directory for GUI themes", true);
if (browser.runModal() > 0) {
// User made his choice...
Common::FSNode dir(browser.getResult());
_themePath->setLabel(dir.getPath());
draw();
}
break;
}
case kChooseExtraDirCmd: {
BrowserDialog browser("Select directory for extra files", true);
if (browser.runModal() > 0) {
// User made his choice...
Common::FSNode dir(browser.getResult());
_extraPath->setLabel(dir.getPath());
draw();
}
break;
}
#ifdef DYNAMIC_MODULES
case kChoosePluginsDirCmd: {
BrowserDialog browser("Select directory for plugins", true);
if (browser.runModal() > 0) {
// User made his choice...
Common::FSNode dir(browser.getResult());
_pluginsPath->setLabel(dir.getPath());
draw();
}
break;
}
#endif
case kChooseSoundFontCmd: {
BrowserDialog browser("Select SoundFont", false);
if (browser.runModal() > 0) {
// User made his choice...
Common::FSNode file(browser.getResult());
_soundFont->setLabel(file.getPath());
if (!file.getPath().empty() && (file.getPath() != "None"))
_soundFontClearButton->setEnabled(true);
else
_soundFontClearButton->setEnabled(false);
draw();
}
break;
}
case kClearSoundFontCmd: {
_soundFont->setLabel("None");
_soundFontClearButton->setEnabled(false);
draw();
break;
}
case kChooseThemeCmd: {
ThemeBrowser browser;
if (browser.runModal() > 0) {
// User made his choice...
const Common::String &theme = browser.selected();
if (0 != theme.compareToIgnoreCase(g_gui.theme()->getThemeFileName()))
if (g_gui.loadNewTheme(theme)) {
_curTheme->setLabel(g_gui.theme()->getThemeName());
ConfMan.set("gui_theme", theme);
}
draw();
}
break;
}
#ifdef SMALL_SCREEN_DEVICE
case kChooseKeyMappingCmd:
_keysDialog->runModal();
break;
#endif
default:
OptionsDialog::handleCommand(sender, cmd, data);
}
}
} // End of namespace GUI