Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/network/src/core/KeyBinder.cc @ 1461

Last change on this file since 1461 was 1461, checked in by rgrieder, 16 years ago
  • "set" —> "config"
  • adjusted Shell output levels for keybind and calibrate
File size: 26.8 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 <limits.h>
37#include "util/Convert.h"
38#include "util/SubString.h"
39#include "util/String.h"
40#include "Debug.h"
41#include "ConfigValueIncludes.h"
42#include "CoreIncludes.h"
43#include "CommandExecutor.h"
44#include "ConsoleCommand.h"
45#include "Executor.h"
46// TODO: only needed by the CalibratorCallback class; move to new file
47#include "InputManager.h"
48
49namespace orxonox
50{
51  // ###############################
52  // ###  BufferedParamCommand   ###
53  // ###############################
54
55  /**
56  * Executes a buffered command. This is used for commands with additional
57  * parameters.
58  * @return True if command execution was successful or value was zero.
59  */
60  bool BufferedParamCommand::execute()
61  {
62    if (nValuesAdded_)
63    {
64      BufferedParamCommand& cmd = *this;
65      cmd.evaluation_.setEvaluatedParameter(cmd.paramIndex_, cmd.value_);
66      // reset
67      cmd.nValuesAdded_ = 0;
68      cmd.value_ = 0;
69      return cmd.evaluation_.execute();
70    }
71    else
72      return true;
73  }
74
75  // ###############################
76  // #####    SimpleCommand    #####
77  // ###############################
78
79  /**
80  * Executes a simple command with no additional paramters.
81  * @return True if command execution was successful, false otherwise.
82  */
83  bool SimpleCommand::execute(float abs, float rel)
84  {
85    return evaluation_.execute();
86  }
87
88  // ###############################
89  // #####    ParamCommand     #####
90  // ###############################
91
92  /**
93  * Executes a parameter command. The commmand string is not directly executed,
94  * but instead stored in a buffer list so that values can be combined.
95  * @return Always true.
96  */
97  bool ParamCommand::execute(float abs, float rel)
98  {
99    BufferedParamCommand& cmd = *paramCommand_;
100    // command has an additional parameter
101    if (bRelative_)
102    {
103      if (rel != 0.0f)
104      {
105        // we have to calculate a relative movement.
106        // paramModifier_ says how much one keystroke is
107        cmd.value_ += paramModifier_ * rel;
108      }
109    }
110    else if (abs != 0.0f)
111    {
112      // Usually, joy sticks create 'noise' (they return values if they're in 0 position)
113      // and normally this is caught in tickInput(), but that threshold cannot be to high
114      // in order to preserve accuracy. Instead, we have to catch the problem here. An example:
115      // Someone only uses buttons with an active joystick. The joy stick value could then
116      // be 0.05 for instance and the the key value 1. Without handling the problem, the final
117      // value would be computed to (1+0.05)/2=0.5025 which is not what the user expects.
118      float absQ = abs * abs;
119      float valueQ = cmd.value_ * cmd.value_;
120      if (absQ > 50.0f * valueQ) // ease up comparison by using quadratics
121      {
122        cmd.value_ = abs * paramModifier_;
123        cmd.nValuesAdded_ = 1;
124      }
125      else if (absQ * 50.0f < valueQ)
126      {
127        // abs is too small, we just don't do anything
128      }
129      else
130      {
131        // we have to calculate the absolute position of the axis.
132        // Since there might be another axis that is affected, we have to wait and
133        // store the result in a temporary place
134        cmd.value_ = (cmd.value_ * cmd.nValuesAdded_ + paramModifier_ * abs) / ++cmd.nValuesAdded_;
135      }
136    }
137    return true;
138  }
139
140  // ###############################
141  // #####       Button        #####
142  // ###############################
143
144  void Button::clear()
145  {
146    for (unsigned int j = 0; j < 3; j++)
147    {
148      if (nCommands_[j])
149      {
150        // delete all commands and the command pointer array
151        for (unsigned int i = 0; i < nCommands_[j]; i++)
152          delete commands_[j][i];
153        delete[] commands_[j];
154        commands_[j] = 0;
155        nCommands_[j] = 0;
156      }
157      else
158      {
159        commands_[j] = 0;
160      }
161    }
162  }
163
164  void Button::parse(std::vector<BufferedParamCommand*>& paramCommandBuffer)
165  {
166    if (isEmpty(bindingString_))
167    {
168      clear();
169      return;
170    }
171
172    // use std::vector for a temporary dynamic array
173    std::vector<BaseCommand*> commands[3];
174
175
176    // separate the commands
177    SubString commandStrings(bindingString_, "|", SubString::WhiteSpaces, false,
178        '\\', false, '"', false, '(', ')', false, '\0');
179
180    for (unsigned int iCommand = 0; iCommand < commandStrings.size(); iCommand++)
181    {
182      if (commandStrings[iCommand] != "")
183      {
184        SubString tokens(commandStrings[iCommand], " ", SubString::WhiteSpaces, false,
185            '\\', false, '"', false, '(', ')', false, '\0');
186
187        unsigned int iToken = 0;
188
189        // for real axes, we can feed a ButtonThreshold argument as entire command
190        if (getLowercase(tokens[0]) == "buttonthreshold")
191        {
192          if (tokens.size() == 1)
193            continue;
194          // may fail, but doesn't matter
195          convertValue(&buttonThreshold_, tokens[1]);
196          continue;
197        }
198
199        // first argument can be OnPress, OnHold OnRelease or nothing
200        KeybindMode::Enum mode = KeybindMode::None;
201        if (getLowercase(tokens[iToken]) == "onpress")
202          mode = KeybindMode::OnPress,   iToken++;
203        if (getLowercase(tokens[iToken]) == "onrelease")
204          mode = KeybindMode::OnRelease, iToken++;
205        if (getLowercase(tokens[iToken]) == "onhold")
206          mode = KeybindMode::OnHold,    iToken++;
207
208        if (iToken == tokens.size())
209          continue;
210
211        // second argument can be the amplitude for the case it as an axis command
212        // default amplitude is 1.0f
213        float paramModifier = 1.0f;
214        if (getLowercase(tokens[iToken]) == "scale")
215        {
216          iToken++;
217          if (iToken == tokens.size() || !convertValue(&paramModifier, tokens[iToken]))
218          {
219            COUT(2) << "Error while parsing key binding " << name_
220                << ". Numeric expression expected afer 'AxisAmp', switching to default value" << std::endl;
221            if (iToken == tokens.size())
222              continue;
223          }
224          iToken++;
225        }
226
227        // no more arguments expected except for the actual command
228        if (iToken == tokens.size())
229          continue;
230
231        std::string commandStr;
232        while (iToken != tokens.size())
233          commandStr += tokens[iToken++] + " ";
234
235        // evaluate the command
236        CommandEvaluation eval = CommandExecutor::evaluate(commandStr);
237        if (!eval.isValid())
238          continue;
239
240        // check for param command
241        int paramIndex = eval.getConsoleCommand()->getAxisParamIndex();
242        if (paramIndex >= 0)
243        {
244          // parameter supported command
245          ParamCommand* cmd = new ParamCommand();
246          cmd->paramModifier_ = paramModifier;
247          cmd->bRelative_ = eval.getConsoleCommand()->getIsAxisRelative();
248
249          // add command to the buffer if not yet existing
250          for (unsigned int iParamCmd = 0; iParamCmd < paramCommandBuffer.size(); iParamCmd++)
251          {
252            if (getLowercase(paramCommandBuffer[iParamCmd]->evaluation_.getOriginalCommand())
253                == getLowercase(commandStr))
254            {
255              // already in list
256              cmd->paramCommand_ = paramCommandBuffer[iParamCmd];
257              break;
258            }
259          }
260          if (cmd->paramCommand_ == 0)
261          {
262            cmd->paramCommand_ = new BufferedParamCommand();
263            paramCommandBuffer.push_back(cmd->paramCommand_);
264            cmd->paramCommand_->evaluation_ = eval;
265            cmd->paramCommand_->paramIndex_ = paramIndex;
266          }
267
268
269          // we don't know whether this is an actual axis or just a button
270          if (mode == KeybindMode::None)
271          {
272            if (!addParamCommand(cmd))
273            {
274              mode = eval.getConsoleCommand()->getKeybindMode();
275              commands[mode].push_back(cmd);
276            }
277          }
278        }
279        else
280        {
281          SimpleCommand* cmd = new SimpleCommand();
282          cmd->evaluation_ = eval;
283
284          if (mode == KeybindMode::None)
285            mode = eval.getConsoleCommand()->getKeybindMode();
286
287          commands[mode].push_back(cmd);
288        }
289      }
290    }
291
292    for (unsigned int j = 0; j < 3; j++)
293    {
294      nCommands_[j] = commands[j].size();
295      if (nCommands_[j])
296      {
297        commands_[j] = new BaseCommand*[nCommands_[j]];
298        for (unsigned int i = 0; i < commands[j].size(); i++)
299          commands_[j][i] = commands[j][i];
300      }
301      else
302        commands_[j] = 0;
303    }
304  }
305
306  bool Button::execute(KeybindMode::Enum mode, float abs, float rel)
307  {
308    // execute all the parsed commands in the string
309    for (unsigned int iCommand = 0; iCommand < nCommands_[mode]; iCommand++)
310      commands_[mode][iCommand]->execute(abs, rel);
311    return true;
312  }
313
314  // ###############################
315  // #####      HalfAxis       #####
316  // ###############################
317
318  void HalfAxis::clear()
319  {
320    Button::clear();
321    if (nParamCommands_)
322    {
323      // delete all commands and the command pointer array
324      for (unsigned int i = 0; i < nParamCommands_; i++)
325        delete paramCommands_[i];
326      delete[] paramCommands_;
327      nParamCommands_ = 0;
328    }
329    else
330    {
331      nParamCommands_ = 0; nParamCommands_ = 0;
332    }
333  }
334
335  bool HalfAxis::addParamCommand(ParamCommand* command)
336  {
337    ParamCommand** cmds = paramCommands_;
338    paramCommands_ = new ParamCommand*[++nParamCommands_];
339    unsigned int i;
340    for (i = 0; i < nParamCommands_ - 1; i++)
341      paramCommands_[i] = cmds[i];
342    paramCommands_[i] = command;
343    delete[] cmds;
344    return true;
345  }
346
347  bool HalfAxis::execute()
348  {
349    bool success = true;
350    for (unsigned int i = 0; i < nParamCommands_; i++)
351      success = success && paramCommands_[i]->execute(absVal_, relVal_);
352    return success;
353  }
354
355
356  // ###############################
357  // ######     KeyBinder     ######
358  // ###############################
359
360  /**
361    @brief Constructor that does as little as necessary.
362  */
363  KeyBinder::KeyBinder() : deriveTime_(0.0f)
364  {
365    mouseRelative_[0] = 0;
366    mouseRelative_[1] = 0;
367    mousePosition_[0] = 0;
368    mousePosition_[1] = 0;
369
370    RegisterObject(KeyBinder);
371
372    // keys
373    std::string keyNames[] = {
374      "UNASSIGNED",
375      "ESCAPE",
376      "1", "2", "3", "4", "5", "6", "7", "8", "9", "0",
377      "MINUS", "EQUALS", "BACK", "TAB",
378      "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P",
379      "LBRACKET", "RBRACKET",
380      "RETURN", "LCONTROL",
381      "A", "S", "D", "F", "G", "H", "J", "K", "L",
382      "SEMICOLON", "APOSTROPHE", "GRAVE",
383      "LSHIFT", "BACKSLASH",
384      "Z", "X", "C", "V", "B", "N", "M",
385      "COMMA", "PERIOD", "SLASH",
386      "RSHIFT",
387      "MULTIPLY",
388      "LMENU",
389      "SPACE",
390      "CAPITAL",
391      "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10",
392      "NUMLOCK", "SCROLL",
393      "NUMPAD7", "NUMPAD8", "NUMPAD9",
394      "SUBTRACT",
395      "NUMPAD4", "NUMPAD5", "NUMPAD6",
396      "ADD",
397      "NUMPAD1", "NUMPAD2", "NUMPAD3", "NUMPAD0",
398      "DECIMAL",
399      "","",
400      "OEM_102",
401      "F11", "F12",
402      "","","","","","","","","","","",
403      "F13", "F14", "F15",
404      "","","","","","","","","","",
405      "KANA",
406      "","",
407      "ABNT_C1",
408      "","","","","",
409      "CONVERT",
410      "",
411      "NOCONVERT",
412      "",
413      "YEN",
414      "ABNT_C2",
415      "","","","","","","","","","","","","","",
416      "NUMPADEQUALS",
417      "","",
418      "PREVTRACK",
419      "AT",
420      "COLON", "UNDERLINE",
421      "KANJI",
422      "STOP",
423      "AX",
424      "UNLABELED",
425      "NEXTTRACK",
426      "","",
427      "NUMPADENTER",
428      "RCONTROL",
429      "","",
430      "MUTE",
431      "CALCULATOR",
432      "PLAYPAUSE",
433      "",
434      "MEDIASTOP",
435      "","","","","","","","","",
436      "VOLUMEDOWN",
437      "",
438      "VOLUMEUP",
439      "",
440      "WEBHOME",
441      "NUMPADCOMMA",
442      "",
443      "DIVIDE",
444      "",
445      "SYSRQ",
446      "RMENU",
447      "","","","","","","","","","","","",
448      "PAUSE",
449      "",
450      "HOME",
451      "UP",
452      "PGUP",
453      "",
454      "LEFT",
455      "",
456      "RIGHT",
457      "",
458      "END", "DOWN", "PGDOWN", "INSERT", "DELETE",
459      "","","","","","","",
460      "LWIN", "RWIN", "APPS",
461      "POWER", "SLEEP",
462      "","","",
463      "WAKE",
464      "",
465      "WEBSEARCH", "WEBFAVORITES", "WEBREFRESH", "WEBSTOP", "WEBFORWARD", "WEBBACK",
466      "MYCOMPUTER", "MAIL", "MEDIASELECT"
467    };
468    for (unsigned int i = 0; i < nKeys_s; i++)
469      keys_[i].name_ = "Key" + keyNames[i];
470
471    // mouse buttons
472    std::string mouseButtonNames[] = {
473      "MouseLeft", "MouseRight", "MouseMiddle",
474      "MouseButton3", "MouseButton4", "MouseButton5",
475      "MouseButton6", "MouseButton7",
476      "MouseWheel1Up", "MouseWheel1Down",
477      "MouseWheel2Up", "MouseWheel2Down" };
478    for (unsigned int i = 0; i < nMouseButtons_s; i++)
479      mouseButtons_[i].name_ = mouseButtonNames[i];
480
481    // joy stick buttons
482    for (unsigned int i = 0; i < 32; i++)
483      joyStickButtons_[i].name_ = "JoyButton" + getConvertedValue<int, std::string>(i);
484    for (unsigned int i = 32; i < nJoyStickButtons_s; i += 4)
485    {
486                  joyStickButtons_[i + 0].name_ = "JoyPOV" + getConvertedValue<int, std::string>((i - 32)/4 + 1) + "North";
487                  joyStickButtons_[i + 1].name_ = "JoyPOV" + getConvertedValue<int, std::string>((i - 32)/4 + 1) + "South";
488                  joyStickButtons_[i + 2].name_ = "JoyPOV" + getConvertedValue<int, std::string>((i - 32)/4 + 1) + "East";
489                  joyStickButtons_[i + 3].name_ = "JoyPOV" + getConvertedValue<int, std::string>((i - 32)/4 + 1) + "West";
490    }
491
492    // half axes
493    std::string rawNames[nHalfAxes_s/2];
494    rawNames[0] = "MouseX";
495    rawNames[1] = "MouseY";
496    rawNames[2] = "Empty1";
497    rawNames[3] = "Empty2";
498    for (unsigned int i = 4; i < nHalfAxes_s/2; i++)
499      rawNames[i] = "JoyAxis" + getConvertedValue<int, std::string>(i - 3);
500    for (unsigned int i = 0; i < nHalfAxes_s/2; i++)
501    {
502      halfAxes_[i * 2 + 0].name_ = rawNames[i] + "Pos";
503      halfAxes_[i * 2 + 1].name_ = rawNames[i] + "Neg";
504    }
505
506    for (unsigned int i = 0; i < this->nHalfAxes_s; i++)
507      halfAxes_[i].buttonThreshold_ = buttonThreshold_;
508  }
509
510  /**
511    @brief Destructor
512  */
513  KeyBinder::~KeyBinder()
514  {
515    // almost no destructors required because most of the arrays are static.
516    clearBindings(); // does some destruction work
517  }
518
519  /**
520    @brief Loads the key and button bindings.
521    @return True if loading succeeded.
522  */
523  void KeyBinder::loadBindings()
524  {
525    COUT(3) << "KeyBinder: Loading key bindings..." << std::endl;
526
527    clearBindings();
528
529    std::ifstream infile;
530    infile.open("keybindings.ini");
531    if (!infile.is_open())
532    {
533      ConfigFileManager::getSingleton()->setFile(CFT_Keybindings, "def_keybindings.ini");
534      ConfigFileManager::getSingleton()->save(CFT_Keybindings, "keybindings.ini");
535    }
536    infile.close();
537    ConfigFileManager::getSingleton()->setFile(CFT_Keybindings, "keybindings.ini");
538
539    // parse key bindings
540    setConfigValues();
541
542    COUT(3) << "KeyBinder: Loading key bindings done." << std::endl;
543  }
544
545  /**
546    @brief Loader for the key bindings, managed by config values.
547  */
548  void KeyBinder::setConfigValues()
549  {
550    SetConfigValueGeneric(KeyBinder, analogThreshold_, 0.01f)  .description("Threshold for analog axes until which the state is 0.");
551    SetConfigValueGeneric(KeyBinder, mouseSensitivity_, 1.0f)  .description("Mouse sensitivity.");
552    SetConfigValueGeneric(KeyBinder, bDeriveMouseInput_, false).description("Whether or not to derive moues movement for the absolute value.");
553    SetConfigValueGeneric(KeyBinder, derivePeriod_, 0.5f).description("Accuracy of the mouse input deriver. The higher the more precise, but laggier.");
554    SetConfigValueGeneric(KeyBinder, mouseSensitivityDerived_, 1.0f).description("Mouse sensitivity if mouse input is derived.");
555    SetConfigValueGeneric(KeyBinder, bClipMouse_, true).description("Whether or not to clip absolute value of mouse in non derive mode.");
556
557    float oldThresh = buttonThreshold_;
558    SetConfigValueGeneric(KeyBinder, buttonThreshold_, 0.80f).description("Threshold for analog axes until which the button is not pressed.");
559    if (oldThresh != buttonThreshold_)
560      for (unsigned int i = 0; i < nHalfAxes_s; i++)
561        if (halfAxes_[i].buttonThreshold_ == oldThresh)
562          halfAxes_[i].buttonThreshold_ = buttonThreshold_;
563
564    // keys
565    for (unsigned int i = 0; i < nKeys_s; i++)
566      readTrigger(keys_[i]);
567    // mouse buttons
568    for (unsigned int i = 0; i < nMouseButtons_s; i++)
569      readTrigger(mouseButtons_[i]);
570    // joy stick buttons
571    for (unsigned int i = 0; i < nJoyStickButtons_s; i++)
572      readTrigger(joyStickButtons_[i]);
573    // half axes
574    for (unsigned int i = 0; i < nHalfAxes_s; i++)
575      readTrigger(halfAxes_[i]);
576  }
577
578  void KeyBinder::readTrigger(Button& button)
579  {
580    // config value stuff
581    ConfigValueContainer* cont = ClassManager<KeyBinder>::getIdentifier()->getConfigValueContainer(button.name_);
582    if (!cont)
583    {
584      cont = new ConfigValueContainer(CFT_Keybindings, ClassManager<KeyBinder>::getIdentifier(), button.name_, "");
585      ClassManager<KeyBinder>::getIdentifier()->addConfigValueContainer(button.name_, cont);
586    }
587    std::string old = button.bindingString_;
588    cont->getValue(&button.bindingString_);
589
590    // keybinder stuff
591    if (old != button.bindingString_)
592    {
593      // clear everything so we don't get old axis ParamCommands mixed up
594      button.clear();
595
596      // binding has changed
597      button.parse(paramCommandBuffer_);
598    }
599  }
600
601  /**
602    @brief Overwrites all bindings with ""
603  */
604  void KeyBinder::clearBindings()
605  {
606    for (unsigned int i = 0; i < nKeys_s; i++)
607      keys_[i].clear();
608
609    for (unsigned int i = 0; i < nMouseButtons_s; i++)
610      mouseButtons_[i].clear();
611
612    for (unsigned int i = 0; i < nJoyStickButtons_s; i++)
613      joyStickButtons_[i].clear();
614
615    for (unsigned int i = 0; i < nHalfAxes_s; i++)
616      halfAxes_[i].clear();
617
618    for (unsigned int i = 0; i < paramCommandBuffer_.size(); i++)
619      delete paramCommandBuffer_[i];
620    paramCommandBuffer_.clear();
621  }
622
623  void KeyBinder::resetJoyStickAxes()
624  {
625    for (unsigned int i = 8; i < nHalfAxes_s; i++)
626    {
627      halfAxes_[i].absVal_ = 0.0f;
628      halfAxes_[i].relVal_ = 0.0f;
629    }
630  }
631
632  void KeyBinder::tickInput(float dt, const HandlerState& state)
633  {
634    // we have to process all the analog input since there is e.g. no 'mouseDoesntMove' event.
635    unsigned int iBegin = 8;
636    unsigned int iEnd   = 8;
637    if (state.joyStick)
638      iEnd = nHalfAxes_s;
639    if (state.mouse)
640      iBegin = 0;
641    for (unsigned int i = iBegin; i < iEnd; i++)
642    {
643      if (halfAxes_[i].hasChanged_)
644      {
645        if (!halfAxes_[i].wasDown_ && halfAxes_[i].absVal_ > halfAxes_[i].buttonThreshold_)
646        {
647          halfAxes_[i].wasDown_ = true;
648          if (halfAxes_[i].nCommands_[KeybindMode::OnPress])
649            halfAxes_[i].execute(KeybindMode::OnPress);
650        }
651        else if (halfAxes_[i].wasDown_ && halfAxes_[i].absVal_ < halfAxes_[i].buttonThreshold_)
652        {
653          halfAxes_[i].wasDown_ = false;
654          if (halfAxes_[i].nCommands_[KeybindMode::OnRelease])
655            halfAxes_[i].execute(KeybindMode::OnRelease);
656        }
657        halfAxes_[i].hasChanged_ = false;
658      }
659
660      if (halfAxes_[i].wasDown_)
661      {
662        if (halfAxes_[i].nCommands_[KeybindMode::OnHold])
663          halfAxes_[i].execute(KeybindMode::OnHold);
664      }
665
666      // these are the actually useful axis bindings for analog input AND output
667      if (halfAxes_[i].relVal_ > analogThreshold_ || halfAxes_[i].absVal_ > analogThreshold_)
668      {
669        //COUT(3) << halfAxes_[i].name_ << "\t" << halfAxes_[i].absVal_ << std::endl;
670        halfAxes_[i].execute();
671      }
672    }
673
674    if (bDeriveMouseInput_ && state.mouse)
675    {
676      if (deriveTime_ > derivePeriod_)
677      {
678        //CCOUT(3) << "mouse abs: ";
679        for (int i = 0; i < 2; i++)
680        {
681          if (mouseRelative_[i] > 0)
682          {
683            halfAxes_[2*i + 0].absVal_ =  mouseRelative_[i] / deriveTime_ * 0.0005 * mouseSensitivityDerived_;
684            halfAxes_[2*i + 1].absVal_ = 0.0f;
685          }
686          else if (mouseRelative_[i] < 0)
687          {
688            halfAxes_[2*i + 0].absVal_ = 0.0f;
689            halfAxes_[2*i + 1].absVal_ = -mouseRelative_[i] / deriveTime_ * 0.0005 * mouseSensitivityDerived_;
690          }
691          else
692          {
693            halfAxes_[2*i + 0].absVal_ = 0.0f;
694            halfAxes_[2*i + 1].absVal_ = 0.0f;
695          }
696          //COUT(3) << mouseRelative_[i] << " | ";
697          mouseRelative_[i] = 0;
698          halfAxes_[2*i + 0].hasChanged_ = true;
699          halfAxes_[2*i + 1].hasChanged_ = true;
700        }
701        deriveTime_ = 0.0f;
702        //COUT(3) << std::endl;
703      }
704      else
705        deriveTime_ += dt;
706    }
707
708    // execute all buffered bindings (addional parameter)
709    for (unsigned int i = 0; i < paramCommandBuffer_.size(); i++)
710      paramCommandBuffer_[i]->execute();
711
712    // always reset the relative movement of the mouse
713    if (state.mouse)
714      for (unsigned int i = 0; i < 8; i++)
715        halfAxes_[i].relVal_ = 0.0f;
716  }
717
718  void KeyBinder::keyPressed (const KeyEvent& evt)
719  { keys_[evt.key].execute(KeybindMode::OnPress); }
720
721  void KeyBinder::keyReleased(const KeyEvent& evt)
722  { keys_[evt.key].execute(KeybindMode::OnRelease); }
723
724  void KeyBinder::keyHeld    (const KeyEvent& evt)
725  { keys_[evt.key].execute(KeybindMode::OnHold); }
726
727
728  void KeyBinder::mouseButtonPressed (MouseButton::Enum id)
729  { mouseButtons_[id].execute(KeybindMode::OnPress); }
730
731  void KeyBinder::mouseButtonReleased(MouseButton::Enum id)
732  { mouseButtons_[id].execute(KeybindMode::OnRelease); }
733
734  void KeyBinder::mouseButtonHeld    (MouseButton::Enum id)
735  { mouseButtons_[id].execute(KeybindMode::OnHold); }
736
737
738  void KeyBinder::joyStickButtonPressed (int joyStickID, int button)
739  { joyStickButtons_[button].execute(KeybindMode::OnPress); }
740
741  void KeyBinder::joyStickButtonReleased(int joyStickID, int button)
742  { joyStickButtons_[button].execute(KeybindMode::OnRelease); }
743
744  void KeyBinder::joyStickButtonHeld    (int joyStickID, int button)
745  { joyStickButtons_[button].execute(KeybindMode::OnHold); }
746
747  /**
748    @brief Event handler for the mouseMoved Event.
749    @param e Mouse state information
750  */
751  void KeyBinder::mouseMoved(IntVector2 abs_, IntVector2 rel_, IntVector2 clippingSize)
752  {
753    // y axis of mouse input is inverted
754    int rel[] = { rel_.x, -rel_.y };
755
756    if (!bDeriveMouseInput_)
757    {
758      for (int i = 0; i < 2; i++)
759      {
760        if (rel[i])
761        {
762          // absolute
763          halfAxes_[2*i + 0].hasChanged_ = true;
764          halfAxes_[2*i + 1].hasChanged_ = true;
765          mousePosition_[i] += rel[i];
766
767          if (bClipMouse_)
768          {
769            if (mousePosition_[i] > 1024)
770              mousePosition_[i] =  1024;
771            if (mousePosition_[i] < -1024)
772              mousePosition_[i] = -1024;
773          }
774
775          if (mousePosition_[i] >= 0)
776          {
777            halfAxes_[2*i + 0].absVal_ =   mousePosition_[i]/1024.0f * mouseSensitivity_;
778            halfAxes_[2*i + 1].absVal_ =  0.0f;
779          }
780          else
781          {
782            halfAxes_[2*i + 0].absVal_ =  0.0f;
783            halfAxes_[2*i + 1].absVal_ =  -mousePosition_[i]/1024.0f * mouseSensitivity_;
784          }
785        }
786      }
787    }
788    else
789    {
790      mouseRelative_[0] += rel[0];
791      mouseRelative_[1] += rel[1];
792    }
793
794    // relative
795    for (int i = 0; i < 2; i++)
796    {
797      if (rel[i] > 0)
798        halfAxes_[0 + 2*i].relVal_ =  ((float)rel[i])/1024 * mouseSensitivity_;
799      else
800        halfAxes_[1 + 2*i].relVal_ = -((float)rel[i])/1024 * mouseSensitivity_;
801    }
802  }
803
804  /**
805    @brief Event handler for the mouseScrolled Event.
806    @param e Mouse state information
807  */
808  void KeyBinder::mouseScrolled(int abs, int rel)
809  {
810    //COUT(3) << mouseButtons_[8].name_ << "   " << abs << " | " << rel << std::endl;
811
812    if (rel > 0)
813      for (int i = 0; i < rel/120; i++)
814        mouseButtons_[8].execute(KeybindMode::OnPress, ((float)abs)/120.0f);
815    else
816      for (int i = 0; i < -rel/120; i++)
817        mouseButtons_[9].execute(KeybindMode::OnPress, ((float)abs)/120.0f);
818  }
819
820  void KeyBinder::joyStickAxisMoved(int joyStickID, int axis, float value)
821  {
822    // TODO: Use proper calibration values instead of generally 16-bit integer
823    int i = 8 + axis * 2;
824    if (value >= 0)
825    {
826      //if (value > 10000)
827      //{ CCOUT(3) << halfAxes_[i].name_ << std::endl; }
828
829      halfAxes_[i].absVal_ = value;
830      halfAxes_[i].relVal_ = value;
831      halfAxes_[i].hasChanged_ = true;
832      if (halfAxes_[i + 1].absVal_ > 0.0f)
833      {
834        halfAxes_[i + 1].absVal_ = -0.0f;
835        halfAxes_[i + 1].relVal_ = -0.0f;
836        halfAxes_[i + 1].hasChanged_ = true;
837      }
838    }
839    else
840    {
841      //if (value < -10000)
842      //{ CCOUT(3) << halfAxes_[i + 1].name_ << std::endl; }
843
844      halfAxes_[i + 1].absVal_ = -value;
845      halfAxes_[i + 1].relVal_ = -value;
846      halfAxes_[i + 1].hasChanged_ = true;
847      if (halfAxes_[i].absVal_ > 0.0f)
848      {
849        halfAxes_[i].absVal_ = -0.0f;
850        halfAxes_[i].relVal_ = -0.0f;
851        halfAxes_[i].hasChanged_ = true;
852      }
853    }
854  }
855
856
857  // ###############################
858  // #####     KeyDetector     #####
859  // ###############################
860
861  /**
862    @brief Constructor
863  */
864  KeyDetector::KeyDetector()
865  {
866    RegisterObject(KeyDetector);
867  }
868
869  /**
870    @brief Destructor
871  */
872  KeyDetector::~KeyDetector()
873  {
874  }
875
876  /**
877    @brief Loads the key and button bindings.
878    @return True if loading succeeded.
879  */
880  void KeyDetector::loadBindings()
881  {
882    clearBindings();
883    setConfigValues();
884  }
885
886  void KeyDetector::readTrigger(Button& button)
887  {
888    SimpleCommand* cmd = new SimpleCommand();
889    cmd->evaluation_ = CommandExecutor::evaluate("storeKeyStroke " + button.name_);
890    button.commands_[KeybindMode::OnPress] = new BaseCommand*[1];
891    button.commands_[KeybindMode::OnPress][0] = cmd;
892    button.nCommands_[KeybindMode::OnPress] = 1;
893  }
894
895
896  // ###############################
897  // ##### CalibratorCallback  #####
898  // ###############################
899
900  void CalibratorCallback::keyPressed(const orxonox::KeyEvent &evt)
901  {
902    if (evt.key == KeyCode::Return)
903    {
904      InputManager::setInputState(InputManager::IS_NOCALIBRATE);
905    }
906  }
907}
Note: See TracBrowser for help on using the repository browser.