Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/core/input/KeyBinder.cc @ 1875

Last change on this file since 1875 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
RevLine 
[971]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
[1349]3 *                    > www.orxonox.net <
[971]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 */
[973]28
[971]29/**
30 @file
[973]31 @brief Implementation of the different input handlers.
[971]32 */
33
[1413]34#include "KeyBinder.h"
35#include <fstream>
[1520]36#include <string>
[1293]37#include "util/Convert.h"
[1747]38#include "util/Debug.h"
[1519]39#include "core/ConfigValueIncludes.h"
40#include "core/CoreIncludes.h"
[1795]41#include "core/ConfigFileManager.h"
[1520]42#include "InputCommands.h"
[971]43
44namespace orxonox
45{
[1755]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;
[1391]57
[1755]58        RegisterRootObject(KeyBinder);
[1293]59
[1755]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];
[1349]158
[1755]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];
[1349]169
[1755]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_;
[1413]197    }
198
[1755]199    /**
200    @brief
201        Destructor
202    */
203    KeyBinder::~KeyBinder()
[1413]204    {
[1755]205        // almost no destructors required because most of the arrays are static.
206        clearBindings(); // does some destruction work
[1413]207    }
208
[1755]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;
[973]218
[1755]219        clearBindings();
[973]220
[1755]221        std::ifstream infile;
222        infile.open("keybindings.ini");
223        if (!infile)
224        {
[1795]225            ConfigFileManager::getInstance().setFile(CFT_Keybindings, "def_keybindings.ini");
226            ConfigFileManager::getInstance().save(CFT_Keybindings, "keybindings.ini");
[1755]227        }
228        else
229            infile.close();
[1795]230        ConfigFileManager::getInstance().setFile(CFT_Keybindings, "keybindings.ini");
[1022]231
[1755]232        // parse key bindings
233        setConfigValues();
[1398]234
[1755]235        COUT(3) << "KeyBinder: Loading key bindings done." << std::endl;
[1398]236    }
[1413]237
[1755]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.");
[1349]256
[1755]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_;
[973]264
[1755]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    }
[1293]278
[1755]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);
[1293]292
[1755]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();
[973]298
[1755]299            // binding has changed
300            button.parse(paramCommandBuffer_);
301        }
[1349]302    }
303
[1755]304    /**
305    @brief
306        Overwrites all bindings with ""
307    */
308    void KeyBinder::clearBindings()
[1349]309    {
[1755]310        for (unsigned int i = 0; i < nKeys_s; i++)
311            keys_[i].clear();
[1428]312
[1755]313        for (unsigned int i = 0; i < nMouseButtons_s; i++)
314            mouseButtons_[i].clear();
[1293]315
[1755]316        for (unsigned int i = 0; i < nJoyStickButtons_s; i++)
317            joyStickButtons_[i].clear();
[1219]318
[1755]319        for (unsigned int i = 0; i < nHalfAxes_s; i++)
320            halfAxes_[i].clear();
[1349]321
[1755]322        for (unsigned int i = 0; i < paramCommandBuffer_.size(); i++)
323            delete paramCommandBuffer_[i];
324        paramCommandBuffer_.clear();
325    }
[1349]326
[1755]327    void KeyBinder::resetJoyStickAxes()
[1461]328    {
[1755]329        for (unsigned int i = 8; i < nHalfAxes_s; i++)
330        {
331            halfAxes_[i].absVal_ = 0.0f;
332            halfAxes_[i].relVal_ = 0.0f;
333        }
[1461]334    }
335
[1755]336    void KeyBinder::tickMouse(float dt)
[1349]337    {
[1755]338        tickDevices(0, 8);
339
340        if (bDeriveMouseInput_)
[1349]341        {
[1755]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;
[1349]374        }
[1755]375    }
[1219]376
[1755]377    void KeyBinder::tickJoyStick(float dt, unsigned int joyStick)
378    {
379        tickDevices(8, nHalfAxes_s);
380    }
[1420]381
[1755]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;
[1349]391    }
392
[1755]393    void KeyBinder::tickDevices(unsigned int begin, unsigned int end)
[1349]394    {
[1755]395        for (unsigned int i = begin; i < end; i++)
[1349]396        {
[1755]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            }
[1349]428        }
429    }
430
[1755]431    void KeyBinder::keyPressed (const KeyEvent& evt)
432    { keys_[evt.key].execute(KeybindMode::OnPress); }
[1349]433
[1755]434    void KeyBinder::keyReleased(const KeyEvent& evt)
435    { keys_[evt.key].execute(KeybindMode::OnRelease); }
[973]436
[1755]437    void KeyBinder::keyHeld    (const KeyEvent& evt)
438    { keys_[evt.key].execute(KeybindMode::OnHold); }
[1349]439
440
[1755]441    void KeyBinder::mouseButtonPressed (MouseButton::Enum id)
442    { mouseButtons_[id].execute(KeybindMode::OnPress); }
[1349]443
[1755]444    void KeyBinder::mouseButtonReleased(MouseButton::Enum id)
445    { mouseButtons_[id].execute(KeybindMode::OnRelease); }
[1349]446
[1755]447    void KeyBinder::mouseButtonHeld    (MouseButton::Enum id)
448    { mouseButtons_[id].execute(KeybindMode::OnHold); }
[1349]449
450
[1755]451    void KeyBinder::joyStickButtonPressed (unsigned int joyStickID, JoyStickButton::Enum id)
452    { joyStickButtons_[id].execute(KeybindMode::OnPress); }
[1349]453
[1755]454    void KeyBinder::joyStickButtonReleased(unsigned int joyStickID, JoyStickButton::Enum id)
455    { joyStickButtons_[id].execute(KeybindMode::OnRelease); }
[1349]456
[1755]457    void KeyBinder::joyStickButtonHeld    (unsigned int joyStickID, JoyStickButton::Enum id)
458    { joyStickButtons_[id].execute(KeybindMode::OnHold); }
[1349]459
[1755]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 };
[1349]470
[1755]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];
[1349]481
[1755]482                    if (bClipMouse_)
483                    {
484                        if (mousePosition_[i] > 1024)
485                            mousePosition_[i] =  1024;
486                        if (mousePosition_[i] < -1024)
487                            mousePosition_[i] = -1024;
488                    }
[1428]489
[1755]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
[1349]504        {
[1755]505            mouseRelative_[0] += rel[0];
506            mouseRelative_[1] += rel[1];
507        }
[1428]508
[1755]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_;
[1349]516        }
517    }
[1428]518
[1755]519    /**
[1349]520    @brief Event handler for the mouseScrolled Event.
521    @param e Mouse state information
[1755]522    */
523    void KeyBinder::mouseScrolled(int abs, int rel)
[1349]524    {
[1755]525        //COUT(3) << mouseButtons_[8].name_ << "   " << abs << " | " << rel << std::endl;
[1391]526
[1755]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);
[1349]533    }
[1755]534
535    void KeyBinder::joyStickAxisMoved(unsigned int joyStickID, unsigned int axis, float value)
[1349]536    {
[1755]537        int i = 8 + axis * 2;
538        if (value >= 0)
539        {
540            //if (value > 10000)
541            //{ CCOUT(3) << halfAxes_[i].name_ << std::endl; }
[1391]542
[1755]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        }
[1349]568    }
[971]569}
Note: See TracBrowser for help on using the repository browser.