Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 1428 was 1428, checked in by rgrieder, 16 years ago
  • added SetConfigValueGeneric to set the config value of the actual class when using hierarchies
  • fixed a bug when handling derived mouse input
  • refined 'keybind' command so that input goes to KeyDetector only
File size: 26.3 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      nParamCommands_ = 0;
324    }
325    else
326    {
327      nParamCommands_ = 0; nParamCommands_ = 0;
328    }
329  }
330 
331  bool HalfAxis::addParamCommand(ParamCommand* command)
332  {
333    ParamCommand** cmds = paramCommands_;
334    paramCommands_ = new ParamCommand*[++nParamCommands_];
335    unsigned int i;
336    for (i = 0; i < nParamCommands_ - 1; i++)
337      paramCommands_[i] = cmds[i];
338    paramCommands_[i] = command;
339    delete[] cmds;
340    return true;
341  }
342
343  bool HalfAxis::execute()
344  {
345    bool success = true;
346    for (unsigned int i = 0; i < nParamCommands_; i++)
347      success = success && paramCommands_[i]->execute(absVal_, relVal_);
348    return success;
349  }
350
351
352  // ###############################
353  // ######     KeyBinder     ######
354  // ###############################
355
356  /**
357    @brief Constructor that does as little as necessary.
358  */
359  KeyBinder::KeyBinder() : deriveTime_(0.0f)
360  {
361    mouseRelative_[0] = 0;
362    mouseRelative_[1] = 0;
363    mousePosition_[0] = 0;
364    mousePosition_[1] = 0;
365
366    RegisterObject(KeyBinder);
367
368    // keys
369    std::string keyNames[] = {
370      "UNASSIGNED",
371      "ESCAPE",
372      "1", "2", "3", "4", "5", "6", "7", "8", "9", "0",
373      "MINUS", "EQUALS", "BACK", "TAB",
374      "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P",
375      "LBRACKET", "RBRACKET",
376      "RETURN", "LCONTROL",
377      "A", "S", "D", "F", "G", "H", "J", "K", "L",
378      "SEMICOLON", "APOSTROPHE", "GRAVE",
379      "LSHIFT", "BACKSLASH",
380      "Z", "X", "C", "V", "B", "N", "M",
381      "COMMA", "PERIOD", "SLASH",
382      "RSHIFT",
383      "MULTIPLY",
384      "LMENU",
385      "SPACE",
386      "CAPITAL",
387      "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10",
388      "NUMLOCK", "SCROLL",
389      "NUMPAD7", "NUMPAD8", "NUMPAD9",
390      "SUBTRACT",
391      "NUMPAD4", "NUMPAD5", "NUMPAD6",
392      "ADD",
393      "NUMPAD1", "NUMPAD2", "NUMPAD3", "NUMPAD0",
394      "DECIMAL",
395      "","",
396      "OEM_102",
397      "F11", "F12",
398      "","","","","","","","","","","",
399      "F13", "F14", "F15",
400      "","","","","","","","","","",
401      "KANA",
402      "","",
403      "ABNT_C1",
404      "","","","","",
405      "CONVERT",
406      "",
407      "NOCONVERT",
408      "",
409      "YEN",
410      "ABNT_C2",
411      "","","","","","","","","","","","","","",
412      "NUMPADEQUALS",
413      "","",
414      "PREVTRACK",
415      "AT",
416      "COLON", "UNDERLINE",
417      "KANJI",
418      "STOP",
419      "AX",
420      "UNLABELED",
421      "NEXTTRACK",
422      "","",
423      "NUMPADENTER",
424      "RCONTROL",
425      "","",
426      "MUTE",
427      "CALCULATOR",
428      "PLAYPAUSE",
429      "",
430      "MEDIASTOP",
431      "","","","","","","","","",
432      "VOLUMEDOWN",
433      "",
434      "VOLUMEUP",
435      "",
436      "WEBHOME",
437      "NUMPADCOMMA",
438      "",
439      "DIVIDE",
440      "",
441      "SYSRQ",
442      "RMENU",
443      "","","","","","","","","","","","",
444      "PAUSE",
445      "",
446      "HOME",
447      "UP",
448      "PGUP",
449      "",
450      "LEFT",
451      "",
452      "RIGHT",
453      "",
454      "END", "DOWN", "PGDOWN", "INSERT", "DELETE",
455      "","","","","","","",
456      "LWIN", "RWIN", "APPS",
457      "POWER", "SLEEP",
458      "","","",
459      "WAKE",
460      "",
461      "WEBSEARCH", "WEBFAVORITES", "WEBREFRESH", "WEBSTOP", "WEBFORWARD", "WEBBACK",
462      "MYCOMPUTER", "MAIL", "MEDIASELECT"
463    };
464    for (unsigned int i = 0; i < nKeys_s; i++)
465      keys_[i].name_ = "Key" + keyNames[i];
466
467    // mouse buttons
468    std::string mouseButtonNames[] = {
469      "MouseLeft", "MouseRight", "MouseMiddle",
470      "MouseButton3", "MouseButton4", "MouseButton5",
471      "MouseButton6", "MouseButton7",
472      "MouseWheel1Up", "MouseWheel1Down",
473      "MouseWheel2Up", "MouseWheel2Down" };
474    for (unsigned int i = 0; i < nMouseButtons_s; i++)
475      mouseButtons_[i].name_ = mouseButtonNames[i];
476
477    // joy stick buttons
478    for (unsigned int i = 0; i < 32; i++)
479      joyStickButtons_[i].name_ = "JoyButton" + getConvertedValue<int, std::string>(i);
480    for (unsigned int i = 32; i < nJoyStickButtons_s; i += 4)
481    {
482                  joyStickButtons_[i + 0].name_ = "JoyPOV" + getConvertedValue<int, std::string>((i - 32)/4 + 1) + "North";
483                  joyStickButtons_[i + 1].name_ = "JoyPOV" + getConvertedValue<int, std::string>((i - 32)/4 + 1) + "South";
484                  joyStickButtons_[i + 2].name_ = "JoyPOV" + getConvertedValue<int, std::string>((i - 32)/4 + 1) + "East";
485                  joyStickButtons_[i + 3].name_ = "JoyPOV" + getConvertedValue<int, std::string>((i - 32)/4 + 1) + "West";
486    }
487
488    // half axes
489    std::string rawNames[nHalfAxes_s/2];
490    rawNames[0] = "MouseX";
491    rawNames[1] = "MouseY";
492    rawNames[2] = "Empty1";
493    rawNames[3] = "Empty2";
494    for (unsigned int i = 4; i < nHalfAxes_s/2; i++)
495      rawNames[i] = "JoyAxis" + getConvertedValue<int, std::string>(i - 3);
496    for (unsigned int i = 0; i < nHalfAxes_s/2; i++)
497    {
498      halfAxes_[i * 2 + 0].name_ = rawNames[i] + "Pos";
499      halfAxes_[i * 2 + 1].name_ = rawNames[i] + "Neg";
500    }
501
502    for (unsigned int i = 0; i < this->nHalfAxes_s; i++)
503      halfAxes_[i].buttonThreshold_ = buttonThreshold_;
504  }
505
506  /**
507    @brief Destructor
508  */
509  KeyBinder::~KeyBinder()
510  {
511    // almost no destructors required because most of the arrays are static.
512    clearBindings(); // does some destruction work
513  }
514
515  /**
516    @brief Loads the key and button bindings.
517    @return True if loading succeeded.
518  */
519  void KeyBinder::loadBindings()
520  {
521    COUT(3) << "KeyBinder: Loading key bindings..." << std::endl;
522
523    clearBindings();
524
525    std::ifstream infile;
526    infile.open("keybindings.ini");
527    if (!infile.is_open())
528    {
529      ConfigFileManager::getSingleton()->setFile(CFT_Keybindings, "def_keybindings.ini");
530      ConfigFileManager::getSingleton()->save(CFT_Keybindings, "keybindings.ini");
531    }
532    infile.close();
533    ConfigFileManager::getSingleton()->setFile(CFT_Keybindings, "keybindings.ini");
534
535    // parse key bindings
536    setConfigValues();
537
538    COUT(3) << "KeyBinder: Loading key bindings done." << std::endl;
539  }
540
541  /**
542    @brief Loader for the key bindings, managed by config values.
543  */
544  void KeyBinder::setConfigValues()
545  {
546    SetConfigValueGeneric(KeyBinder, analogThreshold_, 0.01f)  .description("Threshold for analog axes until which the state is 0.");
547    SetConfigValueGeneric(KeyBinder, mouseSensitivity_, 1.0f)  .description("Mouse sensitivity.");
548    SetConfigValueGeneric(KeyBinder, bDeriveMouseInput_, false).description("Whether or not to derive moues movement for the absolute value.");
549    SetConfigValueGeneric(KeyBinder, derivePeriod_, 0.5f).description("Accuracy of the mouse input deriver. The higher the more precise, but laggier.");
550    SetConfigValueGeneric(KeyBinder, mouseSensitivityDerived_, 1.0f).description("Mouse sensitivity if mouse input is derived.");
551    SetConfigValueGeneric(KeyBinder, bClipMouse_, true).description("Whether or not to clip absolute value of mouse in non derive mode.");
552
553    float oldThresh = buttonThreshold_;
554    SetConfigValueGeneric(KeyBinder, buttonThreshold_, 0.80f).description("Threshold for analog axes until which the button is not pressed.");
555    if (oldThresh != buttonThreshold_)
556      for (unsigned int i = 0; i < nHalfAxes_s; i++)
557        if (halfAxes_[i].buttonThreshold_ == oldThresh)
558          halfAxes_[i].buttonThreshold_ = buttonThreshold_;
559
560    // keys
561    for (unsigned int i = 0; i < nKeys_s; i++)
562      readTrigger(keys_[i]);
563    // mouse buttons
564    for (unsigned int i = 0; i < nMouseButtons_s; i++)
565      readTrigger(mouseButtons_[i]);
566    // joy stick buttons
567    for (unsigned int i = 0; i < nJoyStickButtons_s; i++)
568      readTrigger(joyStickButtons_[i]);
569    // half axes
570    for (unsigned int i = 0; i < nHalfAxes_s; i++)
571      readTrigger(halfAxes_[i]);
572  }
573
574  void KeyBinder::readTrigger(Button& button)
575  {
576    // config value stuff
577    ConfigValueContainer* cont = ClassManager<KeyBinder>::getIdentifier()->getConfigValueContainer(button.name_);
578    if (!cont)
579    {
580      cont = new ConfigValueContainer(CFT_Keybindings, ClassManager<KeyBinder>::getIdentifier(), button.name_, "");
581      ClassManager<KeyBinder>::getIdentifier()->addConfigValueContainer(button.name_, cont);
582    }
583    std::string old = button.bindingString_;
584    cont->getValue(&button.bindingString_);
585
586    // keybinder stuff
587    if (old != button.bindingString_)
588    {
589      // clear everything so we don't get old axis ParamCommands mixed up
590      button.clear();
591
592      // binding has changed
593      button.parse(paramCommandBuffer_);
594    }
595  }
596
597  /**
598    @brief Overwrites all bindings with ""
599  */
600  void KeyBinder::clearBindings()
601  {
602    for (unsigned int i = 0; i < nKeys_s; i++)
603      keys_[i].clear();
604
605    for (unsigned int i = 0; i < nMouseButtons_s; i++)
606      mouseButtons_[i].clear();
607
608    for (unsigned int i = 0; i < nJoyStickButtons_s; i++)
609      joyStickButtons_[i].clear();
610
611    for (unsigned int i = 0; i < nHalfAxes_s; i++)
612      halfAxes_[i].clear();
613
614    for (unsigned int i = 0; i < paramCommandBuffer_.size(); i++)
615      delete paramCommandBuffer_[i];
616    paramCommandBuffer_.clear();
617  }
618
619  void KeyBinder::tickInput(float dt, const HandlerState& state)
620  {
621    // we have to process all the analog input since there is e.g. no 'mouseDoesntMove' event.
622    unsigned int iBegin = 8;
623    unsigned int iEnd   = 8;
624    if (state.joyStick)
625      iEnd = nHalfAxes_s;
626    if (state.mouse)
627      iBegin = 0;
628    for (unsigned int i = iBegin; i < iEnd; i++)
629    {
630      if (halfAxes_[i].hasChanged_)
631      {
632        if (!halfAxes_[i].wasDown_ && halfAxes_[i].absVal_ > halfAxes_[i].buttonThreshold_)
633        {
634          halfAxes_[i].wasDown_ = true;
635          if (halfAxes_[i].nCommands_[KeybindMode::OnPress])
636            halfAxes_[i].execute(KeybindMode::OnPress);
637        }
638        else if (halfAxes_[i].wasDown_ && halfAxes_[i].absVal_ < halfAxes_[i].buttonThreshold_)
639        {
640          halfAxes_[i].wasDown_ = false;
641          if (halfAxes_[i].nCommands_[KeybindMode::OnRelease])
642            halfAxes_[i].execute(KeybindMode::OnRelease);
643        }
644        halfAxes_[i].hasChanged_ = false;
645      }
646
647      if (halfAxes_[i].wasDown_)
648      {
649        if (halfAxes_[i].nCommands_[KeybindMode::OnHold])
650          halfAxes_[i].execute(KeybindMode::OnHold);
651      }
652
653      // these are the actually useful axis bindings for analog input AND output
654      if (halfAxes_[i].relVal_ > analogThreshold_ || halfAxes_[i].absVal_ > analogThreshold_)
655      {
656        //COUT(3) << halfAxes_[i].name_ << "\t" << halfAxes_[i].absVal_ << std::endl;
657        halfAxes_[i].execute();
658      }
659    }
660
661    if (bDeriveMouseInput_ && state.mouse)
662    {
663      if (deriveTime_ > derivePeriod_)
664      {
665        //CCOUT(3) << "mouse abs: ";
666        for (int i = 0; i < 2; i++)
667        {
668          if (mouseRelative_[i] > 0)
669          {
670            halfAxes_[2*i + 0].absVal_ =  mouseRelative_[i] / deriveTime_ * 0.0005 * mouseSensitivityDerived_;
671            halfAxes_[2*i + 1].absVal_ = 0.0f;
672          }
673          else if (mouseRelative_[i] < 0)
674          {
675            halfAxes_[2*i + 0].absVal_ = 0.0f;
676            halfAxes_[2*i + 1].absVal_ = -mouseRelative_[i] / deriveTime_ * 0.0005 * mouseSensitivityDerived_;
677          }
678          else
679          {
680            halfAxes_[2*i + 0].absVal_ = 0.0f;
681            halfAxes_[2*i + 1].absVal_ = 0.0f;
682          }
683          //COUT(3) << mouseRelative_[i] << " | ";
684          mouseRelative_[i] = 0;
685          halfAxes_[2*i + 0].hasChanged_ = true;
686          halfAxes_[2*i + 1].hasChanged_ = true;
687        }
688        deriveTime_ = 0.0f;
689        //COUT(3) << std::endl;
690      }
691      else
692        deriveTime_ += dt;
693    }
694
695    // execute all buffered bindings (addional parameter)
696    for (unsigned int i = 0; i < paramCommandBuffer_.size(); i++)
697      paramCommandBuffer_[i]->execute();
698
699    // always reset the relative movement of the mouse
700    if (state.mouse)
701      for (unsigned int i = 0; i < 8; i++)
702        halfAxes_[i].relVal_ = 0.0f;
703  }
704
705  void KeyBinder::keyPressed (const KeyEvent& evt)
706  { keys_[evt.key].execute(KeybindMode::OnPress); }
707
708  void KeyBinder::keyReleased(const KeyEvent& evt)
709  { keys_[evt.key].execute(KeybindMode::OnRelease); }
710
711  void KeyBinder::keyHeld    (const KeyEvent& evt)
712  { keys_[evt.key].execute(KeybindMode::OnHold); }
713
714
715  void KeyBinder::mouseButtonPressed (MouseButton::Enum id)
716  { mouseButtons_[id].execute(KeybindMode::OnPress); }
717
718  void KeyBinder::mouseButtonReleased(MouseButton::Enum id)
719  { mouseButtons_[id].execute(KeybindMode::OnRelease); }
720
721  void KeyBinder::mouseButtonHeld    (MouseButton::Enum id)
722  { mouseButtons_[id].execute(KeybindMode::OnHold); }
723
724
725  void KeyBinder::joyStickButtonPressed (int joyStickID, int button)
726  { joyStickButtons_[button].execute(KeybindMode::OnPress); }
727
728  void KeyBinder::joyStickButtonReleased(int joyStickID, int button)
729  { joyStickButtons_[button].execute(KeybindMode::OnRelease); }
730
731  void KeyBinder::joyStickButtonHeld    (int joyStickID, int button)
732  { joyStickButtons_[button].execute(KeybindMode::OnHold); }
733
734  /**
735    @brief Event handler for the mouseMoved Event.
736    @param e Mouse state information
737  */
738  void KeyBinder::mouseMoved(IntVector2 abs_, IntVector2 rel_, IntVector2 clippingSize)
739  {
740    // y axis of mouse input is inverted
741    int rel[] = { rel_.x, -rel_.y };
742
743    if (!bDeriveMouseInput_)
744    {
745      for (int i = 0; i < 2; i++)
746      {
747        if (rel[i])
748        {
749          // absolute
750          halfAxes_[2*i + 0].hasChanged_ = true;
751          halfAxes_[2*i + 1].hasChanged_ = true;
752          mousePosition_[i] += rel[i];
753
754          if (bClipMouse_)
755          {
756            if (mousePosition_[i] > 1024)
757              mousePosition_[i] =  1024;
758            if (mousePosition_[i] < -1024)
759              mousePosition_[i] = -1024;
760          }
761
762          if (mousePosition_[i] >= 0)
763          {
764            halfAxes_[2*i + 0].absVal_ =   mousePosition_[i]/1024.0f * mouseSensitivity_;
765            halfAxes_[2*i + 1].absVal_ =  0.0f;
766          }
767          else
768          {
769            halfAxes_[2*i + 0].absVal_ =  0.0f;
770            halfAxes_[2*i + 1].absVal_ =  -mousePosition_[i]/1024.0f * mouseSensitivity_;
771          }
772        }
773      }
774    }
775    else
776    {
777      mouseRelative_[0] += rel[0];
778      mouseRelative_[1] += rel[1];
779    }
780
781    // relative
782    for (int i = 0; i < 2; i++)
783    {
784      if (rel[i] > 0)
785        halfAxes_[0 + 2*i].relVal_ =  ((float)rel[i])/1024 * mouseSensitivity_;
786      else
787        halfAxes_[1 + 2*i].relVal_ = -((float)rel[i])/1024 * mouseSensitivity_;
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  void KeyDetector::readTrigger(Button& button)
874  {
875    SimpleCommand* cmd = new SimpleCommand();
876    cmd->evaluation_ = CommandExecutor::evaluate("storeKeyStroke " + button.name_);
877    button.commands_[KeybindMode::OnPress] = new BaseCommand*[1];
878    button.commands_[KeybindMode::OnPress][0] = cmd;
879    button.nCommands_[KeybindMode::OnPress] = 1;
880  }
881 
882}
Note: See TracBrowser for help on using the repository browser.