Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

converted input system to 4 spaces/tab

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