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
30namespace {
31
32template<typename T>
33std::string fmt_to_string(const T& v)
34{
35 std::ostringstream out;
36 out << v;
37 return out.str();
38}
39
40} // namespace
41
42ObjectOption::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
49ObjectOption::~ObjectOption()
50{
51}
52
53BoolObjectOption::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
62void
63BoolObjectOption::add_to_menu(Menu& menu) const
64{
65 menu.add_toggle(-1, get_text(), m_pointer);
66}
67
68void
69BoolObjectOption::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
80std::string
81BoolObjectOption::to_string() const
82{
83 return *m_pointer ? _("true") : _("false");
84}
85
86IntObjectOption::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
95void
96IntObjectOption::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
107std::string
108IntObjectOption::to_string() const
109{
110 return fmt_to_string(*m_pointer);
111}
112
113void
114IntObjectOption::add_to_menu(Menu& menu) const
115{
116 menu.add_intfield(get_text(), m_pointer);
117}
118
119RectfObjectOption::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
128void
129RectfObjectOption::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
137std::string
138RectfObjectOption::to_string() const
139{
140 std::ostringstream out;
141 out << *m_pointer;
142 return out.str();
143}
144
145void
146RectfObjectOption::add_to_menu(Menu& 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
152FloatObjectOption::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
161void
162FloatObjectOption::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
173std::string
174FloatObjectOption::to_string() const
175{
176 return fmt_to_string(*m_pointer);
177}
178
179void
180FloatObjectOption::add_to_menu(Menu& menu) const
181{
182 menu.add_floatfield(get_text(), m_pointer);
183}
184
185StringObjectOption::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
194void
195StringObjectOption::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
206std::string
207StringObjectOption::to_string() const
208{
209 return *m_pointer;
210}
211
212void
213StringObjectOption::add_to_menu(Menu& menu) const
214{
215 menu.add_textfield(get_text(), m_pointer);
216}
217
218StringSelectObjectOption::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
229void
230StringSelectObjectOption::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
241std::string
242StringSelectObjectOption::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
252void
253StringSelectObjectOption::add_to_menu(Menu& 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
262EnumObjectOption::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
275void
276EnumObjectOption::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
289std::string
290EnumObjectOption::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
299void
300EnumObjectOption::add_to_menu(Menu& 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
309ScriptObjectOption::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
316void
317ScriptObjectOption::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
328std::string
329ScriptObjectOption::to_string() const
330{
331 if (!m_pointer->empty()) {
332 return "...";
333 }
334 return "";
335}
336
337void
338ScriptObjectOption::add_to_menu(Menu& menu) const
339{
340 menu.add_script(get_text(), m_pointer);
341}
342
343FileObjectOption::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
357void
358FileObjectOption::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
373std::string
374FileObjectOption::to_string() const
375{
376 return *m_pointer;
377}
378
379void
380FileObjectOption::add_to_menu(Menu& menu) const
381{
382 menu.add_file(get_text(), m_pointer, m_filter, m_basedir);
383}
384
385ColorObjectOption::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
395void
396ColorObjectOption::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
411std::string
412ColorObjectOption::to_string() const
413{
414 return m_pointer->to_string();
415}
416
417void
418ColorObjectOption::add_to_menu(Menu& menu) const
419{
420 menu.add_color(get_text(), m_pointer);
421}
422
423BadGuySelectObjectOption::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
430void
431BadGuySelectObjectOption::save(Writer& writer) const
432{
433 if (!get_key().empty()) {
434 writer.write(get_key(), *m_pointer);
435 }
436}
437
438std::string
439BadGuySelectObjectOption::to_string() const
440{
441 return fmt_to_string(m_pointer->size());
442}
443
444void
445BadGuySelectObjectOption::add_to_menu(Menu& menu) const
446{
447 menu.add_badguy_select(get_text(), m_pointer);
448}
449
450TilesObjectOption::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
457void
458TilesObjectOption::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
465std::string
466TilesObjectOption::to_string() const
467{
468 return {};
469}
470
471void
472TilesObjectOption::add_to_menu(Menu& menu) const
473{
474}
475
476PathObjectOption::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
483void
484PathObjectOption::save(Writer& write) const
485{
486 m_path->save(write);
487}
488
489std::string
490PathObjectOption::to_string() const
491{
492 return {};
493}
494
495void
496PathObjectOption::add_to_menu(Menu& menu) const
497{
498}
499
500PathRefObjectOption::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
507void
508PathRefObjectOption::save(Writer& writer) const
509{
510 if (!m_path_ref.empty()) {
511 writer.write(get_key(), m_path_ref);
512 }
513}
514
515std::string
516PathRefObjectOption::to_string() const
517{
518 return m_path_ref;
519}
520
521void
522PathRefObjectOption::add_to_menu(Menu& menu) const
523{
524}
525
526SExpObjectOption::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
533void
534SExpObjectOption::save(Writer& writer) const
535{
536 if (!m_sx.is_nil()) {
537 writer.write(get_key(), m_sx);
538 }
539}
540
541std::string
542SExpObjectOption::to_string() const
543{
544 return m_sx.str();
545}
546
547void
548SExpObjectOption::add_to_menu(Menu& menu) const
549{
550}
551
552RemoveObjectOption::RemoveObjectOption() :
553 ObjectOption(_("Remove"), "", 0)
554{
555}
556
557std::string
558RemoveObjectOption::to_string() const
559{
560 return {};
561}
562
563void
564RemoveObjectOption::add_to_menu(Menu& menu) const
565{
566 menu.add_entry(ObjectMenu::MNID_REMOVE, get_text());
567}
568
569/* EOF */
570