1// SuperTux - A Jump'n Run
2// Copyright (C) 2006 Matthias Braun <matze@braunis.de>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (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, see <http://www.gnu.org/licenses/>.
16
17#include "supertux/gameconfig.hpp"
18
19#include "util/reader_collection.hpp"
20#include "util/reader_document.hpp"
21#include "util/reader_mapping.hpp"
22#include "util/writer.hpp"
23#include "util/log.hpp"
24
25Config::Config() :
26 profile(1),
27 fullscreen_size(0, 0),
28 fullscreen_refresh_rate(0),
29 window_size(1280, 800),
30 window_resizable(true),
31 aspect_size(0, 0), // auto detect
32 magnification(0.0f),
33 use_fullscreen(false),
34 video(VideoSystem::VIDEO_AUTO),
35 try_vsync(true),
36 show_fps(false),
37 show_player_pos(false),
38 sound_enabled(true),
39 music_enabled(true),
40 sound_volume(100),
41 music_volume(50),
42 random_seed(0), // set by time(), by default (unless in config)
43 enable_script_debugger(false),
44 start_demo(),
45 record_demo(),
46 tux_spawn_pos(),
47 locale(),
48 keyboard_config(),
49 joystick_config(),
50 addons(),
51 developer_mode(false),
52 christmas_mode(false),
53 transitions_enabled(true),
54 confirmation_dialog(false),
55 pause_on_focusloss(true),
56 repository_url()
57{
58}
59
60void
61Config::load()
62{
63 auto doc = ReaderDocument::from_file("config");
64 auto root = doc.get_root();
65 if (root.get_name() != "supertux-config")
66 {
67 throw std::runtime_error("File is not a supertux-config file");
68 }
69
70 auto config_mapping = root.get_mapping();
71 config_mapping.get("profile", profile);
72 config_mapping.get("show_fps", show_fps);
73 config_mapping.get("show_player_pos", show_player_pos);
74 config_mapping.get("developer", developer_mode);
75 config_mapping.get("confirmation_dialog", confirmation_dialog);
76 config_mapping.get("pause_on_focusloss", pause_on_focusloss);
77
78 if (is_christmas()) {
79 if (!config_mapping.get("christmas", christmas_mode))
80 {
81 christmas_mode = true;
82 }
83 }
84 config_mapping.get("transitions_enabled", transitions_enabled);
85 config_mapping.get("locale", locale);
86 config_mapping.get("random_seed", random_seed);
87 config_mapping.get("repository_url", repository_url);
88
89 boost::optional<ReaderMapping> config_video_mapping;
90 if (config_mapping.get("video", config_video_mapping))
91 {
92 config_video_mapping->get("fullscreen", use_fullscreen);
93 std::string video_string;
94 config_video_mapping->get("video", video_string);
95 video = VideoSystem::get_video_system(video_string);
96 config_video_mapping->get("vsync", try_vsync);
97
98 config_video_mapping->get("fullscreen_width", fullscreen_size.width);
99 config_video_mapping->get("fullscreen_height", fullscreen_size.height);
100 if (fullscreen_size.width < 0 || fullscreen_size.height < 0)
101 {
102 // Somehow, an invalid size got entered into the config file,
103 // let's use the "auto" setting instead.
104 fullscreen_size = Size(0, 0);
105 }
106 config_video_mapping->get("fullscreen_refresh_rate", fullscreen_refresh_rate);
107
108 config_video_mapping->get("window_width", window_size.width);
109 config_video_mapping->get("window_height", window_size.height);
110
111 config_video_mapping->get("window_resizable", window_resizable);
112
113 config_video_mapping->get("aspect_width", aspect_size.width);
114 config_video_mapping->get("aspect_height", aspect_size.height);
115
116 config_video_mapping->get("magnification", magnification);
117 }
118
119 boost::optional<ReaderMapping> config_audio_mapping;
120 if (config_mapping.get("audio", config_audio_mapping))
121 {
122 config_audio_mapping->get("sound_enabled", sound_enabled);
123 config_audio_mapping->get("music_enabled", music_enabled);
124 config_audio_mapping->get("sound_volume", sound_volume);
125 config_audio_mapping->get("music_volume", music_volume);
126 }
127
128 boost::optional<ReaderMapping> config_control_mapping;
129 if (config_mapping.get("control", config_control_mapping))
130 {
131 boost::optional<ReaderMapping> keymap_mapping;
132 if (config_control_mapping->get("keymap", keymap_mapping))
133 {
134 keyboard_config.read(*keymap_mapping);
135 }
136
137 boost::optional<ReaderMapping> joystick_mapping;
138 if (config_control_mapping->get("joystick", joystick_mapping))
139 {
140 joystick_config.read(*joystick_mapping);
141 }
142 }
143
144 boost::optional<ReaderCollection> config_addons_mapping;
145 if (config_mapping.get("addons", config_addons_mapping))
146 {
147 for (auto const& addon_node : config_addons_mapping->get_objects())
148 {
149 if (addon_node.get_name() == "addon")
150 {
151 auto addon = addon_node.get_mapping();
152
153 std::string id;
154 bool enabled = false;
155 if (addon.get("id", id) &&
156 addon.get("enabled", enabled))
157 {
158 addons.push_back({id, enabled});
159 }
160 }
161 else
162 {
163 log_warning << "Unknown token in config file: " << addon_node.get_name() << std::endl;
164 }
165 }
166 }
167}
168
169void
170Config::save()
171{
172 Writer writer("config");
173
174 writer.start_list("supertux-config");
175
176 writer.write("profile", profile);
177 writer.write("show_fps", show_fps);
178 writer.write("show_player_pos", show_player_pos);
179 writer.write("developer", developer_mode);
180 writer.write("confirmation_dialog", confirmation_dialog);
181 writer.write("pause_on_focusloss", pause_on_focusloss);
182 if (is_christmas()) {
183 writer.write("christmas", christmas_mode);
184 }
185 writer.write("transitions_enabled", transitions_enabled);
186 writer.write("locale", locale);
187 writer.write("repository_url", repository_url);
188
189 writer.start_list("video");
190 writer.write("fullscreen", use_fullscreen);
191 if (video == VideoSystem::VIDEO_NULL) {
192 // don't save NULL renderer to config as starting SuperTux without
193 // getting a window is rather confusing
194 } else {
195 writer.write("video", VideoSystem::get_video_string(video));
196 }
197 writer.write("vsync", try_vsync);
198
199 writer.write("fullscreen_width", fullscreen_size.width);
200 writer.write("fullscreen_height", fullscreen_size.height);
201 writer.write("fullscreen_refresh_rate", fullscreen_refresh_rate);
202
203 writer.write("window_width", window_size.width);
204 writer.write("window_height", window_size.height);
205
206 writer.write("window_resizable", window_resizable);
207
208 writer.write("aspect_width", aspect_size.width);
209 writer.write("aspect_height", aspect_size.height);
210
211 writer.write("magnification", magnification);
212
213 writer.end_list("video");
214
215 writer.start_list("audio");
216 writer.write("sound_enabled", sound_enabled);
217 writer.write("music_enabled", music_enabled);
218 writer.write("sound_volume", sound_volume);
219 writer.write("music_volume", music_volume);
220 writer.end_list("audio");
221
222 writer.start_list("control");
223 {
224 writer.start_list("keymap");
225 keyboard_config.write(writer);
226 writer.end_list("keymap");
227
228 writer.start_list("joystick");
229 joystick_config.write(writer);
230 writer.end_list("joystick");
231 }
232 writer.end_list("control");
233
234 writer.start_list("addons");
235 for (const auto& addon : addons)
236 {
237 writer.start_list("addon");
238 writer.write("id", addon.id);
239 writer.write("enabled", addon.enabled);
240 writer.end_list("addon");
241 }
242 writer.end_list("addons");
243
244 writer.end_list("supertux-config");
245}
246
247/* EOF */
248