Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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