diff -r 7e0cfc5f0944 -r 440763821484 src/Input.cc --- a/src/Input.cc Mon Dec 08 21:15:52 2008 +0000 +++ b/src/Input.cc Mon Dec 08 21:18:08 2008 +0000 @@ -1,44 +1,108 @@ - -#define INPUT_CC #include "Input.hh" - -template struct InputKeymapEntry { - BitEnumType input; - int keycode1, keycode2; -}; +#include "Config.hh" InputKeymapEntry INPUT_PLAYER_KEYMAP[] = { - { INPUT_AIM_UP, -CL_KEY_ENTER, CL_KEY_UP }, - { INPUT_AIM_DOWN, -CL_KEY_ENTER, CL_KEY_DOWN }, - { INPUT_MOVE_LEFT, -CL_KEY_ENTER, CL_KEY_LEFT }, - { INPUT_MOVE_RIGHT, -CL_KEY_ENTER, CL_KEY_RIGHT }, - { INPUT_JUMP, -CL_KEY_ENTER, CL_KEY_RSHIFT }, - { INPUT_DIG, CL_KEY_LEFT, CL_KEY_RIGHT }, - { INPUT_SHOOT, CL_KEY_RCONTROL, 0 }, - { INPUT_CHANGE_PREV, CL_KEY_ENTER, CL_KEY_LEFT }, - { INPUT_CHANGE_NEXT, CL_KEY_ENTER, CL_KEY_RIGHT }, - { INPUT_ROPE, CL_KEY_ENTER, CL_KEY_RSHIFT }, - { INPUT_UNROPE, -CL_KEY_ENTER, CL_KEY_RSHIFT }, - { INPUT_ROPE_UP, CL_KEY_ENTER, CL_KEY_UP }, - { INPUT_ROPE_DOWN, CL_KEY_ENTER, CL_KEY_DOWN }, - { INPUT_SUICIDE, CL_KEY_LCONTROL, CL_KEY_K }, - { INPUT_NONE, 0, 0 } + { INPUT_AIM_UP, INPUT_FLAG_REPEAT, { -CL_KEY_ENTER, CL_KEY_UP } }, + { INPUT_AIM_DOWN, INPUT_FLAG_REPEAT, { -CL_KEY_ENTER, CL_KEY_DOWN } }, + { INPUT_MOVE_LEFT, INPUT_FLAG_REPEAT, { -CL_KEY_ENTER, CL_KEY_LEFT } }, + { INPUT_MOVE_RIGHT, INPUT_FLAG_REPEAT, { -CL_KEY_ENTER, CL_KEY_RIGHT } }, + { INPUT_JUMP, INPUT_FLAG_NOREPEAT, { -CL_KEY_ENTER, CL_KEY_RSHIFT } }, + { INPUT_DIG, INPUT_FLAG_NOREPEAT, { CL_KEY_LEFT, CL_KEY_RIGHT } }, + { INPUT_SHOOT, INPUT_FLAG_REPEAT, { CL_KEY_RCONTROL, 0 } }, + { INPUT_CHANGE_PREV, INPUT_FLAG_NOREPEAT, { CL_KEY_ENTER, CL_KEY_LEFT } }, + { INPUT_CHANGE_NEXT, INPUT_FLAG_NOREPEAT, { CL_KEY_ENTER, CL_KEY_RIGHT } }, + { INPUT_ROPE, INPUT_FLAG_NOREPEAT, { CL_KEY_ENTER, CL_KEY_RSHIFT } }, + { INPUT_UNROPE, INPUT_FLAG_NOREPEAT, { -CL_KEY_ENTER, CL_KEY_RSHIFT } }, + { INPUT_ROPE_UP, INPUT_FLAG_REPEAT, { CL_KEY_ENTER, CL_KEY_UP } }, + { INPUT_ROPE_DOWN, INPUT_FLAG_REPEAT, { CL_KEY_ENTER, CL_KEY_DOWN } }, + { INPUT_SUICIDE, INPUT_FLAG_NOREPEAT, { CL_KEY_LCONTROL, CL_KEY_K } }, + { INPUT_NONE, 0, { 0, 0 } } }; InputKeymapEntry INPUT_GUI_KEYMAP[] = { - { GUI_INPUT_QUIT, CL_KEY_ESCAPE, 0 }, - { GUI_INPUT_DISPLAY_WEAPON, CL_KEY_ENTER, 0 }, - { GUI_INPUT_DEBUG_PLAYER, CL_KEY_I, 0 }, + { GUI_INPUT_QUIT, 0, { CL_KEY_ESCAPE, 0 } }, + { GUI_INPUT_DISPLAY_WEAPON, 0, { CL_KEY_ENTER, 0 } }, + { GUI_INPUT_DEBUG_PLAYER, 0, { CL_KEY_I, 0 } }, + { GUI_INPUT_NONE, 0, { 0, 0, } } }; -Input::Input (CL_InputDevice &keyboard) : - keyboard(keyboard) +/* + * InputKeyRepeatEntry + */ +template +InputKeyRepeatEntry::InputKeyRepeatEntry (BitEnumType value, TimeMS expire) : + value(value), expire(expire) { } + +template +bool InputKeyRepeatEntry::operator< (const struct InputKeyRepeatEntry &other) { + return other.expire > expire; +} + +template +bool InputKeyRepeatEntry::updateExpired (TimeMS dt) { + expire -= dt; + + return (expire <= 0); +} + +/* + * InputKeyRepeatQueue + */ +template +InputKeyRepeatQueue::InputKeyRepeatQueue (TimeMS expire) : + expire(expire) +{ + +} + +template +void InputKeyRepeatQueue::push (BitEnumType bit) { + list.push_back(InputKeyRepeatEntry(bit, expire)); +} + +template +bool InputKeyRepeatQueue::find (BitEnumType bit) { + for (list_iterator it = list.begin(); it != list.end(); it++) { + if (it->value == bit) + return true; + } + + return false; +} + +template +void InputKeyRepeatQueue::update (TimeMS dt) { + list_iterator it = list.begin(); -bool Input::checkKeycode (int keycode) { + // go through each entry, updateExpired and remove if expired + while (it != list.end()) { + if (it->updateExpired(dt)) + it = list.erase(it); + else + it++; + } +} + +/* + * InputHandler + */ +template +InputHandler::InputHandler (CL_InputDevice &keyboard, InputKeymapEntry *keymap, TimeMS keyrepeat_expire) : + keyboard(keyboard), + keymap(keymap), + value(0), + dt(0), + queue(keyrepeat_expire) +{ + +} + +template +bool InputHandler::checkKeycode (int keycode) { if (keycode > 0) return keyboard.get_keycode(keycode); @@ -48,23 +112,71 @@ else // == 0 return true; } - -template BitMaskType Input::buildMask (InputKeymapEntry *keymap) { - BitMaskType input_mask = 0; + +template +void InputHandler::readValue (BitMaskType &mask, TimeMS &dt) { + // copy to args + mask = this->value; + dt = this->dt; - for (InputKeymapEntry *e = keymap; (e->keycode1 || e->keycode2) && e->input; e++) { - if (checkKeycode(e->keycode1) && checkKeycode(e->keycode2)) - input_mask |= e->input; - } - - return input_mask; + this->value = 0; + this->dt = 0; } -PlayerInput Input::readPlayerInput (void) { - return buildMask(INPUT_PLAYER_KEYMAP); +template +void InputHandler::update (TimeMS dt) { + // update the key-repeat queue + queue.update(dt); + + // then go through the keymap + for (InputKeymapEntry *e = keymap; e->input != 0; e++) { + // check if we've got the correct keycodes + if (checkKeycode(e->keycodes[0]) && checkKeycode(e->keycodes[1])) { + // should we do keyrepeats? + if (e->flags & INPUT_FLAG_NOREPEAT) { + // if it's in the queue, ignore, else add it + if (queue.find(e->input)) + continue; + else + queue.push(e->input); + } + + // set bit in mask + this->value |= e->input; + } + } + + // then increment our dt + this->dt += dt; +} + +/** + * Input + */ +Input::Input (CL_InputDevice &keyboard) : + keyboard(keyboard), + update_timer(INPUT_POLL_INTERVAL), + player(keyboard, INPUT_PLAYER_KEYMAP, INPUT_REPEAT_DELAY), + gui(keyboard, INPUT_GUI_KEYMAP, INPUT_REPEAT_DELAY) +{ + // connect timer + slots.connect(update_timer.sig_tick(), &player, &InputHandler::update); + slots.connect(update_timer.sig_tick(), &gui, &InputHandler::update); + + // enable timer + update_timer.start(); +} + +void Input::readPlayerInput (PlayerInput &mask, TimeMS &dt) { + player.readValue(mask, dt); } GuiInput Input::readGuiInput (void) { - return buildMask(INPUT_GUI_KEYMAP); + GuiInput mask; + TimeMS dt; + + gui.readValue(mask, dt); + + return mask; }