// $Id$
-//
+//
// SuperTux
-// Copyright (C) 2005 Matthias Braun <matze@braunis.de>
+// Copyright (C) 2006 Matthias Braun <matze@braunis.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// 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.
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <config.h>
#include <sstream>
-#include "joystickkeyboardcontroller.h"
-#include "gui/menu.h"
-#include "app/gettext.h"
-#include "lisp/lisp.h"
-#include "lisp/list_iterator.h"
-#include "game_session.h"
+#include "joystickkeyboardcontroller.hpp"
+#include "log.hpp"
+#include "gui/menu.hpp"
+#include "gettext.hpp"
+#include "lisp/lisp.hpp"
+#include "lisp/list_iterator.hpp"
+#include "game_session.hpp"
+#include "console.hpp"
class JoystickKeyboardController::JoystickMenu : public Menu
{
};
JoystickKeyboardController::JoystickKeyboardController()
- : wait_for_key(-1), wait_for_joybutton(-1)
+ : wait_for_key(-1), wait_for_joybutton(-1), key_options_menu(0),
+ joystick_options_menu(0)
{
- memset(last_keys, 0, sizeof(last_keys));
-
// 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_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));
- joystick_count = SDL_NumJoysticks();
+ int joystick_count = SDL_NumJoysticks();
min_joybuttons = -1;
max_joybuttons = -1;
-#ifdef DEBUG
- std::cout << "Found " << joystick_count << " joysticks.\n";
-#endif
for(int i = 0; i < joystick_count; ++i) {
SDL_Joystick* joystick = SDL_JoystickOpen(i);
bool good = true;
if(SDL_JoystickNumButtons(joystick) < 2) {
- std::cerr << "Joystick " << i << " has less than 2 buttons.\n";
+ log_warning << "Joystick " << i << " has less than 2 buttons" << std::endl;
good = false;
}
if(SDL_JoystickNumAxes(joystick) < 2
&& SDL_JoystickNumHats(joystick) == 0) {
- std::cerr << "Joystick " << i << " has less than 2 axes and no hat.\n";
+ log_warning << "Joystick " << i << " has less than 2 axes and no hat" << std::endl;
good = false;
}
if(!good) {
SDL_JoystickClose(joystick);
- joysticks.push_back(0);
- joystick_names.push_back("");
continue;
}
max_joybuttons = SDL_JoystickNumButtons(joystick);
}
- joystick_names.push_back(SDL_JoystickName(i));
joysticks.push_back(joystick);
}
if(i != min_joybuttons-1)
joy_button_map.insert(std::make_pair(i, MENU_SELECT));
}
+
+ // some joysticks or SDL seem to produce some bogus events after being opened
+ Uint32 ticks = SDL_GetTicks();
+ while(SDL_GetTicks() - ticks < 200) {
+ SDL_Event event;
+ SDL_PollEvent(&event);
+ }
}
JoystickKeyboardController::~JoystickKeyboardController()
map->get("key", key);
map->get("control", control);
if(key < SDLK_FIRST || key >= SDLK_LAST) {
- std::cerr << "Invalid key '" << key << "' in keymap.\n";
+ log_warning << "Invalid key '" << key << "' in keymap" << std::endl;
continue;
}
break;
}
if(controlNames[i] == 0) {
- std::cerr << "Invalid control '" << control << "' in keymap.\n";
+ log_warning << "Invalid control '" << control << "' in keymap" << std::endl;
continue;
}
keymap.insert(std::make_pair((SDLKey) key, (Control) i));
} else {
- std::cerr << "Invalid lisp element '" << iter.item() << "' in keymap.\n";
+ log_warning << "Invalid lisp element '" << iter.item() << "' in keymap" << std::endl;
}
}
}
map->get("button", button);
map->get("control", control);
if(button < 0 || button >= max_joybuttons) {
- std::cerr << "Invalid button '" << button << "' in buttonmap.\n";
+ log_warning << "Invalid button '" << button << "' in buttonmap" << std::endl;
continue;
}
break;
}
if(controlNames[i] == 0) {
- std::cerr << "Invalid control '" << control << "' in buttonmap.\n";
+ log_warning << "Invalid control '" << control << "' in buttonmap" << std::endl;
continue;
}
reset_joybutton(button, (Control) i);
}
void
+JoystickKeyboardController::reset()
+{
+ Controller::reset();
+}
+
+void
JoystickKeyboardController::process_event(const SDL_Event& event)
{
switch(event.type) {
case SDL_KEYUP:
case SDL_KEYDOWN:
- // remember ascii keys for cheat codes...
- if(event.type == SDL_KEYDOWN &&
- (event.key.keysym.unicode & 0xFF80) == 0) {
- memmove(last_keys, last_keys+1, sizeof(last_keys)-1);
- last_keys[sizeof(last_keys)-1] = event.key.keysym.unicode;
- if(GameSession::current())
- GameSession::current()->try_cheats();
- }
-
- // menu mode?
- if(Menu::current()) { // menu mode
- process_menu_key_event(event);
- return;
- } else {
- // normal mode, find key in keymap
- KeyMap::iterator i = keymap.find(event.key.keysym.sym);
- if(i == keymap.end()) {
-#ifdef DEBUG
- std::cerr << "Pressed key without mapping.\n";
-#endif
- return;
- }
- Control control = i->second;
- controls[control] = event.type == SDL_KEYDOWN ? true : false;
- }
+ process_key_event(event);
break;
case SDL_JOYAXISMOTION:
ButtonMap::iterator i = joy_button_map.find(event.jbutton.button);
if(i == joy_button_map.end()) {
-#ifdef DEBUG
- std::cerr << "Unmapped joybutton " << (int) event.jbutton.button
- << " pressed.\n";
-#endif
+ log_debug << "Unmapped joybutton " << (int)event.jbutton.button << " pressed" << std::endl;
return;
}
}
void
+JoystickKeyboardController::process_key_event(const SDL_Event& event)
+{
+ KeyMap::iterator key_mapping = keymap.find(event.key.keysym.sym);
+
+ // if console key was pressed: toggle console
+ if ((key_mapping != keymap.end()) && (key_mapping->second == CONSOLE)) {
+ if (event.type != SDL_KEYDOWN) return;
+ Console::instance->toggle();
+ return;
+ }
+
+ // if console is open: send key there
+ if (Console::instance->hasFocus()) {
+ process_console_key_event(event);
+ return;
+ }
+
+ // if menu mode: send key there
+ if (Menu::current()) {
+ process_menu_key_event(event);
+ return;
+ }
+
+ // default action: update controls
+ if(key_mapping == keymap.end()) {
+ log_debug << "Key " << event.key.keysym.sym << " is unbound" << std::endl;
+ return;
+ }
+ Control control = key_mapping->second;
+ controls[control] = event.type == SDL_KEYDOWN ? true : false;
+}
+
+void
+JoystickKeyboardController::process_console_key_event(const SDL_Event& event)
+{
+ if (event.type != SDL_KEYDOWN) return;
+
+ switch (event.key.keysym.sym) {
+ case SDLK_RETURN:
+ Console::instance->input << std::endl;
+ break;
+ case SDLK_BACKSPACE:
+ Console::instance->backspace();
+ break;
+ case SDLK_TAB:
+ Console::instance->autocomplete();
+ break;
+ case SDLK_PAGEUP:
+ Console::instance->scroll(-1);
+ break;
+ case SDLK_PAGEDOWN:
+ Console::instance->scroll(+1);
+ break;
+ case SDLK_END:
+ Console::instance->scroll(+65535);
+ break;
+ default:
+ int c = event.key.keysym.unicode;
+ if ((c >= 32) && (c <= 126)) {
+ Console::instance->input << (char)c;
+ }
+ break;
+ }
+}
+
+void
JoystickKeyboardController::process_menu_key_event(const SDL_Event& event)
{
// wait for key mode?
return joystick_options_menu;
}
-bool
-JoystickKeyboardController::check_cheatcode(const std::string& cheatcode)
-{
- if(cheatcode.size() > sizeof(last_keys)) {
-#ifdef DEBUG
- std::cerr << "Cheat Code too long.\n";
-#endif
- return false;
- }
-
- for(int i = 0; i < cheatcode.size(); ++i) {
- if(last_keys[sizeof(last_keys)-1 - i] != cheatcode[cheatcode.size()-1-i])
- return false;
- }
- return true;
-}
-
//----------------------------------------------------------------------------
JoystickKeyboardController::KeyboardMenu::KeyboardMenu(
add_controlfield(Controller::LEFT, _("Left"));
add_controlfield(Controller::RIGHT, _("Right"));
add_controlfield(Controller::JUMP, _("Jump"));
- add_controlfield(Controller::ACTION, _("Shoot/Run"));
+ add_controlfield(Controller::ACTION, _("Action"));
add_hl();
add_back(_("Back"));
update();
{
add_label(_("Joystick Setup"));
add_hl();
- add_controlfield(Controller::JUMP, _("Jump"));
- add_controlfield(Controller::ACTION, _("Shoot/Run"));
- add_controlfield(Controller::PAUSE_MENU, _("Pause/Menu"));
+ if(controller->joysticks.size() > 0) {
+ add_controlfield(Controller::JUMP, _("Jump"));
+ add_controlfield(Controller::ACTION, _("Action"));
+ add_controlfield(Controller::PAUSE_MENU, _("Pause/Menu"));
+ } else {
+ add_deactive(-1, _("No Joysticks found"));
+ }
add_hl();
add_back(_("Back"));
update();
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)));