From fe229598d7437a85988eb9255cd0f6bdb6e07cb7 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sun, 21 Feb 2010 19:45:50 +0000 Subject: optimized keyboard input handling routines --- src/client/action.h | 23 ++- src/client/input.cc | 400 +++++++++++++++++++++++++------------------------ src/client/key.cc | 21 ++- src/client/key.h | 22 ++- src/client/keyboard.cc | 87 +++++++---- 5 files changed, 307 insertions(+), 246 deletions(-) (limited to 'src/client') diff --git a/src/client/action.h b/src/client/action.h index 778c40d..5d56bb9 100644 --- a/src/client/action.h +++ b/src/client/action.h @@ -12,27 +12,42 @@ namespace client { -/// an Action that can be bound to a key +/** + * @brief a client action key slot. + * actions are interpreted directly by the client and do not go throught the + * command line systems. + */ class Action { public: /// actions - enum Identifier {None = 0}; + enum Identifier {None = 0, + Console, + Left, Right, Up, Down, + RollLeft, RollRight, + StrafeLeft, StrafeRight, + ThrustUp, ThrustDown, + Afterburner, Reverse, + Control, + CamLeft, CamRight, CamUp, CamDown, + ZoomIn, ZoomOut, + }; /// define a new action Action(const char *name, Identifier action, const char *info = 0); ~Action(); - /// name of the Action + /// name inline std::string const & name() const { return action_name; } - /// Action Identifier + /// identifier inline Identifier id() const { return action_id; } + /// text description inline std::string const & info() const { return action_info; } diff --git a/src/client/input.cc b/src/client/input.cc index 1886967..e8f0725 100644 --- a/src/client/input.cc +++ b/src/client/input.cc @@ -8,6 +8,7 @@ #include "audio/audio.h" #include "auxiliary/functions.h" +#include "client/action.h" #include "client/client.h" #include "client/input.h" #include "client/joystick.h" @@ -134,7 +135,7 @@ void func_ui_control(std::string const &args) render::Camera::set_pitch(0.0f); } - con_debug << "mouse control is " << ((input_mousecontrol->value()) ? "on" : "off") << std::endl; + con_print << "mouse control is " << ((input_mousecontrol->value()) ? "on" : "off") << std::endl; audio::play("ui/control"); } @@ -341,146 +342,172 @@ void shutdown() } -void action_press(Key const *key, std::string const &action) +void action_press(Key *key) { - /* -- thruster ------------------------------------ */ - if (action.compare("+thrustup") == 0) { - local_thrust += thruster_offset; - - - } else if (action.compare("+thrustdown") == 0) { - local_thrust -= 2.0f * thruster_offset; - - /* -- mouse control ------------------------------- */ - } else if (action.compare("+control") == 0) { - if (!mouse_control_override) { - mouse_control_override = true; - mouse_control_override_time = key->pressed(); - } - - /* -- directional control ------------------------- */ - } else if (action.compare("+left") == 0) { - local_direction = 1.0f; - - } else if (action.compare("+right") == 0) { - local_direction = -1.0f; - - } else if (action.compare("+up") == 0) { - local_pitch = 1.0f; - - } else if (action.compare("+down") == 0) { - local_pitch = -1.0f; - - } else if (action.compare("+rollleft") == 0) { - local_roll = 1.0f; - - } else if (action.compare("+rollright") == 0) { - local_roll = -1.0f; - - } else if (action.compare("+strafeleft") == 0) { - local_strafe = 1.0f; - - } else if (action.compare("+straferight") == 0) { - local_strafe = -1.0f; - - } else if (action.compare("+afterburner") == 0) { - local_afterburner = 1.0f; - - } else if (action.compare("+reverse") == 0) { - local_afterburner = -1.0f; - - /* -- camera control ------------------------------ */ - - } else if (action.compare("+zoomin") == 0) { - render::Camera::set_zoom(-0.1f); - - } else if (action.compare("+zoomout") == 0) { - render::Camera::set_zoom(+0.1f); - - } else if (action.compare("+camleft") == 0) { - render::Camera::set_direction(math::min(key->pressed() - core::application()->time(), 1.0f)); - - } else if (action.compare("+camright") == 0) { - render::Camera::set_direction(-math::min(key->pressed() - core::application()->time(), 1.0f)); - - } else if (action.compare("+camup") == 0) { - render::Camera::set_pitch(math::min(key->pressed() - core::application()->time(), 1.0f)); - - } else if (action.compare("+camdown") == 0) { - render::Camera::set_pitch(-math::min(key->pressed() - core::application()->time(), 1.0f)); - } else - con_warn << "Unknown action " << action << std::endl; + switch(key->action()->id()) { + case Action::None: + case Action::Console: + return; + break; + + /* -- directional control ------------------------- */ + case Action::Left: + local_direction = 1.0f; + break; + case Action::Right: + local_direction = -1.0f; + break; + case Action::Up: + local_pitch = 1.0f; + break; + case Action::Down: + local_pitch = -1.0f; + break; + case Action::RollLeft: + local_roll = 1.0f; + break; + case Action::RollRight: + local_roll = -1.0f; + break; + case Action::StrafeLeft: + local_strafe = 1.0f; + break; + case Action::StrafeRight: + local_strafe = -1.0f; + break; + + /* -- thruster ------------------------------------ */ + case Action::ThrustUp: + local_thrust += thruster_offset; + break; + case Action::ThrustDown: + local_thrust -= 2.0f * thruster_offset; + break; + + case Action::Afterburner: + local_afterburner = 1.0f; + break; + case Action::Reverse: + local_afterburner = -1.0f; + break; + + /* -- mouse control ------------------------------- */ + case Action::Control: + if (!mouse_control_override) { + mouse_control_override = true; + mouse_control_override_time = key->pressed(); + } + break; + + /* -- camera control ------------------------------ */ + + case Action::CamLeft: + render::Camera::set_direction(math::min(key->pressed() - core::application()->time(), 1.0f)); + break; + case Action::CamRight: + render::Camera::set_direction(-math::min(key->pressed() - core::application()->time(), 1.0f)); + break; + case Action::CamUp: + render::Camera::set_pitch(math::min(key->pressed() - core::application()->time(), 1.0f)); + break; + case Action::CamDown: + render::Camera::set_pitch(-math::min(key->pressed() - core::application()->time(), 1.0f)); + break; + case Action::ZoomIn: + render::Camera::set_zoom(-0.1f); + break; + case Action::ZoomOut: + render::Camera::set_zoom(+0.1f); + break; + } } -void action_release(Key *key, std::string const &action) +void action_release(Key *key) { - /* -- thruster ------------------------------------ */ - if (action.compare("+thrustup") == 0) { - - - } else if (action.compare("+thrustdown") == 0) { - - - /* -- mouse control ------------------------------- */ - } else if (action.compare("+control") == 0) { - if (mouse_control_override) { - mouse_control_override = false; - mouse_control_override_time = 0; - - if (!input_mousecontrol->value() || (joystick_control && mouse_control && - (render::Camera::mode() == render::Camera::Track || render::Camera::mode() == render::Camera::Cockpit))) { - local_direction = 0.0f; - local_pitch = 0.0f; - local_roll = 0.0f; - - render::Camera::set_direction(0.0f); - render::Camera::set_pitch(0.0f); + switch(key->action()->id()) { + + case Action::None: + case Action::Console: + return; + break; + + /* -- directional control ------------------------- */ + case Action::Left: + local_direction = 0.0f; + break; + case Action::Right: + local_direction = 0.0f; + break; + case Action::Up: + local_pitch = 0.0f; + break; + case Action::Down: + local_pitch = 0.0f; + break; + case Action::RollLeft: + local_roll = 0.0f; + break; + case Action::RollRight: + local_roll = 0.0f; + break; + case Action::StrafeLeft: + local_strafe = 0.0f; + break; + case Action::StrafeRight: + local_strafe = 0.0f; + break; + + /* -- thruster ------------------------------------ */ + case Action::ThrustUp: + //local_thrust += 0; + break; + case Action::ThrustDown: + //local_thrust += 0; + break; + + case Action::Afterburner: + local_afterburner = 0.0f; + break; + case Action::Reverse: + local_afterburner = 0.0f; + break; + + /* -- mouse control ------------------------------- */ + case Action::Control: + if (mouse_control_override) { + mouse_control_override = false; + mouse_control_override_time = 0; + + if (!input_mousecontrol->value() || (joystick_control && mouse_control && + (render::Camera::mode() == render::Camera::Track || render::Camera::mode() == render::Camera::Cockpit))) { + local_direction = 0.0f; + local_pitch = 0.0f; + local_roll = 0.0f; + + render::Camera::set_direction(0.0f); + render::Camera::set_pitch(0.0f); + } } - } - - /* -- directional control ------------------------- */ - } else if (action.compare("+left") == 0) { - local_direction = 0.0f; - - } else if (action.compare("+right") == 0) { - local_direction = 0.0f; - - } else if (action.compare("+up") == 0) { - local_pitch = 0.0f; - - } else if (action.compare("+down") == 0) { - local_pitch = 0.0f; - - } else if (action.compare("+rollleft") == 0) { - local_roll = 0.0f; - - } else if (action.compare("+rollright") == 0) { - local_roll = 0.0f; - - } else if (action.compare("+strafeleft") == 0) { - local_strafe = 0.0f; - - } else if (action.compare("+straferight") == 0) { - local_strafe = 0.0f; - - } else if (action.compare("+afterburner") == 0) { - local_afterburner = 0.0f; - - } else if (action.compare("+reverse") == 0) { - local_afterburner = 0.0f; - + break; + /* -- camera control ------------------------------ */ - } else if (action.compare("+camleft") == 0) { - render::Camera::set_direction(0.0f); - - } else if (action.compare("+camright") == 0) { - render::Camera::set_direction(0.0f); - - } else if (action.compare("+camup") == 0) { - render::Camera::set_pitch(0.0f); - - } else if (action.compare("+camdown") == 0) { - render::Camera::set_pitch(0.0f); + + case Action::CamLeft: + render::Camera::set_direction(0.0f); + break; + case Action::CamRight: + render::Camera::set_direction(0.0f); + break; + case Action::CamUp: + render::Camera::set_pitch(0); + break; + case Action::CamDown: + render::Camera::set_pitch(0); + break; + case Action::ZoomIn: + break; + case Action::ZoomOut: + break; } } @@ -498,10 +525,7 @@ Key::Modifier modifier() void key_pressed(Key *key) { - // FIXME implement a real 'console key' - - if (key->bind(Key::None).compare("ui_console") == 0) { - // FIXME bah + if (key->action() && (key->action()->id() == Action::Console)) { local_direction = 0.0f; local_pitch = 0.0f; local_roll = 0.0f; @@ -513,40 +537,38 @@ void key_pressed(Key *key) return; } - if (ui::root()->active()) { - local_direction = 0.0f; - local_pitch = 0.0f; - local_roll = 0.0f; - - render::Camera::set_direction(0.0f); - render::Camera::set_pitch(0.0f); - } - if (ui::root()->input_key(true, Keyboard::translate_keysym(key->sym(), keyboard_modifiers), keyboard_modifiers)) { - return; - } else if (!core::localplayer()->view() && core::application()->connected() && core::localcontrol()) { - - char c = key->bind(modifier()).c_str()[0]; - if (c == '@') { - // target bind - if (targets::current_id()) - core::cmd() << key->bind(modifier()) << " " << targets::current_id() << "\n"; - } else if (c == '+') { - // action bind - action_press(key, key->bind(modifier())); + } else if (key->bind(modifier()).size() && core::application()->connected()) { + + if (!core::localplayer()->view() && core::localcontrol()) { + + if (key->action()) { + action_press(key); + return; + } + + const char c = key->bind(modifier()).c_str()[0]; + if (c == '@') { + // target bind + if (targets::current_id()) { + core::cmd() << key->bind(modifier()) << " " << targets::current_id() << "\n"; + } + return; + } else if (c) { + // normal bind + core::cmd() << key->bind(modifier()) << "\n"; + return; + } + } else { - // normal bind - core::cmd() << key->bind(modifier()) << "\n"; - } - - } else if (core::application()->connected()) { - - char c = key->bind(modifier()).c_str()[0]; - if (c && c != '+' && c != '@') { - // normal bind - core::cmd() << key->bind(modifier()) << "\n"; + const char c = key->bind(modifier()).c_str()[0]; + if (c && c != '+' && c != '@') { + // normal bind + core::cmd() << key->bind(modifier()) << "\n"; + return; + } } } } @@ -556,35 +578,16 @@ void key_released(Key *key) ui::root()->input_key(false, Keyboard::translate_keysym(key->sym(), keyboard_modifiers), keyboard_modifiers); if (core::application()->connected() && core::localcontrol()) { - + // FIXME mouse release selection should be handled inside the hud + // note: mouse button can double as an action key if ((key->sym() == 512 + SDL_BUTTON_LEFT) && targets::hover() && (key->waspressed() <= (input_mousedelay->value() / 1000.0f))) { // hovering target selected targets::select_target(targets::hover()); } - - - // the release event must still be processed as usual - char c = 0; - c = key->bind(Key::None).c_str()[0]; - if (c == '+') { - // action bind - action_release(key, key->bind(Key::None)); - } - c = key->bind(Key::Shift).c_str()[0]; - if (c == '+') { - // action bind - action_release(key, key->bind(Key::Shift)); - } - c = key->bind(Key::Ctrl).c_str()[0]; - if (c == '+') { - // action bind - action_release(key, key->bind(Key::Ctrl)); - } - c = key->bind(Key::Alt).c_str()[0]; - if (c == '+') { - // action bind - action_release(key, key->bind(Key::Alt)); + + if (key->action()) { + action_release(key); } } } @@ -828,7 +831,7 @@ void frame() if (core::application()->connected() && core::localcontrol()) { mouse_control = ui::console()->hidden() && !ui::root()->active() && ((input_mousecontrol->value() > 0) || (mouse_control_override && (mouse_control_override_time + (input_mousedelay->value() / 1000.0f) < core::application()->time()))); - + if (mouse_control && joystick_control && ((render::Camera::mode() == render::Camera::Track) || (render::Camera::mode() == render::Camera::Cockpit))) { if (!(mouse_control_override && (mouse_control_override_time + (input_mousedelay->value() / 1000.0f) < core::application()->time()))) { mouse_control = false; @@ -895,6 +898,15 @@ void frame() core::localcontrol()->set_roll(local_roll); core::localcontrol()->set_strafe(local_strafe); core::localcontrol()->set_afterburner(local_afterburner); + + } else { + + local_direction = 0.0f; + local_pitch = 0.0f; + local_roll = 0.0f; + + render::Camera::set_direction(0.0f); + render::Camera::set_pitch(0.0f); } } diff --git a/src/client/key.cc b/src/client/key.cc index c25fa2b..2ab32ae 100644 --- a/src/client/key.cc +++ b/src/client/key.cc @@ -10,7 +10,7 @@ namespace client { -Key::Key(const char *name, int keysym, char ascii, const char *bind) +Key::Key(const char *name, int keysym, char ascii) { key_sym = keysym; key_ascii = ascii; @@ -21,17 +21,11 @@ Key::Key(const char *name, int keysym, char ascii, const char *bind) key_name.assign(name); clear(); - - if (bind) - key_bind.assign(bind); - - key_bind_shift.clear(); - key_bind_ctrl.clear(); - key_bind_alt.clear(); } Key::~Key() { + clear(); } std::string const & Key::bind(Modifier mod) const @@ -47,10 +41,11 @@ std::string const & Key::bind(Modifier mod) const return key_bind_ctrl; break; case Alt: + return key_bind_alt; break; } - return key_bind_alt; + return key_bind; } void Key::clear() @@ -59,12 +54,15 @@ void Key::clear() key_bind_shift.clear(); key_bind_ctrl.clear(); key_bind_alt.clear(); + + key_action = 0; } void Key::clear(Modifier mod) { switch (mod) { case None: + key_action = 0; key_bind.clear(); break; case Shift: @@ -79,15 +77,16 @@ void Key::clear(Modifier mod) } } -void Key::assign(Modifier mod, const char *bind) +void Key::assign(Modifier mod, const char *bind, Action *action) { if (!bind) { clear(mod); return; } - + switch (mod) { case None: + key_action = action; key_bind.assign(bind); aux::trim(key_bind); break; diff --git a/src/client/key.h b/src/client/key.h index 3bb3e2b..3d97dd1 100644 --- a/src/client/key.h +++ b/src/client/key.h @@ -11,19 +11,24 @@ #include +#include "client/action.h" + namespace client { -/// a pressable key /** + * @brief a key on the keyboard * a Key instance can contain any kind of 'key' like a keyboard key, - * a mouse button, or a joystick button + * a mouse button, or a joystick button. Any key can be bound to + * a command string or an action. + * @see Action + * @see Keyboard */ class Key { public: /// define a new key - Key(const char *name, int keysym, char ascii = 0, const char *bind = 0); + Key(const char *name, int keysym, char ascii = 0); ~Key(); /// key modifiers @@ -33,7 +38,7 @@ public: void clear(); /// set the bind for a specific modifier - void assign(Modifier mod, const char *bind); + void assign(Modifier mod, const char *bind, Action *action = 0); /// clear the bind for a specific modifier void clear(Modifier mod); @@ -41,6 +46,11 @@ public: /// return the bind for a specific modifier std::string const & bind(Modifier mod) const; + /// return the action this key is bound to, 0 if unbound + inline Action *action() const { + return key_action; + } + /// first time the key was pressed since previous release inline float pressed() const { return key_pressed; @@ -74,8 +84,10 @@ public: private: std::string key_name; - int key_sym; + int key_sym; char key_ascii; + + Action *key_action; std::string key_bind; std::string key_bind_shift; diff --git a/src/client/keyboard.cc b/src/client/keyboard.cc index bf08db1..f3d2181 100644 --- a/src/client/keyboard.cc +++ b/src/client/keyboard.cc @@ -31,37 +31,34 @@ Keyboard::Keyboard() // ------------------ ACTIONS // FIXME actions should be state keys and not use key repeat + add_action("+console", Action::Console, "console key"); - add_action("+left", Action::None, "rotate left"); - add_action("+right", Action::None, "rotate right"); - add_action("+up", Action::None, "rotate up"); - add_action("+down", Action::None, "rotate down"); + add_action("+left", Action::Left, "rotate left"); + add_action("+right", Action::Right, "rotate right"); + add_action("+up", Action::Up, "rotate up"); + add_action("+down", Action::Down, "rotate down"); - add_action("+rollleft", Action::None, "roll left"); - add_action("+rollright", Action::None, "roll right"); + add_action("+rollleft", Action::RollLeft, "roll left"); + add_action("+rollright", Action::RollRight, "roll right"); - add_action("+camleft", Action::None, "rotate camera left"); - add_action("+camright", Action::None, "rotate camera right"); - add_action("+camup", Action::None, "rotate camera up"); - add_action("+camdown", Action::None, "rotate camera down"); + add_action("+camleft", Action::CamLeft, "rotate camera left"); + add_action("+camright", Action::CamRight, "rotate camera right"); + add_action("+camup", Action::CamUp, "rotate camera up"); + add_action("+camdown", Action::CamDown, "rotate camera down"); - add_action("+zoomin", Action::None, "zoom camera in"); - add_action("+zoomout", Action::None, "zoom camera out"); + add_action("+zoomin", Action::ZoomIn, "zoom camera in"); + add_action("+zoomout", Action::ZoomOut, "zoom camera out"); - add_action("+thrustup", Action::None, "increase thruster"); - add_action("+thrustdown", Action::None, "decrease thruster"); + add_action("+thrustup", Action::ThrustUp, "increase thruster"); + add_action("+thrustdown", Action::ThrustDown, "decrease thruster"); - add_action("+strafeleft", Action::None, "strafe left"); - add_action("+straferight", Action::None, "strafe right"); + add_action("+strafeleft", Action::StrafeLeft, "strafe left"); + add_action("+straferight", Action::StrafeRight, "strafe right"); - add_action("+afterburner", Action::None, "afterburner"); - add_action("+reverse", Action::None, "reverse engine"); + add_action("+afterburner", Action::Afterburner, "afterburner"); + add_action("+reverse", Action::Reverse, "reverse engine"); - add_action("+control", Action::None, "enable mouse control while pressed"); - - // TODO the @ is a hack for functions that take the current entity as param - - add_action("@dock", Action::None, "send docking request to target"); + add_action("+control", Action::Control, "enable mouse control while pressed"); // ------------------ KEYS Key *key = 0; @@ -112,7 +109,7 @@ Keyboard::Keyboard() add_key("]", SDLK_RIGHTBRACKET, ']'); add_key("^", SDLK_CARET, '^'); add_key("_", SDLK_UNDERSCORE, '_'); - add_key("`", SDLK_BACKQUOTE, '`', "ui_console"); + add_key("`", SDLK_BACKQUOTE, '`', "+console"); add_key("a", SDLK_a, 'a', "+strafeleft"); add_key("b", SDLK_b, 'b'); @@ -407,20 +404,41 @@ void Keyboard::bind(std::string const &name, const std::string str) Key *key = find(keyname); if (key) { - if (str.size()) - key->assign(modifier, str.c_str()); + // assign new bind of requested + if (str.size()) { + Action *action = 0; + for (std::list::iterator it = actions.begin(); it != actions.end(); it++) { + if ((*it)->name().compare(str) == 0) { + action = (*it); + } + } + + if (action && (modifier != Key::None)) { + if (modifier == Key::Shift) { + con_warn << "Key with modifier 'shift+" << key->name() << "' can not be bound to action '" << action->name() << "'!" << std::endl; + } else if (modifier == Key::Ctrl) { + con_warn << "Key with modifier 'ctrl+" << key->name() << "' can not be bound to action '" << action->name() << "'!" << std::endl; + } else if (modifier == Key::Alt) { + con_warn << "Key with modifier 'alt+" << key->name() << "' can not be bound to action '" << action->name() << "'!" << std::endl; + } + return; + } + key->assign(modifier, str.c_str(), action); + } + // print current bind to console, even when no new bind was assigned if (modifier == Key::None) { - con_debug << " " << aux::pad_right(key->name(), 6) << " " << key->bind(Key::None) << std::endl; + con_print << " " << aux::pad_right(key->name(), 6) << " " << key->bind(Key::None) << std::endl; } else if (modifier == Key::Shift) { - con_debug << " shift+" << aux::pad_right(key->name(), 6) << " " << key->bind(Key::Shift) << std::endl; + con_print << " shift+" << aux::pad_right(key->name(), 6) << " " << key->bind(Key::Shift) << std::endl; } else if (modifier == Key::Ctrl) { - con_debug << " ctrl+" << aux::pad_right(key->name(), 6) << " " << key->bind(Key::Ctrl) << std::endl; + con_print << " ctrl+" << aux::pad_right(key->name(), 6) << " " << key->bind(Key::Ctrl) << std::endl; } else if (modifier == Key::Alt) { - con_debug << " alt+" << aux::pad_right(key->name(), 6) << " " << key->bind(Key::Alt) << std::endl; + con_print << " alt+" << aux::pad_right(key->name(), 6) << " " << key->bind(Key::Alt) << std::endl; } + } else { - con_print << "Key '" << name << "' not found." << std::endl; + con_warn << "Key '" << name << "' not found!" << std::endl; } } @@ -468,8 +486,13 @@ void Keyboard::unbindall() Key * Keyboard::add_key(const char *name, const unsigned int keysym, const char ascii, const char *bind) { - Key *newkey = new Key(name, keysym, ascii, bind); + Key *newkey = new Key(name, keysym, ascii); keys[keysym] = newkey; + if (bind) { + std::string bindstr(bind); + this->bind(newkey->name(), bindstr); + } + return newkey; } -- cgit v1.2.3