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 "OptionsVideoState.h"
20 #include "../Engine/Game.h"
21 #include "../Resource/ResourcePack.h"
22 #include "../Engine/Language.h"
23 #include "../Engine/Palette.h"
24 #include "../Interface/TextButton.h"
25 #include "../Engine/Action.h"
26 #include "../Interface/Window.h"
27 #include "../Interface/Text.h"
28 #include "../Interface/TextEdit.h"
29 #include "../Interface/ToggleTextButton.h"
30 #include "../Engine/Options.h"
31 #include "../Engine/Screen.h"
32 #include "../Interface/ArrowButton.h"
33 #include "../Engine/CrossPlatform.h"
34 #include "../Engine/Logger.h"
35 #include "../Interface/ComboBox.h"
36
37 namespace OpenXcom
38 {
39
40 const std::string OptionsVideoState::GL_EXT = "OpenGL.shader";
41 const std::string OptionsVideoState::GL_FOLDER = "Shaders/";
42 const std::string OptionsVideoState::GL_STRING = "*";
43
44 /**
45 * Initializes all the elements in the Video Options screen.
46 * @param game Pointer to the core game.
47 * @param origin Game section that originated this state.
48 */
OptionsVideoState(Game * game,OptionsOrigin origin)49 OptionsVideoState::OptionsVideoState(Game *game, OptionsOrigin origin) : OptionsBaseState(game, origin)
50 {
51 setCategory(_btnVideo);
52
53 // Create objects
54 _displaySurface = new InteractiveSurface(110, 32, 94, 18);
55 _txtDisplayResolution = new Text(114, 9, 94, 8);
56 _txtDisplayWidth = new TextEdit(this, 40, 17, 94, 26);
57 _txtDisplayX = new Text(16, 17, 132, 26);
58 _txtDisplayHeight = new TextEdit(this, 40, 17, 144, 26);
59 _btnDisplayResolutionUp = new ArrowButton(ARROW_BIG_UP, 14, 14, 186, 18);
60 _btnDisplayResolutionDown = new ArrowButton(ARROW_BIG_DOWN, 14, 14, 186, 36);
61
62 _txtLanguage = new Text(114, 9, 94, 52);
63 _cbxLanguage = new ComboBox(this, 104, 16, 94, 62);
64
65 _txtFilter = new Text(114, 9, 206, 52);
66 _cbxFilter = new ComboBox(this, 104, 16, 206, 62);
67
68 _txtMode = new Text(114, 9, 206, 22);
69 _cbxDisplayMode = new ComboBox(this, 104, 16, 206, 32);
70
71 _txtGeoScale = new Text(114, 9, 94, 82);
72 _cbxGeoScale = new ComboBox(this, 104, 16, 94, 92);
73
74 _txtBattleScale = new Text(114, 9, 94, 112);
75 _cbxBattleScale = new ComboBox(this, 104, 16, 94, 122);
76
77 _txtOptions = new Text(114, 9, 206, 82);
78 _btnLetterbox = new ToggleTextButton(104, 16, 206, 92);
79 _btnLockMouse = new ToggleTextButton(104, 16, 206, 110);
80
81 // Get available fullscreen modes
82 _res = SDL_ListModes(NULL, SDL_FULLSCREEN);
83 if (_res != (SDL_Rect**)-1 && _res != (SDL_Rect**)0)
84 {
85 int i;
86 _resCurrent = -1;
87 for (i = 0; _res[i]; ++i)
88 {
89 if (_resCurrent == -1 &&
90 ((_res[i]->w == Options::displayWidth && _res[i]->h <= Options::displayHeight) || _res[i]->w < Options::displayWidth))
91 {
92 _resCurrent = i;
93 }
94 }
95 _resAmount = i;
96 }
97 else
98 {
99 _resCurrent = -1;
100 _resAmount = 0;
101 _btnDisplayResolutionDown->setVisible(false);
102 _btnDisplayResolutionUp->setVisible(false);
103 Log(LOG_WARNING) << "Couldn't get display resolutions";
104 }
105
106 add(_displaySurface);
107 add(_txtDisplayResolution);
108 add(_txtDisplayWidth);
109 add(_txtDisplayX);
110 add(_txtDisplayHeight);
111 add(_btnDisplayResolutionUp);
112 add(_btnDisplayResolutionDown);
113
114 add(_txtLanguage);
115 add(_txtFilter);
116
117 add(_txtMode);
118
119 add(_txtOptions);
120 add(_btnLetterbox);
121 add(_btnLockMouse);
122
123
124 add(_cbxFilter);
125 add(_cbxDisplayMode);
126
127 add(_txtBattleScale);
128 add(_cbxBattleScale);
129
130 add(_txtGeoScale);
131 add(_cbxGeoScale);
132
133 add(_cbxLanguage);
134 centerAllSurfaces();
135
136 // Set up objects
137 _txtDisplayResolution->setColor(Palette::blockOffset(8)+10);
138 _txtDisplayResolution->setText(tr("STR_DISPLAY_RESOLUTION"));
139
140 _displaySurface->setTooltip("STR_DISPLAY_RESOLUTION_DESC");
141 _displaySurface->onMouseIn((ActionHandler)&OptionsVideoState::txtTooltipIn);
142 _displaySurface->onMouseOut((ActionHandler)&OptionsVideoState::txtTooltipOut);
143
144 _txtDisplayWidth->setColor(Palette::blockOffset(15)-1);
145 _txtDisplayWidth->setAlign(ALIGN_CENTER);
146 _txtDisplayWidth->setBig();
147 _txtDisplayWidth->setNumerical(true);
148 _txtDisplayWidth->onChange((ActionHandler)&OptionsVideoState::txtDisplayWidthChange);
149
150 _txtDisplayX->setColor(Palette::blockOffset(15)-1);
151 _txtDisplayX->setAlign(ALIGN_CENTER);
152 _txtDisplayX->setBig();
153 _txtDisplayX->setText(L"x");
154
155 _txtDisplayHeight->setColor(Palette::blockOffset(15)-1);
156 _txtDisplayHeight->setAlign(ALIGN_CENTER);
157 _txtDisplayHeight->setBig();
158 _txtDisplayHeight->setNumerical(true);
159 _txtDisplayHeight->onChange((ActionHandler)&OptionsVideoState::txtDisplayHeightChange);
160
161 std::wostringstream ssW, ssH;
162 ssW << Options::displayWidth;
163 ssH << Options::displayHeight;
164 _txtDisplayWidth->setText(ssW.str());
165 _txtDisplayHeight->setText(ssH.str());
166
167 _btnDisplayResolutionUp->setColor(Palette::blockOffset(15)-1);
168 _btnDisplayResolutionUp->onMouseClick((ActionHandler)&OptionsVideoState::btnDisplayResolutionUpClick);
169
170 _btnDisplayResolutionDown->setColor(Palette::blockOffset(15)-1);
171 _btnDisplayResolutionDown->onMouseClick((ActionHandler)&OptionsVideoState::btnDisplayResolutionDownClick);
172
173 _txtMode->setColor(Palette::blockOffset(8)+10);
174 _txtMode->setText(tr("STR_DISPLAY_MODE"));
175
176 _txtOptions->setColor(Palette::blockOffset(8)+10);
177 _txtOptions->setText(tr("STR_DISPLAY_OPTIONS"));
178
179 _btnLetterbox->setColor(Palette::blockOffset(15)-1);
180 _btnLetterbox->setText(tr("STR_LETTERBOXED"));
181 _btnLetterbox->setPressed(Options::keepAspectRatio);
182 _btnLetterbox->onMouseClick((ActionHandler)&OptionsVideoState::btnLetterboxClick);
183 _btnLetterbox->setTooltip("STR_LETTERBOXED_DESC");
184 _btnLetterbox->onMouseIn((ActionHandler)&OptionsVideoState::txtTooltipIn);
185 _btnLetterbox->onMouseOut((ActionHandler)&OptionsVideoState::txtTooltipOut);
186
187 _btnLockMouse->setColor(Palette::blockOffset(15)-1);
188 _btnLockMouse->setText(tr("STR_LOCK_MOUSE"));
189 _btnLockMouse->setPressed(Options::captureMouse == SDL_GRAB_ON);
190 _btnLockMouse->onMouseClick((ActionHandler)&OptionsVideoState::btnLockMouseClick);
191 _btnLockMouse->setTooltip("STR_LOCK_MOUSE_DESC");
192 _btnLockMouse->onMouseIn((ActionHandler)&OptionsVideoState::txtTooltipIn);
193 _btnLockMouse->onMouseOut((ActionHandler)&OptionsVideoState::txtTooltipOut);
194
195 _txtLanguage->setColor(Palette::blockOffset(8)+10);
196 _txtLanguage->setText(tr("STR_DISPLAY_LANGUAGE"));
197
198 std::vector<std::wstring> names;
199 Language::getList(_langs, names);
200 _cbxLanguage->setColor(Palette::blockOffset(15)-1);
201 _cbxLanguage->setOptions(names);
202 for (size_t i = 0; i < names.size(); ++i)
203 {
204 if (_langs[i] == Options::language)
205 {
206 _cbxLanguage->setSelected(i);
207 break;
208 }
209 }
210 _cbxLanguage->onChange((ActionHandler)&OptionsVideoState::cbxLanguageChange);
211 _cbxLanguage->setTooltip("STR_DISPLAY_LANGUAGE_DESC");
212 _cbxLanguage->onMouseIn((ActionHandler)&OptionsVideoState::txtTooltipIn);
213 _cbxLanguage->onMouseOut((ActionHandler)&OptionsVideoState::txtTooltipOut);
214
215 std::vector<std::wstring> filterNames;
216 filterNames.push_back(tr("STR_DISABLED"));
217 filterNames.push_back(L"Scale");
218 filterNames.push_back(L"HQX");
219 _filters.push_back("");
220 _filters.push_back("");
221 _filters.push_back("");
222
223 #ifndef __NO_OPENGL
224 std::vector<std::string> filters = CrossPlatform::getFolderContents(CrossPlatform::getDataFolder(GL_FOLDER), GL_EXT);
225 for (std::vector<std::string>::iterator i = filters.begin(); i != filters.end(); ++i)
226 {
227 std::string file = (*i);
228 std::string path = GL_FOLDER + file;
229 std::string name = file.substr(0, file.length() - GL_EXT.length() - 1) + GL_STRING;
230 filterNames.push_back(Language::fsToWstr(name));
231 _filters.push_back(path);
232 }
233 #endif
234
235 size_t selFilter = 0;
236 if (Screen::isOpenGLEnabled())
237 {
238 #ifndef __NO_OPENGL
239 std::string path = Options::useOpenGLShader;
240 for (size_t i = 0; i < _filters.size(); ++i)
241 {
242 if (_filters[i] == path)
243 {
244 selFilter = i;
245 }
246 }
247 #endif
248 }
249 else if (Options::useScaleFilter)
250 {
251 selFilter = 1;
252 }
253 else if (Options::useHQXFilter)
254 {
255 selFilter = 2;
256 }
257
258 _txtFilter->setColor(Palette::blockOffset(8)+10);
259 _txtFilter->setText(tr("STR_DISPLAY_FILTER"));
260
261 _cbxFilter->setColor(Palette::blockOffset(15)-1);
262 _cbxFilter->setOptions(filterNames);
263 _cbxFilter->setSelected(selFilter);
264 _cbxFilter->onChange((ActionHandler)&OptionsVideoState::cbxFilterChange);
265 _cbxFilter->setTooltip("STR_DISPLAY_FILTER_DESC");
266 _cbxFilter->onMouseIn((ActionHandler)&OptionsVideoState::txtTooltipIn);
267 _cbxFilter->onMouseOut((ActionHandler)&OptionsVideoState::txtTooltipOut);
268
269
270 std::vector<std::string> displayModes;
271 displayModes.push_back("STR_WINDOWED");
272 displayModes.push_back("STR_FULLSCREEN");
273 displayModes.push_back("STR_BORDERLESS");
274 displayModes.push_back("STR_RESIZABLE");
275
276 int displayMode = 0;
277 if (Options::fullscreen)
278 displayMode = 1;
279 else if (Options::borderless)
280 displayMode = 2;
281 else if (Options::allowResize)
282 displayMode = 3;
283
284 _cbxDisplayMode->setColor(Palette::blockOffset(15)-1);
285 _cbxDisplayMode->setOptions(displayModes);
286 _cbxDisplayMode->setSelected(displayMode);
287 _cbxDisplayMode->onChange((ActionHandler)&OptionsVideoState::updateDisplayMode);
288 _cbxDisplayMode->setTooltip("STR_DISPLAY_MODE_DESC");
289 _cbxDisplayMode->onMouseIn((ActionHandler)&OptionsVideoState::txtTooltipIn);
290 _cbxDisplayMode->onMouseOut((ActionHandler)&OptionsVideoState::txtTooltipOut);
291
292 _txtGeoScale->setColor(Palette::blockOffset(8)+10);
293 _txtGeoScale->setText(tr("STR_GEOSCAPE_SCALE"));
294
295 std::vector<std::string> scales;
296 scales.push_back("STR_ORIGINAL");
297 scales.push_back("STR_1.5X");
298 scales.push_back("STR_2X");
299 scales.push_back("STR_THIRD_DISPLAY");
300 scales.push_back("STR_HALF_DISPLAY");
301 scales.push_back("STR_FULL_DISPLAY");
302
303 _cbxGeoScale->setColor(Palette::blockOffset(15)-1);
304 _cbxGeoScale->setOptions(scales);
305 _cbxGeoScale->setSelected(Options::geoscapeScale);
306 _cbxGeoScale->onChange((ActionHandler)&OptionsVideoState::updateGeoscapeScale);
307 _cbxGeoScale->setTooltip("STR_GEOSCAPESCALE_SCALE_DESC");
308 _cbxGeoScale->onMouseIn((ActionHandler)&OptionsVideoState::txtTooltipIn);
309 _cbxGeoScale->onMouseOut((ActionHandler)&OptionsVideoState::txtTooltipOut);
310
311 _txtBattleScale->setColor(Palette::blockOffset(8)+10);
312 _txtBattleScale->setText(tr("STR_BATTLESCAPE_SCALE"));
313
314 _cbxBattleScale->setColor(Palette::blockOffset(15)-1);
315 _cbxBattleScale->setOptions(scales);
316 _cbxBattleScale->setSelected(Options::battlescapeScale);
317 _cbxBattleScale->onChange((ActionHandler)&OptionsVideoState::updateBattlescapeScale);
318 _cbxBattleScale->setTooltip("STR_BATTLESCAPE_SCALE_DESC");
319 _cbxBattleScale->onMouseIn((ActionHandler)&OptionsVideoState::txtTooltipIn);
320 _cbxBattleScale->onMouseOut((ActionHandler)&OptionsVideoState::txtTooltipOut);
321
322 }
323
324 /**
325 *
326 */
~OptionsVideoState()327 OptionsVideoState::~OptionsVideoState()
328 {
329
330 }
331
332 /**
333 * Selects a bigger display resolution.
334 * @param action Pointer to an action.
335 */
btnDisplayResolutionUpClick(Action *)336 void OptionsVideoState::btnDisplayResolutionUpClick(Action *)
337 {
338 if (_resAmount == 0)
339 return;
340 if (_resCurrent <= 0)
341 {
342 _resCurrent = _resAmount-1;
343 }
344 else
345 {
346 _resCurrent--;
347 }
348 updateDisplayResolution();
349 }
350
351 /**
352 * Selects a smaller display resolution.
353 * @param action Pointer to an action.
354 */
btnDisplayResolutionDownClick(Action *)355 void OptionsVideoState::btnDisplayResolutionDownClick(Action *)
356 {
357 if (_resAmount == 0)
358 return;
359 if (_resCurrent >= _resAmount-1)
360 {
361 _resCurrent = 0;
362 }
363 else
364 {
365 _resCurrent++;
366 }
367 updateDisplayResolution();
368 }
369
370 /**
371 * Updates the display resolution based on the selection.
372 */
updateDisplayResolution()373 void OptionsVideoState::updateDisplayResolution()
374 {
375 std::wostringstream ssW, ssH;
376 ssW << (int)_res[_resCurrent]->w;
377 ssH << (int)_res[_resCurrent]->h;
378 _txtDisplayWidth->setText(ssW.str());
379 _txtDisplayHeight->setText(ssH.str());
380
381 Options::newDisplayWidth = _res[_resCurrent]->w;
382 Options::newDisplayHeight = _res[_resCurrent]->h;
383 }
384 /**
385 * Changes the Display Width option.
386 * @param action Pointer to an action.
387 */
txtDisplayWidthChange(Action *)388 void OptionsVideoState::txtDisplayWidthChange(Action *)
389 {
390 std::wstringstream ss;
391 int width = 0;
392 ss << std::dec << _txtDisplayWidth->getText();
393 ss >> std::dec >> width;
394 Options::newDisplayWidth = width;
395 // Update resolution mode
396 if (_res != (SDL_Rect**)-1 && _res != (SDL_Rect**)0)
397 {
398 int i;
399 _resCurrent = -1;
400 for (i = 0; _res[i]; ++i)
401 {
402 if (_resCurrent == -1 &&
403 ((_res[i]->w == Options::newDisplayWidth && _res[i]->h <= Options::newDisplayHeight) || _res[i]->w < Options::newDisplayWidth))
404 {
405 _resCurrent = i;
406 }
407 }
408 }
409 }
410
411 /**
412 * Changes the Display Height option.
413 * @param action Pointer to an action.
414 */
txtDisplayHeightChange(Action *)415 void OptionsVideoState::txtDisplayHeightChange(Action *)
416 {
417 std::wstringstream ss;
418 int height = 0;
419 ss << std::dec << _txtDisplayHeight->getText();
420 ss >> std::dec >> height;
421 Options::newDisplayHeight = height;
422 // Update resolution mode
423 if (_res != (SDL_Rect**)-1 && _res != (SDL_Rect**)0)
424 {
425 int i;
426 _resCurrent = -1;
427 for (i = 0; _res[i]; ++i)
428 {
429 if (_resCurrent == -1 &&
430 ((_res[i]->w == Options::newDisplayWidth && _res[i]->h <= Options::newDisplayHeight) || _res[i]->w < Options::newDisplayWidth))
431 {
432 _resCurrent = i;
433 }
434 }
435 }
436 }
437
438 /**
439 * Changes the Language option.
440 * @param action Pointer to an action.
441 */
cbxLanguageChange(Action *)442 void OptionsVideoState::cbxLanguageChange(Action *)
443 {
444 Options::language = _langs[_cbxLanguage->getSelected()];
445 }
446
447 /**
448 * Changes the Filter options.
449 * @param action Pointer to an action.
450 */
cbxFilterChange(Action *)451 void OptionsVideoState::cbxFilterChange(Action *)
452 {
453 switch (_cbxFilter->getSelected())
454 {
455 case 0:
456 Options::newOpenGL = false;
457 Options::newScaleFilter = false;
458 Options::newHQXFilter = false;
459 break;
460 case 1:
461 Options::newOpenGL = false;
462 Options::newScaleFilter = true;
463 Options::newHQXFilter = false;
464 break;
465 case 2:
466 Options::newOpenGL = false;
467 Options::newScaleFilter = false;
468 Options::newHQXFilter = true;
469 break;
470 default:
471 Options::newOpenGL = true;
472 Options::newScaleFilter = false;
473 Options::newHQXFilter = false;
474 Options::newOpenGLShader = _filters[_cbxFilter->getSelected()];
475 break;
476 }
477 }
478
479 /**
480 * Changes the Display Mode options.
481 * @param action Pointer to an action.
482 */
updateDisplayMode(Action *)483 void OptionsVideoState::updateDisplayMode(Action *)
484 {
485 switch(_cbxDisplayMode->getSelected())
486 {
487 case 0:
488 Options::fullscreen = false;
489 Options::borderless = false;
490 Options::allowResize = false;
491 break;
492 case 1:
493 Options::fullscreen = true;
494 Options::borderless = false;
495 Options::allowResize = false;
496 break;
497 case 2:
498 Options::fullscreen = false;
499 Options::borderless = true;
500 Options::allowResize = false;
501 break;
502 case 3:
503 Options::fullscreen = false;
504 Options::borderless = false;
505 Options::allowResize = true;
506 break;
507 default:
508 break;
509 }
510 }
511
512 /**
513 * Changes the Letterboxing option.
514 * @param action Pointer to an action.
515 */
btnLetterboxClick(Action *)516 void OptionsVideoState::btnLetterboxClick(Action *)
517 {
518 Options::keepAspectRatio = _btnLetterbox->getPressed();
519 }
520
521 /**
522 * Changes the Lock Mouse option.
523 * @param action Pointer to an action.
524 */
btnLockMouseClick(Action *)525 void OptionsVideoState::btnLockMouseClick(Action *)
526 {
527 Options::captureMouse = (SDL_GrabMode)_btnLockMouse->getPressed();
528 SDL_WM_GrabInput(Options::captureMouse);
529 }
530
531 /**
532 * Changes the geoscape scale.
533 * @param action Pointer to an action.
534 */
updateGeoscapeScale(Action *)535 void OptionsVideoState::updateGeoscapeScale(Action *)
536 {
537 Options::newGeoscapeScale = _cbxGeoScale->getSelected();
538 }
539
540 /**
541 * Updates the Battlescape scale.
542 * @param action Pointer to an action.
543 */
updateBattlescapeScale(Action *)544 void OptionsVideoState::updateBattlescapeScale(Action *)
545 {
546 Options::newBattlescapeScale = _cbxBattleScale->getSelected();
547 }
548
549 /**
550 * Updates the scale.
551 * @param dX delta of X;
552 * @param dY delta of Y;
553 */
resize(int & dX,int & dY)554 void OptionsVideoState::resize(int &dX, int &dY)
555 {
556 OptionsBaseState::resize(dX, dY);
557 std::wostringstream ss;
558 ss << Options::displayWidth;
559 _txtDisplayWidth->setText(ss.str());
560 ss.str(L"");
561 ss << Options::displayHeight;
562 _txtDisplayHeight->setText(ss.str());
563 }
564
565 /**
566 * Takes care of any events from the core game engine.
567 * @param action Pointer to an action.
568 */
handle(Action * action)569 void OptionsVideoState::handle(Action *action)
570 {
571 State::handle(action);
572 if (action->getDetails()->key.keysym.sym == SDLK_g && (SDL_GetModState() & KMOD_CTRL) != 0)
573 {
574 _btnLockMouse->setPressed(Options::captureMouse == SDL_GRAB_ON);
575 }
576 }
577 }
578