X-Git-Url: https://git.octo.it/?a=blobdiff_plain;ds=sidebyside;f=src%2Fcontrol%2Fjoystickkeyboardcontroller.cpp;h=de414fadcaa6a4a4c56fecffeaaee115e3da75f0;hb=c0a483397740673cd5b0c3c67f65562f5270a0eb;hp=cffa6f5cb053f12d4454ed2de12b1d21bef542e4;hpb=67690e081c28b818e94796be284206326bc8a6b9;p=supertux.git diff --git a/src/control/joystickkeyboardcontroller.cpp b/src/control/joystickkeyboardcontroller.cpp index cffa6f5cb..de414fadc 100644 --- a/src/control/joystickkeyboardcontroller.cpp +++ b/src/control/joystickkeyboardcontroller.cpp @@ -1,121 +1,170 @@ -// $Id$ -// // SuperTux -// Copyright (C) 2005 Matthias Braun +// Copyright (C) 2006 Matthias Braun , +// 2007 Ingo Ruhnke // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -// +// // You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -// 02111-1307, USA. -#include - -#include -#include "joystickkeyboardcontroller.hpp" -#include "msg.hpp" -#include "gui/menu.hpp" -#include "gettext.hpp" -#include "lisp/lisp.hpp" -#include "lisp/list_iterator.hpp" -#include "game_session.hpp" -#include "console.hpp" +// along with this program. If not, see . + +#include "control/joystickkeyboardcontroller.hpp" + +#include -class JoystickKeyboardController::JoystickMenu : public Menu +#include "lisp/list_iterator.hpp" +#include "gui/menu_manager.hpp" +#include "supertux/console.hpp" +#include "supertux/gameconfig.hpp" +#include "supertux/menu/menu_storage.hpp" +#include "supertux/menu/joystick_menu.hpp" +#include "supertux/menu/keyboard_menu.hpp" +#include "util/gettext.hpp" +#include "util/writer.hpp" + +JoystickKeyboardController::JoystickKeyboardController() : + controller(), + keymap(), + joy_button_map(), + joy_axis_map(), + joy_hat_map(), + joysticks(), + name(), + dead_zone(), + min_joybuttons(), + max_joybuttons(), + max_joyaxis(), + max_joyhats(), + hat_state(0), + jump_with_up_joy(), + jump_with_up_kbd(), + wait_for_key(-1), + wait_for_joystick(-1) { -public: - JoystickMenu(JoystickKeyboardController* controller); - virtual ~JoystickMenu(); + controller = new Controller; + + // initialize default keyboard map + keymap[SDLK_LEFT] = Controller::LEFT; + keymap[SDLK_RIGHT] = Controller::RIGHT; + keymap[SDLK_UP] = Controller::UP; + keymap[SDLK_DOWN] = Controller::DOWN; + keymap[SDLK_SPACE] = Controller::JUMP; + keymap[SDLK_LCTRL] = Controller::ACTION; + keymap[SDLK_LALT] = Controller::ACTION; + keymap[SDLK_ESCAPE] = Controller::PAUSE_MENU; + keymap[SDLK_p] = Controller::PAUSE_MENU; + keymap[SDLK_PAUSE] = Controller::PAUSE_MENU; + keymap[SDLK_RETURN] = Controller::MENU_SELECT; + keymap[SDLK_KP_ENTER] = Controller::MENU_SELECT; + keymap[SDLK_CARET] = Controller::CONSOLE; + keymap[SDLK_DELETE] = Controller::PEEK_LEFT; + keymap[SDLK_PAGEDOWN] = Controller::PEEK_RIGHT; + keymap[SDLK_HOME] = Controller::PEEK_UP; + keymap[SDLK_END] = Controller::PEEK_DOWN; + + jump_with_up_joy = false; + jump_with_up_kbd = false; + + updateAvailableJoysticks(); + + dead_zone = 1000; + + // Default joystick button configuration + bind_joybutton(0, 0, Controller::JUMP); + bind_joybutton(0, 1, Controller::ACTION); + // 6 or more Buttons + if( min_joybuttons > 5 ){ + bind_joybutton(0, 4, Controller::PEEK_LEFT); + bind_joybutton(0, 5, Controller::PEEK_RIGHT); + // 8 or more + if(min_joybuttons > 7) + bind_joybutton(0, min_joybuttons-1, Controller::PAUSE_MENU); + } else { + // map the last 2 buttons to menu and pause + if(min_joybuttons > 2) + bind_joybutton(0, min_joybuttons-1, Controller::PAUSE_MENU); + // map all remaining joystick buttons to MENU_SELECT + for(int i = 2; i < max_joybuttons; ++i) { + if(i != min_joybuttons-1) + bind_joybutton(0, i, Controller::MENU_SELECT); + } + } - void update(); - std::string get_button_name(int button); - virtual void menu_action(MenuItem* item); - JoystickKeyboardController* controller; -}; + // Default joystick axis configuration + bind_joyaxis(0, -1, Controller::LEFT); + bind_joyaxis(0, 1, Controller::RIGHT); + bind_joyaxis(0, -2, Controller::UP); + bind_joyaxis(0, 2, Controller::DOWN); +} -class JoystickKeyboardController::KeyboardMenu : public Menu +JoystickKeyboardController::~JoystickKeyboardController() { -public: - KeyboardMenu(JoystickKeyboardController* controller); - ~KeyboardMenu(); - - void update(); - std::string get_key_name(SDLKey key); - virtual void menu_action(MenuItem* item); - JoystickKeyboardController* controller; -}; - -JoystickKeyboardController::JoystickKeyboardController() - : wait_for_key(-1), wait_for_joybutton(-1), key_options_menu(0), - joystick_options_menu(0) + for(std::vector::iterator i = joysticks.begin(); + i != joysticks.end(); ++i) { + if(*i != 0) + SDL_JoystickClose(*i); + } + delete controller; +} + +void +JoystickKeyboardController::updateAvailableJoysticks() { - // initialize default keyboard map - keymap.insert(std::make_pair(SDLK_LEFT, LEFT)); - keymap.insert(std::make_pair(SDLK_RIGHT, RIGHT)); - keymap.insert(std::make_pair(SDLK_UP, UP)); - keymap.insert(std::make_pair(SDLK_DOWN, DOWN)); - keymap.insert(std::make_pair(SDLK_SPACE, JUMP)); - keymap.insert(std::make_pair(SDLK_LCTRL, ACTION)); - keymap.insert(std::make_pair(SDLK_LALT, ACTION)); - keymap.insert(std::make_pair(SDLK_ESCAPE, PAUSE_MENU)); - keymap.insert(std::make_pair(SDLK_p, PAUSE_MENU)); - keymap.insert(std::make_pair(SDLK_PAUSE, PAUSE_MENU)); - keymap.insert(std::make_pair(SDLK_RETURN, MENU_SELECT)); - keymap.insert(std::make_pair(SDLK_KP_ENTER, MENU_SELECT)); - keymap.insert(std::make_pair(SDLK_CARET, CONSOLE)); + for(std::vector::iterator i = joysticks.begin(); + i != joysticks.end(); ++i) { + if(*i != 0) + SDL_JoystickClose(*i); + } + joysticks.clear(); + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + SDL_InitSubSystem(SDL_INIT_JOYSTICK); + int joystick_count = SDL_NumJoysticks(); min_joybuttons = -1; max_joybuttons = -1; - for(int i = 0; i < joystick_count; ++i) { - SDL_Joystick* joystick = SDL_JoystickOpen(i); - bool good = true; - if(SDL_JoystickNumButtons(joystick) < 2) { - msg_warning << "Joystick " << i << " has less than 2 buttons" << std::endl; - good = false; - } - if(SDL_JoystickNumAxes(joystick) < 2 - && SDL_JoystickNumHats(joystick) == 0) { - msg_warning << "Joystick " << i << " has less than 2 axes and no hat" << std::endl; - good = false; - } - if(!good) { - SDL_JoystickClose(joystick); - continue; - } - - if(min_joybuttons < 0 || SDL_JoystickNumButtons(joystick) < min_joybuttons) - min_joybuttons = SDL_JoystickNumButtons(joystick); - if(SDL_JoystickNumButtons(joystick) > max_joybuttons) { - max_joybuttons = SDL_JoystickNumButtons(joystick); - } + max_joyaxis = -1; + max_joyhats = -1; + + if( joystick_count > 0 ){ + for(int i = 0; i < joystick_count; ++i) { + SDL_Joystick* joystick = SDL_JoystickOpen(i); + bool good = true; + if(SDL_JoystickNumButtons(joystick) < 2) { + log_info << "Joystick " << i << ": " << SDL_JoystickName(i) << " has less than 2 buttons" << std::endl; + good = false; + } + if(SDL_JoystickNumAxes(joystick) < 2 + && SDL_JoystickNumHats(joystick) == 0) { + log_info << "Joystick " << i << ": " << SDL_JoystickName(i) << " has less than 2 axes and no hat" << std::endl; + good = false; + } + if(!good) { + SDL_JoystickClose(joystick); + continue; + } - joysticks.push_back(joystick); - } + if(min_joybuttons < 0 || SDL_JoystickNumButtons(joystick) < min_joybuttons) + min_joybuttons = SDL_JoystickNumButtons(joystick); - use_hat = true; - joyaxis_x = 0; - joyaxis_y = 1; - dead_zone_x = 1000; - dead_zone_y = 1000; - - joy_button_map.insert(std::make_pair(0, JUMP)); - joy_button_map.insert(std::make_pair(1, ACTION)); - // map the last 2 buttons to menu and pause - if(min_joybuttons > 2) - joy_button_map.insert(std::make_pair(min_joybuttons-1, PAUSE_MENU)); - // map all remaining joystick buttons to MENU_SELECT - for(int i = 2; i < max_joybuttons; ++i) { - if(i != min_joybuttons-1) - joy_button_map.insert(std::make_pair(i, MENU_SELECT)); + if(SDL_JoystickNumButtons(joystick) > max_joybuttons) + max_joybuttons = SDL_JoystickNumButtons(joystick); + + if(SDL_JoystickNumAxes(joystick) > max_joyaxis) + max_joyaxis = SDL_JoystickNumAxes(joystick); + + if(SDL_JoystickNumHats(joystick) > max_joyhats) + max_joyhats = SDL_JoystickNumHats(joystick); + + joysticks.push_back(joystick); + } } // some joysticks or SDL seem to produce some bogus events after being opened @@ -126,24 +175,19 @@ JoystickKeyboardController::JoystickKeyboardController() } } -JoystickKeyboardController::~JoystickKeyboardController() +Controller* +JoystickKeyboardController::get_main_controller() { - for(std::vector::iterator i = joysticks.begin(); - i != joysticks.end(); ++i) { - if(*i != 0) - SDL_JoystickClose(*i); - } - - delete key_options_menu; - delete joystick_options_menu; + return controller; } void -JoystickKeyboardController::read(const lisp::Lisp& lisp) +JoystickKeyboardController::read(const Reader& lisp) { const lisp::Lisp* keymap_lisp = lisp.get_lisp("keymap"); if(keymap_lisp) { keymap.clear(); + keymap_lisp->get("jump-with-up", jump_with_up_kbd); lisp::ListIterator iter(keymap_lisp); while(iter.next()) { if(iter.item() == "map") { @@ -153,92 +197,141 @@ JoystickKeyboardController::read(const lisp::Lisp& lisp) map->get("key", key); map->get("control", control); if(key < SDLK_FIRST || key >= SDLK_LAST) { - msg_warning << "Invalid key '" << key << "' in keymap" << std::endl; + log_info << "Invalid key '" << key << "' in keymap" << std::endl; continue; } int i = 0; - for(i = 0; controlNames[i] != 0; ++i) { - if(control == controlNames[i]) + for(i = 0; Controller::controlNames[i] != 0; ++i) { + if(control == Controller::controlNames[i]) break; } - if(controlNames[i] == 0) { - msg_warning << "Invalid control '" << control << "' in keymap" << std::endl; + if(Controller::controlNames[i] == 0) { + log_info << "Invalid control '" << control << "' in keymap" << std::endl; continue; } - keymap.insert(std::make_pair((SDLKey) key, (Control) i)); - } else { - msg_warning << "Invalid lisp element '" << iter.item() << "' in keymap" << std::endl; + keymap[SDLKey(key)] = Control(i); } } } const lisp::Lisp* joystick_lisp = lisp.get_lisp("joystick"); if(joystick_lisp) { - joystick_lisp->get("use_hat", use_hat); - joystick_lisp->get("axis_x", joyaxis_x); - joystick_lisp->get("axis_y", joyaxis_y); - joystick_lisp->get("dead_zone_x", dead_zone_x); - joystick_lisp->get("dead_zone_y", dead_zone_y); + joystick_lisp->get("dead-zone", dead_zone); + joystick_lisp->get("jump-with-up", jump_with_up_joy); lisp::ListIterator iter(joystick_lisp); while(iter.next()) { if(iter.item() == "map") { int button = -1; + int axis = 0; + int hat = -1; std::string control; const lisp::Lisp* map = iter.lisp(); - map->get("button", button); + map->get("control", control); - if(button < 0 || button >= max_joybuttons) { - msg_warning << "Invalid button '" << button << "' in buttonmap" << std::endl; - continue; - } - int i = 0; - for(i = 0; controlNames[i] != 0; ++i) { - if(control == controlNames[i]) + for(i = 0; Controller::controlNames[i] != 0; ++i) { + if(control == Controller::controlNames[i]) break; - } - if(controlNames[i] == 0) { - msg_warning << "Invalid control '" << control << "' in buttonmap" << std::endl; + } + if(Controller::controlNames[i] == 0) { + log_info << "Invalid control '" << control << "' in buttonmap" << std::endl; continue; } - reset_joybutton(button, (Control) i); + + if (map->get("button", button)) { + if(button < 0 || button >= max_joybuttons) { + log_info << "Invalid button '" << button << "' in buttonmap" << std::endl; + continue; + } + bind_joybutton(0, button, Control(i)); + } + + if (map->get("axis", axis)) { + if (axis == 0 || abs(axis) > max_joyaxis) { + log_info << "Invalid axis '" << axis << "' in axismap" << std::endl; + continue; + } + bind_joyaxis(0, axis, Control(i)); + } + + if (map->get("hat", hat)) { + if (hat != SDL_HAT_UP && + hat != SDL_HAT_DOWN && + hat != SDL_HAT_LEFT && + hat != SDL_HAT_RIGHT) { + log_info << "Invalid axis '" << axis << "' in axismap" << std::endl; + continue; + } else { + bind_joyhat(0, hat, Control(i)); + } + } } } } } void -JoystickKeyboardController::write(lisp::Writer& writer) +JoystickKeyboardController::write(Writer& writer) { writer.start_list("keymap"); + writer.write("jump-with-up", jump_with_up_kbd); for(KeyMap::iterator i = keymap.begin(); i != keymap.end(); ++i) { writer.start_list("map"); - writer.write_int("key", (int) i->first); - writer.write_string("control", controlNames[i->second]); + writer.write("key", (int) i->first); + writer.write("control", Controller::controlNames[i->second]); writer.end_list("map"); } writer.end_list("keymap"); + writer.start_list("joystick"); - writer.write_bool("use_hat", use_hat); - writer.write_int("axis_x", joyaxis_x); - writer.write_int("axis_y", joyaxis_y); - writer.write_int("dead_zone_x", dead_zone_x); - writer.write_int("dead_zone_y", dead_zone_y); + writer.write("dead-zone", dead_zone); + writer.write("jump-with-up", jump_with_up_joy); + for(ButtonMap::iterator i = joy_button_map.begin(); i != joy_button_map.end(); ++i) { writer.start_list("map"); - writer.write_int("button", i->first); - writer.write_string("control", controlNames[i->second]); + writer.write("button", i->first.second); + writer.write("control", Controller::controlNames[i->second]); writer.end_list("map"); } - writer.end_list("joystick"); + + for(HatMap::iterator i = joy_hat_map.begin(); i != joy_hat_map.end(); ++i) { + writer.start_list("map"); + writer.write("hat", i->first.second); + writer.write("control", Controller::controlNames[i->second]); + writer.end_list("map"); + } + + for(AxisMap::iterator i = joy_axis_map.begin(); i != joy_axis_map.end(); ++i) { + writer.start_list("map"); + writer.write("axis", i->first.second); + writer.write("control", Controller::controlNames[i->second]); + writer.end_list("map"); + } + + writer.end_list("joystick"); +} + +void +JoystickKeyboardController::update() +{ + controller->update(); } void JoystickKeyboardController::reset() { - Controller::reset(); + controller->reset(); +} + +void +JoystickKeyboardController::set_joy_controls(Control id, bool value) +{ + if (jump_with_up_joy && id == Controller::UP) + controller->set_control(Controller::JUMP, value); + + controller->set_control(id, value); } void @@ -247,88 +340,21 @@ JoystickKeyboardController::process_event(const SDL_Event& event) switch(event.type) { case SDL_KEYUP: case SDL_KEYDOWN: - process_key_event(event); + process_key_event(event.key); break; case SDL_JOYAXISMOTION: - if(event.jaxis.axis == joyaxis_x) { - if(event.jaxis.value < -dead_zone_x) { - controls[LEFT] = true; - controls[RIGHT] = false; - } else if(event.jaxis.value > dead_zone_x) { - controls[LEFT] = false; - controls[RIGHT] = true; - } else { - controls[LEFT] = false; - controls[RIGHT] = false; - } - } else if(event.jaxis.axis == joyaxis_y) { - if(event.jaxis.value < -dead_zone_y) { - controls[UP] = true; - controls[DOWN] = false; - } else if(event.jaxis.value > dead_zone_y) { - controls[UP] = false; - controls[DOWN] = true; - } else { - controls[UP] = false; - controls[DOWN] = false; - } - } + process_axis_event(event.jaxis); break; case SDL_JOYHATMOTION: - if(!use_hat) - break; - - if(event.jhat.value & SDL_HAT_UP) { - controls[UP] = true; - controls[DOWN] = false; - } - if(event.jhat.value & SDL_HAT_DOWN) { - controls[UP] = false; - controls[DOWN] = true; - } - if(event.jhat.value & SDL_HAT_LEFT) { - controls[LEFT] = true; - controls[RIGHT] = false; - } - if(event.jhat.value & SDL_HAT_RIGHT) { - controls[LEFT] = false; - controls[RIGHT] = true; - } - if(event.jhat.value == SDL_HAT_CENTERED) { - controls[UP] = false; - controls[DOWN] = false; - controls[LEFT] = false; - controls[RIGHT] = false; - } + process_hat_event(event.jhat); break; case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: - { - if(wait_for_joybutton >= 0) { - if(event.type == SDL_JOYBUTTONUP) - return; - - Control c = (Control) wait_for_joybutton; - reset_joybutton(event.jbutton.button, c); - reset(); - joystick_options_menu->update(); - wait_for_joybutton = -1; - return; - } - - ButtonMap::iterator i = joy_button_map.find(event.jbutton.button); - if(i == joy_button_map.end()) { - msg_debug << "Unmapped joybutton " << (int)event.jbutton.button << " pressed" << std::endl; - return; - } - - controls[i->second] = - event.type == SDL_JOYBUTTONDOWN ? true : false; + process_button_event(event.jbutton); break; - } default: break; @@ -336,164 +362,331 @@ JoystickKeyboardController::process_event(const SDL_Event& event) } void -JoystickKeyboardController::process_key_event(const SDL_Event& event) +JoystickKeyboardController::process_button_event(const SDL_JoyButtonEvent& jbutton) { - KeyMap::iterator key_mapping = keymap.find(event.key.keysym.sym); + if(wait_for_joystick >= 0) + { + if(jbutton.state == SDL_PRESSED) + { + bind_joybutton(jbutton.which, jbutton.button, (Control)wait_for_joystick); + MenuStorage::get_joystick_options_menu()->update(); + reset(); + wait_for_joystick = -1; + } + } + else + { + ButtonMap::iterator i = joy_button_map.find(std::make_pair(jbutton.which, jbutton.button)); + if(i == joy_button_map.end()) { + log_debug << "Unmapped joybutton " << (int)jbutton.button << " pressed" << std::endl; + } else { + set_joy_controls(i->second, (jbutton.state == SDL_PRESSED)); + } + } +} - // if console key was pressed: toggle console - if ((key_mapping != keymap.end()) && (key_mapping->second == CONSOLE)) { - if (event.type != SDL_KEYDOWN) return; - Console::toggle(); - return; +void +JoystickKeyboardController::process_axis_event(const SDL_JoyAxisEvent& jaxis) +{ + if (wait_for_joystick >= 0) + { + if (abs(jaxis.value) > dead_zone) { + if (jaxis.value < 0) + bind_joyaxis(jaxis.which, -(jaxis.axis + 1), Control(wait_for_joystick)); + else + bind_joyaxis(jaxis.which, jaxis.axis + 1, Control(wait_for_joystick)); + + MenuStorage::get_joystick_options_menu()->update(); + wait_for_joystick = -1; + } } + else + { + // Split the axis into left and right, so that both can be + // mapped separately (needed for jump/down vs up/down) + int axis = jaxis.axis + 1; - // if console is open: send key there - if (Console::hasFocus()) { - process_console_key_event(event); - return; - } + AxisMap::iterator left = joy_axis_map.find(std::make_pair(jaxis.which, -axis)); + AxisMap::iterator right = joy_axis_map.find(std::make_pair(jaxis.which, axis)); - // if menu mode: send key there - if (Menu::current()) { - process_menu_key_event(event); - return; + if(left == joy_axis_map.end()) { + // std::cout << "Unmapped joyaxis " << (int)jaxis.axis << " moved" << std::endl; + } else { + if (jaxis.value < -dead_zone) + set_joy_controls(left->second, true); + else if (jaxis.value > dead_zone) + set_joy_controls(left->second, false); + else + set_joy_controls(left->second, false); + } + + if(right == joy_axis_map.end()) { + // std::cout << "Unmapped joyaxis " << (int)jaxis.axis << " moved" << std::endl; + } else { + if (jaxis.value < -dead_zone) + set_joy_controls(right->second, false); + else if (jaxis.value > dead_zone) + set_joy_controls(right->second, true); + else + set_joy_controls(right->second, false); + } } +} - // default action: update controls - if(key_mapping == keymap.end()) { - msg_debug << "Key " << event.key.keysym.sym << " is unbound" << std::endl; - return; +void +JoystickKeyboardController::process_hat_event(const SDL_JoyHatEvent& jhat) +{ + Uint8 changed = hat_state ^ jhat.value; + + if (wait_for_joystick >= 0) + { + if (changed & SDL_HAT_UP && jhat.value & SDL_HAT_UP) + bind_joyhat(jhat.which, SDL_HAT_UP, Control(wait_for_joystick)); + + if (changed & SDL_HAT_DOWN && jhat.value & SDL_HAT_DOWN) + bind_joyhat(jhat.which, SDL_HAT_DOWN, Control(wait_for_joystick)); + + if (changed & SDL_HAT_LEFT && jhat.value & SDL_HAT_LEFT) + bind_joyhat(jhat.which, SDL_HAT_LEFT, Control(wait_for_joystick)); + + if (changed & SDL_HAT_RIGHT && jhat.value & SDL_HAT_RIGHT) + bind_joyhat(jhat.which, SDL_HAT_RIGHT, Control(wait_for_joystick)); + + MenuStorage::get_joystick_options_menu()->update(); + wait_for_joystick = -1; + } + else + { + if (changed & SDL_HAT_UP) + { + HatMap::iterator it = joy_hat_map.find(std::make_pair(jhat.which, SDL_HAT_UP)); + if (it != joy_hat_map.end()) + set_joy_controls(it->second, jhat.value & SDL_HAT_UP); + } + + if (changed & SDL_HAT_DOWN) + { + HatMap::iterator it = joy_hat_map.find(std::make_pair(jhat.which, SDL_HAT_DOWN)); + if (it != joy_hat_map.end()) + set_joy_controls(it->second, jhat.value & SDL_HAT_DOWN); + } + + if (changed & SDL_HAT_LEFT) + { + HatMap::iterator it = joy_hat_map.find(std::make_pair(jhat.which, SDL_HAT_LEFT)); + if (it != joy_hat_map.end()) + set_joy_controls(it->second, jhat.value & SDL_HAT_LEFT); + } + + if (changed & SDL_HAT_RIGHT) + { + HatMap::iterator it = joy_hat_map.find(std::make_pair(jhat.which, SDL_HAT_RIGHT)); + if (it != joy_hat_map.end()) + set_joy_controls(it->second, jhat.value & SDL_HAT_RIGHT); + } } - Control control = key_mapping->second; - controls[control] = event.type == SDL_KEYDOWN ? true : false; + + hat_state = jhat.value; } void -JoystickKeyboardController::process_console_key_event(const SDL_Event& event) +JoystickKeyboardController::process_key_event(const SDL_KeyboardEvent& event) +{ + KeyMap::iterator key_mapping = keymap.find(event.keysym.sym); + + // if console key was pressed: toggle console + if ((key_mapping != keymap.end()) && (key_mapping->second == Controller::CONSOLE)) { + if (event.type == SDL_KEYDOWN) + Console::instance->toggle(); + } else { + if (Console::instance->hasFocus()) { + // if console is open: send key there + process_console_key_event(event); + } else if (MenuManager::current()) { + // if menu mode: send key there + process_menu_key_event(event); + } else if(key_mapping == keymap.end()) { + // default action: update controls + //log_debug << "Key " << event.key.keysym.sym << " is unbound" << std::endl; + } else { + Control control = key_mapping->second; + bool value = (event.type == SDL_KEYDOWN); + controller->set_control(control, value); + if (jump_with_up_kbd && control == Controller::UP){ + controller->set_control(Controller::JUMP, value); + } + } + } +} + +void +JoystickKeyboardController::process_console_key_event(const SDL_KeyboardEvent& event) { if (event.type != SDL_KEYDOWN) return; - switch (event.key.keysym.sym) { + switch (event.keysym.sym) { case SDLK_RETURN: - Console::input << std::endl; + Console::instance->enter(); break; case SDLK_BACKSPACE: - Console::backspace(); + Console::instance->backspace(); break; case SDLK_TAB: - Console::autocomplete(); + Console::instance->autocomplete(); break; case SDLK_PAGEUP: - Console::scroll(-1); + Console::instance->scroll(-1); break; case SDLK_PAGEDOWN: - Console::scroll(+1); + Console::instance->scroll(+1); + break; + case SDLK_HOME: + Console::instance->move_cursor(-65535); break; case SDLK_END: - Console::scroll(+65535); + Console::instance->move_cursor(+65535); + break; + case SDLK_UP: + Console::instance->show_history(-1); + break; + case SDLK_DOWN: + Console::instance->show_history(+1); + break; + case SDLK_LEFT: + Console::instance->move_cursor(-1); + break; + case SDLK_RIGHT: + Console::instance->move_cursor(+1); break; default: - int c = event.key.keysym.unicode; + int c = event.keysym.unicode; if ((c >= 32) && (c <= 126)) { - Console::input << (char)c; + Console::instance->input((char)c); } break; } } void -JoystickKeyboardController::process_menu_key_event(const SDL_Event& event) +JoystickKeyboardController::process_menu_key_event(const SDL_KeyboardEvent& event) { // wait for key mode? if(wait_for_key >= 0) { if(event.type == SDL_KEYUP) return; - if(event.key.keysym.sym != SDLK_ESCAPE - && event.key.keysym.sym != SDLK_PAUSE) { - reset_key(event.key.keysym.sym, (Control) wait_for_key); + if(event.keysym.sym != SDLK_ESCAPE + && event.keysym.sym != SDLK_PAUSE) { + bind_key(event.keysym.sym, Control(wait_for_key)); } reset(); - key_options_menu->update(); + MenuStorage::get_key_options_menu()->update(); wait_for_key = -1; return; - } - if(wait_for_joybutton >= 0) { - if(event.key.keysym.sym == SDLK_ESCAPE) { + } + if(wait_for_joystick >= 0) { + if(event.keysym.sym == SDLK_ESCAPE) { reset(); - joystick_options_menu->update(); - wait_for_joybutton = -1; + MenuStorage::get_joystick_options_menu()->update(); + wait_for_joystick = -1; } return; } - + Control control; /* we use default keys when the menu is open (to avoid problems when * redefining keys to invalid settings */ - switch(event.key.keysym.sym) { + switch(event.keysym.sym) { case SDLK_UP: - control = UP; + control = Controller::UP; break; case SDLK_DOWN: - control = DOWN; + control = Controller::DOWN; break; case SDLK_LEFT: - control = LEFT; + control = Controller::LEFT; break; case SDLK_RIGHT: - control = RIGHT; + control = Controller::RIGHT; break; case SDLK_SPACE: case SDLK_RETURN: case SDLK_KP_ENTER: - control = MENU_SELECT; + control = Controller::MENU_SELECT; break; case SDLK_ESCAPE: case SDLK_PAUSE: - control = PAUSE_MENU; + control = Controller::PAUSE_MENU; break; default: return; break; } - controls[control] = event.type == SDL_KEYDOWN ? true : false; + controller->set_control(control, (event.type == SDL_KEYDOWN)); } void -JoystickKeyboardController::reset_joybutton(int button, Control control) +JoystickKeyboardController::unbind_joystick_control(Control control) { - // remove all previous mappings for that control and for that key - for(ButtonMap::iterator i = joy_button_map.begin(); - i != joy_button_map.end(); /* no ++i */) { - if(i->second == control) { - ButtonMap::iterator e = i; + // remove all previous mappings for that control + for(AxisMap::iterator i = joy_axis_map.begin(); i != joy_axis_map.end(); /* no ++i */) { + if(i->second == control) + joy_axis_map.erase(i++); + else ++i; - joy_button_map.erase(e); - } else { + } + + for(ButtonMap::iterator i = joy_button_map.begin(); i != joy_button_map.end(); /* no ++i */) { + if(i->second == control) + joy_button_map.erase(i++); + else + ++i; + } + + for(HatMap::iterator i = joy_hat_map.begin(); i != joy_hat_map.end(); /* no ++i */) { + if(i->second == control) + joy_hat_map.erase(i++); + else ++i; - } } - ButtonMap::iterator i = joy_button_map.find(button); - if(i != joy_button_map.end()) - joy_button_map.erase(i); +} + +void +JoystickKeyboardController::bind_joyaxis(JoyId joy_id, int axis, Control control) +{ + // axis isn't the SDL axis number, but axisnumber + 1 with sign + // changed depending on if the positive or negative end is to be + // used (negative axis 0 becomes -1, positive axis 2 becomes +3, + // etc.) + + unbind_joystick_control(control); // add new mapping - joy_button_map.insert(std::make_pair(button, control)); + joy_axis_map[std::make_pair(joy_id, axis)] = control; +} - // map all unused buttons to MENU_SELECT - for(int b = 0; b < max_joybuttons; ++b) { - ButtonMap::iterator i = joy_button_map.find(b); - if(i != joy_button_map.end()) - continue; +void +JoystickKeyboardController::bind_joyhat(JoyId joy_id, int dir, Control c) +{ + unbind_joystick_control(c); - joy_button_map.insert(std::make_pair(b, MENU_SELECT)); - } + // add new mapping + joy_hat_map[std::make_pair(joy_id, dir)] = c; } void -JoystickKeyboardController::reset_key(SDLKey key, Control control) +JoystickKeyboardController::bind_joybutton(JoyId joy_id, int button, Control control) +{ + unbind_joystick_control(control); + + // add new mapping + joy_button_map[std::make_pair(joy_id, button)] = control; +} + +void +JoystickKeyboardController::bind_key(SDLKey key, Control control) { // remove all previous mappings for that control and for that key for(KeyMap::iterator i = keymap.begin(); @@ -506,12 +699,32 @@ JoystickKeyboardController::reset_key(SDLKey key, Control control) ++i; } } + KeyMap::iterator i = keymap.find(key); if(i != keymap.end()) keymap.erase(i); // add new mapping - keymap.insert(std::make_pair(key, control)); + keymap[key] = control; +} + +void +JoystickKeyboardController::print_joystick_mappings() +{ + std::cout << "Joystick Mappings" << std::endl; + std::cout << "-----------------" << std::endl; + for(AxisMap::iterator i = joy_axis_map.begin(); i != joy_axis_map.end(); ++i) { + std::cout << "Axis: " << i->first.second << " -> " << i->second << std::endl; + } + + for(ButtonMap::iterator i = joy_button_map.begin(); i != joy_button_map.end(); ++i) { + std::cout << "Button: " << i->first.second << " -> " << i->second << std::endl; + } + + for(HatMap::iterator i = joy_hat_map.begin(); i != joy_hat_map.end(); ++i) { + std::cout << "Hat: " << i->first.second << " -> " << i->second << std::endl; + } + std::cout << std::endl; } SDLKey @@ -526,174 +739,36 @@ JoystickKeyboardController::reversemap_key(Control c) } int -JoystickKeyboardController::reversemap_joybutton(Control c) +JoystickKeyboardController::reversemap_joyaxis(Control c) { - for(ButtonMap::iterator i = joy_button_map.begin(); - i != joy_button_map.end(); ++i) { + for(AxisMap::iterator i = joy_axis_map.begin(); i != joy_axis_map.end(); ++i) { if(i->second == c) - return i->first; - } - - return -1; -} - -Menu* -JoystickKeyboardController::get_key_options_menu() -{ - if(key_options_menu == 0) { - key_options_menu = new KeyboardMenu(this); + return i->first.second; } - return key_options_menu; + return 0; } -Menu* -JoystickKeyboardController::get_joystick_options_menu() -{ - if(joystick_options_menu == 0) { - joystick_options_menu = new JoystickMenu(this); - } - - return joystick_options_menu; -} - -//---------------------------------------------------------------------------- - -JoystickKeyboardController::KeyboardMenu::KeyboardMenu( - JoystickKeyboardController* _controller) - : controller(_controller) -{ - add_label(_("Keyboard Setup")); - add_hl(); - add_controlfield(Controller::UP, _("Up")); - add_controlfield(Controller::DOWN, _("Down")); - add_controlfield(Controller::LEFT, _("Left")); - add_controlfield(Controller::RIGHT, _("Right")); - add_controlfield(Controller::JUMP, _("Jump")); - add_controlfield(Controller::ACTION, _("Shoot/Run")); - add_hl(); - add_back(_("Back")); - update(); -} - -JoystickKeyboardController::KeyboardMenu::~KeyboardMenu() -{} - -std::string -JoystickKeyboardController::KeyboardMenu::get_key_name(SDLKey key) +int +JoystickKeyboardController::reversemap_joybutton(Control c) { - switch(key) { - case SDLK_UNKNOWN: - return _("None"); - case SDLK_UP: - return _("Up cursor"); - case SDLK_DOWN: - return _("Down cursor"); - case SDLK_LEFT: - return _("Left cursor"); - case SDLK_RIGHT: - return _("Right cursor"); - case SDLK_RETURN: - return _("Return"); - case SDLK_SPACE: - return _("Space"); - case SDLK_RSHIFT: - return _("Right Shift"); - case SDLK_LSHIFT: - return _("Left Shift"); - case SDLK_RCTRL: - return _("Right Control"); - case SDLK_LCTRL: - return _("Left Control"); - case SDLK_RALT: - return _("Right Alt"); - case SDLK_LALT: - return _("Left Alt"); - default: - return SDL_GetKeyName((SDLKey) key); + for(ButtonMap::iterator i = joy_button_map.begin(); i != joy_button_map.end(); ++i) { + if(i->second == c) + return i->first.second; } -} -void -JoystickKeyboardController::KeyboardMenu::menu_action(MenuItem* item) -{ - assert(item->id >= 0 && item->id < Controller::CONTROLCOUNT); - item->change_input(_("Press Key")); - controller->wait_for_key = item->id; -} - -void -JoystickKeyboardController::KeyboardMenu::update() -{ - // update menu - get_item_by_id((int) Controller::UP).change_input(get_key_name( - controller->reversemap_key(Controller::UP))); - get_item_by_id((int) Controller::DOWN).change_input(get_key_name( - controller->reversemap_key(Controller::DOWN))); - get_item_by_id((int) Controller::LEFT).change_input(get_key_name( - controller->reversemap_key(Controller::LEFT))); - get_item_by_id((int) Controller::RIGHT).change_input(get_key_name( - controller->reversemap_key(Controller::RIGHT))); - get_item_by_id((int) Controller::JUMP).change_input(get_key_name( - controller->reversemap_key(Controller::JUMP))); - get_item_by_id((int) Controller::ACTION).change_input(get_key_name( - controller->reversemap_key(Controller::ACTION))); + return -1; } -//--------------------------------------------------------------------------- - -JoystickKeyboardController::JoystickMenu::JoystickMenu( - JoystickKeyboardController* _controller) - : controller(_controller) +int +JoystickKeyboardController::reversemap_joyhat(Control c) { - add_label(_("Joystick Setup")); - add_hl(); - if(controller->joysticks.size() > 0) { - add_controlfield(Controller::JUMP, _("Jump")); - add_controlfield(Controller::ACTION, _("Shoot/Run")); - add_controlfield(Controller::PAUSE_MENU, _("Pause/Menu")); - } else { - add_deactive(-1, _("No Joysticks found")); + for(HatMap::iterator i = joy_hat_map.begin(); i != joy_hat_map.end(); ++i) { + if(i->second == c) + return i->first.second; } - add_hl(); - add_back(_("Back")); - update(); -} - -JoystickKeyboardController::JoystickMenu::~JoystickMenu() -{} - -std::string -JoystickKeyboardController::JoystickMenu::get_button_name(int button) -{ - if(button < 0) - return _("None"); - - std::ostringstream name; - name << "Button " << button; - return name.str(); -} -void -JoystickKeyboardController::JoystickMenu::menu_action(MenuItem* item) -{ - assert(item->id >= 0 && item->id < Controller::CONTROLCOUNT); - item->change_input(_("Press Button")); - controller->wait_for_joybutton = item->id; -} - -void -JoystickKeyboardController::JoystickMenu::update() -{ - if(controller->joysticks.size() == 0) - return; - - // update menu - get_item_by_id((int) Controller::JUMP).change_input(get_button_name( - controller->reversemap_joybutton(Controller::JUMP))); - get_item_by_id((int) Controller::ACTION).change_input(get_button_name( - controller->reversemap_joybutton(Controller::ACTION))); - get_item_by_id((int) Controller::PAUSE_MENU).change_input(get_button_name( - controller->reversemap_joybutton(Controller::PAUSE_MENU))); + return -1; } +/* EOF */