1 /*
2  * Copyright 2010-2014 OpenXcom Developers.
3  *
4  * This file is part of OpenXcom.
5  *
6  * OpenXcom is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * OpenXcom is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with OpenXcom.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 #include "OptionsBaseState.h"
20 #include <SDL.h>
21 #include "../Engine/Game.h"
22 #include "../Engine/Options.h"
23 #include "../Engine/Palette.h"
24 #include "../Engine/Language.h"
25 #include "../Engine/Screen.h"
26 #include "../Resource/ResourcePack.h"
27 #include "../Savegame/SavedGame.h"
28 #include "../Savegame/SavedBattleGame.h"
29 #include "../Interface/Window.h"
30 #include "../Interface/TextButton.h"
31 #include "../Interface/Text.h"
32 #include "../Engine/Action.h"
33 #include "MainMenuState.h"
34 #include "../Geoscape/GeoscapeState.h"
35 #include "../Battlescape/BattlescapeState.h"
36 #include "OptionsVideoState.h"
37 #include "OptionsAudioState.h"
38 #include "OptionsNoAudioState.h"
39 #include "OptionsControlsState.h"
40 #include "OptionsGeoscapeState.h"
41 #include "OptionsBattlescapeState.h"
42 #include "OptionsAdvancedState.h"
43 #include "OptionsModsState.h"
44 #include "OptionsDefaultsState.h"
45 #include "OptionsConfirmState.h"
46 #include "StartState.h"
47 
48 namespace OpenXcom
49 {
50 
51 /**
52  * Initializes all the elements in the Options window.
53  * @param game Pointer to the core game.
54  * @param origin Game section that originated this state.
55  */
OptionsBaseState(Game * game,OptionsOrigin origin)56 OptionsBaseState::OptionsBaseState(Game *game, OptionsOrigin origin) : State(game), _origin(origin)
57 {
58 	// Create objects
59 	_window = new Window(this, 320, 200, 0, 0);
60 
61 	_btnVideo = new TextButton(80, 16, 8, 8);
62 	_btnAudio = new TextButton(80, 16, 8, 28);
63 	_btnControls = new TextButton(80, 16, 8, 48);
64 	_btnGeoscape = new TextButton(80, 16, 8, 68);
65 	_btnBattlescape = new TextButton(80, 16, 8, 88);
66 	_btnAdvanced = new TextButton(80, 16, 8, 108);
67 	_btnMods = new TextButton(80, 16, 8, 128);
68 
69 	_btnOk = new TextButton(100, 16, 8, 176);
70 	_btnCancel = new TextButton(100, 16, 110, 176);
71 	_btnDefault = new TextButton(100, 16, 212, 176);
72 
73 	_txtTooltip = new Text(305, 25, 8, 148);
74 
75 	// Set palette
76 	if (_origin == OPT_BATTLESCAPE)
77 	{
78 		setPalette("PAL_BATTLESCAPE");
79 	}
80 	else
81 	{
82 		setPalette("PAL_GEOSCAPE", 0);
83 	}
84 
85 	add(_window);
86 
87 	add(_btnVideo);
88 	add(_btnAudio);
89 	add(_btnControls);
90 	add(_btnGeoscape);
91 	add(_btnBattlescape);
92 	add(_btnAdvanced);
93 	add(_btnMods);
94 
95 	add(_btnOk);
96 	add(_btnCancel);
97 	add(_btnDefault);
98 
99 	add(_txtTooltip);
100 
101 	// Set up objects
102 	_window->setColor(Palette::blockOffset(8)+5);
103 	_window->setBackground(_game->getResourcePack()->getSurface("BACK01.SCR"));
104 
105 	_btnVideo->setColor(Palette::blockOffset(8)+5);
106 	_btnVideo->setText(tr("STR_VIDEO"));
107 	_btnVideo->onMousePress((ActionHandler)&OptionsBaseState::btnGroupPress, SDL_BUTTON_LEFT);
108 
109 	_btnAudio->setColor(Palette::blockOffset(8)+5);
110 	_btnAudio->setText(tr("STR_AUDIO"));
111 	_btnAudio->onMousePress((ActionHandler)&OptionsBaseState::btnGroupPress, SDL_BUTTON_LEFT);
112 
113 	_btnControls->setColor(Palette::blockOffset(8)+5);
114 	_btnControls->setText(tr("STR_CONTROLS"));
115 	_btnControls->onMousePress((ActionHandler)&OptionsBaseState::btnGroupPress, SDL_BUTTON_LEFT);
116 
117 	_btnGeoscape->setColor(Palette::blockOffset(8)+5);
118 	_btnGeoscape->setText(tr("STR_GEOSCAPE_UC"));
119 	_btnGeoscape->onMousePress((ActionHandler)&OptionsBaseState::btnGroupPress, SDL_BUTTON_LEFT);
120 
121 	_btnBattlescape->setColor(Palette::blockOffset(8)+5);
122 	_btnBattlescape->setText(tr("STR_BATTLESCAPE_UC"));
123 	_btnBattlescape->onMousePress((ActionHandler)&OptionsBaseState::btnGroupPress, SDL_BUTTON_LEFT);
124 
125 	_btnAdvanced->setColor(Palette::blockOffset(8)+5);
126 	_btnAdvanced->setText(tr("STR_ADVANCED"));
127 	_btnAdvanced->onMousePress((ActionHandler)&OptionsBaseState::btnGroupPress, SDL_BUTTON_LEFT);
128 
129 	_btnMods->setColor(Palette::blockOffset(8)+5);
130 	_btnMods->setText(tr("STR_MODS"));
131 	_btnMods->onMousePress((ActionHandler)&OptionsBaseState::btnGroupPress, SDL_BUTTON_LEFT);
132 	_btnMods->setVisible(_origin == OPT_MENU); // Mods require a restart, don't enable them in-game
133 
134 	_btnOk->setColor(Palette::blockOffset(8)+5);
135 	_btnOk->setText(tr("STR_OK"));
136 	_btnOk->onMouseClick((ActionHandler)&OptionsBaseState::btnOkClick);
137 	_btnOk->onKeyboardPress((ActionHandler)&OptionsBaseState::btnOkClick, Options::keyOk);
138 
139 	_btnCancel->setColor(Palette::blockOffset(8)+5);
140 	_btnCancel->setText(tr("STR_CANCEL"));
141 	_btnCancel->onMouseClick((ActionHandler)&OptionsBaseState::btnCancelClick);
142 	_btnCancel->onKeyboardPress((ActionHandler)&OptionsBaseState::btnCancelClick, Options::keyCancel);
143 
144 	_btnDefault->setColor(Palette::blockOffset(8)+5);
145 	_btnDefault->setText(tr("STR_RESTORE_DEFAULTS"));
146 	_btnDefault->onMouseClick((ActionHandler)&OptionsBaseState::btnDefaultClick);
147 
148 	_txtTooltip->setColor(Palette::blockOffset(8)+5);
149 	_txtTooltip->setWordWrap(true);
150 }
151 
152 /**
153  *
154  */
~OptionsBaseState()155 OptionsBaseState::~OptionsBaseState()
156 {
157 
158 }
159 
restart(Game * game,OptionsOrigin origin)160 void OptionsBaseState::restart(Game *game, OptionsOrigin origin)
161 {
162 	if (origin == OPT_MENU)
163 	{
164 		game->setState(new MainMenuState(game));
165 	}
166 	else if (origin == OPT_GEOSCAPE)
167 	{
168 		game->setState(new GeoscapeState(game));
169 	}
170 	else if (origin == OPT_BATTLESCAPE)
171 	{
172 		game->setState(new GeoscapeState(game));
173 		BattlescapeState *bs = new BattlescapeState(game);
174 		game->pushState(bs);
175 		game->getSavedGame()->getSavedBattle()->setBattleState(bs);
176 	}
177 }
178 
179 /**
180  * Initializes UI colors according to origin.
181  */
init()182 void OptionsBaseState::init()
183 {
184 	State::init();
185 	if (_origin == OPT_BATTLESCAPE)
186 	{
187 		applyBattlescapeTheme();
188 	}
189 }
190 
191 /**
192  * Handles the pressed-button state for the category buttons.
193  * @param button Button to press.
194  */
setCategory(TextButton * button)195 void OptionsBaseState::setCategory(TextButton *button)
196 {
197 	_group = button;
198 	_btnVideo->setGroup(&_group);
199 	_btnAudio->setGroup(&_group);
200 	_btnControls->setGroup(&_group);
201 	_btnGeoscape->setGroup(&_group);
202 	_btnBattlescape->setGroup(&_group);
203 	_btnAdvanced->setGroup(&_group);
204 	_btnMods->setGroup(&_group);
205 }
206 
207 /**
208  * Saves the new options and returns to the proper origin screen.
209  * @param action Pointer to an action.
210  */
btnOkClick(Action *)211 void OptionsBaseState::btnOkClick(Action *)
212 {
213 	int dX = Options::baseXResolution;
214 	int dY = Options::baseYResolution;
215 	Screen::updateScale(Options::battlescapeScale, Options::newBattlescapeScale, Options::baseXBattlescape, Options::baseYBattlescape, _origin == OPT_BATTLESCAPE);
216 	Screen::updateScale(Options::geoscapeScale, Options::newGeoscapeScale, Options::baseXGeoscape, Options::baseYGeoscape, _origin != OPT_BATTLESCAPE);
217 	dX = Options::baseXResolution - dX;
218 	dY = Options::baseYResolution - dY;
219 	recenter(dX, dY);
220 	Options::switchDisplay();
221 	Options::save();
222 	_game->loadLanguage(Options::language);
223 	SDL_WM_GrabInput(Options::captureMouse);
224 	_game->getScreen()->resetDisplay();
225 	_game->setVolume(Options::soundVolume, Options::musicVolume, Options::uiVolume);
226 	if (Options::reload && _origin == OPT_MENU)
227 	{
228 		_game->setState(new StartState(_game));
229 	}
230 	else
231 	{
232 		// Confirm any video options changes
233 		if (Options::displayWidth != Options::newDisplayWidth ||
234 			Options::displayHeight != Options::newDisplayHeight ||
235 			Options::useOpenGL != Options::newOpenGL ||
236 			Options::useScaleFilter != Options::newScaleFilter ||
237 			Options::useHQXFilter != Options::newHQXFilter ||
238 			Options::useOpenGLShader != Options::newOpenGLShader)
239 		{
240 			_game->pushState(new OptionsConfirmState(_game, _origin));
241 		}
242 		else
243 		{
244 			restart(_game, _origin);
245 		}
246 	}
247 }
248 
249 /**
250  * Loads previous options and returns to the previous screen.
251  * @param action Pointer to an action.
252  */
btnCancelClick(Action *)253 void OptionsBaseState::btnCancelClick(Action *)
254 {
255 	Options::reload = false;
256 	Options::load();
257 	SDL_WM_GrabInput(Options::captureMouse);
258 	Screen::updateScale(Options::newBattlescapeScale, Options::battlescapeScale, Options::baseXBattlescape, Options::baseYBattlescape, _origin == OPT_BATTLESCAPE);
259 	Screen::updateScale(Options::newGeoscapeScale, Options::geoscapeScale, Options::baseXGeoscape, Options::baseYGeoscape, _origin != OPT_BATTLESCAPE);
260 	_game->setVolume(Options::soundVolume, Options::musicVolume, Options::uiVolume);
261 	_game->popState();
262 }
263 
264 /**
265  * Restores the Options to default settings.
266  * @param action Pointer to an action.
267  */
btnDefaultClick(Action * action)268 void OptionsBaseState::btnDefaultClick(Action *action)
269 {
270 	_game->pushState(new OptionsDefaultsState(_game, _origin, this));
271 }
272 
btnGroupPress(Action * action)273 void OptionsBaseState::btnGroupPress(Action *action)
274 {
275 	Surface *sender = action->getSender();
276 	//if (sender != _group)
277 	{
278 		_game->popState();
279 		if (sender == _btnVideo)
280 		{
281 			_game->pushState(new OptionsVideoState(_game, _origin));
282 		}
283 		else if (sender == _btnAudio)
284 		{
285 			if (!Options::mute)
286 			{
287 				_game->pushState(new OptionsAudioState(_game, _origin));
288 			}
289 			else
290 			{
291 				_game->pushState(new OptionsNoAudioState(_game, _origin));
292 			}
293 		}
294 		else if (sender == _btnControls)
295 		{
296 			_game->pushState(new OptionsControlsState(_game, _origin));
297 		}
298 		else if (sender == _btnGeoscape)
299 		{
300 			_game->pushState(new OptionsGeoscapeState(_game, _origin));
301 		}
302 		else if (sender == _btnBattlescape)
303 		{
304 			_game->pushState(new OptionsBattlescapeState(_game, _origin));
305 		}
306 		else if (sender == _btnAdvanced)
307 		{
308 			_game->pushState(new OptionsAdvancedState(_game, _origin));
309 		}
310 		else if (sender == _btnMods)
311 		{
312 			_game->pushState(new OptionsModsState(_game, _origin));
313 		}
314 	}
315 }
316 
317 /**
318 * Shows a tooltip for the appropriate button.
319 * @param action Pointer to an action.
320 */
txtTooltipIn(Action * action)321 void OptionsBaseState::txtTooltipIn(Action *action)
322 {
323 	_currentTooltip = action->getSender()->getTooltip();
324 	_txtTooltip->setText(tr(_currentTooltip));
325 }
326 
327 /**
328 * Clears the tooltip text.
329 * @param action Pointer to an action.
330 */
txtTooltipOut(Action * action)331 void OptionsBaseState::txtTooltipOut(Action *action)
332 {
333 	if (_currentTooltip == action->getSender()->getTooltip())
334 	{
335 		_txtTooltip->setText(L"");
336 	}
337 }
338 
339 /**
340  * Updates the scale.
341  * @param dX delta of X;
342  * @param dY delta of Y;
343  */
resize(int & dX,int & dY)344 void OptionsBaseState::resize(int &dX, int &dY)
345 {
346 	Options::newDisplayWidth = Options::displayWidth;
347 	Options::newDisplayHeight = Options::displayHeight;
348 	State::resize(dX, dY);
349 
350 }
351 }
352