1 //  SuperTuxKart - a fun racing game with go-kart
2 //  Copyright (C) 2009-2015 Marianne Gagnon
3 //
4 //  This program is free software; you can redistribute it and/or
5 //  modify it under the terms of the GNU General Public License
6 //  as published by the Free Software Foundation; either version 3
7 //  of the License, or (at your option) any later version.
8 //
9 //  This program is distributed in the hope that it will be useful,
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //  GNU General Public License for more details.
13 //
14 //  You should have received a copy of the GNU General Public License
15 //  along with this program; if not, write to the Free Software
16 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17 
18 #include "states_screens/options/options_screen_ui.hpp"
19 
20 #include "addons/news_manager.hpp"
21 #include "audio/sfx_manager.hpp"
22 #include "audio/sfx_base.hpp"
23 #include "graphics/camera.hpp"
24 #include "graphics/camera_normal.hpp"
25 #include "challenges/story_mode_timer.hpp"
26 #include "config/hardware_stats.hpp"
27 #include "config/player_manager.hpp"
28 #include "config/user_config.hpp"
29 #include "config/stk_config.hpp"
30 #include "font/bold_face.hpp"
31 #include "font/font_manager.hpp"
32 #include "font/regular_face.hpp"
33 #include "graphics/irr_driver.hpp"
34 #include "guiengine/scalable_font.hpp"
35 #include "guiengine/screen.hpp"
36 #include "guiengine/widgets/button_widget.hpp"
37 #include "guiengine/widgets/check_box_widget.hpp"
38 #include "guiengine/widgets/dynamic_ribbon_widget.hpp"
39 #include "guiengine/widgets/label_widget.hpp"
40 #include "guiengine/widgets/list_widget.hpp"
41 #include "guiengine/widgets/spinner_widget.hpp"
42 #include "guiengine/widget.hpp"
43 #include "io/file_manager.hpp"
44 #include "online/request_manager.hpp"
45 #include "states_screens/dialogs/message_dialog.hpp"
46 #include "states_screens/main_menu_screen.hpp"
47 #include "states_screens/dialogs/custom_camera_settings.hpp"
48 #include "states_screens/options/options_screen_audio.hpp"
49 #include "states_screens/options/options_screen_general.hpp"
50 #include "states_screens/options/options_screen_input.hpp"
51 #include "states_screens/options/options_screen_language.hpp"
52 #include "states_screens/options/options_screen_video.hpp"
53 #include "states_screens/state_manager.hpp"
54 #include "states_screens/options/user_screen.hpp"
55 #include "utils/log.hpp"
56 #include "utils/string_utils.hpp"
57 #include "utils/translation.hpp"
58 
59 #include <algorithm>
60 #include <iostream>
61 #include <sstream>
62 
63 using namespace GUIEngine;
64 using namespace Online;
65 
66 // -----------------------------------------------------------------------------
67 
OptionsScreenUI()68 OptionsScreenUI::OptionsScreenUI() : Screen("options_ui.stkgui")
69 {
70     m_inited = false;
71 }   // OptionsScreenVideo
72 
73 // -----------------------------------------------------------------------------
74 
loadedFromFile()75 void OptionsScreenUI::loadedFromFile()
76 {
77     m_inited = false;
78 
79     GUIEngine::SpinnerWidget* skinSelector = getWidget<GUIEngine::SpinnerWidget>("skinchoice");
80     assert( skinSelector != NULL );
81 
82     skinSelector->m_properties[PROP_WRAP_AROUND] = "true";
83 
84     // Setup the minimap options spinner
85     GUIEngine::SpinnerWidget* minimap_options = getWidget<GUIEngine::SpinnerWidget>("minimap");
86     assert( minimap_options != NULL );
87 
88     minimap_options->m_properties[PROP_WRAP_AROUND] = "true";
89     minimap_options->clearLabels();
90     //I18N: In the UI options, minimap position in the race UI
91     minimap_options->addLabel( core::stringw(_("In the bottom-left")));
92     //I18N: In the UI options, minimap position in the race UI
93     minimap_options->addLabel( core::stringw(_("On the right side")));
94     //I18N: In the UI options, minimap position in the race UI
95     minimap_options->addLabel( core::stringw(_("Hidden")));
96     //I18N: In the UI options, minimap position in the race UI
97     minimap_options->addLabel( core::stringw(_("Centered")));
98     minimap_options->m_properties[GUIEngine::PROP_MIN_VALUE] = "0";
99 
100     bool multitouch_enabled = (UserConfigParams::m_multitouch_active == 1 &&
101                                irr_driver->getDevice()->supportsTouchDevice()) ||
102                                UserConfigParams::m_multitouch_active > 1;
103 
104     if (multitouch_enabled && UserConfigParams::m_multitouch_draw_gui)
105     {
106         minimap_options->m_properties[GUIEngine::PROP_MIN_VALUE] = "1";
107     }
108     minimap_options->m_properties[GUIEngine::PROP_MAX_VALUE] = "3";
109 
110     // Setup splitscreen spinner
111     GUIEngine::SpinnerWidget* splitscreen_method = getWidget<GUIEngine::SpinnerWidget>("splitscreen_method");
112     splitscreen_method->m_properties[PROP_WRAP_AROUND] = "true";
113     splitscreen_method->clearLabels();
114     //I18N: In the UI options, splitscreen_method in the race UI
115     splitscreen_method->addLabel( core::stringw(_("Vertical")));
116     //I18N: In the UI options, splitscreen_method position in the race UI
117     splitscreen_method->addLabel( core::stringw(_("Horizontal")));
118     splitscreen_method->m_properties[GUIEngine::PROP_MIN_VALUE] = "0";
119     splitscreen_method->m_properties[GUIEngine::PROP_MAX_VALUE] = "1";
120 
121     // Setup fontsize spinner
122     GUIEngine::SpinnerWidget* font_size = getWidget<GUIEngine::SpinnerWidget>("font_size");
123     assert( font_size != NULL );
124 
125     font_size->clearLabels();
126     font_size->addLabel(L"Extremely small");
127     //I18N: In the UI options, Very small font size
128     font_size->addLabel(_("Very small"));
129     //I18N: In the UI options, Small font size
130     font_size->addLabel(_("Small"));
131     //I18N: In the UI options, Medium font size
132     font_size->addLabel(_("Medium"));
133     //I18N: In the UI options, Large font size
134     font_size->addLabel(_("Large"));
135     //I18N: In the UI options, Very large font size
136     font_size->addLabel(_("Very large"));
137     font_size->addLabel(L"Extremely large");
138 
139     if (UserConfigParams::m_artist_debug_mode)
140     {
141         // Only show extreme size in artist debug mode
142         font_size->m_properties[GUIEngine::PROP_MIN_VALUE] = "0";
143         font_size->m_properties[GUIEngine::PROP_MAX_VALUE] = "6";
144     }
145     else
146     {
147         font_size->m_properties[GUIEngine::PROP_MIN_VALUE] = "1";
148         font_size->m_properties[GUIEngine::PROP_MAX_VALUE] = "5";
149     }
150 
151     updateCameraPresetSpinner();
152 
153     font_size->setValueUpdatedCallback([this](SpinnerWidget* spinner)
154     {
155         // Add a special value updated callback so font size is updated when
156         // it's pressed instead of release to prevent multiple event
157         bool right = spinner->isButtonSelected(true/*right*/);
158         UserConfigParams::m_font_size = spinner->getValue();
159         m_reload_option = std::unique_ptr<ReloadOption>(new ReloadOption);
160         m_reload_option->m_reload_font = true;
161         m_reload_option->m_reload_skin = false;
162         m_reload_option->m_focus_name = "font_size";
163         m_reload_option->m_focus_right = right;
164     });
165 
166 }   // loadedFromFile
167 
168 // -----------------------------------------------------------------------------
169 
init()170 void OptionsScreenUI::init()
171 {
172     Screen::init();
173     RibbonWidget* ribbon = getWidget<RibbonWidget>("options_choice");
174     assert(ribbon != NULL);
175     ribbon->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
176     ribbon->select( "tab_ui", PLAYER_ID_GAME_MASTER );
177 
178     GUIEngine::SpinnerWidget* skinSelector = getWidget<GUIEngine::SpinnerWidget>("skinchoice");
179     assert( skinSelector != NULL );
180 
181     m_skins.clear();
182     skinSelector->clearLabels();
183 
184     std::set<std::string> skin_files;
185     file_manager->listFiles(skin_files /* out */, file_manager->getAsset(FileManager::SKIN,""),
186                             true /* make full path */ );
187     std::set<std::string> addon_skin_files;
188     file_manager->listFiles(addon_skin_files /* out */, file_manager->getAddonsFile("skins/"),
189                             true /* make full path */ );
190 
191     auto lb = [](const std::set<std::string>& files, bool addon,
192                  std::map<core::stringw, std::string>& result)->void
193         {
194             for (auto& f : files)
195             {
196                 std::string stkskin = f + "/stkskin.xml";
197                 if (file_manager->fileExists(stkskin))
198                 {
199                     XMLNode* root = file_manager->createXMLTree(stkskin);
200                     if (!root)
201                         continue;
202                     core::stringw skin_name;
203                     if (root->get("name", &skin_name))
204                     {
205                         std::string skin_id = StringUtils::getBasename(f);
206                         if (addon)
207                             skin_id = std::string("addon_") + skin_id;
208                         result[skin_name] = skin_id;
209                     }
210                     delete root;
211                 }
212             }
213         };
214     lb(skin_files, false, m_skins);
215     lb(addon_skin_files, true, m_skins);
216 
217     if (m_skins.size() == 0)
218     {
219         Log::warn("OptionsScreenUI", "Could not find a single skin, make sure that "
220                                      "the data files are correctly installed");
221         skinSelector->setActive(false);
222         return;
223     }
224 
225     const int skin_count = (int)m_skins.size();
226     for (auto& p : m_skins)
227         skinSelector->addLabel(p.first);
228     skinSelector->m_properties[GUIEngine::PROP_MIN_VALUE] = "0";
229     skinSelector->m_properties[GUIEngine::PROP_MAX_VALUE] = StringUtils::toString(skin_count-1);
230 
231     GUIEngine::SpinnerWidget* minimap_options = getWidget<GUIEngine::SpinnerWidget>("minimap");
232     assert( minimap_options != NULL );
233 
234     bool multitouch_enabled = (UserConfigParams::m_multitouch_active == 1 &&
235                                irr_driver->getDevice()->supportsTouchDevice()) ||
236                                UserConfigParams::m_multitouch_active > 1;
237 
238     if (multitouch_enabled && UserConfigParams::m_multitouch_draw_gui &&
239         UserConfigParams::m_minimap_display == 0)
240     {
241         UserConfigParams::m_minimap_display = 1;
242     }
243     minimap_options->setValue(UserConfigParams::m_minimap_display);
244 
245     bool in_game = StateManager::get()->getGameState() == GUIEngine::INGAME_MENU;
246 
247     GUIEngine::SpinnerWidget* font_size = getWidget<GUIEngine::SpinnerWidget>("font_size");
248     assert( font_size != NULL );
249 
250     int size_int = (int)roundf(UserConfigParams::m_font_size);
251     if (size_int < 0 || size_int > 6)
252         size_int = 3;
253 
254     if (!UserConfigParams::m_artist_debug_mode &&
255         (size_int < 1 || size_int > 5))
256         size_int = 3;
257 
258     font_size->setValue(size_int);
259     UserConfigParams::m_font_size = font_size->getValue();
260     font_size->setActive(!in_game);
261 
262     // ---- video modes
263     GUIEngine::SpinnerWidget* splitscreen_method = getWidget<GUIEngine::SpinnerWidget>("splitscreen_method");
264     assert( splitscreen_method != NULL );
265     if (UserConfigParams::split_screen_horizontally) splitscreen_method->setValue(1);
266     else splitscreen_method->setValue(0);
267     splitscreen_method->setActive(!in_game);
268 
269     CheckBoxWidget* karts_powerup_gui = getWidget<CheckBoxWidget>("karts_powerup_gui");
270     assert(karts_powerup_gui != NULL);
271     karts_powerup_gui->setState(UserConfigParams::m_karts_powerup_gui);
272 
273     CheckBoxWidget* fps = getWidget<CheckBoxWidget>("showfps");
274     assert( fps != NULL );
275     fps->setState( UserConfigParams::m_display_fps );
276 
277     CheckBoxWidget* story_timer = getWidget<CheckBoxWidget>("story-mode-timer");
278     assert( story_timer != NULL );
279     story_timer->setState( UserConfigParams::m_display_story_mode_timer );
280     CheckBoxWidget* speedrun_timer = getWidget<CheckBoxWidget>("speedrun-timer");
281     assert( speedrun_timer != NULL );
282     if (story_mode_timer->getStoryModeTime() < 0)
283     {
284         story_timer->setActive(false);
285         speedrun_timer->setActive(false);
286     }
287     else
288     {
289         story_timer->setActive(true);
290 
291         speedrun_timer->setActive(UserConfigParams::m_display_story_mode_timer);
292         getWidget<LabelWidget>("speedrun-timer-text")
293             ->setActive(UserConfigParams::m_display_story_mode_timer);
294     }
295     if (UserConfigParams::m_speedrun_mode)
296     {
297         if (!story_mode_timer->playerCanRun())
298         {
299             UserConfigParams::m_speedrun_mode = false;
300             new MessageDialog(_("Speedrun mode disabled. It can only be enabled if the game"
301                                 " has not been closed since the launch of the story mode.\n\n"
302                                 "Closing the game before the story mode's"
303                                 " completion invalidates the timer.\n\n"
304                                 "To use the speedrun mode, please use a new profile."),
305                                 MessageDialog::MESSAGE_DIALOG_OK,
306                                 NULL, false, false, 0.6f, 0.7f);
307         }
308     }
309     speedrun_timer->setState( UserConfigParams::m_speedrun_mode );
310 
311     // --- select the right skin in the spinner
312     bool currSkinFound = false;
313     const std::string& user_skin = UserConfigParams::m_skin_file;
314     skinSelector->setActive(!in_game);
315 
316     for (int n = 0; n <= skinSelector->getMax(); n++)
317     {
318         auto ret = m_skins.find(skinSelector->getStringValueFromID(n));
319         if (ret == m_skins.end())
320             continue;
321         const std::string skinFileName = ret->second;
322 
323         if (user_skin == skinFileName)
324         {
325             skinSelector->setValue(n);
326             currSkinFound = true;
327             break;
328         }
329     }
330     if (!currSkinFound)
331     {
332         Log::warn("OptionsScreenUI",
333                   "Couldn't find current skin in the list of skins!");
334         skinSelector->setValue(0);
335         irr_driver->unsetMaxTextureSize();
336         GUIEngine::reloadSkin();
337         irr_driver->setMaxTextureSize();
338     }
339 
340     // Camera presets
341     m_camera_presets.push_back // Standard
342     ({
343         80 /* fov */, 1.0f /* distance */, 0.0f  /* angle */, true /* smoothing */, 5.0f /* backward angle */,
344     });
345 
346     m_camera_presets.push_back // Drone chase
347     ({
348         100 /* fov */, 2.6f /* distance */, 33.0f  /* angle */, false /* smoothing */, 10.0f /* backward angle */,
349     });
350 
351     GUIEngine::SpinnerWidget* camera_preset = getWidget<GUIEngine::SpinnerWidget>("camera_preset");
352     assert( camera_preset != NULL );
353 
354     camera_preset->m_properties[PROP_WRAP_AROUND] = "true";
355     camera_preset->clearLabels();
356     //I18N: custom camera setting
357     camera_preset->addLabel( core::stringw(_("Custom")));
358     //I18N: In the UI options,litscreen_method in the race UI
359     camera_preset->addLabel( core::stringw(_("Standard")));
360     //I18N: In the UI options, splitscreen_method position in the race UI
361     camera_preset->addLabel( core::stringw(_("Drone chase")));
362     camera_preset->m_properties[GUIEngine::PROP_MIN_VALUE] = "1";
363     camera_preset->m_properties[GUIEngine::PROP_MAX_VALUE] = "2";
364 
365     updateCameraPresetSpinner();
366 }   // init
367 
updateCamera()368 void OptionsScreenUI::updateCamera()
369 {
370     bool in_game = StateManager::get()->getGameState() == GUIEngine::INGAME_MENU;
371     if (in_game)
372     {
373         (Camera::getActiveCamera()->getCameraSceneNode())->setFOV(DEGREE_TO_RAD * UserConfigParams::m_camera_fov);
374         CameraNormal *camera = dynamic_cast<CameraNormal*>(Camera::getActiveCamera());
375         if (camera)
376         {
377             camera->setDistanceToKart(UserConfigParams::m_camera_distance);
378         }
379     }
380 }
381 
updateCameraPresetSpinner()382 void OptionsScreenUI::updateCameraPresetSpinner()
383 {
384     GUIEngine::SpinnerWidget* camera_preset = getWidget<GUIEngine::SpinnerWidget>("camera_preset");
385     assert( camera_preset != NULL );
386 
387 #define FLOAT_EPSILON 0.001
388 
389     bool found = false;
390     unsigned int i = 0;
391     for (; i < m_camera_presets.size(); i++)
392     {
393         if (m_camera_presets[i].fov == UserConfigParams::m_camera_fov &&
394             m_camera_presets[i].smoothing == UserConfigParams::m_camera_forward_smoothing &&
395             fabs(m_camera_presets[i].distance - UserConfigParams::m_camera_distance) < FLOAT_EPSILON &&
396             fabs(m_camera_presets[i].angle - UserConfigParams::m_camera_forward_up_angle) < FLOAT_EPSILON &&
397             fabs(m_camera_presets[i].backward_angle - UserConfigParams::m_camera_backward_up_angle) < FLOAT_EPSILON)
398         {
399             camera_preset->setValue(i + 1);
400             found = true;
401             break;
402         }
403     }
404 
405     if (!found)
406     {
407         camera_preset->setValue(0);
408         camera_preset->m_properties[GUIEngine::PROP_MIN_VALUE] = std::to_string(0);
409     }
410     updateCamera();
411 
412 } // updateCameraPresetSpinner
413 
414 // -----------------------------------------------------------------------------
415 
eventCallback(Widget * widget,const std::string & name,const int playerID)416 void OptionsScreenUI::eventCallback(Widget* widget, const std::string& name, const int playerID)
417 {
418 #ifndef SERVER_ONLY
419     if (name == "options_choice")
420     {
421         std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER);
422 
423         Screen *screen = NULL;
424         if (selection == "tab_audio")
425             screen = OptionsScreenAudio::getInstance();
426         else if (selection == "tab_video")
427             screen = OptionsScreenVideo::getInstance();
428         else if (selection == "tab_players")
429             screen = TabbedUserScreen::getInstance();
430         else if (selection == "tab_controls")
431             screen = OptionsScreenInput::getInstance();
432         //else if (selection == "tab_ui")
433         //    screen = OptionsScreenUI::getInstance();
434         else if (selection == "tab_general")
435             screen = OptionsScreenGeneral::getInstance();
436         else if (selection == "tab_language")
437             screen = OptionsScreenLanguage::getInstance();
438         if(screen)
439             StateManager::get()->replaceTopMostScreen(screen);
440     }
441     else if(name == "back")
442     {
443         StateManager::get()->escapePressed();
444     }
445     else if (name == "skinchoice")
446     {
447         GUIEngine::SpinnerWidget* skinSelector = getWidget<GUIEngine::SpinnerWidget>("skinchoice");
448         assert( skinSelector != NULL );
449 
450         const core::stringw selectedSkin = skinSelector->getStringValue();
451         bool right = skinSelector->isButtonSelected(true/*right*/);
452         UserConfigParams::m_skin_file = m_skins[selectedSkin];
453         bool prev_font = GUIEngine::getSkin()->hasFont();
454         irr_driver->unsetMaxTextureSize();
455         GUIEngine::reloadSkin();
456         // Reload GUIEngine will clear widgets so we don't do that in eventCallback
457         m_reload_option = std::unique_ptr<ReloadOption>(new ReloadOption);
458         m_reload_option->m_reload_font = prev_font != GUIEngine::getSkin()->hasFont();
459         m_reload_option->m_reload_skin = true;
460         m_reload_option->m_focus_name = "skinchoice";
461         m_reload_option->m_focus_right = right;
462     }
463     else if (name == "minimap")
464     {
465         GUIEngine::SpinnerWidget* minimap_options = getWidget<GUIEngine::SpinnerWidget>("minimap");
466         assert( minimap_options != NULL );
467         UserConfigParams::m_minimap_display = minimap_options->getValue();
468     }
469     else if (name == "font_size")
470     {
471         GUIEngine::SpinnerWidget* font_size = getWidget<GUIEngine::SpinnerWidget>("font_size");
472         assert( font_size != NULL );
473         bool right = font_size->isButtonSelected(true/*right*/);
474         UserConfigParams::m_font_size = font_size->getValue();
475         // Reload GUIEngine will clear widgets so we don't do that in eventCallback
476         m_reload_option = std::unique_ptr<ReloadOption>(new ReloadOption);
477         m_reload_option->m_reload_font = true;
478         m_reload_option->m_reload_skin = false;
479         m_reload_option->m_focus_name = "font_size";
480         m_reload_option->m_focus_right = right;
481     }
482     else if (name == "splitscreen_method")
483     {
484         GUIEngine::SpinnerWidget* splitscreen_method = getWidget<GUIEngine::SpinnerWidget>("splitscreen_method");
485         assert( splitscreen_method != NULL );
486         UserConfigParams::split_screen_horizontally = (splitscreen_method->getValue() == 1);
487     }
488     else if (name == "karts_powerup_gui")
489     {
490         CheckBoxWidget* karts_powerup_gui = getWidget<CheckBoxWidget>("karts_powerup_gui");
491         assert(karts_powerup_gui != NULL);
492         UserConfigParams::m_karts_powerup_gui = karts_powerup_gui->getState();
493     }
494     else if (name == "showfps")
495     {
496         CheckBoxWidget* fps = getWidget<CheckBoxWidget>("showfps");
497         assert( fps != NULL );
498         UserConfigParams::m_display_fps = fps->getState();
499     }
500     else if (name == "story-mode-timer")
501     {
502         CheckBoxWidget* story_timer = getWidget<CheckBoxWidget>("story-mode-timer");
503         assert( story_timer != NULL );
504         UserConfigParams::m_display_story_mode_timer = story_timer->getState();
505 
506         CheckBoxWidget* speedrun_timer = getWidget<CheckBoxWidget>("speedrun-timer");
507         assert( speedrun_timer != NULL );
508         speedrun_timer->setActive( UserConfigParams::m_display_story_mode_timer );
509         getWidget<LabelWidget>("speedrun-timer-text")
510             ->setActive(UserConfigParams::m_display_story_mode_timer);
511 
512         // Disable speedrun mode if the story mode timer is disabled
513         if (!UserConfigParams::m_display_story_mode_timer)
514         {
515             UserConfigParams::m_speedrun_mode = false;
516             speedrun_timer->setState(false);
517         }
518 
519     }
520     else if (name == "speedrun-timer")
521     {
522         CheckBoxWidget* speedrun_timer = getWidget<CheckBoxWidget>("speedrun-timer");
523         assert( speedrun_timer != NULL );
524         if (speedrun_timer->getState())
525         {
526             if (!story_mode_timer->playerCanRun())
527             {
528                 speedrun_timer->setState(false);
529                 new MessageDialog(_("Speedrun mode can only be enabled if the game has not"
530                                     " been closed since the launch of the story mode.\n\n"
531                                     "Closing the game before the story mode's"
532                                     " completion invalidates the timer.\n\n"
533                                     "To use the speedrun mode, please use a new profile."),
534                                     MessageDialog::MESSAGE_DIALOG_OK,
535                                     NULL, false, false, 0.6f, 0.7f);
536             }
537         }
538         UserConfigParams::m_speedrun_mode = speedrun_timer->getState();
539     }
540     else if (name == "camera_preset")
541     {
542         GUIEngine::SpinnerWidget* camera_preset = getWidget<GUIEngine::SpinnerWidget>("camera_preset");
543         assert( camera_preset != NULL );
544         unsigned int i = camera_preset->getValue();
545         if (i != 0) {
546             UserConfigParams::m_camera_fov = m_camera_presets[i-1].fov;
547             UserConfigParams::m_camera_distance = m_camera_presets[i-1].distance;
548             UserConfigParams::m_camera_forward_up_angle = m_camera_presets[i-1].angle;
549             UserConfigParams::m_camera_forward_smoothing = m_camera_presets[i-1].smoothing;
550             UserConfigParams::m_camera_backward_up_angle = m_camera_presets[i-1].backward_angle;
551         }
552         updateCamera();
553     }
554     else if(name == "custom_camera")
555     {
556         new CustomCameraSettingsDialog(0.8f, 0.9f);
557     }
558 #endif
559 }   // eventCallback
560 
561 // -----------------------------------------------------------------------------
562 
onUpdate(float delta)563 void OptionsScreenUI::onUpdate(float delta)
564 {
565     if (m_reload_option)
566         reloadGUIEngine();
567 }   // onUpdate
568 
569 // -----------------------------------------------------------------------------
570 
reloadGUIEngine()571 void OptionsScreenUI::reloadGUIEngine()
572 {
573     bool reload_font = m_reload_option->m_reload_font;
574     bool reload_skin = m_reload_option->m_reload_skin;
575     std::string focus_name = m_reload_option->m_focus_name;
576     bool focus_right = m_reload_option->m_focus_right;
577 
578     if (reload_skin || reload_font)
579     {
580         if (reload_font)
581         {
582             GUIEngine::clear();
583             GUIEngine::cleanUp();
584         }
585 
586         GUIEngine::clearScreenCache();
587 
588         if (reload_font)
589         {
590             delete font_manager;
591             font_manager = new FontManager();
592             font_manager->loadFonts();
593             GUIEngine::init(irr_driver->getDevice(), irr_driver->getVideoDriver(),
594                 StateManager::get(), false/*loading*/);
595         }
596 
597         Screen* screen_list[] =
598             {
599                 MainMenuScreen::getInstance(),
600                 OptionsScreenUI::getInstance(),
601                 nullptr
602             };
603         GUIEngine::switchToScreen(MainMenuScreen::getInstance());
604         StateManager::get()->resetAndSetStack(screen_list);
605         GUIEngine::SpinnerWidget* spinner = OptionsScreenUI::getInstance()
606             ->getWidget<GUIEngine::SpinnerWidget>(focus_name.c_str());
607         spinner->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
608         spinner->setSelectedButton(focus_right);
609     }
610     if (reload_skin)
611     {
612         irr_driver->setMaxTextureSize();
613     }
614     OptionsScreenUI::getInstance()->m_reload_option = nullptr;
615 }   // reloadGUIEngine
616 
617 // -----------------------------------------------------------------------------
618 
tearDown()619 void OptionsScreenUI::tearDown()
620 {
621     Screen::tearDown();
622     // save changes when leaving screen
623     user_config->saveConfig();
624 }   // tearDown
625 
626 // -----------------------------------------------------------------------------
627 
unloaded()628 void OptionsScreenUI::unloaded()
629 {
630     m_inited = false;
631 }   // unloaded
632 
633 // -----------------------------------------------------------------------------
634