From 540b500f2176966ebfb7f21ebd2c17ddfdcd34e6 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Tue, 22 Jul 2008 21:17:15 +0000 Subject: keyboard key repeat --- src/client/input.cc | 56 +++++++++++++++++++++++++++++++++++++++++++++++--- src/client/key.cc | 1 + src/client/key.h | 5 +++++ src/client/keyboard.cc | 9 +++++++- src/client/keyboard.h | 7 +++++-- 5 files changed, 72 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/client/input.cc b/src/client/input.cc index f8d76f2..819ce27 100644 --- a/src/client/input.cc +++ b/src/client/input.cc @@ -23,6 +23,8 @@ namespace client { core::Cvar *input_mousecontrol = 0; +core::Cvar *input_keydelay = 0; +core::Cvar *input_keyrepeat = 0; namespace input { @@ -204,9 +206,15 @@ void init() SDL_WM_GrabInput(SDL_GRAB_ON); // SDL_EnableUNICODE(1); - input_mousecontrol = core::Cvar::get("input_mousecontrol", "1", core::Cvar::Archive); + input_mousecontrol = core::Cvar::get("input_mousecontrol", 1.0f, core::Cvar::Archive); input_mousecontrol->set_info("[bool] enable or disable mouse control"); + input_keydelay = core::Cvar::get("input_keydelay", 250.0f, core::Cvar::Archive); + input_keydelay->set_info("[int] keyboard delay time-out in milliseconds"); + + input_keyrepeat = core::Cvar::get("input_keyrepeat", 30.0f, core::Cvar::Archive); + input_keyrepeat->set_info("[int] keyboard repeat time-out in milliseconds"); + core::Func *func = 0; func = core::Func::add("ui_console", func_ui_console); @@ -270,7 +278,7 @@ void shutdown() SDL_ShowCursor(SDL_ENABLE); SDL_WM_GrabInput(SDL_GRAB_OFF); -// SDL_EnableUNICODE(0); +// SDL_DisableUNICODE(0); } @@ -447,6 +455,7 @@ void key_released(Key *key) void frame(float seconds) { + /* -- detect localcontrol() changes --------------- */ if (core::localcontrol() && (last_control != core::localcontrol()->id())) { local_direction = 0.0f; @@ -464,6 +473,7 @@ void frame(float seconds) render::reset(); } + /* -- poll SDL keyboard events -------------------- */ SDL_Event event; Key *key = 0; bool pressed = false; @@ -515,10 +525,50 @@ void frame(float seconds) key_released(key); } } + + /* -- handle key repeat --------------------------- */ + float delay = 250.0f; // key delay time-out in milliseconds + if (input_keydelay) { + delay = input_keydelay->value(); + math::clamp(delay, 50.0f, 500.0f); + } + + float repeat = 30.0f; // key repeat time-out in milliseconds + if (input_keyrepeat) { + repeat = input_keyrepeat->value(); + math::clamp(repeat, 10.0f, 250.0f); + } + + if (repeat > delay) { + float tmp = repeat; + repeat = delay; + delay = tmp; + } + if (input_keydelay) + (*input_keydelay) = delay; + if (input_keyrepeat) + (*input_keyrepeat) = repeat; + repeat /= 1000.0f; + delay /= 1000.0f; + + for (Keyboard::iterator it = keyboard->begin(); it != keyboard->end(); it++) { + key = (*it).second; + if (key && key->sym() < 512 && key->pressed()) { + while ((key->pressed()+delay < core::application()->time()) && (key->lastpressed()+repeat < core::application()->time())) { + if (key->lastpressed() > key->pressed()) + key->lastpressed() += repeat; + else + key->lastpressed() += delay; + key_pressed(key); + } + } + } + + /* -- process mouse movement ----------------------*/ mouse_control = false; mouse_deadzone = false; - + key->lastpressed() += repeat; if (core::application()->connected() && core::localcontrol()) { mouse_control = !console()->visible() && ((input_mousecontrol->value() > 0) || mouse_control_override); diff --git a/src/client/key.cc b/src/client/key.cc index 27ed22a..27d280f 100644 --- a/src/client/key.cc +++ b/src/client/key.cc @@ -14,6 +14,7 @@ Key::Key(const char *name, int keysym, char ascii, const char *bind) key_sym = keysym; key_ascii = ascii; key_pressed = 0; + key_lastpressed = 0; key_name.assign(name); diff --git a/src/client/key.h b/src/client/key.h index 6f190c0..d1a8e96 100644 --- a/src/client/key.h +++ b/src/client/key.h @@ -40,8 +40,12 @@ public: /// return the bind for a specific modifier std::string const & bind(Modifier mod) const; + /// first time the key was pressed since previous release inline float & pressed() { return key_pressed; } + /// last time the key was pressed + inline float & lastpressed() { return key_lastpressed; } + inline std::string const & name() const { return key_name; } inline char ascii() const { return key_ascii; } @@ -54,6 +58,7 @@ private: char key_ascii; float key_pressed; + float key_lastpressed; std::string key_bind; std::string key_bind_shift; diff --git a/src/client/keyboard.cc b/src/client/keyboard.cc index 410e76c..10d98ea 100644 --- a/src/client/keyboard.cc +++ b/src/client/keyboard.cc @@ -214,7 +214,7 @@ Keyboard::~Keyboard() { // clear key map for (iterator it = begin(); it != end(); it++) - delete(*it).second; + delete (*it).second; keys.clear(); // clear action list @@ -284,6 +284,7 @@ Key * Keyboard::release(unsigned int sym) } key->pressed() = 0; + key->lastpressed() = 0; return key; } @@ -294,8 +295,14 @@ Key * Keyboard::press(unsigned int sym) return 0; } + return press(key); +} + +Key * Keyboard::press(Key *key) +{ if (!key->pressed()) key->pressed() = core::application()->time(); + key->lastpressed() = core::application()->time(); return key; } diff --git a/src/client/keyboard.h b/src/client/keyboard.h index 9712009..e4995e6 100644 --- a/src/client/keyboard.h +++ b/src/client/keyboard.h @@ -60,16 +60,19 @@ public: /// a key has been pressed Key *press(unsigned int sym); + /// a key has been pressed + Key *press(Key *key); + /// a key has been pressed Key *release(unsigned int sym); -private: typedef std::map::iterator iterator; - + inline iterator begin() { return keys.begin(); } inline iterator end() { return keys.end(); } +private: void add_key(const char *name, const unsigned int keysym, const char ascii=0, const char *bind=0); void add_action(const char *name, Action::Identifier action, const char *info = 0); -- cgit v1.2.3