Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/buildsystem/src/core/input/KeyBinder.cc @ 2023

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

changed return type of ConfigFileManager::getInstance() to ConfigFileManager& (from pointer before).

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