1 | // SuperTux |
2 | // Copyright (C) 2014 Ingo Ruhnke <grumbel@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 "control/keyboard_config.hpp" |
18 | |
19 | #include <boost/optional.hpp> |
20 | |
21 | #include "util/log.hpp" |
22 | #include "util/reader_mapping.hpp" |
23 | #include "util/writer.hpp" |
24 | |
25 | KeyboardConfig::KeyboardConfig() : |
26 | m_keymap(), |
27 | m_jump_with_up_kbd(false) |
28 | { |
29 | // initialize default keyboard map |
30 | m_keymap[SDLK_LEFT] = Control::LEFT; |
31 | m_keymap[SDLK_RIGHT] = Control::RIGHT; |
32 | m_keymap[SDLK_UP] = Control::UP; |
33 | m_keymap[SDLK_DOWN] = Control::DOWN; |
34 | m_keymap[SDLK_SPACE] = Control::JUMP; |
35 | m_keymap[SDLK_LCTRL] = Control::ACTION; |
36 | m_keymap[SDLK_LALT] = Control::ACTION; |
37 | m_keymap[SDLK_ESCAPE] = Control::ESCAPE; |
38 | m_keymap[SDLK_p] = Control::START; |
39 | m_keymap[SDLK_PAUSE] = Control::START; |
40 | m_keymap[SDLK_RETURN] = Control::MENU_SELECT; |
41 | m_keymap[SDLK_KP_ENTER] = Control::MENU_SELECT; |
42 | m_keymap[SDLK_CARET] = Control::CONSOLE; |
43 | m_keymap[SDLK_DELETE] = Control::PEEK_LEFT; |
44 | m_keymap[SDLK_PAGEDOWN] = Control::PEEK_RIGHT; |
45 | m_keymap[SDLK_HOME] = Control::PEEK_UP; |
46 | m_keymap[SDLK_END] = Control::PEEK_DOWN; |
47 | m_keymap[SDLK_F1] = Control::CHEAT_MENU; |
48 | m_keymap[SDLK_F2] = Control::DEBUG_MENU; |
49 | m_keymap[SDLK_BACKSPACE]= Control::REMOVE; |
50 | } |
51 | |
52 | void |
53 | KeyboardConfig::read(const ReaderMapping& keymap_mapping) |
54 | { |
55 | // keycode values changed between SDL1 and SDL2, so we skip old SDL1 |
56 | // based values and use the defaults instead on the first read of |
57 | // the config file |
58 | bool config_is_sdl2 = false; |
59 | keymap_mapping.get("sdl2" , config_is_sdl2); |
60 | if (config_is_sdl2) |
61 | { |
62 | keymap_mapping.get("jump-with-up" , m_jump_with_up_kbd); |
63 | |
64 | auto iter = keymap_mapping.get_iter(); |
65 | while (iter.next()) |
66 | { |
67 | if (iter.get_key() == "map" ) |
68 | { |
69 | int key = -1; |
70 | auto map = iter.as_mapping(); |
71 | map.get("key" , key); |
72 | |
73 | std::string control_text; |
74 | map.get("control" , control_text); |
75 | |
76 | const boost::optional<Control> maybe_control = Control_from_string(control_text); |
77 | if (!maybe_control) { |
78 | log_info << "Invalid control '" << control_text << "' in keymap" << std::endl; |
79 | } else { |
80 | const Control control = *maybe_control; |
81 | m_keymap[static_cast<SDL_Keycode>(key)] = control; |
82 | } |
83 | } |
84 | } |
85 | } |
86 | } |
87 | |
88 | void |
89 | KeyboardConfig::bind_key(SDL_Keycode key, Control control) |
90 | { |
91 | // remove all previous mappings for that control and for that key |
92 | for (auto i = m_keymap.begin(); i != m_keymap.end(); /* no ++i */) |
93 | { |
94 | if (i->second == control) |
95 | { |
96 | auto e = i; |
97 | ++i; |
98 | m_keymap.erase(e); |
99 | } |
100 | else |
101 | { |
102 | ++i; |
103 | } |
104 | } |
105 | |
106 | auto i = m_keymap.find(key); |
107 | if (i != m_keymap.end()) |
108 | m_keymap.erase(i); |
109 | |
110 | // add new mapping |
111 | m_keymap[key] = control; |
112 | } |
113 | |
114 | SDL_Keycode |
115 | KeyboardConfig::reversemap_key(Control c) const |
116 | { |
117 | for (const auto& i : m_keymap) |
118 | { |
119 | if (i.second == c) |
120 | { |
121 | return i.first; |
122 | } |
123 | } |
124 | |
125 | return SDLK_UNKNOWN; |
126 | } |
127 | |
128 | void |
129 | KeyboardConfig::write(Writer& writer) |
130 | { |
131 | // this flag handles the transition from SDL1 to SDL2, as keycodes |
132 | // are incompatible between the two, if it's not set an old SDL1 |
133 | // config file is assumed and controls are reset to default |
134 | writer.write("sdl2" , true); |
135 | |
136 | writer.write("jump-with-up" , m_jump_with_up_kbd); |
137 | |
138 | for (const auto& i : m_keymap) |
139 | { |
140 | writer.start_list("map" ); |
141 | writer.write("key" , static_cast<int>(i.first)); |
142 | writer.write("control" , Control_to_string(i.second)); |
143 | writer.end_list("map" ); |
144 | } |
145 | } |
146 | |
147 | /* EOF */ |
148 | |