1 #include <i18n.h>
2 #include "engine.h"
3 #include "optionsMenu.h"
4 #include "hotkeyMenu.h"
5 #include "main.h"
6 #include "preferenceManager.h"
7
8 #include "gui/gui2_autolayout.h"
9 #include "gui/gui2_overlay.h"
10 #include "gui/gui2_button.h"
11 #include "gui/gui2_togglebutton.h"
12 #include "gui/gui2_selector.h"
13 #include "gui/gui2_label.h"
14 #include "gui/gui2_slider.h"
15 #include "gui/gui2_listbox.h"
16 #include "gui/gui2_keyvaluedisplay.h"
17
OptionsMenu()18 OptionsMenu::OptionsMenu()
19 {
20 P<WindowManager> windowManager = engine->getObject("windowManager");
21
22 new GuiOverlay(this, "", colorConfig.background);
23 (new GuiOverlay(this, "", sf::Color::White))->setTextureTiled("gui/BackgroundCrosses");
24
25 // Initialize autolayout columns.
26 left_container = new GuiAutoLayout(this, "OPTIONS_LEFT_CONTAINER", GuiAutoLayout::LayoutVerticalTopToBottom);
27 left_container->setPosition(50, 50, ATopLeft)->setSize(300, GuiElement::GuiSizeMax);
28
29 right_container = new GuiAutoLayout(this, "OPTIONS_RIGHT_CONTAINER", GuiAutoLayout::LayoutVerticalTopToBottom);
30 right_container->setPosition(-50, 50, ATopRight)->setSize(600, GuiElement::GuiSizeMax);
31
32 // Options pager
33 options_pager = new GuiSelector(left_container, "OPTIONS_PAGER", [this](int index, string value)
34 {
35 graphics_page->setVisible(index == 0);
36 audio_page->setVisible(index == 1);
37 interface_page->setVisible(index == 2);
38 });
39 options_pager->setOptions({tr("Graphics options"), tr("Audio options"), tr("Interface options")})->setSelectionIndex(0)->setSize(GuiElement::GuiSizeMax, 50);
40
41 graphics_page = new GuiAutoLayout(left_container, "OPTIONS_GRAPHICS", GuiAutoLayout::LayoutVerticalTopToBottom);
42 graphics_page->setPosition(0, 0, ATopLeft)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax)->show();
43 audio_page = new GuiAutoLayout(left_container, "OPTIONS_AUDIO", GuiAutoLayout::LayoutVerticalTopToBottom);
44 audio_page->setPosition(0, 0, ATopLeft)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax)->hide();
45 interface_page = new GuiAutoLayout(left_container, "OPTIONS_INTERFACE", GuiAutoLayout::LayoutVerticalTopToBottom);
46 interface_page->setPosition(0, 0, ATopLeft)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax)->hide();
47
48 // Graphics options
49 // Fullscreen toggle.
50 (new GuiButton(graphics_page, "FULLSCREEN_TOGGLE", tr("Fullscreen toggle"), []()
51 {
52 P<WindowManager> windowManager = engine->getObject("windowManager");
53 windowManager->setFullscreen(!windowManager->isFullscreen());
54 }))->setSize(GuiElement::GuiSizeMax, 50);
55
56 // FSAA configuration.
57 int fsaa = std::max(1, windowManager->getFSAA());
58 int fsaa_index = 0;
59
60 // Convert selector index to an FSAA amount.
61 switch(fsaa)
62 {
63 case 8: fsaa_index = 3; break;
64 case 4: fsaa_index = 2; break;
65 case 2: fsaa_index = 1; break;
66 default: fsaa_index = 0; break;
67 }
68
69 // FSAA selector.
70 (new GuiSelector(graphics_page, "FSAA", [](int index, string value)
71 {
72 P<WindowManager> windowManager = engine->getObject("windowManager");
73 static const int fsaa[] = { 0, 2, 4, 8 };
74 windowManager->setFSAA(fsaa[index]);
75 }))->setOptions({"FSAA: off", "FSAA: 2x", "FSAA: 4x", "FSAA: 8x"})->setSelectionIndex(fsaa_index)->setSize(GuiElement::GuiSizeMax, 50);
76
77 // Audio optionss
78 // Sound volume slider.
79 sound_volume_slider = new GuiSlider(audio_page, "SOUND_VOLUME_SLIDER", 0.0f, 100.0f, soundManager->getMasterSoundVolume(), [this](float volume)
80 {
81 soundManager->setMasterSoundVolume(volume);
82 sound_volume_overlay_label->setText(tr("Sound Volume: {volume}%").format({{"volume", string(int(soundManager->getMasterSoundVolume()))}}));
83 });
84 sound_volume_slider->setSize(GuiElement::GuiSizeMax, 50);
85
86 // Override overlay label.
87 sound_volume_overlay_label = new GuiLabel(sound_volume_slider, "SOUND_VOLUME_SLIDER_LABEL", tr("Sound Volume: {volume}%").format({{"volume", string(int(soundManager->getMasterSoundVolume()))}}), 30);
88 sound_volume_overlay_label->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax);
89
90 // Music playback state.
91 (new GuiLabel(audio_page, "MUSIC_PLAYBACK_LABEL", tr("Music Playback"), 30))->addBackground()->setSize(GuiElement::GuiSizeMax, 50);
92
93 // Determine when music is enabled.
94 int music_enabled_index = PreferencesManager::get("music_enabled", "2").toInt();
95 (new GuiSelector(audio_page, "MUSIC_ENABLED", [](int index, string value)
96 {
97 // 0: Always off
98 // 1: Always on
99 // 2: On if main screen, off otherwise (default)
100 PreferencesManager::set("music_enabled", string(index));
101 }))->setOptions({tr("Disabled"), tr("Enabled"), tr("Main Screen only")})->setSelectionIndex(music_enabled_index)->setSize(GuiElement::GuiSizeMax, 50);
102
103 // Music volume slider.
104 music_volume_slider = new GuiSlider(audio_page, "MUSIC_VOLUME_SLIDER", 0.0f, 100.0f, soundManager->getMusicVolume(), [this](float volume)
105 {
106 soundManager->setMusicVolume(volume);
107 music_volume_overlay_label->setText(tr("Music Volume: {volume}%").format({{"volume", string(int(soundManager->getMusicVolume()))}}));
108 });
109 music_volume_slider->setSize(GuiElement::GuiSizeMax, 50);
110
111 // Override overlay label.
112 music_volume_overlay_label = new GuiLabel(music_volume_slider, "MUSIC_VOLUME_SLIDER_LABEL", tr("Music Volume: {volume}%").format({{"volume", string(int(soundManager->getMusicVolume()))}}), 30);
113 music_volume_overlay_label->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax);
114
115 // Engine playback state.
116 (new GuiLabel(audio_page, "IMPULSE_SOUND_LABEL", tr("Impulse Engine sound"), 30))->addBackground()->setSize(GuiElement::GuiSizeMax, 50);
117
118 // Determine when engine sound effects are enabled.
119 int impulse_enabled_index = PreferencesManager::get("impulse_sound_enabled", "2").toInt();
120 (new GuiSelector(audio_page, "ENGINE_ENABLED", [](int index, string value)
121 {
122 // 0: Always off
123 // 1: Always on
124 // 2: On if main screen, off otherwise (default)
125 PreferencesManager::set("impulse_sound_enabled", string(index));
126 }))->setOptions({tr("Disabled"), tr("Enabled"), tr("Main Screen only")})->setSelectionIndex(impulse_enabled_index)->setSize(GuiElement::GuiSizeMax, 50);
127
128 // Impulse engine volume slider.
129 impulse_volume_slider = new GuiSlider(audio_page, "IMPULSE_VOLUME_SLIDER", 0.0f, 100.0f, PreferencesManager::get("impulse_sound_volume", "50").toInt(), [this](float volume)
130 {
131 PreferencesManager::set("impulse_sound_volume", volume);
132 impulse_volume_overlay_label->setText(tr("Impulse Volume: {volume}%").format({{"volume", string(PreferencesManager::get("impulse_sound_volume", "50").toInt())}}));
133 });
134 impulse_volume_slider->setSize(GuiElement::GuiSizeMax, 50);
135
136 // Override overlay label.
137 impulse_volume_overlay_label = new GuiLabel(impulse_volume_slider, "IMPULSE_VOLUME_SLIDER_LABEL", tr("Impulse Volume: {volume}%").format({{"volume", string(PreferencesManager::get("impulse_sound_volume", "50").toInt())}}), 30);
138 impulse_volume_overlay_label->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax);
139
140 // Interface options
141 // Helms rotation lock.
142 (new GuiToggleButton(interface_page, "HEMS_RADAR_LOCK", tr("Helms Radar Lock"), [](bool value)
143 {
144 PreferencesManager::set("helms_radar_lock", value ? "1" : "");
145 PreferencesManager::set("tactical_radar_lock", value ? "1" : "");
146 PreferencesManager::set("single_pilot_radar_lock", value ? "1" : "");
147 }))->setValue(PreferencesManager::get("helms_radar_lock", "0") == "1")->setSize(GuiElement::GuiSizeMax, 50);
148
149 // Weapons rotation lock.
150 (new GuiToggleButton(interface_page, "WEAPONS_RADAR_LOCK", tr("Weapons Radar Lock"), [](bool value)
151 {
152 PreferencesManager::set("weapons_radar_lock", value ? "1" : "");
153 }))->setValue(PreferencesManager::get("weapons_radar_lock", "0") == "1")->setSize(GuiElement::GuiSizeMax, 50);
154
155 // Science rotation lock.
156 (new GuiToggleButton(interface_page, "SCIENCE_RADAR_LOCK", tr("Science Radar Lock"), [](bool value)
157 {
158 PreferencesManager::set("science_radar_lock", value ? "1" : "");
159 PreferencesManager::set("operations_radar_lock", value ? "1" : "");
160 }))->setValue(PreferencesManager::get("science_radar_lock", "0") == "1")->setSize(GuiElement::GuiSizeMax, 50);
161
162 // Control configuration
163 (new GuiLabel(interface_page, "CONTROL_OPTIONS_LABEL", tr("Control Options"), 30))->addBackground()->setSize(GuiElement::GuiSizeMax, 50);
164
165 // Keyboard config (hotkeys/keybindings)
166 (new GuiButton(interface_page, "CONFIGURE_KEYBOARD", tr("Configure Keyboard"), [this]()
167 {
168 new HotkeyMenu();
169 destroy();
170 }))->setSize(GuiElement::GuiSizeMax, 50);
171
172 //Select the language
173 (new GuiLabel(interface_page, "LANGUAGE_OPTIONS_LABEL", tr("Language (applies on back)"), 30))->addBackground()->setSize(GuiElement::GuiSizeMax, 50);
174
175 std::vector<string> languages = findResources("locale/main.*.po");
176
177 for(string &language : languages)
178 {
179 //strip extension
180 language = language.substr(language.find(".") + 1, language.rfind("."));
181 }
182 std::sort(languages.begin(), languages.end());
183
184 int default_index = 0;
185 auto default_elem = std::find(languages.begin(), languages.end(), PreferencesManager::get("language", "en"));
186 if(default_elem != languages.end())
187 {
188 default_index = default_elem - languages.begin();
189 }
190
191 (new GuiSelector(interface_page, "LANGUAGE_SELECTOR", [](int index, string value)
192 {
193 i18n::reset();
194 i18n::load("locale/main." + value + ".po");
195 PreferencesManager::set("language", value);
196 }))->setOptions(languages)->setSelectionIndex(default_index)->setSize(GuiElement::GuiSizeMax, 50);
197
198
199 // Right column, auto layout. Draw first element 50px from top.
200 // Music preview jukebox.
201
202 // Draw list of available music. Grabs every ogg file in the
203 // resources/music folder and lists them by filename.
204 std::vector<string> ambient_music_filenames = findResources("music/ambient/*.ogg");
205 std::sort(ambient_music_filenames.begin(), ambient_music_filenames.end());
206 std::vector<string> combat_music_filenames = findResources("music/combat/*.ogg");
207 std::sort(combat_music_filenames.begin(), combat_music_filenames.end());
208
209 (new GuiLabel(right_container, "PREVIEW_LABEL", tr("Preview Soundtracks"), 30))->addBackground()->setSize(GuiElement::GuiSizeMax, 50);
210
211 GuiListbox* music_list = new GuiListbox(right_container, "MUSIC_PLAY", [this](int index, string value)
212 {
213 soundManager->playMusic(value);
214 });
215
216 for(string filename : ambient_music_filenames)
217 music_list->addEntry(filename.substr(filename.rfind("/") + 1, filename.rfind(".")), filename);
218 for(string filename : combat_music_filenames)
219 music_list->addEntry(filename.substr(filename.rfind("/") + 1, filename.rfind(".")), filename);
220
221 music_list->setSize(GuiElement::GuiSizeMax, 750);
222
223 // Bottom GUI.
224 // Back button.
225 (new GuiButton(this, "BACK", tr("button", "Back"), [this]()
226 {
227 // Close this menu, stop the music, and return to the main menu.
228 destroy();
229 soundManager->stopMusic();
230 returnToMainMenu();
231 }))->setPosition(50, -50, ABottomLeft)->setSize(150, 50);
232 // Save options button.
233 (new GuiButton(this, "SAVE_OPTIONS", tr("options", "Save"), [this]()
234 {
235 if (getenv("HOME"))
236 PreferencesManager::save(string(getenv("HOME")) + "/.emptyepsilon/options.ini");
237 else
238 PreferencesManager::save("options.ini");
239 }))->setPosition(200, -50, ABottomLeft)->setSize(150, 50);
240 }
241
onKey(sf::Event::KeyEvent key,int unicode)242 void OptionsMenu::onKey(sf::Event::KeyEvent key, int unicode)
243 {
244 switch(key.code)
245 {
246 //TODO: This is more generic code and is duplicated.
247 case sf::Keyboard::Escape:
248 case sf::Keyboard::Home:
249 destroy();
250 soundManager->stopMusic();
251 returnToMainMenu();
252 break;
253 default:
254 break;
255 }
256 }
257