/*
* Copyright 2010-2013 OpenXcom Developers.
*
* This file is part of OpenXcom.
*
* OpenXcom is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenXcom 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 OpenXcom. If not, see .
*/
#include "OptionsState.h"
#include "../Engine/Game.h"
#include "../Resource/ResourcePack.h"
#include "../Engine/Language.h"
#include "../Engine/Palette.h"
#include "../Interface/TextButton.h"
#include "../Engine/Action.h"
#include "../Interface/Window.h"
#include "../Interface/Text.h"
#include "../Interface/TextEdit.h"
#include "../Interface/Slider.h"
#include "../Engine/Options.h"
#include "../Engine/Screen.h"
#include "../Interface/ArrowButton.h"
#include "OptionsLanguageState.h"
#include "OptionsControlsState.h"
#include "OptionsAdvancedState.h"
#include "OptionsBattlescapeState.h"
#include "../Engine/CrossPlatform.h"
#include "../Engine/Logger.h"
#include "../Engine/Sound.h"
namespace OpenXcom
{
const std::string OptionsState::GL_EXT = "OpenGL.shader";
const std::string OptionsState::GL_FOLDER = "Shaders/";
const std::string OptionsState::GL_STRING = " (OpenGL)";
/**
* Initializes all the elements in the Options window.
* @param game Pointer to the core game.
* @param origin Game section that originated this state.
*/
OptionsState::OptionsState(Game *game, OptionsOrigin origin) : OptionsBaseState(game, origin)
{
_wClicked = false;
_hClicked = false;
// Create objects
_window = new Window(this, 320, 200, 0, 0, POPUP_BOTH);
_txtTitle = new Text(320, 16, 0, 8);
_btnLanguage = new TextButton(100, 16, 8, 154);
_btnControls = new TextButton(100, 16, 110, 154);
_btnAdvanced = new TextButton(100, 16, 212, 154);
_btnOk = new TextButton(100, 16, 8, 176);
_btnCancel = new TextButton(100, 16, 110, 176);
_btnDefault = new TextButton(100, 16, 212, 176);
_txtDisplayResolution = new Text(140, 9, 28, 32);
_txtDisplayWidth = new TextEdit(48, 16, 30, 47);
_txtDisplayX = new Text(16, 16, 76, 47);
_txtDisplayHeight = new TextEdit(48, 16, 88, 47);
_btnDisplayUp = new ArrowButton(ARROW_BIG_UP, 14, 14, 140, 36);
_btnDisplayDown = new ArrowButton(ARROW_BIG_DOWN, 14, 14, 140, 58);
_txtDisplayMode = new Text(140, 9, 28, 72);
_btnDisplayWindowed = new TextButton(126, 16, 28, 82);
_btnDisplayFullscreen = new TextButton(126, 16, 28, 100);
_txtDisplayFilter = new Text(140, 9, 28, 122);
_btnDisplayFilter = new TextButton(126, 16, 28, 132);
_txtMusicVolume = new Text(140, 9, 174, 32);
_slrMusicVolume = new Slider(118, 20, 174, 42);
_txtSoundVolume = new Text(140, 9, 174, 72);
_slrSoundVolume = new Slider(118, 20, 174, 82);
/* Get available fullscreen modes */
_res = SDL_ListModes(NULL, SDL_FULLSCREEN);
if (_res > (SDL_Rect**)0)
{
int i;
int width = Options::getInt("displayWidth");
int height = Options::getInt("displayHeight");
_resCurrent = -1;
for (i = 0; _res[i]; ++i)
{
if (_resCurrent == -1 && ((_res[i]->w == width && _res[i]->h <= height) || _res[i]->w < width))
{
_resCurrent = i;
}
}
_resAmount = i;
}
else
{
_resCurrent = -1;
_resAmount = 0;
_btnDisplayDown->setVisible(false);
_btnDisplayUp->setVisible(false);
Log(LOG_WARNING) << "Couldn't get display resolutions";
}
if (Options::getBool("fullscreen"))
_displayMode = _btnDisplayFullscreen;
else
_displayMode = _btnDisplayWindowed;
add(_window);
add(_txtTitle);
add(_btnOk);
add(_btnCancel);
add(_btnDefault);
add(_btnLanguage);
add(_btnControls);
add(_btnAdvanced);
add(_txtDisplayResolution);
add(_txtDisplayWidth);
add(_txtDisplayX);
add(_txtDisplayHeight);
add(_btnDisplayUp);
add(_btnDisplayDown);
add(_txtDisplayMode);
add(_btnDisplayWindowed);
add(_btnDisplayFullscreen);
add(_txtDisplayFilter);
add(_btnDisplayFilter);
add(_txtMusicVolume);
add(_slrMusicVolume);
add(_txtSoundVolume);
add(_slrSoundVolume);
centerAllSurfaces();
// Set up objects
_window->setColor(Palette::blockOffset(8)+5);
_window->setBackground(_game->getResourcePack()->getSurface("BACK01.SCR"));
_txtTitle->setColor(Palette::blockOffset(8)+10);
_txtTitle->setAlign(ALIGN_CENTER);
_txtTitle->setBig();
_txtTitle->setText(tr("STR_GAME_OPTIONS"));
_btnOk->setColor(Palette::blockOffset(8)+5);
_btnOk->setText(tr("STR_OK"));
_btnOk->onMouseClick((ActionHandler)&OptionsState::btnOkClick);
//_btnOk->onKeyboardPress((ActionHandler)&OptionsState::btnOkClick, (SDLKey)Options::getInt("keyOk"));
_btnCancel->setColor(Palette::blockOffset(8)+5);
_btnCancel->setText(tr("STR_CANCEL"));
_btnCancel->onMouseClick((ActionHandler)&OptionsState::btnCancelClick);
_btnCancel->onKeyboardPress((ActionHandler)&OptionsState::btnCancelClick, (SDLKey)Options::getInt("keyCancel"));
_btnDefault->setColor(Palette::blockOffset(8)+5);
//_btnDefault->setText(tr("STR_RESTORE_DEFAULTS"));
_btnDefault->setText(tr("STR_BATTLESCAPE"));
_btnDefault->onMouseClick((ActionHandler)&OptionsState::btnDefaultClick);
_btnLanguage->setColor(Palette::blockOffset(8)+5);
_btnLanguage->setText(tr("STR_LANGUAGE"));
_btnLanguage->onMouseClick((ActionHandler)&OptionsState::btnLanguageClick);
_btnControls->setColor(Palette::blockOffset(8)+5);
_btnControls->setText(tr("STR_CONTROLS"));
_btnControls->onMouseClick((ActionHandler)&OptionsState::btnControlsClick);
_btnAdvanced->setColor(Palette::blockOffset(8)+5);
_btnAdvanced->setText(tr("STR_ADVANCED"));
_btnAdvanced->onMouseClick((ActionHandler)&OptionsState::btnAdvancedClick);
_txtDisplayResolution->setColor(Palette::blockOffset(8)+10);
_txtDisplayResolution->setText(tr("STR_DISPLAY_RESOLUTION"));
_txtDisplayWidth->setColor(Palette::blockOffset(15)-1);
_txtDisplayWidth->setAlign(ALIGN_CENTER);
_txtDisplayWidth->setBig();
_txtDisplayWidth->setText(Language::utf8ToWstr(Options::getString("displayWidth")));
_txtDisplayWidth->setNumerical(true);
_txtDisplayWidth->onMouseClick((ActionHandler)&OptionsState::txtDisplayWidthClick);
_txtDisplayX->setColor(Palette::blockOffset(15)-1);
_txtDisplayX->setAlign(ALIGN_CENTER);
_txtDisplayX->setBig();
_txtDisplayX->setText(L"x");
_txtDisplayHeight->setColor(Palette::blockOffset(15)-1);
_txtDisplayHeight->setAlign(ALIGN_CENTER);
_txtDisplayHeight->setBig();
_txtDisplayHeight->setText(Language::utf8ToWstr(Options::getString("displayHeight")));
_txtDisplayHeight->setNumerical(true);
_txtDisplayHeight->onMouseClick((ActionHandler)&OptionsState::txtDisplayHeightClick);
_btnDisplayUp->setColor(Palette::blockOffset(15)-1);
_btnDisplayUp->onMouseClick((ActionHandler)&OptionsState::btnDisplayUpClick);
_btnDisplayDown->setColor(Palette::blockOffset(15)-1);
_btnDisplayDown->onMouseClick((ActionHandler)&OptionsState::btnDisplayDownClick);
_txtDisplayMode->setColor(Palette::blockOffset(8)+10);
_txtDisplayMode->setText(tr("STR_DISPLAY_MODE"));
_btnDisplayWindowed->setColor(Palette::blockOffset(15)-1);
_btnDisplayWindowed->setText(tr("STR_WINDOWED"));
_btnDisplayWindowed->setGroup(&_displayMode);
_btnDisplayFullscreen->setColor(Palette::blockOffset(15)-1);
_btnDisplayFullscreen->setText(tr("STR_FULLSCREEN"));
_btnDisplayFullscreen->setGroup(&_displayMode);
_filters.push_back("-");
_filters.push_back("Scale");
_filters.push_back("HQX");
_filterPaths.push_back("");
_filterPaths.push_back("");
_filterPaths.push_back("");
#ifndef __NO_SHADERS
std::vector filters = CrossPlatform::getFolderContents(CrossPlatform::getDataFolder(GL_FOLDER), GL_EXT);
for (std::vector::iterator i = filters.begin(); i != filters.end(); ++i)
{
std::string file = (*i);
std::string path = GL_FOLDER + file;
std::string name = file.substr(0, file.length() - GL_EXT.length() - 1) + GL_STRING;
_filters.push_back(name);
_filterPaths.push_back(path);
}
#endif
_selFilter = 0;
if (Options::getBool("useOpenGL"))
{
#ifndef __NO_SHADERS
std::string path = Options::getString("useOpenGLShader");
for (size_t i = 0; i < _filterPaths.size(); ++i)
{
if (_filterPaths[i] == path)
{
_selFilter = i;
}
}
#endif
}
else if (Options::getBool("useScaleFilter"))
{
_selFilter = 1;
}
else if (Options::getBool("useHQXFilter"))
{
_selFilter = 2;
}
_txtDisplayFilter->setColor(Palette::blockOffset(8)+10);
_txtDisplayFilter->setText(tr("STR_DISPLAY_FILTER"));
_btnDisplayFilter->setColor(Palette::blockOffset(15)-1);
_btnDisplayFilter->setText(Language::utf8ToWstr(_filters[_selFilter]));
_btnDisplayFilter->onMouseClick((ActionHandler)&OptionsState::btnDisplayFilterClick, 0);
_txtMusicVolume->setColor(Palette::blockOffset(8)+10);
_txtMusicVolume->setText(tr("STR_MUSIC_VOLUME"));
_slrMusicVolume->setColor(Palette::blockOffset(15)-1);
_slrMusicVolume->setValue((double)Options::getInt("musicVolume") / SDL_MIX_MAXVOLUME);
_slrMusicVolume->onMouseRelease((ActionHandler)&OptionsState::slrMusicVolumeRelease);
_txtSoundVolume->setColor(Palette::blockOffset(8)+10);
_txtSoundVolume->setText(tr("STR_SFX_VOLUME"));
_slrSoundVolume->setColor(Palette::blockOffset(15) - 1);
_slrSoundVolume->setValue((double)Options::getInt("soundVolume") / SDL_MIX_MAXVOLUME);
_slrSoundVolume->onMouseRelease((ActionHandler)&OptionsState::slrSoundVolumeRelease);
}
/**
*
*/
OptionsState::~OptionsState()
{
}
/**
* Stores the current volume settings.
*/
void OptionsState::init()
{
OptionsBaseState::init();
_musicVolume = _slrMusicVolume->getValue() * SDL_MIX_MAXVOLUME;
_soundVolume = _slrSoundVolume->getValue() * SDL_MIX_MAXVOLUME;
}
/**
* Adjusts the music volume for prehearing.
* @param action Pointer to an action.
*/
void OptionsState::slrMusicVolumeRelease(Action *)
{
_game->setVolume(_slrSoundVolume->getValue() * SDL_MIX_MAXVOLUME, _slrMusicVolume->getValue() * SDL_MIX_MAXVOLUME);
}
/**
* Adjusts the sound volume for prehearing.
* @param action Pointer to an action.
*/
void OptionsState::slrSoundVolumeRelease(Action *)
{
_game->setVolume(_slrSoundVolume->getValue() * SDL_MIX_MAXVOLUME, _slrMusicVolume->getValue() * SDL_MIX_MAXVOLUME);
_game->getResourcePack()->getSound("GEO.CAT", 0)->play();
}
/**
* Saves the options.
* @param action Pointer to an action.
*/
void OptionsState::btnOkClick(Action *)
{
Options::setString("displayWidth", Language::wstrToUtf8(_txtDisplayWidth->getText()));
Options::setString("displayHeight", Language::wstrToUtf8(_txtDisplayHeight->getText()));
if (_displayMode == _btnDisplayWindowed)
Options::setBool("fullscreen", false);
else if (_displayMode == _btnDisplayFullscreen)
Options::setBool("fullscreen", true);
Options::setInt("musicVolume", _slrMusicVolume->getValue() * SDL_MIX_MAXVOLUME);
Options::setInt("soundVolume", _slrSoundVolume->getValue() * SDL_MIX_MAXVOLUME);
switch (_selFilter)
{
case 0:
Options::setBool("useOpenGL", false);
Options::setBool("useScaleFilter", false);
Options::setBool("useHQXFilter", false);
break;
case 1:
Options::setBool("useOpenGL", false);
Options::setBool("useScaleFilter", true);
Options::setBool("useHQXFilter", false);
break;
case 2:
Options::setBool("useOpenGL", false);
Options::setBool("useScaleFilter", false);
Options::setBool("useHQXFilter", true);
break;
default:
Options::setBool("useOpenGL", true);
Options::setBool("useScaleFilter", false);
Options::setBool("useHQXFilter", false);
Options::setString("useOpenGLShader", _filterPaths[_selFilter]);
break;
}
_game->getScreen()->setResolution(Options::getInt("displayWidth"), Options::getInt("displayHeight"));
_game->getScreen()->setFullscreen(Options::getBool("fullscreen"));
_game->setVolume(Options::getInt("soundVolume"), Options::getInt("musicVolume"));
saveOptions();
}
/**
* Returns to the previous screen.
* @param action Pointer to an action.
*/
void OptionsState::btnCancelClick(Action *)
{
// restore previous volume settings
Options::setInt("musicVolume", _musicVolume);
Options::setInt("soundVolume", _soundVolume);
_game->setVolume(_soundVolume,_musicVolume);
_game->popState();
}
/**
* Restores the Options to default settings.
* @param action Pointer to an action.
*/
void OptionsState::btnDefaultClick(Action *)
{
/*
Options::createDefault();
Options::setString("language", "English");
Options::save();
_game->getScreen()->setResolution(Options::getInt("displayWidth"), Options::getInt("displayHeight"));
_game->getScreen()->setFullscreen(Options::getBool("fullscreen"));
_game->setVolume(Options::getInt("soundVolume"), Options::getInt("musicVolume"));
_game->popState();
*/
_game->pushState(new OptionsBattlescapeState(_game, _origin));
}
/**
* Shows the Language screen.
* @param action Pointer to an action.
*/
void OptionsState::btnLanguageClick(Action *)
{
_game->pushState(new OptionsLanguageState(_game, _origin));
}
/**
* Shows the Controls screen.
* @param action Pointer to an action.
*/
void OptionsState::btnControlsClick(Action *)
{
_game->pushState(new OptionsControlsState(_game, _origin));
}
/**
* Selects a bigger resolution.
* @param action Pointer to an action.
*/
void OptionsState::btnDisplayUpClick(Action *)
{
if (_resAmount == 0)
return;
if (_resCurrent <= 0)
{
_resCurrent = _resAmount-1;
}
else
{
_resCurrent--;
}
std::wstringstream ssW, ssH;
ssW << (int)_res[_resCurrent]->w;
ssH << (int)_res[_resCurrent]->h;
_txtDisplayWidth->setText(ssW.str());
_txtDisplayHeight->setText(ssH.str());
}
/**
* Selects a smaller resolution.
* @param action Pointer to an action.
*/
void OptionsState::btnDisplayDownClick(Action *)
{
if (_resAmount == 0)
return;
if (_resCurrent >= _resAmount-1)
{
_resCurrent = 0;
}
else
{
_resCurrent++;
}
std::wstringstream ssW, ssH;
ssW << (int)_res[_resCurrent]->w;
ssH << (int)_res[_resCurrent]->h;
_txtDisplayWidth->setText(ssW.str());
_txtDisplayHeight->setText(ssH.str());
}
void OptionsState::txtDisplayWidthClick(Action *)
{
_wClicked = true;
if (_hClicked)
{
_txtDisplayHeight->deFocus();
_hClicked = false;
}
}
void OptionsState::txtDisplayHeightClick(Action *)
{
_hClicked = true;
if (_wClicked)
{
_txtDisplayWidth->deFocus();
_wClicked = false;
}
}
void OptionsState::btnDisplayFilterClick(Action *action)
{
int change = 0;
if (action->getDetails()->button.button == SDL_BUTTON_LEFT)
{
change = 1;
}
else if (action->getDetails()->button.button == SDL_BUTTON_RIGHT)
{
change = -1;
}
int i = _selFilter;
if (i + change >= (int)_filters.size())
{
_selFilter = 0;
}
else if (i + change < 0)
{
_selFilter = _filters.size() - 1;
}
else
{
_selFilter += change;
}
_btnDisplayFilter->setText(Language::utf8ToWstr(_filters[_selFilter]));
}
void OptionsState::btnAdvancedClick(Action *)
{
_game->pushState(new OptionsAdvancedState(_game, _origin));
}
}