2 // Copyright (C) 2006 Matthias Braun <matze@braunis.de>,
3 // 2007 Ingo Ruhnke <grumbel@gmx.de>
5 // This program is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "control/joystickkeyboardcontroller.hpp"
22 #include "control/joystick_manager.hpp"
23 #include "gui/menu_manager.hpp"
24 #include "lisp/list_iterator.hpp"
25 #include "supertux/console.hpp"
26 #include "supertux/gameconfig.hpp"
27 #include "supertux/menu/joystick_menu.hpp"
28 #include "supertux/menu/keyboard_menu.hpp"
29 #include "supertux/menu/menu_storage.hpp"
30 #include "util/gettext.hpp"
31 #include "util/writer.hpp"
33 JoystickKeyboardController::JoystickKeyboardController() :
34 controller(new Controller),
35 joystick_manager(new JoystickManager(this)),
41 // initialize default keyboard map
42 keymap[SDLK_LEFT] = Controller::LEFT;
43 keymap[SDLK_RIGHT] = Controller::RIGHT;
44 keymap[SDLK_UP] = Controller::UP;
45 keymap[SDLK_DOWN] = Controller::DOWN;
46 keymap[SDLK_SPACE] = Controller::JUMP;
47 keymap[SDLK_LCTRL] = Controller::ACTION;
48 keymap[SDLK_LALT] = Controller::ACTION;
49 keymap[SDLK_ESCAPE] = Controller::PAUSE_MENU;
50 keymap[SDLK_p] = Controller::PAUSE_MENU;
51 keymap[SDLK_PAUSE] = Controller::PAUSE_MENU;
52 keymap[SDLK_RETURN] = Controller::MENU_SELECT;
53 keymap[SDLK_KP_ENTER] = Controller::MENU_SELECT;
54 keymap[SDLK_CARET] = Controller::CONSOLE;
55 keymap[SDLK_DELETE] = Controller::PEEK_LEFT;
56 keymap[SDLK_PAGEDOWN] = Controller::PEEK_RIGHT;
57 keymap[SDLK_HOME] = Controller::PEEK_UP;
58 keymap[SDLK_END] = Controller::PEEK_DOWN;
60 jump_with_up_kbd = false;
63 JoystickKeyboardController::~JoystickKeyboardController()
68 JoystickKeyboardController::get_main_controller()
70 return controller.get();
74 JoystickKeyboardController::read(const Reader& lisp)
76 const lisp::Lisp* keymap_lisp = lisp.get_lisp("keymap");
79 keymap_lisp->get("jump-with-up", jump_with_up_kbd);
80 lisp::ListIterator iter(keymap_lisp);
82 if (iter.item() == "map") {
85 const lisp::Lisp* map = iter.lisp();
87 map->get("control", control);
88 // if (key < SDLK_FIRST || key >= SDLK_LAST) {
89 // log_info << "Invalid key '" << key << "' in keymap" << std::endl;
94 for(i = 0; Controller::controlNames[i] != 0; ++i) {
95 if (control == Controller::controlNames[i])
98 if (Controller::controlNames[i] == 0) {
99 log_info << "Invalid control '" << control << "' in keymap" << std::endl;
102 keymap[SDL_Keycode(key)] = Control(i);
107 const lisp::Lisp* joystick_lisp = lisp.get_lisp(_("joystick"));
110 joystick_manager->read(joystick_lisp);
115 JoystickKeyboardController::write(Writer& writer)
117 writer.start_list("keymap");
118 writer.write("jump-with-up", jump_with_up_kbd);
119 for(KeyMap::iterator i = keymap.begin(); i != keymap.end(); ++i) {
120 writer.start_list("map");
121 writer.write("key", (int) i->first);
122 writer.write("control", Controller::controlNames[i->second]);
123 writer.end_list("map");
125 writer.end_list("keymap");
127 writer.start_list("joystick");
128 joystick_manager->write(writer);
129 writer.end_list("joystick");
133 JoystickKeyboardController::update()
135 controller->update();
139 JoystickKeyboardController::reset()
145 JoystickKeyboardController::process_event(const SDL_Event& event)
149 process_text_input_event(event.text);
154 process_key_event(event.key);
157 case SDL_JOYAXISMOTION:
158 joystick_manager->process_axis_event(event.jaxis);
161 case SDL_JOYHATMOTION:
162 joystick_manager->process_hat_event(event.jhat);
165 case SDL_JOYBUTTONDOWN:
166 case SDL_JOYBUTTONUP:
167 joystick_manager->process_button_event(event.jbutton);
170 case SDL_JOYDEVICEADDED:
171 joystick_manager->on_joystick_added(event.jdevice.which);
174 case SDL_JOYDEVICEREMOVED:
175 joystick_manager->on_joystick_removed(event.jdevice.which);
178 case SDL_CONTROLLERBUTTONDOWN:
179 std::cout << "SDL_CONTROLLERBUTTONDOWN" << std::endl;
182 case SDL_CONTROLLERBUTTONUP:
183 std::cout << "SDL_CONTROLLERBUTTONUP" << std::endl;
186 case SDL_CONTROLLERDEVICEADDED:
187 // ignored, handled in SDL_JOYDEVICEADDED
188 std::cout << "SDL_CONTROLLERDEVICEADDED" << std::endl;
191 case SDL_CONTROLLERDEVICEREMOVED:
192 // ignored, handled in SDL_JOYDEVICEREMOVED
193 std::cout << "SDL_CONTROLLERDEVICEREMOVED" << std::endl;
196 case SDL_CONTROLLERDEVICEREMAPPED:
197 std::cout << "SDL_CONTROLLERDEVICEREMAPPED" << std::endl;
206 JoystickKeyboardController::process_text_input_event(const SDL_TextInputEvent& event)
208 if (Console::instance->hasFocus()) {
209 for(int i = 0; event.text[i] != '\0'; ++i)
211 Console::instance->input(event.text[i]);
217 JoystickKeyboardController::process_key_event(const SDL_KeyboardEvent& event)
219 KeyMap::iterator key_mapping = keymap.find(event.keysym.sym);
221 // if console key was pressed: toggle console
222 if ((key_mapping != keymap.end()) && (key_mapping->second == Controller::CONSOLE)) {
223 if (event.type == SDL_KEYDOWN)
224 Console::instance->toggle();
226 if (Console::instance->hasFocus()) {
227 // if console is open: send key there
228 process_console_key_event(event);
229 } else if (MenuManager::current()) {
230 // if menu mode: send key there
231 process_menu_key_event(event);
232 } else if (key_mapping == keymap.end()) {
233 // default action: update controls
234 //log_debug << "Key " << event.key.SDL_Keycode.sym << " is unbound" << std::endl;
236 Control control = key_mapping->second;
237 bool value = (event.type == SDL_KEYDOWN);
238 controller->set_control(control, value);
239 if (jump_with_up_kbd && control == Controller::UP){
240 controller->set_control(Controller::JUMP, value);
247 JoystickKeyboardController::process_console_key_event(const SDL_KeyboardEvent& event)
249 if (event.type != SDL_KEYDOWN) return;
251 switch (event.keysym.sym) {
253 Console::instance->enter();
256 Console::instance->backspace();
259 Console::instance->autocomplete();
262 Console::instance->scroll(-1);
265 Console::instance->scroll(+1);
268 Console::instance->move_cursor(-65535);
271 Console::instance->move_cursor(+65535);
274 Console::instance->show_history(-1);
277 Console::instance->show_history(+1);
280 Console::instance->move_cursor(-1);
283 Console::instance->move_cursor(+1);
291 JoystickKeyboardController::process_menu_key_event(const SDL_KeyboardEvent& event)
293 // wait for key mode?
294 if (wait_for_key >= 0) {
295 if (event.type == SDL_KEYUP)
298 if (event.keysym.sym != SDLK_ESCAPE
299 && event.keysym.sym != SDLK_PAUSE) {
300 bind_key(event.keysym.sym, Control(wait_for_key));
303 MenuStorage::get_key_options_menu()->update();
307 if (joystick_manager->wait_for_joystick >= 0) {
308 if (event.keysym.sym == SDLK_ESCAPE) {
310 MenuStorage::get_joystick_options_menu()->update();
311 joystick_manager->wait_for_joystick = -1;
317 /* we use default keys when the menu is open (to avoid problems when
318 * redefining keys to invalid settings
320 switch(event.keysym.sym) {
322 control = Controller::UP;
325 control = Controller::DOWN;
328 control = Controller::LEFT;
331 control = Controller::RIGHT;
336 control = Controller::MENU_SELECT;
340 control = Controller::PAUSE_MENU;
347 controller->set_control(control, (event.type == SDL_KEYDOWN));
351 JoystickKeyboardController::bind_key(SDL_Keycode key, Control control)
353 // remove all previous mappings for that control and for that key
354 for(KeyMap::iterator i = keymap.begin();
355 i != keymap.end(); /* no ++i */) {
356 if (i->second == control) {
357 KeyMap::iterator e = i;
365 KeyMap::iterator i = keymap.find(key);
366 if (i != keymap.end())
370 keymap[key] = control;
374 JoystickKeyboardController::reversemap_key(Control c)
376 for(KeyMap::iterator i = keymap.begin(); i != keymap.end(); ++i) {