Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/core/input/KeyBinder.cc @ 1535

Last change on this file since 1535 was 1535, checked in by rgrieder, 16 years ago

merged input branch back to trunk

  • Property svn:eol-style set to native
File size: 16.2 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Reto Grieder
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30 @file
31 @brief Implementation of the different input handlers.
32 */
33
34#include "KeyBinder.h"
35#include <fstream>
36#include <string>
37#include "util/Convert.h"
38#include "core/Debug.h"
39#include "core/ConfigValueIncludes.h"
40#include "core/CoreIncludes.h"
41#include "InputCommands.h"
42
43namespace orxonox
44{
45  /**
46    @brief Constructor that does as little as necessary.
47  */
48  KeyBinder::KeyBinder() : deriveTime_(0.0f)
49  {
50    mouseRelative_[0] = 0;
51    mouseRelative_[1] = 0;
52    mousePosition_[0] = 0;
53    mousePosition_[1] = 0;
54
55    RegisterRootObject(KeyBinder);
56
57    // keys
58    std::string keyNames[] = {
59      "UNASSIGNED",
60      "ESCAPE",
61      "1", "2", "3", "4", "5", "6", "7", "8", "9", "0",
62      "MINUS", "EQUALS", "BACK", "TAB",
63      "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P",
64      "LBRACKET", "RBRACKET",
65      "RETURN", "LCONTROL",
66      "A", "S", "D", "F", "G", "H", "J", "K", "L",
67      "SEMICOLON", "APOSTROPHE", "GRAVE",
68      "LSHIFT", "BACKSLASH",
69      "Z", "X", "C", "V", "B", "N", "M",
70      "COMMA", "PERIOD", "SLASH",
71      "RSHIFT",
72      "MULTIPLY",
73      "LMENU",
74      "SPACE",
75      "CAPITAL",
76      "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10",
77      "NUMLOCK", "SCROLL",
78      "NUMPAD7", "NUMPAD8", "NUMPAD9",
79      "SUBTRACT",
80      "NUMPAD4", "NUMPAD5", "NUMPAD6",
81      "ADD",
82      "NUMPAD1", "NUMPAD2", "NUMPAD3", "NUMPAD0",
83      "DECIMAL",
84      "","",
85      "OEM_102",
86      "F11", "F12",
87      "","","","","","","","","","","",
88      "F13", "F14", "F15",
89      "","","","","","","","","","",
90      "KANA",
91      "","",
92      "ABNT_C1",
93      "","","","","",
94      "CONVERT",
95      "",
96      "NOCONVERT",
97      "",
98      "YEN",
99      "ABNT_C2",
100      "","","","","","","","","","","","","","",
101      "NUMPADEQUALS",
102      "","",
103      "PREVTRACK",
104      "AT",
105      "COLON", "UNDERLINE",
106      "KANJI",
107      "STOP",
108      "AX",
109      "UNLABELED",
110      "NEXTTRACK",
111      "","",
112      "NUMPADENTER",
113      "RCONTROL",
114      "","",
115      "MUTE",
116      "CALCULATOR",
117      "PLAYPAUSE",
118      "",
119      "MEDIASTOP",
120      "","","","","","","","","",
121      "VOLUMEDOWN",
122      "",
123      "VOLUMEUP",
124      "",
125      "WEBHOME",
126      "NUMPADCOMMA",
127      "",
128      "DIVIDE",
129      "",
130      "SYSRQ",
131      "RMENU",
132      "","","","","","","","","","","","",
133      "PAUSE",
134      "",
135      "HOME",
136      "UP",
137      "PGUP",
138      "",
139      "LEFT",
140      "",
141      "RIGHT",
142      "",
143      "END", "DOWN", "PGDOWN", "INSERT", "DELETE",
144      "","","","","","","",
145      "LWIN", "RWIN", "APPS",
146      "POWER", "SLEEP",
147      "","","",
148      "WAKE",
149      "",
150      "WEBSEARCH", "WEBFAVORITES", "WEBREFRESH", "WEBSTOP", "WEBFORWARD", "WEBBACK",
151      "MYCOMPUTER", "MAIL", "MEDIASELECT"
152    };
153    for (unsigned int i = 0; i < nKeys_s; i++)
154      keys_[i].name_ = "Key" + keyNames[i];
155
156    // mouse buttons
157    std::string mouseButtonNames[] = {
158      "MouseLeft", "MouseRight", "MouseMiddle",
159      "MouseButton3", "MouseButton4", "MouseButton5",
160      "MouseButton6", "MouseButton7",
161      "MouseWheel1Up", "MouseWheel1Down",
162      "MouseWheel2Up", "MouseWheel2Down" };
163    for (unsigned int i = 0; i < nMouseButtons_s; i++)
164      mouseButtons_[i].name_ = mouseButtonNames[i];
165
166    // joy stick buttons
167    for (unsigned int i = 0; i < 32; i++)
168      joyStickButtons_[i].name_ = "JoyButton" + getConvertedValue<int, std::string>(i);
169    for (unsigned int i = 32; i < nJoyStickButtons_s; i += 4)
170    {
171                  joyStickButtons_[i + 0].name_ = "JoyPOV" + getConvertedValue<int, std::string>((i - 32)/4 + 1) + "North";
172                  joyStickButtons_[i + 1].name_ = "JoyPOV" + getConvertedValue<int, std::string>((i - 32)/4 + 1) + "South";
173                  joyStickButtons_[i + 2].name_ = "JoyPOV" + getConvertedValue<int, std::string>((i - 32)/4 + 1) + "East";
174                  joyStickButtons_[i + 3].name_ = "JoyPOV" + getConvertedValue<int, std::string>((i - 32)/4 + 1) + "West";
175    }
176
177    // half axes
178    std::string rawNames[nHalfAxes_s/2];
179    rawNames[0] = "MouseX";
180    rawNames[1] = "MouseY";
181    rawNames[2] = "Empty1";
182    rawNames[3] = "Empty2";
183    for (unsigned int i = 4; i < nHalfAxes_s/2; i++)
184      rawNames[i] = "JoyAxis" + getConvertedValue<int, std::string>(i - 3);
185    for (unsigned int i = 0; i < nHalfAxes_s/2; i++)
186    {
187      halfAxes_[i * 2 + 0].name_ = rawNames[i] + "Pos";
188      halfAxes_[i * 2 + 1].name_ = rawNames[i] + "Neg";
189    }
190
191    for (unsigned int i = 0; i < this->nHalfAxes_s; i++)
192      halfAxes_[i].buttonThreshold_ = buttonThreshold_;
193  }
194
195  /**
196    @brief Destructor
197  */
198  KeyBinder::~KeyBinder()
199  {
200    // almost no destructors required because most of the arrays are static.
201    clearBindings(); // does some destruction work
202  }
203
204  /**
205    @brief Loads the key and button bindings.
206    @return True if loading succeeded.
207  */
208  void KeyBinder::loadBindings()
209  {
210    COUT(3) << "KeyBinder: Loading key bindings..." << std::endl;
211
212    clearBindings();
213
214    std::ifstream infile;
215    infile.open("keybindings.ini");
216    if (!infile.is_open())
217    {
218      ConfigFileManager::getSingleton()->setFile(CFT_Keybindings, "def_keybindings.ini");
219      ConfigFileManager::getSingleton()->save(CFT_Keybindings, "keybindings.ini");
220    }
221    infile.close();
222    ConfigFileManager::getSingleton()->setFile(CFT_Keybindings, "keybindings.ini");
223
224    // parse key bindings
225    setConfigValues();
226
227    COUT(3) << "KeyBinder: Loading key bindings done." << std::endl;
228  }
229
230  /**
231    @brief Loader for the key bindings, managed by config values.
232  */
233  void KeyBinder::setConfigValues()
234  {
235    SetConfigValueGeneric(KeyBinder, analogThreshold_, 0.01f)  .description("Threshold for analog axes until which the state is 0.");
236    SetConfigValueGeneric(KeyBinder, mouseSensitivity_, 1.0f)  .description("Mouse sensitivity.");
237    SetConfigValueGeneric(KeyBinder, bDeriveMouseInput_, false).description("Whether or not to derive moues movement for the absolute value.");
238    SetConfigValueGeneric(KeyBinder, derivePeriod_, 0.5f).description("Accuracy of the mouse input deriver. The higher the more precise, but laggier.");
239    SetConfigValueGeneric(KeyBinder, mouseSensitivityDerived_, 1.0f).description("Mouse sensitivity if mouse input is derived.");
240    SetConfigValueGeneric(KeyBinder, bClipMouse_, true).description("Whether or not to clip absolute value of mouse in non derive mode.");
241
242    float oldThresh = buttonThreshold_;
243    SetConfigValueGeneric(KeyBinder, buttonThreshold_, 0.80f).description("Threshold for analog axes until which the button is not pressed.");
244    if (oldThresh != buttonThreshold_)
245      for (unsigned int i = 0; i < nHalfAxes_s; i++)
246        if (halfAxes_[i].buttonThreshold_ == oldThresh)
247          halfAxes_[i].buttonThreshold_ = buttonThreshold_;
248
249    // keys
250    for (unsigned int i = 0; i < nKeys_s; i++)
251      readTrigger(keys_[i]);
252    // mouse buttons
253    for (unsigned int i = 0; i < nMouseButtons_s; i++)
254      readTrigger(mouseButtons_[i]);
255    // joy stick buttons
256    for (unsigned int i = 0; i < nJoyStickButtons_s; i++)
257      readTrigger(joyStickButtons_[i]);
258    // half axes
259    for (unsigned int i = 0; i < nHalfAxes_s; i++)
260      readTrigger(halfAxes_[i]);
261  }
262
263  void KeyBinder::readTrigger(Button& button)
264  {
265    // config value stuff
266    ConfigValueContainer* cont = ClassManager<KeyBinder>::getIdentifier()->getConfigValueContainer(button.name_);
267    if (!cont)
268    {
269      cont = new ConfigValueContainer(CFT_Keybindings, ClassManager<KeyBinder>::getIdentifier(), button.name_, "");
270      ClassManager<KeyBinder>::getIdentifier()->addConfigValueContainer(button.name_, cont);
271    }
272    std::string old = button.bindingString_;
273    cont->getValue(&button.bindingString_);
274
275    // keybinder stuff
276    if (old != button.bindingString_)
277    {
278      // clear everything so we don't get old axis ParamCommands mixed up
279      button.clear();
280
281      // binding has changed
282      button.parse(paramCommandBuffer_);
283    }
284  }
285
286  /**
287    @brief Overwrites all bindings with ""
288  */
289  void KeyBinder::clearBindings()
290  {
291    for (unsigned int i = 0; i < nKeys_s; i++)
292      keys_[i].clear();
293
294    for (unsigned int i = 0; i < nMouseButtons_s; i++)
295      mouseButtons_[i].clear();
296
297    for (unsigned int i = 0; i < nJoyStickButtons_s; i++)
298      joyStickButtons_[i].clear();
299
300    for (unsigned int i = 0; i < nHalfAxes_s; i++)
301      halfAxes_[i].clear();
302
303    for (unsigned int i = 0; i < paramCommandBuffer_.size(); i++)
304      delete paramCommandBuffer_[i];
305    paramCommandBuffer_.clear();
306  }
307
308  void KeyBinder::resetJoyStickAxes()
309  {
310    for (unsigned int i = 8; i < nHalfAxes_s; i++)
311    {
312      halfAxes_[i].absVal_ = 0.0f;
313      halfAxes_[i].relVal_ = 0.0f;
314    }
315  }
316
317  void KeyBinder::tickInput(float dt, const HandlerState& state)
318  {
319    // we have to process all the analog input since there is e.g. no 'mouseDoesntMove' event.
320    unsigned int iBegin = 8;
321    unsigned int iEnd   = 8;
322    if (state.joyStick)
323      iEnd = nHalfAxes_s;
324    if (state.mouse)
325      iBegin = 0;
326    for (unsigned int i = iBegin; i < iEnd; i++)
327    {
328      if (halfAxes_[i].hasChanged_)
329      {
330        if (!halfAxes_[i].wasDown_ && halfAxes_[i].absVal_ > halfAxes_[i].buttonThreshold_)
331        {
332          halfAxes_[i].wasDown_ = true;
333          if (halfAxes_[i].nCommands_[KeybindMode::OnPress])
334            halfAxes_[i].execute(KeybindMode::OnPress);
335        }
336        else if (halfAxes_[i].wasDown_ && halfAxes_[i].absVal_ < halfAxes_[i].buttonThreshold_)
337        {
338          halfAxes_[i].wasDown_ = false;
339          if (halfAxes_[i].nCommands_[KeybindMode::OnRelease])
340            halfAxes_[i].execute(KeybindMode::OnRelease);
341        }
342        halfAxes_[i].hasChanged_ = false;
343      }
344
345      if (halfAxes_[i].wasDown_)
346      {
347        if (halfAxes_[i].nCommands_[KeybindMode::OnHold])
348          halfAxes_[i].execute(KeybindMode::OnHold);
349      }
350
351      // these are the actually useful axis bindings for analog input AND output
352      if (halfAxes_[i].relVal_ > analogThreshold_ || halfAxes_[i].absVal_ > analogThreshold_)
353      {
354        //COUT(3) << halfAxes_[i].name_ << "\t" << halfAxes_[i].absVal_ << std::endl;
355        halfAxes_[i].execute();
356      }
357    }
358
359    if (bDeriveMouseInput_ && state.mouse)
360    {
361      if (deriveTime_ > derivePeriod_)
362      {
363        //CCOUT(3) << "mouse abs: ";
364        for (int i = 0; i < 2; i++)
365        {
366          if (mouseRelative_[i] > 0)
367          {
368            halfAxes_[2*i + 0].absVal_ =  mouseRelative_[i] / deriveTime_ * 0.0005 * mouseSensitivityDerived_;
369            halfAxes_[2*i + 1].absVal_ = 0.0f;
370          }
371          else if (mouseRelative_[i] < 0)
372          {
373            halfAxes_[2*i + 0].absVal_ = 0.0f;
374            halfAxes_[2*i + 1].absVal_ = -mouseRelative_[i] / deriveTime_ * 0.0005 * mouseSensitivityDerived_;
375          }
376          else
377          {
378            halfAxes_[2*i + 0].absVal_ = 0.0f;
379            halfAxes_[2*i + 1].absVal_ = 0.0f;
380          }
381          //COUT(3) << mouseRelative_[i] << " | ";
382          mouseRelative_[i] = 0;
383          halfAxes_[2*i + 0].hasChanged_ = true;
384          halfAxes_[2*i + 1].hasChanged_ = true;
385        }
386        deriveTime_ = 0.0f;
387        //COUT(3) << std::endl;
388      }
389      else
390        deriveTime_ += dt;
391    }
392
393    // execute all buffered bindings (addional parameter)
394    for (unsigned int i = 0; i < paramCommandBuffer_.size(); i++)
395      paramCommandBuffer_[i]->execute();
396
397    // always reset the relative movement of the mouse
398    if (state.mouse)
399      for (unsigned int i = 0; i < 8; i++)
400        halfAxes_[i].relVal_ = 0.0f;
401  }
402
403  void KeyBinder::keyPressed (const KeyEvent& evt)
404  { keys_[evt.key].execute(KeybindMode::OnPress); }
405
406  void KeyBinder::keyReleased(const KeyEvent& evt)
407  { keys_[evt.key].execute(KeybindMode::OnRelease); }
408
409  void KeyBinder::keyHeld    (const KeyEvent& evt)
410  { keys_[evt.key].execute(KeybindMode::OnHold); }
411
412
413  void KeyBinder::mouseButtonPressed (MouseButton::Enum id)
414  { mouseButtons_[id].execute(KeybindMode::OnPress); }
415
416  void KeyBinder::mouseButtonReleased(MouseButton::Enum id)
417  { mouseButtons_[id].execute(KeybindMode::OnRelease); }
418
419  void KeyBinder::mouseButtonHeld    (MouseButton::Enum id)
420  { mouseButtons_[id].execute(KeybindMode::OnHold); }
421
422
423  void KeyBinder::joyStickButtonPressed (int joyStickID, int button)
424  { joyStickButtons_[button].execute(KeybindMode::OnPress); }
425
426  void KeyBinder::joyStickButtonReleased(int joyStickID, int button)
427  { joyStickButtons_[button].execute(KeybindMode::OnRelease); }
428
429  void KeyBinder::joyStickButtonHeld    (int joyStickID, int button)
430  { joyStickButtons_[button].execute(KeybindMode::OnHold); }
431
432  /**
433    @brief Event handler for the mouseMoved Event.
434    @param e Mouse state information
435  */
436  void KeyBinder::mouseMoved(IntVector2 abs_, IntVector2 rel_, IntVector2 clippingSize)
437  {
438    // y axis of mouse input is inverted
439    int rel[] = { rel_.x, -rel_.y };
440
441    if (!bDeriveMouseInput_)
442    {
443      for (int i = 0; i < 2; i++)
444      {
445        if (rel[i])
446        {
447          // absolute
448          halfAxes_[2*i + 0].hasChanged_ = true;
449          halfAxes_[2*i + 1].hasChanged_ = true;
450          mousePosition_[i] += rel[i];
451
452          if (bClipMouse_)
453          {
454            if (mousePosition_[i] > 1024)
455              mousePosition_[i] =  1024;
456            if (mousePosition_[i] < -1024)
457              mousePosition_[i] = -1024;
458          }
459
460          if (mousePosition_[i] >= 0)
461          {
462            halfAxes_[2*i + 0].absVal_ =   mousePosition_[i]/1024.0f * mouseSensitivity_;
463            halfAxes_[2*i + 1].absVal_ =  0.0f;
464          }
465          else
466          {
467            halfAxes_[2*i + 0].absVal_ =  0.0f;
468            halfAxes_[2*i + 1].absVal_ =  -mousePosition_[i]/1024.0f * mouseSensitivity_;
469          }
470        }
471      }
472    }
473    else
474    {
475      mouseRelative_[0] += rel[0];
476      mouseRelative_[1] += rel[1];
477    }
478
479    // relative
480    for (int i = 0; i < 2; i++)
481    {
482      if (rel[i] > 0)
483        halfAxes_[0 + 2*i].relVal_ =  ((float)rel[i])/1024 * mouseSensitivity_;
484      else
485        halfAxes_[1 + 2*i].relVal_ = -((float)rel[i])/1024 * mouseSensitivity_;
486    }
487  }
488
489  /**
490    @brief Event handler for the mouseScrolled Event.
491    @param e Mouse state information
492  */
493  void KeyBinder::mouseScrolled(int abs, int rel)
494  {
495    //COUT(3) << mouseButtons_[8].name_ << "   " << abs << " | " << rel << std::endl;
496
497    if (rel > 0)
498      for (int i = 0; i < rel/120; i++)
499        mouseButtons_[8].execute(KeybindMode::OnPress, ((float)abs)/120.0f);
500    else
501      for (int i = 0; i < -rel/120; i++)
502        mouseButtons_[9].execute(KeybindMode::OnPress, ((float)abs)/120.0f);
503  }
504
505  void KeyBinder::joyStickAxisMoved(int joyStickID, int axis, float value)
506  {
507    // TODO: Use proper calibration values instead of generally 16-bit integer
508    int i = 8 + axis * 2;
509    if (value >= 0)
510    {
511      //if (value > 10000)
512      //{ CCOUT(3) << halfAxes_[i].name_ << std::endl; }
513
514      halfAxes_[i].absVal_ = value;
515      halfAxes_[i].relVal_ = value;
516      halfAxes_[i].hasChanged_ = true;
517      if (halfAxes_[i + 1].absVal_ > 0.0f)
518      {
519        halfAxes_[i + 1].absVal_ = -0.0f;
520        halfAxes_[i + 1].relVal_ = -0.0f;
521        halfAxes_[i + 1].hasChanged_ = true;
522      }
523    }
524    else
525    {
526      //if (value < -10000)
527      //{ CCOUT(3) << halfAxes_[i + 1].name_ << std::endl; }
528
529      halfAxes_[i + 1].absVal_ = -value;
530      halfAxes_[i + 1].relVal_ = -value;
531      halfAxes_[i + 1].hasChanged_ = true;
532      if (halfAxes_[i].absVal_ > 0.0f)
533      {
534        halfAxes_[i].absVal_ = -0.0f;
535        halfAxes_[i].relVal_ = -0.0f;
536        halfAxes_[i].hasChanged_ = true;
537      }
538    }
539  }
540}
Note: See TracBrowser for help on using the repository browser.