src/Input.cc
changeset 311 440763821484
parent 300 417183866f35
child 319 9f6a838d58c4
equal deleted inserted replaced
310:7e0cfc5f0944 311:440763821484
     1 
       
     2 #define INPUT_CC
       
     3 
     1 
     4 #include "Input.hh"
     2 #include "Input.hh"
     5 
     3 #include "Config.hh"
     6 template <typename BitEnumType> struct InputKeymapEntry {
       
     7     BitEnumType input;
       
     8     int keycode1, keycode2;
       
     9 };
       
    10 
     4 
    11 InputKeymapEntry<PlayerInputBit> INPUT_PLAYER_KEYMAP[] = {
     5 InputKeymapEntry<PlayerInputBit> INPUT_PLAYER_KEYMAP[] = {
    12     {   INPUT_AIM_UP,       -CL_KEY_ENTER,      CL_KEY_UP       },
     6     {   INPUT_AIM_UP,       INPUT_FLAG_REPEAT,      { -CL_KEY_ENTER,    CL_KEY_UP       } },
    13     {   INPUT_AIM_DOWN,     -CL_KEY_ENTER,      CL_KEY_DOWN     },
     7     {   INPUT_AIM_DOWN,     INPUT_FLAG_REPEAT,      { -CL_KEY_ENTER,    CL_KEY_DOWN     } },
    14     {   INPUT_MOVE_LEFT,    -CL_KEY_ENTER,      CL_KEY_LEFT     },
     8     {   INPUT_MOVE_LEFT,    INPUT_FLAG_REPEAT,      { -CL_KEY_ENTER,    CL_KEY_LEFT     } },
    15     {   INPUT_MOVE_RIGHT,   -CL_KEY_ENTER,      CL_KEY_RIGHT    },
     9     {   INPUT_MOVE_RIGHT,   INPUT_FLAG_REPEAT,      { -CL_KEY_ENTER,    CL_KEY_RIGHT    } },
    16     {   INPUT_JUMP,         -CL_KEY_ENTER,      CL_KEY_RSHIFT   },
    10     {   INPUT_JUMP,         INPUT_FLAG_NOREPEAT,    { -CL_KEY_ENTER,    CL_KEY_RSHIFT   } },
    17     {   INPUT_DIG,          CL_KEY_LEFT,        CL_KEY_RIGHT    },
    11     {   INPUT_DIG,          INPUT_FLAG_NOREPEAT,    { CL_KEY_LEFT,      CL_KEY_RIGHT    } },
    18     {   INPUT_SHOOT,        CL_KEY_RCONTROL,    0               },
    12     {   INPUT_SHOOT,        INPUT_FLAG_REPEAT,      { CL_KEY_RCONTROL,  0               } },
    19     {   INPUT_CHANGE_PREV,  CL_KEY_ENTER,       CL_KEY_LEFT     },
    13     {   INPUT_CHANGE_PREV,  INPUT_FLAG_NOREPEAT,    { CL_KEY_ENTER,     CL_KEY_LEFT     } },
    20     {   INPUT_CHANGE_NEXT,  CL_KEY_ENTER,       CL_KEY_RIGHT    },
    14     {   INPUT_CHANGE_NEXT,  INPUT_FLAG_NOREPEAT,    { CL_KEY_ENTER,     CL_KEY_RIGHT    } },
    21     {   INPUT_ROPE,         CL_KEY_ENTER,       CL_KEY_RSHIFT   },
    15     {   INPUT_ROPE,         INPUT_FLAG_NOREPEAT,    { CL_KEY_ENTER,     CL_KEY_RSHIFT   } },
    22     {   INPUT_UNROPE,       -CL_KEY_ENTER,      CL_KEY_RSHIFT   },
    16     {   INPUT_UNROPE,       INPUT_FLAG_NOREPEAT,    { -CL_KEY_ENTER,    CL_KEY_RSHIFT   } },
    23     {   INPUT_ROPE_UP,      CL_KEY_ENTER,       CL_KEY_UP       },
    17     {   INPUT_ROPE_UP,      INPUT_FLAG_REPEAT,      { CL_KEY_ENTER,     CL_KEY_UP       } },
    24     {   INPUT_ROPE_DOWN,    CL_KEY_ENTER,       CL_KEY_DOWN     },
    18     {   INPUT_ROPE_DOWN,    INPUT_FLAG_REPEAT,      { CL_KEY_ENTER,     CL_KEY_DOWN     } },
    25     {   INPUT_SUICIDE,      CL_KEY_LCONTROL,    CL_KEY_K        },
    19     {   INPUT_SUICIDE,      INPUT_FLAG_NOREPEAT,    { CL_KEY_LCONTROL,  CL_KEY_K        } },
    26     {   INPUT_NONE,         0,                  0               }
    20     {   INPUT_NONE,         0,                      { 0,                0               } }
    27 };
    21 };
    28 
    22 
    29 InputKeymapEntry<GuiInputBit> INPUT_GUI_KEYMAP[] = {
    23 InputKeymapEntry<GuiInputBit> INPUT_GUI_KEYMAP[] = {
    30     {   GUI_INPUT_QUIT,             CL_KEY_ESCAPE,          0   },
    24     {   GUI_INPUT_QUIT,             0,              { CL_KEY_ESCAPE,    0               } },
    31     {   GUI_INPUT_DISPLAY_WEAPON,   CL_KEY_ENTER,           0   },
    25     {   GUI_INPUT_DISPLAY_WEAPON,   0,              { CL_KEY_ENTER,     0               } },
    32     {   GUI_INPUT_DEBUG_PLAYER,     CL_KEY_I,               0   },
    26     {   GUI_INPUT_DEBUG_PLAYER,     0,              { CL_KEY_I,         0               } },
       
    27     {   GUI_INPUT_NONE,             0,              { 0,                0,              } }
    33 };
    28 };
    34 
    29 
    35 Input::Input (CL_InputDevice &keyboard) :
    30 /*
    36     keyboard(keyboard)
    31  * InputKeyRepeatEntry
       
    32  */
       
    33 template <typename BitEnumType> 
       
    34 InputKeyRepeatEntry<BitEnumType>::InputKeyRepeatEntry (BitEnumType value, TimeMS expire) : 
       
    35     value(value), expire(expire) 
    37 {
    36 {
    38 
    37 
    39 }
    38 }
       
    39 
       
    40 template <typename BitEnumType> 
       
    41 bool InputKeyRepeatEntry<BitEnumType>::operator< (const struct InputKeyRepeatEntry &other) {
       
    42     return other.expire > expire;
       
    43 }
       
    44 
       
    45 template <typename BitEnumType> 
       
    46 bool InputKeyRepeatEntry<BitEnumType>::updateExpired (TimeMS dt) {
       
    47     expire -= dt;
       
    48 
       
    49     return (expire <= 0);
       
    50 }
       
    51 
       
    52 /*
       
    53  * InputKeyRepeatQueue
       
    54  */
       
    55 template <typename BitEnumType> 
       
    56 InputKeyRepeatQueue<BitEnumType>::InputKeyRepeatQueue (TimeMS expire) :
       
    57     expire(expire)
       
    58 {
       
    59 
       
    60 }
       
    61 
       
    62 template <typename BitEnumType> 
       
    63 void InputKeyRepeatQueue<BitEnumType>::push (BitEnumType bit) {
       
    64     list.push_back(InputKeyRepeatEntry<BitEnumType>(bit, expire));
       
    65 }
       
    66 
       
    67 template <typename BitEnumType> 
       
    68 bool InputKeyRepeatQueue<BitEnumType>::find (BitEnumType bit) {
       
    69     for (list_iterator it = list.begin(); it != list.end(); it++) {
       
    70         if (it->value == bit)
       
    71             return true;
       
    72     }
       
    73 
       
    74     return false;
       
    75 }
       
    76 
       
    77 template <typename BitEnumType> 
       
    78 void InputKeyRepeatQueue<BitEnumType>::update (TimeMS dt) {
       
    79     list_iterator it = list.begin();
    40     
    80     
    41 bool Input::checkKeycode (int keycode) {
    81     // go through each entry, updateExpired and remove if expired
       
    82     while (it != list.end()) {
       
    83         if (it->updateExpired(dt))
       
    84             it = list.erase(it);
       
    85         else
       
    86             it++;
       
    87     }
       
    88 }
       
    89 
       
    90 /*
       
    91  * InputHandler
       
    92  */
       
    93 template <typename BitEnumType, typename BitMaskType> 
       
    94 InputHandler<BitEnumType, BitMaskType>::InputHandler (CL_InputDevice &keyboard, InputKeymapEntry<BitEnumType> *keymap, TimeMS keyrepeat_expire) :
       
    95     keyboard(keyboard), 
       
    96     keymap(keymap), 
       
    97     value(0), 
       
    98     dt(0),
       
    99     queue(keyrepeat_expire)
       
   100 {
       
   101 
       
   102 }
       
   103 
       
   104 template <typename BitEnumType, typename BitMaskType> 
       
   105 bool InputHandler<BitEnumType, BitMaskType>::checkKeycode (int keycode) {
    42     if (keycode > 0)
   106     if (keycode > 0)
    43         return keyboard.get_keycode(keycode);
   107         return keyboard.get_keycode(keycode);
    44 
   108 
    45     else if (keycode < 0)
   109     else if (keycode < 0)
    46         return !keyboard.get_keycode(-keycode);
   110         return !keyboard.get_keycode(-keycode);
    47 
   111 
    48     else // == 0
   112     else // == 0
    49         return true;
   113         return true;
    50 }
   114 }
       
   115         
       
   116 template <typename BitEnumType, typename BitMaskType> 
       
   117 void InputHandler<BitEnumType, BitMaskType>::readValue (BitMaskType &mask, TimeMS &dt) {
       
   118     // copy to args
       
   119     mask = this->value;
       
   120     dt = this->dt;
    51 
   121 
    52 template <typename BitEnumType, typename BitMaskType> BitMaskType Input::buildMask (InputKeymapEntry<BitEnumType> *keymap) {
   122     this->value = 0;
    53     BitMaskType input_mask = 0;
   123     this->dt = 0;
    54 
       
    55     for (InputKeymapEntry<BitEnumType> *e = keymap; (e->keycode1 || e->keycode2) && e->input; e++) {
       
    56         if (checkKeycode(e->keycode1) && checkKeycode(e->keycode2))
       
    57             input_mask |= e->input;
       
    58     }
       
    59     
       
    60     return input_mask;
       
    61 }
   124 }
    62 
   125 
    63 PlayerInput Input::readPlayerInput (void) {
   126 template <typename BitEnumType, typename BitMaskType> 
    64     return buildMask<PlayerInputBit, PlayerInput>(INPUT_PLAYER_KEYMAP);
   127 void InputHandler<BitEnumType, BitMaskType>::update (TimeMS dt) {
       
   128     // update the key-repeat queue
       
   129     queue.update(dt);
       
   130 
       
   131     // then go through the keymap
       
   132     for (InputKeymapEntry<BitEnumType> *e = keymap; e->input != 0; e++) {
       
   133         // check if we've got the correct keycodes
       
   134         if (checkKeycode(e->keycodes[0]) && checkKeycode(e->keycodes[1])) {
       
   135             // should we do keyrepeats?
       
   136             if (e->flags & INPUT_FLAG_NOREPEAT) {
       
   137                 // if it's in the queue, ignore, else add it
       
   138                 if (queue.find(e->input))
       
   139                     continue;
       
   140                 else
       
   141                     queue.push(e->input);
       
   142             }
       
   143 
       
   144             // set bit in mask
       
   145             this->value |= e->input;
       
   146         }
       
   147     }
       
   148 
       
   149     // then increment our dt
       
   150     this->dt += dt;
       
   151 }
       
   152 
       
   153 /**
       
   154  * Input
       
   155  */
       
   156 Input::Input (CL_InputDevice &keyboard) :
       
   157     keyboard(keyboard),
       
   158     update_timer(INPUT_POLL_INTERVAL),
       
   159     player(keyboard, INPUT_PLAYER_KEYMAP, INPUT_REPEAT_DELAY),
       
   160     gui(keyboard, INPUT_GUI_KEYMAP, INPUT_REPEAT_DELAY)
       
   161 {
       
   162     // connect timer 
       
   163     slots.connect(update_timer.sig_tick(), &player, &InputHandler<PlayerInputBit, PlayerInput>::update);
       
   164     slots.connect(update_timer.sig_tick(), &gui, &InputHandler<GuiInputBit, GuiInput>::update);
       
   165 
       
   166     // enable timer
       
   167     update_timer.start();
       
   168 }
       
   169 
       
   170 void Input::readPlayerInput (PlayerInput &mask, TimeMS &dt) {
       
   171     player.readValue(mask, dt);
    65 }
   172 }
    66 
   173 
    67 GuiInput Input::readGuiInput (void) {
   174 GuiInput Input::readGuiInput (void) {
    68     return buildMask<GuiInputBit, GuiInput>(INPUT_GUI_KEYMAP);
   175     GuiInput mask;
       
   176     TimeMS dt;
       
   177 
       
   178     gui.readValue(mask, dt);
       
   179 
       
   180     return mask;
    69 }
   181 }
    70 
   182