1 | // SuperTux |
2 | // Copyright (C) 2015 Hume2 <teratux.mail@gmail.com> |
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 "editor/object_option.hpp" |
18 | |
19 | #include <string> |
20 | #include <vector> |
21 | #include <sstream> |
22 | |
23 | #include "editor/object_menu.hpp" |
24 | #include "gui/menu.hpp" |
25 | #include "object/tilemap.hpp" |
26 | #include "util/gettext.hpp" |
27 | #include "util/writer.hpp" |
28 | #include "video/color.hpp" |
29 | |
30 | namespace { |
31 | |
32 | template<typename T> |
33 | std::string fmt_to_string(const T& v) |
34 | { |
35 | std::ostringstream out; |
36 | out << v; |
37 | return out.str(); |
38 | } |
39 | |
40 | } // namespace |
41 | |
42 | ObjectOption::ObjectOption(const std::string& text, const std::string& key, unsigned int flags) : |
43 | m_text(text), |
44 | m_key(key), |
45 | m_flags(flags) |
46 | { |
47 | } |
48 | |
49 | ObjectOption::~ObjectOption() |
50 | { |
51 | } |
52 | |
53 | BoolObjectOption::BoolObjectOption(const std::string& text, bool* pointer, const std::string& key, |
54 | boost::optional<bool> default_value, |
55 | unsigned int flags) : |
56 | ObjectOption(text, key, flags), |
57 | m_pointer(pointer), |
58 | m_default_value(default_value) |
59 | { |
60 | } |
61 | |
62 | void |
63 | BoolObjectOption::(Menu& ) const |
64 | { |
65 | menu.add_toggle(-1, get_text(), m_pointer); |
66 | } |
67 | |
68 | void |
69 | BoolObjectOption::save(Writer& writer) const |
70 | { |
71 | if (!get_key().empty()) { |
72 | if (m_default_value && *m_default_value == *m_pointer) { |
73 | // skip |
74 | } else { |
75 | writer.write(get_key(), *m_pointer); |
76 | } |
77 | } |
78 | } |
79 | |
80 | std::string |
81 | BoolObjectOption::to_string() const |
82 | { |
83 | return *m_pointer ? _("true" ) : _("false" ); |
84 | } |
85 | |
86 | IntObjectOption::IntObjectOption(const std::string& text, int* pointer, const std::string& key, |
87 | boost::optional<int> default_value, |
88 | unsigned int flags) : |
89 | ObjectOption(text, key, flags), |
90 | m_pointer(pointer), |
91 | m_default_value(default_value) |
92 | { |
93 | } |
94 | |
95 | void |
96 | IntObjectOption::save(Writer& writer) const |
97 | { |
98 | if (!get_key().empty()) { |
99 | if (m_default_value && *m_default_value == *m_pointer) { |
100 | // skip |
101 | } else { |
102 | writer.write(get_key(), *m_pointer); |
103 | } |
104 | } |
105 | } |
106 | |
107 | std::string |
108 | IntObjectOption::to_string() const |
109 | { |
110 | return fmt_to_string(*m_pointer); |
111 | } |
112 | |
113 | void |
114 | IntObjectOption::(Menu& ) const |
115 | { |
116 | menu.add_intfield(get_text(), m_pointer); |
117 | } |
118 | |
119 | RectfObjectOption::RectfObjectOption(const std::string& text, Rectf* pointer, const std::string& key, |
120 | unsigned int flags) : |
121 | ObjectOption(text, key, flags), |
122 | m_pointer(pointer), |
123 | m_width(m_pointer->get_width()), |
124 | m_height(m_pointer->get_height()) |
125 | { |
126 | } |
127 | |
128 | void |
129 | RectfObjectOption::save(Writer& write) const |
130 | { |
131 | write.write("width" , m_width); |
132 | write.write("height" , m_height); |
133 | // write.write("x", &pointer->p1.x); |
134 | // write.write("y", &pointer->p1.y); |
135 | } |
136 | |
137 | std::string |
138 | RectfObjectOption::to_string() const |
139 | { |
140 | std::ostringstream out; |
141 | out << *m_pointer; |
142 | return out.str(); |
143 | } |
144 | |
145 | void |
146 | RectfObjectOption::(Menu& ) const |
147 | { |
148 | menu.add_floatfield(_("Width" ), const_cast<float*>(&m_width)); |
149 | menu.add_floatfield(_("Height" ), const_cast<float*>(&m_height)); |
150 | } |
151 | |
152 | FloatObjectOption::FloatObjectOption(const std::string& text, float* pointer, const std::string& key, |
153 | boost::optional<float> default_value, |
154 | unsigned int flags) : |
155 | ObjectOption(text, key, flags), |
156 | m_pointer(pointer), |
157 | m_default_value(default_value) |
158 | { |
159 | } |
160 | |
161 | void |
162 | FloatObjectOption::save(Writer& writer) const |
163 | { |
164 | if (!get_key().empty()) { |
165 | if (m_default_value && *m_default_value == *m_pointer) { |
166 | // skip |
167 | } else { |
168 | writer.write(get_key(), *m_pointer); |
169 | } |
170 | } |
171 | } |
172 | |
173 | std::string |
174 | FloatObjectOption::to_string() const |
175 | { |
176 | return fmt_to_string(*m_pointer); |
177 | } |
178 | |
179 | void |
180 | FloatObjectOption::(Menu& ) const |
181 | { |
182 | menu.add_floatfield(get_text(), m_pointer); |
183 | } |
184 | |
185 | StringObjectOption::StringObjectOption(const std::string& text, std::string* pointer, const std::string& key, |
186 | boost::optional<std::string> default_value, |
187 | unsigned int flags) : |
188 | ObjectOption(text, key, flags), |
189 | m_pointer(pointer), |
190 | m_default_value(std::move(default_value)) |
191 | { |
192 | } |
193 | |
194 | void |
195 | StringObjectOption::save(Writer& writer) const |
196 | { |
197 | if (!get_key().empty()) { |
198 | if ((m_default_value && *m_default_value == *m_pointer) || m_pointer->empty()) { |
199 | // skip |
200 | } else { |
201 | writer.write(get_key(), *m_pointer, (get_flags() & OPTION_TRANSLATABLE)); |
202 | } |
203 | } |
204 | } |
205 | |
206 | std::string |
207 | StringObjectOption::to_string() const |
208 | { |
209 | return *m_pointer; |
210 | } |
211 | |
212 | void |
213 | StringObjectOption::(Menu& ) const |
214 | { |
215 | menu.add_textfield(get_text(), m_pointer); |
216 | } |
217 | |
218 | StringSelectObjectOption::StringSelectObjectOption(const std::string& text, int* pointer, |
219 | const std::vector<std::string>& select, |
220 | boost::optional<int> default_value, |
221 | const std::string& key, unsigned int flags) : |
222 | ObjectOption(text, key, flags), |
223 | m_pointer(pointer), |
224 | m_select(select), |
225 | m_default_value(default_value) |
226 | { |
227 | } |
228 | |
229 | void |
230 | StringSelectObjectOption::save(Writer& writer) const |
231 | { |
232 | if (!get_key().empty()) { |
233 | if (m_default_value && *m_default_value == *m_pointer) { |
234 | // skip |
235 | } else { |
236 | writer.write(get_key(), *m_pointer); |
237 | } |
238 | } |
239 | } |
240 | |
241 | std::string |
242 | StringSelectObjectOption::to_string() const |
243 | { |
244 | int* selected_id = static_cast<int*>(m_pointer); |
245 | if (*selected_id >= int(m_select.size()) || *selected_id < 0) { |
246 | return _("invalid" ); //Test whether the selected ID is valid |
247 | } else { |
248 | return m_select[*selected_id]; |
249 | } |
250 | } |
251 | |
252 | void |
253 | StringSelectObjectOption::(Menu& ) const |
254 | { |
255 | int& selected_id = *m_pointer; |
256 | if ( selected_id >= static_cast<int>(m_select.size()) || selected_id < 0 ) { |
257 | selected_id = 0; // Set the option to zero when not selectable |
258 | } |
259 | menu.add_string_select(-1, get_text(), m_pointer, m_select); |
260 | } |
261 | |
262 | EnumObjectOption::EnumObjectOption(const std::string& text, int* pointer, |
263 | const std::vector<std::string>& labels, |
264 | const std::vector<std::string>& symbols, |
265 | boost::optional<int> default_value, |
266 | const std::string& key, unsigned int flags) : |
267 | ObjectOption(text, key, flags), |
268 | m_pointer(pointer), |
269 | m_labels(labels), |
270 | m_symbols(symbols), |
271 | m_default_value(default_value) |
272 | { |
273 | } |
274 | |
275 | void |
276 | EnumObjectOption::save(Writer& writer) const |
277 | { |
278 | if (0 <= *m_pointer && *m_pointer < int(m_symbols.size()) && |
279 | !get_key().empty()) |
280 | { |
281 | if (m_default_value && *m_default_value == *m_pointer) { |
282 | // skip |
283 | } else { |
284 | writer.write(get_key(), m_symbols[*m_pointer]); |
285 | } |
286 | } |
287 | } |
288 | |
289 | std::string |
290 | EnumObjectOption::to_string() const |
291 | { |
292 | if (0 <= *m_pointer && *m_pointer < int(m_labels.size())) { |
293 | return m_labels[*m_pointer]; |
294 | } else { |
295 | return _("invalid" ); |
296 | } |
297 | } |
298 | |
299 | void |
300 | EnumObjectOption::(Menu& ) const |
301 | { |
302 | if (*m_pointer >= static_cast<int>(m_labels.size()) || *m_pointer < 0 ) { |
303 | *m_pointer = 0; // Set the option to zero when not selectable |
304 | } |
305 | menu.add_string_select(-1, get_text(), m_pointer, m_labels); |
306 | } |
307 | |
308 | |
309 | ScriptObjectOption::ScriptObjectOption(const std::string& text, std::string* pointer, const std::string& key, |
310 | unsigned int flags) : |
311 | ObjectOption(text, key, flags), |
312 | m_pointer(pointer) |
313 | { |
314 | } |
315 | |
316 | void |
317 | ScriptObjectOption::save(Writer& writer) const |
318 | { |
319 | auto& value = *m_pointer; |
320 | if (!value.empty()) |
321 | { |
322 | if (!get_key().empty()) { |
323 | writer.write(get_key(), value); |
324 | } |
325 | } |
326 | } |
327 | |
328 | std::string |
329 | ScriptObjectOption::to_string() const |
330 | { |
331 | if (!m_pointer->empty()) { |
332 | return "..." ; |
333 | } |
334 | return "" ; |
335 | } |
336 | |
337 | void |
338 | ScriptObjectOption::(Menu& ) const |
339 | { |
340 | menu.add_script(get_text(), m_pointer); |
341 | } |
342 | |
343 | FileObjectOption::FileObjectOption(const std::string& text, std::string* pointer, |
344 | boost::optional<std::string> default_value, |
345 | const std::string& key, |
346 | std::vector<std::string> filter, |
347 | const std::string& basedir, |
348 | unsigned int flags) : |
349 | ObjectOption(text, key, flags), |
350 | m_pointer(pointer), |
351 | m_default_value(std::move(default_value)), |
352 | m_filter(std::move(filter)), |
353 | m_basedir(basedir) |
354 | { |
355 | } |
356 | |
357 | void |
358 | FileObjectOption::save(Writer& writer) const |
359 | { |
360 | if (m_default_value && *m_default_value == *m_pointer) { |
361 | // skip |
362 | } else { |
363 | auto& value = *m_pointer; |
364 | if (!value.empty()) |
365 | { |
366 | if (!get_key().empty()) { |
367 | writer.write(get_key(), value); |
368 | } |
369 | } |
370 | } |
371 | } |
372 | |
373 | std::string |
374 | FileObjectOption::to_string() const |
375 | { |
376 | return *m_pointer; |
377 | } |
378 | |
379 | void |
380 | FileObjectOption::(Menu& ) const |
381 | { |
382 | menu.add_file(get_text(), m_pointer, m_filter, m_basedir); |
383 | } |
384 | |
385 | ColorObjectOption::ColorObjectOption(const std::string& text, Color* pointer, const std::string& key, |
386 | boost::optional<Color> default_value, bool use_alpha, |
387 | unsigned int flags) : |
388 | ObjectOption(text, key, flags), |
389 | m_pointer(pointer), |
390 | m_default_value(std::move(default_value)), |
391 | m_use_alpha(use_alpha) |
392 | { |
393 | } |
394 | |
395 | void |
396 | ColorObjectOption::save(Writer& writer) const |
397 | { |
398 | if (!get_key().empty()) { |
399 | if (m_default_value && *m_default_value == *m_pointer) { |
400 | // skip |
401 | } else { |
402 | auto vec = m_pointer->toVector(); |
403 | if (!m_use_alpha || vec.back() == 1.0f) { |
404 | vec.pop_back(); |
405 | } |
406 | writer.write(get_key(), vec); |
407 | } |
408 | } |
409 | } |
410 | |
411 | std::string |
412 | ColorObjectOption::to_string() const |
413 | { |
414 | return m_pointer->to_string(); |
415 | } |
416 | |
417 | void |
418 | ColorObjectOption::(Menu& ) const |
419 | { |
420 | menu.add_color(get_text(), m_pointer); |
421 | } |
422 | |
423 | BadGuySelectObjectOption::BadGuySelectObjectOption(const std::string& text, std::vector<std::string>* pointer, const std::string& key, |
424 | unsigned int flags) : |
425 | ObjectOption(text, key, flags), |
426 | m_pointer(pointer) |
427 | { |
428 | } |
429 | |
430 | void |
431 | BadGuySelectObjectOption::save(Writer& writer) const |
432 | { |
433 | if (!get_key().empty()) { |
434 | writer.write(get_key(), *m_pointer); |
435 | } |
436 | } |
437 | |
438 | std::string |
439 | BadGuySelectObjectOption::to_string() const |
440 | { |
441 | return fmt_to_string(m_pointer->size()); |
442 | } |
443 | |
444 | void |
445 | BadGuySelectObjectOption::(Menu& ) const |
446 | { |
447 | menu.add_badguy_select(get_text(), m_pointer); |
448 | } |
449 | |
450 | TilesObjectOption::TilesObjectOption(const std::string& text, TileMap* tilemap, const std::string& key, |
451 | unsigned int flags) : |
452 | ObjectOption(text, key, flags), |
453 | m_tilemap(tilemap) |
454 | { |
455 | } |
456 | |
457 | void |
458 | TilesObjectOption::save(Writer& write) const |
459 | { |
460 | write.write("width" , m_tilemap->get_width()); |
461 | write.write("height" , m_tilemap->get_height()); |
462 | write.write("tiles" , m_tilemap->get_tiles(), m_tilemap->get_width()); |
463 | } |
464 | |
465 | std::string |
466 | TilesObjectOption::to_string() const |
467 | { |
468 | return {}; |
469 | } |
470 | |
471 | void |
472 | TilesObjectOption::(Menu& ) const |
473 | { |
474 | } |
475 | |
476 | PathObjectOption::PathObjectOption(const std::string& text, Path* path, const std::string& key, |
477 | unsigned int flags) : |
478 | ObjectOption(text, key, flags), |
479 | m_path(path) |
480 | { |
481 | } |
482 | |
483 | void |
484 | PathObjectOption::save(Writer& write) const |
485 | { |
486 | m_path->save(write); |
487 | } |
488 | |
489 | std::string |
490 | PathObjectOption::to_string() const |
491 | { |
492 | return {}; |
493 | } |
494 | |
495 | void |
496 | PathObjectOption::(Menu& ) const |
497 | { |
498 | } |
499 | |
500 | PathRefObjectOption::PathRefObjectOption(const std::string& text, const std::string& path_ref, const std::string& key, |
501 | unsigned int flags) : |
502 | ObjectOption(text, key, flags), |
503 | m_path_ref(path_ref) |
504 | { |
505 | } |
506 | |
507 | void |
508 | PathRefObjectOption::save(Writer& writer) const |
509 | { |
510 | if (!m_path_ref.empty()) { |
511 | writer.write(get_key(), m_path_ref); |
512 | } |
513 | } |
514 | |
515 | std::string |
516 | PathRefObjectOption::to_string() const |
517 | { |
518 | return m_path_ref; |
519 | } |
520 | |
521 | void |
522 | PathRefObjectOption::(Menu& ) const |
523 | { |
524 | } |
525 | |
526 | SExpObjectOption::SExpObjectOption(const std::string& text, const std::string& key, sexp::Value& value, |
527 | unsigned int flags) : |
528 | ObjectOption(text, key, flags), |
529 | m_sx(value) |
530 | { |
531 | } |
532 | |
533 | void |
534 | SExpObjectOption::save(Writer& writer) const |
535 | { |
536 | if (!m_sx.is_nil()) { |
537 | writer.write(get_key(), m_sx); |
538 | } |
539 | } |
540 | |
541 | std::string |
542 | SExpObjectOption::to_string() const |
543 | { |
544 | return m_sx.str(); |
545 | } |
546 | |
547 | void |
548 | SExpObjectOption::(Menu& ) const |
549 | { |
550 | } |
551 | |
552 | RemoveObjectOption::RemoveObjectOption() : |
553 | ObjectOption(_("Remove" ), "" , 0) |
554 | { |
555 | } |
556 | |
557 | std::string |
558 | RemoveObjectOption::to_string() const |
559 | { |
560 | return {}; |
561 | } |
562 | |
563 | void |
564 | RemoveObjectOption::(Menu& ) const |
565 | { |
566 | menu.add_entry(ObjectMenu::MNID_REMOVE, get_text()); |
567 | } |
568 | |
569 | /* EOF */ |
570 | |