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);
90 // if (key < SDLK_FIRST || key >= SDLK_LAST) {
91 // log_info << "Invalid key '" << key << "' in keymap" << std::endl;
96 for(i = 0; Controller::controlNames[i] != 0; ++i) {
97 if (control == Controller::controlNames[i])
100 if (Controller::controlNames[i] == 0) {
101 log_info << "Invalid control '" << control << "' in keymap" << std::endl;
104 keymap[SDL_Keycode(key)] = Control(i);
109 const lisp::Lisp* joystick_lisp = lisp.get_lisp(_("joystick"));
112 joystick_manager->read(joystick_lisp);
117 JoystickKeyboardController::write(Writer& writer)
119 writer.start_list("keymap");
120 writer.write("jump-with-up", jump_with_up_kbd);
121 for(KeyMap::iterator i = keymap.begin(); i != keymap.end(); ++i) {
122 writer.start_list("map");
123 writer.write("key", (int) i->first);
124 writer.write("control", Controller::controlNames[i->second]);
125 writer.end_list("map");
127 writer.end_list("keymap");
129 writer.start_list("joystick");
130 joystick_manager->write(writer);
131 writer.end_list("joystick");
135 JoystickKeyboardController::update()
137 controller->update();
141 JoystickKeyboardController::reset()
147 JoystickKeyboardController::process_event(const SDL_Event& event)
151 process_text_input_event(event.text);
156 process_key_event(event.key);
159 case SDL_JOYAXISMOTION:
160 if (!m_use_game_controller) joystick_manager->process_axis_event(event.jaxis);
163 case SDL_JOYHATMOTION:
164 if (!m_use_game_controller) joystick_manager->process_hat_event(event.jhat);
167 case SDL_JOYBUTTONDOWN:
168 case SDL_JOYBUTTONUP:
169 if (!m_use_game_controller) joystick_manager->process_button_event(event.jbutton);
172 case SDL_JOYDEVICEADDED:
173 if (!m_use_game_controller) joystick_manager->on_joystick_added(event.jdevice.which);
176 case SDL_JOYDEVICEREMOVED:
177 if (!m_use_game_controller) joystick_manager->on_joystick_removed(event.jdevice.which);
180 case SDL_CONTROLLERAXISMOTION:
181 if (m_use_game_controller) game_controller_manager->process_axis_event(event.caxis);
184 case SDL_CONTROLLERBUTTONDOWN:
185 if (m_use_game_controller) game_controller_manager->process_button_event(event.cbutton);
188 case SDL_CONTROLLERBUTTONUP:
189 if (m_use_game_controller) game_controller_manager->process_button_event(event.cbutton);
192 case SDL_CONTROLLERDEVICEADDED:
193 std::cout << "SDL_CONTROLLERDEVICEADDED" << std::endl;
194 if (m_use_game_controller) game_controller_manager->on_controller_added(event.cdevice.which);
197 case SDL_CONTROLLERDEVICEREMOVED:
198 std::cout << "SDL_CONTROLLERDEVICEREMOVED" << std::endl;
199 if (m_use_game_controller) game_controller_manager->on_controller_removed(event.cdevice.which);
202 case SDL_CONTROLLERDEVICEREMAPPED:
203 std::cout << "SDL_CONTROLLERDEVICEREMAPPED" << std::endl;
212 JoystickKeyboardController::process_text_input_event(const SDL_TextInputEvent& event)
214 if (Console::instance->hasFocus()) {
215 for(int i = 0; event.text[i] != '\0'; ++i)
217 Console::instance->input(event.text[i]);
223 JoystickKeyboardController::process_key_event(const SDL_KeyboardEvent& event)
225 KeyMap::iterator key_mapping = keymap.find(event.keysym.sym);
227 // if console key was pressed: toggle console
228 if ((key_mapping != keymap.end()) && (key_mapping->second == Controller::CONSOLE)) {
229 if (event.type == SDL_KEYDOWN)
230 Console::instance->toggle();
232 if (Console::instance->hasFocus()) {
233 // if console is open: send key there
234 process_console_key_event(event);
235 } else if (MenuManager::current()) {
236 // if menu mode: send key there
237 process_menu_key_event(event);
238 } else if (key_mapping == keymap.end()) {
239 // default action: update controls
240 //log_debug << "Key " << event.key.SDL_Keycode.sym << " is unbound" << std::endl;
242 Control control = key_mapping->second;
243 bool value = (event.type == SDL_KEYDOWN);
244 controller->set_control(control, value);
245 if (jump_with_up_kbd && control == Controller::UP){
246 controller->set_control(Controller::JUMP, value);
253 JoystickKeyboardController::process_console_key_event(const SDL_KeyboardEvent& event)
255 if (event.type != SDL_KEYDOWN) return;
257 switch (event.keysym.sym) {
259 Console::instance->enter();
262 Console::instance->backspace();
265 Console::instance->autocomplete();
268 Console::instance->scroll(-1);
271 Console::instance->scroll(+1);
274 Console::instance->move_cursor(-65535);
277 Console::instance->move_cursor(+65535);
280 Console::instance->show_history(-1);
283 Console::instance->show_history(+1);
286 Console::instance->move_cursor(-1);
289 Console::instance->move_cursor(+1);
297 JoystickKeyboardController::process_menu_key_event(const SDL_KeyboardEvent& event)
299 // wait for key mode?
300 if (wait_for_key >= 0) {
301 if (event.type == SDL_KEYUP)
304 if (event.keysym.sym != SDLK_ESCAPE
305 && event.keysym.sym != SDLK_PAUSE) {
306 bind_key(event.keysym.sym, Control(wait_for_key));
309 MenuStorage::get_key_options_menu()->update();
313 if (joystick_manager->wait_for_joystick >= 0) {
314 if (event.keysym.sym == SDLK_ESCAPE) {
316 MenuStorage::get_joystick_options_menu()->update();
317 joystick_manager->wait_for_joystick = -1;
323 /* we use default keys when the menu is open (to avoid problems when
324 * redefining keys to invalid settings
326 switch(event.keysym.sym) {
328 control = Controller::UP;
331 control = Controller::DOWN;
334 control = Controller::LEFT;
337 control = Controller::RIGHT;
342 control = Controller::MENU_SELECT;
346 control = Controller::PAUSE_MENU;
353 controller->set_control(control, (event.type == SDL_KEYDOWN));
357 JoystickKeyboardController::bind_key(SDL_Keycode key, Control control)
359 // remove all previous mappings for that control and for that key
360 for(KeyMap::iterator i = keymap.begin();
361 i != keymap.end(); /* no ++i */) {
362 if (i->second == control) {
363 KeyMap::iterator e = i;
371 KeyMap::iterator i = keymap.find(key);
372 if (i != keymap.end())
376 keymap[key] = control;
380 JoystickKeyboardController::reversemap_key(Control c)
382 for(KeyMap::iterator i = keymap.begin(); i != keymap.end(); ++i) {