Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core3/src/core/input/KeyBinder.cc @ 1685

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

ConfigFileManager::getSingleton —> getInstance()

  • Property svn:eol-style set to native
File size: 16.1 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 "util/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)
217    {
218      ConfigFileManager::getInstance()->setFile(CFT_Keybindings, "def_keybindings.ini");
219      ConfigFileManager::getInstance()->save(CFT_Keybindings, "keybindings.ini");
220    }
221    else
222      infile.close();
223    ConfigFileManager::getInstance()->setFile(CFT_Keybindings, "keybindings.ini");
224
225    // parse key bindings
226    setConfigValues();
227
228    COUT(3) << "KeyBinder: Loading key bindings done." << std::endl;
229  }
230
231  /**
232    @brief Loader for the key bindings, managed by config values.
233  */
234  void KeyBinder::setConfigValues()
235  {
236    SetConfigValue(analogThreshold_, 0.05f)  .description("Threshold for analog axes until which the state is 0.");
237    SetConfigValue(mouseSensitivity_, 1.0f)  .description("Mouse sensitivity.");
238    SetConfigValue(bDeriveMouseInput_, false).description("Whether or not to derive moues movement for the absolute value.");
239    SetConfigValue(derivePeriod_, 0.05f).description("Accuracy of the mouse input deriver. The higher the more precise, but laggier.");
240    SetConfigValue(mouseSensitivityDerived_, 1.0f).description("Mouse sensitivity if mouse input is derived.");
241    SetConfigValue(bClipMouse_, true).description("Whether or not to clip absolute value of mouse in non derive mode.");
242
243    float oldThresh = buttonThreshold_;
244    SetConfigValue(buttonThreshold_, 0.80f).description("Threshold for analog axes until which the button is not pressed.");
245    if (oldThresh != buttonThreshold_)
246      for (unsigned int i = 0; i < nHalfAxes_s; i++)
247        if (halfAxes_[i].buttonThreshold_ == oldThresh)
248          halfAxes_[i].buttonThreshold_ = buttonThreshold_;
249
250    // keys
251    for (unsigned int i = 0; i < nKeys_s; i++)
252      readTrigger(keys_[i]);
253    // mouse buttons
254    for (unsigned int i = 0; i < nMouseButtons_s; i++)
255      readTrigger(mouseButtons_[i]);
256    // joy stick buttons
257    for (unsigned int i = 0; i < nJoyStickButtons_s; i++)
258      readTrigger(joyStickButtons_[i]);
259    // half axes
260    for (unsigned int i = 0; i < nHalfAxes_s; i++)
261      readTrigger(halfAxes_[i]);
262  }
263
264  void KeyBinder::readTrigger(Button& button)
265  {
266    // config value stuff
267    ConfigValueContainer* cont = ClassIdentifier<KeyBinder>::getIdentifier()->getConfigValueContainer(button.name_);
268    if (!cont)
269    {
270      cont = new ConfigValueContainer(CFT_Keybindings, ClassIdentifier<KeyBinder>::getIdentifier(), button.name_, "", button.name_);
271      ClassIdentifier<KeyBinder>::getIdentifier()->addConfigValueContainer(button.name_, cont);
272    }
273    std::string old = button.bindingString_;
274    cont->getValue(&button.bindingString_, this);
275
276    // keybinder stuff
277    if (old != button.bindingString_)
278    {
279      // clear everything so we don't get old axis ParamCommands mixed up
280      button.clear();
281
282      // binding has changed
283      button.parse(paramCommandBuffer_);
284    }
285  }
286
287  /**
288    @brief Overwrites all bindings with ""
289  */
290  void KeyBinder::clearBindings()
291  {
292    for (unsigned int i = 0; i < nKeys_s; i++)
293      keys_[i].clear();
294
295    for (unsigned int i = 0; i < nMouseButtons_s; i++)
296      mouseButtons_[i].clear();
297
298    for (unsigned int i = 0; i < nJoyStickButtons_s; i++)
299      joyStickButtons_[i].clear();
300
301    for (unsigned int i = 0; i < nHalfAxes_s; i++)
302      halfAxes_[i].clear();
303
304    for (unsigned int i = 0; i < paramCommandBuffer_.size(); i++)
305      delete paramCommandBuffer_[i];
306    paramCommandBuffer_.clear();
307  }
308
309  void KeyBinder::resetJoyStickAxes()
310  {
311    for (unsigned int i = 8; i < nHalfAxes_s; i++)
312    {
313      halfAxes_[i].absVal_ = 0.0f;
314      halfAxes_[i].relVal_ = 0.0f;
315    }
316  }
317
318  void KeyBinder::tickInput(float dt, const HandlerState& state)
319  {
320    // we have to process all the analog input since there is e.g. no 'mouseDoesntMove' event.
321    unsigned int iBegin = 8;
322    unsigned int iEnd   = 8;
323    if (state.joyStick)
324      iEnd = nHalfAxes_s;
325    if (state.mouse)
326      iBegin = 0;
327    for (unsigned int i = iBegin; i < iEnd; i++)
328    {
329      if (halfAxes_[i].hasChanged_)
330      {
331        if (!halfAxes_[i].wasDown_ && halfAxes_[i].absVal_ > halfAxes_[i].buttonThreshold_)
332        {
333          halfAxes_[i].wasDown_ = true;
334          if (halfAxes_[i].nCommands_[KeybindMode::OnPress])
335            halfAxes_[i].execute(KeybindMode::OnPress);
336        }
337        else if (halfAxes_[i].wasDown_ && halfAxes_[i].absVal_ < halfAxes_[i].buttonThreshold_)
338        {
339          halfAxes_[i].wasDown_ = false;
340          if (halfAxes_[i].nCommands_[KeybindMode::OnRelease])
341            halfAxes_[i].execute(KeybindMode::OnRelease);
342        }
343        halfAxes_[i].hasChanged_ = false;
344      }
345
346      if (halfAxes_[i].wasDown_)
347      {
348        if (halfAxes_[i].nCommands_[KeybindMode::OnHold])
349          halfAxes_[i].execute(KeybindMode::OnHold);
350      }
351
352      // these are the actually useful axis bindings for analog input AND output
353      if (halfAxes_[i].relVal_ > analogThreshold_ || halfAxes_[i].absVal_ > analogThreshold_)
354      {
355        //COUT(3) << halfAxes_[i].name_ << "\t" << halfAxes_[i].absVal_ << std::endl;
356        halfAxes_[i].execute();
357      }
358    }
359
360    if (bDeriveMouseInput_ && state.mouse)
361    {
362      if (deriveTime_ > derivePeriod_)
363      {
364        //CCOUT(3) << "mouse abs: ";
365        for (int i = 0; i < 2; i++)
366        {
367          if (mouseRelative_[i] > 0)
368          {
369            halfAxes_[2*i + 0].absVal_ =  mouseRelative_[i] / deriveTime_ * 0.0005 * mouseSensitivityDerived_;
370            halfAxes_[2*i + 1].absVal_ = 0.0f;
371          }
372          else if (mouseRelative_[i] < 0)
373          {
374            halfAxes_[2*i + 0].absVal_ = 0.0f;
375            halfAxes_[2*i + 1].absVal_ = -mouseRelative_[i] / deriveTime_ * 0.0005 * mouseSensitivityDerived_;
376          }
377          else
378          {
379            halfAxes_[2*i + 0].absVal_ = 0.0f;
380            halfAxes_[2*i + 1].absVal_ = 0.0f;
381          }
382          //COUT(3) << mouseRelative_[i] << " | ";
383          mouseRelative_[i] = 0;
384          halfAxes_[2*i + 0].hasChanged_ = true;
385          halfAxes_[2*i + 1].hasChanged_ = true;
386        }
387        deriveTime_ = 0.0f;
388        //COUT(3) << std::endl;
389      }
390      else
391        deriveTime_ += dt;
392    }
393
394    // execute all buffered bindings (addional parameter)
395    for (unsigned int i = 0; i < paramCommandBuffer_.size(); i++)
396      paramCommandBuffer_[i]->execute();
397
398    // always reset the relative movement of the mouse
399    if (state.mouse)
400      for (unsigned int i = 0; i < 8; i++)
401        halfAxes_[i].relVal_ = 0.0f;
402  }
403
404  void KeyBinder::keyPressed (const KeyEvent& evt)
405  { keys_[evt.key].execute(KeybindMode::OnPress); }
406
407  void KeyBinder::keyReleased(const KeyEvent& evt)
408  { keys_[evt.key].execute(KeybindMode::OnRelease); }
409
410  void KeyBinder::keyHeld    (const KeyEvent& evt)
411  { keys_[evt.key].execute(KeybindMode::OnHold); }
412
413
414  void KeyBinder::mouseButtonPressed (MouseButton::Enum id)
415  { mouseButtons_[id].execute(KeybindMode::OnPress); }
416
417  void KeyBinder::mouseButtonReleased(MouseButton::Enum id)
418  { mouseButtons_[id].execute(KeybindMode::OnRelease); }
419
420  void KeyBinder::mouseButtonHeld    (MouseButton::Enum id)
421  { mouseButtons_[id].execute(KeybindMode::OnHold); }
422
423
424  void KeyBinder::joyStickButtonPressed (int joyStickID, int button)
425  { joyStickButtons_[button].execute(KeybindMode::OnPress); }
426
427  void KeyBinder::joyStickButtonReleased(int joyStickID, int button)
428  { joyStickButtons_[button].execute(KeybindMode::OnRelease); }
429
430  void KeyBinder::joyStickButtonHeld    (int joyStickID, int button)
431  { joyStickButtons_[button].execute(KeybindMode::OnHold); }
432
433  /**
434    @brief Event handler for the mouseMoved Event.
435    @param e Mouse state information
436  */
437  void KeyBinder::mouseMoved(IntVector2 abs_, IntVector2 rel_, IntVector2 clippingSize)
438  {
439    // y axis of mouse input is inverted
440    int rel[] = { rel_.x, -rel_.y };
441
442    if (!bDeriveMouseInput_)
443    {
444      for (int i = 0; i < 2; i++)
445      {
446        if (rel[i])
447        {
448          // absolute
449          halfAxes_[2*i + 0].hasChanged_ = true;
450          halfAxes_[2*i + 1].hasChanged_ = true;
451          mousePosition_[i] += rel[i];
452
453          if (bClipMouse_)
454          {
455            if (mousePosition_[i] > 1024)
456              mousePosition_[i] =  1024;
457            if (mousePosition_[i] < -1024)
458              mousePosition_[i] = -1024;
459          }
460
461          if (mousePosition_[i] >= 0)
462          {
463            halfAxes_[2*i + 0].absVal_ =   mousePosition_[i]/1024.0f * mouseSensitivity_;
464            halfAxes_[2*i + 1].absVal_ =  0.0f;
465          }
466          else
467          {
468            halfAxes_[2*i + 0].absVal_ =  0.0f;
469            halfAxes_[2*i + 1].absVal_ =  -mousePosition_[i]/1024.0f * mouseSensitivity_;
470          }
471        }
472      }
473    }
474    else
475    {
476      mouseRelative_[0] += rel[0];
477      mouseRelative_[1] += rel[1];
478    }
479
480    // relative
481    for (int i = 0; i < 2; i++)
482    {
483      if (rel[i] > 0)
484        halfAxes_[0 + 2*i].relVal_ =  ((float)rel[i])/1024 * mouseSensitivity_;
485      else
486        halfAxes_[1 + 2*i].relVal_ = -((float)rel[i])/1024 * mouseSensitivity_;
487    }
488  }
489
490  /**
491    @brief Event handler for the mouseScrolled Event.
492    @param e Mouse state information
493  */
494  void KeyBinder::mouseScrolled(int abs, int rel)
495  {
496    //COUT(3) << mouseButtons_[8].name_ << "   " << abs << " | " << rel << std::endl;
497
498    if (rel > 0)
499      for (int i = 0; i < rel/120; i++)
500        mouseButtons_[8].execute(KeybindMode::OnPress, ((float)abs)/120.0f);
501    else
502      for (int i = 0; i < -rel/120; i++)
503        mouseButtons_[9].execute(KeybindMode::OnPress, ((float)abs)/120.0f);
504  }
505
506  void KeyBinder::joyStickAxisMoved(int joyStickID, int axis, float value)
507  {
508    // TODO: Use proper calibration values instead of generally 16-bit integer
509    int i = 8 + axis * 2;
510    if (value >= 0)
511    {
512      //if (value > 10000)
513      //{ CCOUT(3) << halfAxes_[i].name_ << std::endl; }
514
515      halfAxes_[i].absVal_ = value;
516      halfAxes_[i].relVal_ = value;
517      halfAxes_[i].hasChanged_ = true;
518      if (halfAxes_[i + 1].absVal_ > 0.0f)
519      {
520        halfAxes_[i + 1].absVal_ = -0.0f;
521        halfAxes_[i + 1].relVal_ = -0.0f;
522        halfAxes_[i + 1].hasChanged_ = true;
523      }
524    }
525    else
526    {
527      //if (value < -10000)
528      //{ CCOUT(3) << halfAxes_[i + 1].name_ << std::endl; }
529
530      halfAxes_[i + 1].absVal_ = -value;
531      halfAxes_[i + 1].relVal_ = -value;
532      halfAxes_[i + 1].hasChanged_ = true;
533      if (halfAxes_[i].absVal_ > 0.0f)
534      {
535        halfAxes_[i].absVal_ = -0.0f;
536        halfAxes_[i].relVal_ = -0.0f;
537        halfAxes_[i].hasChanged_ = true;
538      }
539    }
540  }
541}
Note: See TracBrowser for help on using the repository browser.