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 "control/game_controller_manager.hpp"
24 #include "gui/menu_manager.hpp"
25 #include "lisp/list_iterator.hpp"
26 #include "supertux/console.hpp"
27 #include "supertux/gameconfig.hpp"
28 #include "supertux/menu/joystick_menu.hpp"
29 #include "supertux/menu/keyboard_menu.hpp"
30 #include "supertux/menu/menu_storage.hpp"
31 #include "util/gettext.hpp"
32 #include "util/writer.hpp"
34 JoystickKeyboardController::JoystickKeyboardController() :
35 controller(new Controller),
36 m_use_game_controller(true),
37 joystick_manager(new JoystickManager(this)),
38 game_controller_manager(new GameControllerManager(this)),
43 // initialize default keyboard map
44 keymap[SDLK_LEFT] = Controller::LEFT;
45 keymap[SDLK_RIGHT] = Controller::RIGHT;
46 keymap[SDLK_UP] = Controller::UP;
47 keymap[SDLK_DOWN] = Controller::DOWN;
48 keymap[SDLK_SPACE] = Controller::JUMP;
49 keymap[SDLK_LCTRL] = Controller::ACTION;
50 keymap[SDLK_LALT] = Controller::ACTION;
51 keymap[SDLK_ESCAPE] = Controller::PAUSE_MENU;
52 keymap[SDLK_p] = Controller::PAUSE_MENU;
53 keymap[SDLK_PAUSE] = Controller::PAUSE_MENU;
54 keymap[SDLK_RETURN] = Controller::MENU_SELECT;
55 keymap[SDLK_KP_ENTER] = Controller::MENU_SELECT;
56 keymap[SDLK_CARET] = Controller::CONSOLE;
57 keymap[SDLK_DELETE] = Controller::PEEK_LEFT;
58 keymap[SDLK_PAGEDOWN] = Controller::PEEK_RIGHT;
59 keymap[SDLK_HOME] = Controller::PEEK_UP;
60 keymap[SDLK_END] = Controller::PEEK_DOWN;
62 jump_with_up_kbd = false;
65 JoystickKeyboardController::~JoystickKeyboardController()
70 JoystickKeyboardController::get_main_controller()
72 return controller.get();
76 JoystickKeyboardController::read(const Reader& lisp)
78 const lisp::Lisp* keymap_lisp = lisp.get_lisp("keymap");
81 keymap_lisp->get("jump-with-up", jump_with_up_kbd);
82 lisp::ListIterator iter(keymap_lisp);
84 if (iter.item() == "map") {
87 const lisp::Lisp* map = iter.lisp();
89 map->get("control", control);
92 for(i = 0; Controller::controlNames[i] != 0; ++i) {
93 if (control == Controller::controlNames[i])
96 if (Controller::controlNames[i] == 0) {
97 log_info << "Invalid control '" << control << "' in keymap" << std::endl;
100 keymap[SDL_Keycode(key)] = Control(i);
105 const lisp::Lisp* joystick_lisp = lisp.get_lisp(_("joystick"));
108 joystick_manager->read(joystick_lisp);
113 JoystickKeyboardController::write(Writer& writer)
115 writer.start_list("keymap");
116 writer.write("jump-with-up", jump_with_up_kbd);
117 for(KeyMap::iterator i = keymap.begin(); i != keymap.end(); ++i) {
118 writer.start_list("map");
119 writer.write("key", (int) i->first);
120 writer.write("control", Controller::controlNames[i->second]);
121 writer.end_list("map");
123 writer.end_list("keymap");
125 writer.start_list("joystick");
126 joystick_manager->write(writer);
127 writer.end_list("joystick");
131 JoystickKeyboardController::update()
133 controller->update();
137 JoystickKeyboardController::reset()
143 JoystickKeyboardController::process_event(const SDL_Event& event)
147 process_text_input_event(event.text);
152 process_key_event(event.key);
155 case SDL_JOYAXISMOTION:
156 if (!m_use_game_controller) joystick_manager->process_axis_event(event.jaxis);
159 case SDL_JOYHATMOTION:
160 if (!m_use_game_controller) joystick_manager->process_hat_event(event.jhat);
163 case SDL_JOYBUTTONDOWN:
164 case SDL_JOYBUTTONUP:
165 if (!m_use_game_controller) joystick_manager->process_button_event(event.jbutton);
168 case SDL_JOYDEVICEADDED:
169 if (!m_use_game_controller) joystick_manager->on_joystick_added(event.jdevice.which);
172 case SDL_JOYDEVICEREMOVED:
173 if (!m_use_game_controller) joystick_manager->on_joystick_removed(event.jdevice.which);
176 case SDL_CONTROLLERAXISMOTION:
177 if (m_use_game_controller) game_controller_manager->process_axis_event(event.caxis);
180 case SDL_CONTROLLERBUTTONDOWN:
181 if (m_use_game_controller) game_controller_manager->process_button_event(event.cbutton);
184 case SDL_CONTROLLERBUTTONUP:
185 if (m_use_game_controller) game_controller_manager->process_button_event(event.cbutton);
188 case SDL_CONTROLLERDEVICEADDED:
189 std::cout << "SDL_CONTROLLERDEVICEADDED" << std::endl;
190 if (m_use_game_controller) game_controller_manager->on_controller_added(event.cdevice.which);
193 case SDL_CONTROLLERDEVICEREMOVED:
194 std::cout << "SDL_CONTROLLERDEVICEREMOVED" << std::endl;
195 if (m_use_game_controller) game_controller_manager->on_controller_removed(event.cdevice.which);
198 case SDL_CONTROLLERDEVICEREMAPPED:
199 std::cout << "SDL_CONTROLLERDEVICEREMAPPED" << std::endl;
208 JoystickKeyboardController::process_text_input_event(const SDL_TextInputEvent& event)
210 if (Console::instance->hasFocus()) {
211 for(int i = 0; event.text[i] != '\0'; ++i)
213 Console::instance->input(event.text[i]);
219 JoystickKeyboardController::process_key_event(const SDL_KeyboardEvent& event)
221 KeyMap::iterator key_mapping = keymap.find(event.keysym.sym);
223 // if console key was pressed: toggle console
224 if ((key_mapping != keymap.end()) && (key_mapping->second == Controller::CONSOLE)) {
225 if (event.type == SDL_KEYDOWN)
226 Console::instance->toggle();
228 if (Console::instance->hasFocus()) {
229 // if console is open: send key there
230 process_console_key_event(event);
231 } else if (MenuManager::current()) {
232 // if menu mode: send key there
233 process_menu_key_event(event);
234 } else if (key_mapping == keymap.end()) {
235 // default action: update controls
236 //log_debug << "Key " << event.key.SDL_Keycode.sym << " is unbound" << std::endl;
238 Control control = key_mapping->second;
239 bool value = (event.type == SDL_KEYDOWN);
240 controller->set_control(control, value);
241 if (jump_with_up_kbd && control == Controller::UP){
242 controller->set_control(Controller::JUMP, value);
249 JoystickKeyboardController::process_console_key_event(const SDL_KeyboardEvent& event)
251 if (event.type != SDL_KEYDOWN) return;
253 switch (event.keysym.sym) {
255 Console::instance->enter();
258 Console::instance->backspace();
261 Console::instance->autocomplete();
264 Console::instance->scroll(-1);
267 Console::instance->scroll(+1);
270 Console::instance->move_cursor(-65535);
273 Console::instance->move_cursor(+65535);
276 Console::instance->show_history(-1);
279 Console::instance->show_history(+1);
282 Console::instance->move_cursor(-1);
285 Console::instance->move_cursor(+1);
293 JoystickKeyboardController::process_menu_key_event(const SDL_KeyboardEvent& event)
295 // wait for key mode?
296 if (wait_for_key >= 0) {
297 if (event.type == SDL_KEYUP)
300 if (event.keysym.sym != SDLK_ESCAPE
301 && event.keysym.sym != SDLK_PAUSE) {
302 bind_key(event.keysym.sym, Control(wait_for_key));
305 MenuStorage::get_key_options_menu()->update();
309 if (joystick_manager->wait_for_joystick >= 0) {
310 if (event.keysym.sym == SDLK_ESCAPE) {
312 MenuStorage::get_joystick_options_menu()->update();
313 joystick_manager->wait_for_joystick = -1;
319 /* we use default keys when the menu is open (to avoid problems when
320 * redefining keys to invalid settings
322 switch(event.keysym.sym) {
324 control = Controller::UP;
327 control = Controller::DOWN;
330 control = Controller::LEFT;
333 control = Controller::RIGHT;
338 control = Controller::MENU_SELECT;
342 control = Controller::PAUSE_MENU;
349 controller->set_control(control, (event.type == SDL_KEYDOWN));
353 JoystickKeyboardController::bind_key(SDL_Keycode key, Control control)
355 // remove all previous mappings for that control and for that key
356 for(KeyMap::iterator i = keymap.begin();
357 i != keymap.end(); /* no ++i */) {
358 if (i->second == control) {
359 KeyMap::iterator e = i;
367 KeyMap::iterator i = keymap.find(key);
368 if (i != keymap.end())
372 keymap[key] = control;
376 JoystickKeyboardController::reversemap_key(Control c)
378 for(KeyMap::iterator i = keymap.begin(); i != keymap.end(); ++i) {