Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7861 was 7861, checked in by landauf, 13 years ago

added function to KeyBinder which allows to change the keybind mode (OnPress, OnRelease, OnHold) of a command which is bound to a key.
enhanced ConsoleCommand (+Manipulator) to use this feature.

input system experts, please review :D

  • Property svn:eol-style set to native
File size: 24.8 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#include "KeyBinder.h"
30
31#include <algorithm>
32#include <sstream>
33#include "util/Convert.h"
34#include "util/Debug.h"
35#include "util/Exception.h"
36#include "core/ConfigValueIncludes.h"
37#include "core/CoreIncludes.h"
38#include "core/ConfigFileManager.h"
39#include "core/PathConfig.h"
40#include "InputCommands.h"
41#include "JoyStick.h"
42
43namespace orxonox
44{
45    /**
46    @brief
47        Constructor that does as little as necessary.
48    */
49    KeyBinder::KeyBinder(const std::string& filename)
50        : deriveTime_(0.0f)
51        , filename_(filename)
52        , configFile_(NULL)
53        , fallbackConfigFile_(NULL)
54    {
55        mouseRelative_[0] = 0;
56        mouseRelative_[1] = 0;
57        mousePosition_[0] = 0.0;
58        mousePosition_[1] = 0.0;
59
60        RegisterRootObject(KeyBinder);
61
62        // initialise all buttons and half axes to avoid creating everything with 'new'
63        // keys
64        for (unsigned int i = 0; i < KeyCode::numberOfKeys; i++)
65        {
66            const std::string& keyname = KeyCode::ByString[i];
67            if (!keyname.empty())
68                keys_[i].name_ = std::string("Key") + keyname;
69            else
70                keys_[i].name_.clear();
71            keys_[i].paramCommandBuffer_ = &paramCommandBuffer_;
72            keys_[i].groupName_ = "Keys";
73        }
74        // mouse buttons plus 4 mouse wheel buttons only 'generated' by KeyBinder
75        const char* const mouseWheelNames[] = { "Wheel1Down", "Wheel1Up", "Wheel2Down", "Wheel2Up" };
76        for (unsigned int i = 0; i < numberOfMouseButtons_; i++)
77        {
78            std::string nameSuffix;
79            if (i < MouseButtonCode::numberOfButtons)
80                nameSuffix = MouseButtonCode::ByString[i];
81            else
82                nameSuffix = mouseWheelNames[i - MouseButtonCode::numberOfButtons];
83            mouseButtons_[i].name_ = nameSuffix;
84            mouseButtons_[i].paramCommandBuffer_ = &paramCommandBuffer_;
85            mouseButtons_[i].groupName_ = "MouseButtons";
86        }
87        // mouse axes
88        for (unsigned int i = 0; i < MouseAxisCode::numberOfAxes * 2; i++)
89        {
90            mouseAxes_[i].name_ = MouseAxisCode::ByString[i / 2];
91            if (i & 1)
92                mouseAxes_[i].name_ += "Pos";
93            else
94                mouseAxes_[i].name_ += "Neg";
95            mouseAxes_[i].paramCommandBuffer_ = &paramCommandBuffer_;
96            mouseAxes_[i].groupName_ = "MouseAxes";
97        }
98
99        // initialise joy sticks separatly to allow for reloading
100        this->JoyStickQuantityChanged(this->getJoyStickList());
101
102        // set them here to use allHalfAxes_
103        setConfigValues();
104
105        // Load the bindings if filename was given
106        if (!this->filename_.empty())
107            this->loadBindings();
108    }
109
110    /**
111    @brief
112        Destructor
113    */
114    KeyBinder::~KeyBinder()
115    {
116        // almost no destructors required because most of the arrays are static.
117        clearBindings(); // does some destruction work
118        if (this->configFile_)
119            delete this->configFile_;
120        if (this->fallbackConfigFile_)
121            delete this->fallbackConfigFile_;
122    }
123
124    /**
125    @brief
126        Loader for the key bindings, managed by config values.
127    */
128    void KeyBinder::setConfigValues()
129    {
130        SetConfigValue(analogThreshold_, 0.05f)
131            .description("Threshold for analog axes until which the state is 0.");
132        SetConfigValue(bFilterAnalogNoise_, false)
133            .description("Specifies whether to filter small analog values like joy stick fluctuations.");
134        SetConfigValue(mouseSensitivity_, 3.0f)
135            .description("Mouse sensitivity.");
136        this->totalMouseSensitivity_ = this->mouseSensitivity_ / this->mouseClippingSize_;
137        SetConfigValue(bDeriveMouseInput_, false)
138            .description("Whether or not to derive moues movement for the absolute value.");
139        SetConfigValue(derivePeriod_, 0.05f)
140            .description("Accuracy of the mouse input deriver. The higher the more precise, but laggier.");
141        SetConfigValue(mouseSensitivityDerived_, 1.0f)
142            .description("Mouse sensitivity if mouse input is derived.");
143        SetConfigValue(mouseWheelStepSize_, 120)
144            .description("Equals one step of the mousewheel.");
145        SetConfigValue(buttonThreshold_, 0.80f)
146            .description("Threshold for analog axes until which the button is not pressed.")
147            .callback(this, &KeyBinder::buttonThresholdChanged);
148    }
149
150    void KeyBinder::buttonThresholdChanged()
151    {
152        for (unsigned int i = 0; i < allHalfAxes_.size(); i++)
153            if (!allHalfAxes_[i]->bButtonThresholdUser_)
154                allHalfAxes_[i]->buttonThreshold_ = this->buttonThreshold_;
155    }
156
157    void KeyBinder::JoyStickQuantityChanged(const std::vector<JoyStick*>& joyStickList)
158    {
159        unsigned int oldValue = joySticks_.size();
160        joySticks_ = joyStickList;
161
162        // initialise joy stick bindings
163        initialiseJoyStickBindings();
164
165        // collect all Buttons and HalfAxes again
166        compilePointerLists();
167
168        // load the bindings if required
169        if (configFile_ != NULL)
170        {
171            for (unsigned int iDev = oldValue; iDev < joySticks_.size(); ++iDev)
172            {
173                for (unsigned int i = 0; i < JoyStickButtonCode::numberOfButtons; ++i)
174                    (*joyStickButtons_[iDev])[i].readBinding(this->configFile_, this->fallbackConfigFile_);
175                for (unsigned int i = 0; i < JoyStickAxisCode::numberOfAxes * 2; ++i)
176                    (*joyStickAxes_[iDev])[i].readBinding(this->configFile_, this->fallbackConfigFile_);
177            }
178        }
179
180        // Set the button threshold for potential new axes
181        buttonThresholdChanged();
182    }
183
184    void KeyBinder::initialiseJoyStickBindings()
185    {
186        while (joyStickAxes_.size() < joySticks_.size())
187            joyStickAxes_.push_back(shared_ptr<JoyStickAxisVector>(new JoyStickAxisVector()));
188        while (joyStickButtons_.size() < joySticks_.size())
189            joyStickButtons_.push_back(shared_ptr<JoyStickButtonVector>(new JoyStickButtonVector()));
190        // For the case the new size is smaller
191        this->joyStickAxes_.resize(joySticks_.size());
192        this->joyStickButtons_.resize(joySticks_.size());
193
194        // reinitialise all joy stick bindings (doesn't overwrite the old ones)
195        for (unsigned int iDev = 0; iDev < joySticks_.size(); iDev++)
196        {
197            const std::string& deviceName = joySticks_[iDev]->getDeviceName();
198            // joy stick buttons
199            for (unsigned int i = 0; i < JoyStickButtonCode::numberOfButtons; i++)
200            {
201                (*joyStickButtons_[iDev])[i].name_ = JoyStickButtonCode::ByString[i];
202                (*joyStickButtons_[iDev])[i].paramCommandBuffer_ = &paramCommandBuffer_;
203                (*joyStickButtons_[iDev])[i].groupName_ = "JoyStickButtons_" + deviceName;
204            }
205            // joy stick axes
206            for (unsigned int i = 0; i < JoyStickAxisCode::numberOfAxes * 2; i++)
207            {
208                (*joyStickAxes_[iDev])[i].name_ = JoyStickAxisCode::ByString[i / 2];
209                if (i & 1)
210                    (*joyStickAxes_[iDev])[i].name_ += "Pos";
211                else
212                    (*joyStickAxes_[iDev])[i].name_ += "Neg";
213                (*joyStickAxes_[iDev])[i].paramCommandBuffer_ = &paramCommandBuffer_;
214                (*joyStickAxes_[iDev])[i].groupName_ = "JoyStickAxes_" + deviceName;
215            }
216        }
217    }
218
219    void KeyBinder::compilePointerLists()
220    {
221        allButtons_.clear();
222        allHalfAxes_.clear();
223
224        // Note: Don't include the dummy keys which don't actually exist in OIS but have a number
225        for (unsigned int i = 0; i < KeyCode::numberOfKeys; i++)
226            if (!keys_[i].name_.empty())
227                allButtons_[keys_[i].groupName_ + '.' + keys_[i].name_] = keys_ + i;
228        for (unsigned int i = 0; i < numberOfMouseButtons_; i++)
229            allButtons_[mouseButtons_[i].groupName_ + '.' + mouseButtons_[i].name_] = mouseButtons_ + i;
230        for (unsigned int i = 0; i < MouseAxisCode::numberOfAxes * 2; i++)
231        {
232            allButtons_[mouseAxes_[i].groupName_ + '.' + mouseAxes_[i].name_] = mouseAxes_ + i;
233            allHalfAxes_.push_back(mouseAxes_ + i);
234        }
235        for (unsigned int iDev = 0; iDev < joySticks_.size(); iDev++)
236        {
237            for (unsigned int i = 0; i < JoyStickButtonCode::numberOfButtons; i++)
238                allButtons_[(*joyStickButtons_[iDev])[i].groupName_ + '.' + (*joyStickButtons_[iDev])[i].name_] = &((*joyStickButtons_[iDev])[i]);
239            for (unsigned int i = 0; i < JoyStickAxisCode::numberOfAxes * 2; i++)
240            {
241                allButtons_[(*joyStickAxes_[iDev])[i].groupName_ + '.' + (*joyStickAxes_[iDev])[i].name_] = &((*joyStickAxes_[iDev])[i]);
242                allHalfAxes_.push_back(&((*joyStickAxes_[iDev])[i]));
243            }
244        }
245    }
246
247    /**
248    @brief
249        Loads the key and button bindings.
250    */
251    void KeyBinder::loadBindings()
252    {
253        COUT(3) << "KeyBinder: Loading key bindings..." << std::endl;
254
255        this->configFile_ = new ConfigFile(this->filename_, !PathConfig::isDevelopmentRun());
256        this->configFile_->load();
257
258        if (PathConfig::isDevelopmentRun())
259        {
260            // Dev users should have combined key bindings files
261            std::string defaultFilepath(PathConfig::getDataPathString() + ConfigFile::DEFAULT_CONFIG_FOLDER + '/' + this->filename_);
262            std::ifstream file(defaultFilepath.c_str());
263            if (file.is_open())
264            {
265                file.close();
266                // Open the default file for later use (use absolute path!)
267                this->fallbackConfigFile_ = new ConfigFile(defaultFilepath, false);
268                this->fallbackConfigFile_->load();
269            }
270        }
271
272        // Parse bindings and create the ConfigValueContainers if necessary
273        for (std::map<std::string, Button*>::const_iterator it = allButtons_.begin(); it != allButtons_.end(); ++it)
274        {
275            it->second->readBinding(this->configFile_, this->fallbackConfigFile_);
276            addButtonToCommand(it->second->bindingString_, it->second);
277        }
278
279        COUT(3) << "KeyBinder: Loading key bindings done." << std::endl;
280    }
281
282    bool KeyBinder::setBinding(const std::string& binding, const std::string& name, bool bTemporary)
283    {
284        std::map<std::string, Button*>::iterator it = allButtons_.find(name);
285        if (it != allButtons_.end())
286        {
287            addButtonToCommand(binding, it->second);
288            std::string str = binding;
289            if (PathConfig::isDevelopmentRun() && binding.empty())
290                str = "NoBinding";
291            it->second->setBinding(this->configFile_, this->fallbackConfigFile_, binding, bTemporary);
292            return true;
293        }
294        else
295        {
296            COUT(2) << "Could not find key/button/axis with name '" << name << "'." << std::endl;
297            return false;
298        }
299    }
300
301     void KeyBinder::addButtonToCommand(const std::string& command, Button* button)
302     {
303        std::ostringstream stream;
304        stream << button->groupName_  << '.' << button->name_;
305
306        std::vector<std::string>& oldKeynames = this->allCommands_[button->bindingString_];
307        std::vector<std::string>::iterator it = std::find(oldKeynames.begin(), oldKeynames.end(), stream.str());
308        if (it != oldKeynames.end())
309            oldKeynames.erase(it);
310
311        if (!command.empty())
312        {
313            std::vector<std::string>& keynames = this->allCommands_[command];
314            if (std::find(keynames.begin(), keynames.end(), stream.str()) == keynames.end())
315                this->allCommands_[command].push_back(stream.str());
316        }
317     }
318
319    /**
320    @brief
321        Return the first key name for a specific command
322    */
323    const std::string& KeyBinder::getBinding(const std::string& commandName)
324    {
325        if (this->allCommands_.find(commandName) != this->allCommands_.end())
326        {
327            std::vector<std::string>& keynames = this->allCommands_[commandName];
328            return keynames.front();
329        }
330
331        return BLANKSTRING;
332    }
333
334    /**
335    @brief
336        Return the key name for a specific command at a given index.
337    @param commandName
338        The command name the key name is returned for.
339    @param index
340        The index at which the key name is returned for.
341    */
342    const std::string& KeyBinder::getBinding(const std::string& commandName, unsigned int index)
343    {
344        if (this->allCommands_.find(commandName) != this->allCommands_.end())
345        {
346            std::vector<std::string>& keynames = this->allCommands_[commandName];
347            if (index < keynames.size())
348                return keynames[index];
349
350            return BLANKSTRING;
351        }
352
353        return BLANKSTRING;
354    }
355
356    /**
357    @brief
358        Get the number of different key bindings of a specific command.
359    @param commandName
360        The command.
361    */
362    unsigned int KeyBinder::getNumberOfBindings(const std::string& commandName)
363    {
364        if (this->allCommands_.find(commandName) != this->allCommands_.end())
365        {
366            std::vector<std::string>& keynames = this->allCommands_[commandName];
367            return keynames.size();
368        }
369
370        return 0;
371    }
372
373    /**
374    @brief
375        Overwrites all bindings with ""
376    */
377    void KeyBinder::clearBindings()
378    {
379        for (std::map<std::string, Button*>::const_iterator it = allButtons_.begin(); it != allButtons_.end(); ++it)
380            it->second->clear();
381
382        for (unsigned int i = 0; i < paramCommandBuffer_.size(); i++)
383            delete paramCommandBuffer_[i];
384        paramCommandBuffer_.clear();
385    }
386
387    /**
388        @brief Changes the keybind mode of a given console command.
389    */
390    void KeyBinder::changeMode(ConsoleCommand* command, KeybindMode::Value new_mode)
391    {
392        // iterate over all buttons
393        for (std::map<std::string, Button*>::iterator it = this->allButtons_.begin(); it != this->allButtons_.end(); ++it)
394        {
395            Button* button = it->second;
396
397            // iterate over all modes
398            for (size_t mode_index = 0; mode_index < 3; ++mode_index)
399            {
400                if (mode_index == new_mode) // skip commands that are already in the desired mode
401                    continue;
402
403                // iterate over all commands of the given mode at the given button
404                for (size_t command_index = 0; command_index < button->nCommands_[mode_index]; ++command_index)
405                {
406                    CommandEvaluation* evaluation = button->commands_[mode_index][command_index]->getEvaluation();
407
408                    // compare the command
409                    if (evaluation && evaluation->getConsoleCommand() == command)
410                    {
411                        // increase array of new mode
412                        BaseCommand** array_new_mode = new BaseCommand*[button->nCommands_[new_mode] + 1];
413                        // copy array content
414                        for (size_t c = 0; c < button->nCommands_[new_mode]; ++c)
415                            array_new_mode[c] = button->commands_[new_mode][c];
416                        // insert changed command at the end
417                        array_new_mode[button->nCommands_[new_mode]] = button->commands_[mode_index][command_index];
418                        // delete old array
419                        delete[] button->commands_[new_mode];
420                        // assign new array
421                        button->commands_[new_mode] = array_new_mode;
422                        // increase counter
423                        button->nCommands_[new_mode]++;
424
425                        // erase command from old array
426                        for (size_t c = command_index; c < button->nCommands_[mode_index] - 1; ++c)
427                            button->commands_[mode_index][c] = button->commands_[mode_index][c + 1];
428                        // decrease counter
429                        button->nCommands_[mode_index]--;
430                        // note: we don't replace the old array - it's not one element too large, but no one cares since nCommands_ defines the size
431
432                        // decrement the index since we shifted the array and continue searching for more occurrences of the command
433                        command_index--;
434                    }
435                }
436            }
437        }
438    }
439
440    void KeyBinder::resetJoyStickAxes()
441    {
442        for (unsigned int iDev = 0; iDev < joySticks_.size(); ++iDev)
443            for (unsigned int i = 0; i < JoyStickAxisCode::numberOfAxes * 2; i++)
444                (*joyStickAxes_[iDev])[i].reset();
445    }
446
447    /**
448        @brief Sets the position of the mouse back to 0/0.
449    */
450    void KeyBinder::resetMouseAxes()
451    {
452        this->mousePosition_[0] = 0.0f;
453        this->mousePosition_[1] = 0.0f;
454
455        for (unsigned int i = 0; i < MouseAxisCode::numberOfAxes * 2; i++)
456            mouseAxes_[i].reset();
457    }
458
459    void KeyBinder::mouseUpdated(float dt)
460    {
461        if (bDeriveMouseInput_)
462        {
463            // only update when derivation dt has passed
464            if (deriveTime_ > derivePeriod_)
465            {
466                for (int i = 0; i < 2; i++)
467                {
468                    if (mouseRelative_[i] < 0)
469                    {
470                        mouseAxes_[2*i + 0].absVal_
471                            = -mouseRelative_[i] / deriveTime_ * 0.0005f * mouseSensitivityDerived_;
472                        mouseAxes_[2*i + 1].absVal_ = 0.0f;
473                    }
474                    else if (mouseRelative_[i] > 0)
475                    {
476                        mouseAxes_[2*i + 0].absVal_ = 0.0f;
477                        mouseAxes_[2*i + 1].absVal_
478                            =  mouseRelative_[i] / deriveTime_ * 0.0005f * mouseSensitivityDerived_;
479                    }
480                    else
481                    {
482                        mouseAxes_[2*i + 0].absVal_ = 0.0f;
483                        mouseAxes_[2*i + 1].absVal_ = 0.0f;
484                    }
485                    mouseRelative_[i] = 0;
486                    mouseAxes_[2*i + 0].hasChanged_ = true;
487                    mouseAxes_[2*i + 1].hasChanged_ = true;
488                }
489                deriveTime_ = 0.0f;
490            }
491            else
492                deriveTime_ += dt;
493        }
494
495        for (unsigned int i = 0; i < MouseAxisCode::numberOfAxes * 2; i++)
496        {
497            // Why dividing relative value by dt? The reason lies in the simple fact, that when you
498            // press a button that has relative movement, that value has to be multiplied by dt to be
499            // frame rate independent. This can easily (and only) be done in updateInput(float).
500            // Hence we need to divide by dt here for the mouse to compensate, because the relative
501            // move movements have nothing to do with dt.
502            if (dt != 0.0f)
503            {
504                // just ignore if dt == 0.0 because we have multiplied by 0.0 anyway..
505                mouseAxes_[i].relVal_ /= dt;
506            }
507
508            tickHalfAxis(mouseAxes_[i]);
509        }
510    }
511
512    void KeyBinder::joyStickUpdated(unsigned int joyStick, float dt)
513    {
514        for (unsigned int i = 0; i < JoyStickAxisCode::numberOfAxes * 2; i++)
515        {
516            tickHalfAxis((*joyStickAxes_[joyStick])[i]);
517        }
518    }
519
520    void KeyBinder::tickHalfAxis(HalfAxis& halfAxis)
521    {
522        // button mode
523        // TODO: optimize out all the half axes that don't act as a button at the moment
524        if (halfAxis.hasChanged_)
525        {
526            if (!halfAxis.pressed_ && halfAxis.absVal_ > halfAxis.buttonThreshold_)
527            {
528                // key pressed event
529                halfAxis.pressed_ = true;
530                if (halfAxis.nCommands_[KeybindMode::OnPress])
531                    halfAxis.execute(KeybindMode::OnPress);
532            }
533            else if (halfAxis.pressed_ && halfAxis.absVal_ < halfAxis.buttonThreshold_)
534            {
535                // key released event
536                halfAxis.pressed_ = false;
537                if (halfAxis.nCommands_[KeybindMode::OnRelease])
538                    halfAxis.execute(KeybindMode::OnRelease);
539            }
540            halfAxis.hasChanged_ = false;
541        }
542
543        if (halfAxis.pressed_)
544        {
545            // key held event
546            if (halfAxis.nCommands_[KeybindMode::OnHold])
547                halfAxis.execute(KeybindMode::OnHold);
548        }
549
550        // these are the actually useful axis bindings for analog input
551        halfAxis.execute();
552    }
553
554    /**
555    @brief
556        Event handler for the mouseMoved Event.
557    @param abs_
558        The absolute position of the mouse
559    @param rel_
560        The relative movement of the mouse
561    @param clippingSize
562        Mouse screen area in pixels (usually 1024x1024)
563    */
564    void KeyBinder::mouseMoved(IntVector2 abs_, IntVector2 rel_, IntVector2 clippingSize)
565    {
566        // y axis of mouse input is inverted
567        int rel[] = { rel_.x, -rel_.y };
568
569        if (bDeriveMouseInput_)
570        {
571            mouseRelative_[0] += rel[0];
572            mouseRelative_[1] += rel[1];
573        }
574        else
575        {
576            for (int i = 0; i < 2; i++)
577            {
578                if (rel[i]) // performance opt. for the case that rel[i] == 0
579                {
580                    // write absolute values
581                    mouseAxes_[2*i + 0].hasChanged_ = true;
582                    mouseAxes_[2*i + 1].hasChanged_ = true;
583                    mousePosition_[i] += rel[i] * totalMouseSensitivity_;
584
585                    // clip absolute position
586                    if (mousePosition_[i] > 1.0)
587                        mousePosition_[i] =  1.0;
588                    if (mousePosition_[i] < -1.0)
589                        mousePosition_[i] = -1.0;
590
591                    if (mousePosition_[i] < 0.0)
592                    {
593                        mouseAxes_[2*i + 0].absVal_ = -mousePosition_[i];
594                        mouseAxes_[2*i + 1].absVal_ = 0.0f;
595                    }
596                    else
597                    {
598                        mouseAxes_[2*i + 0].absVal_ = 0.0f;
599                        mouseAxes_[2*i + 1].absVal_ =  mousePosition_[i];
600                    }
601                }
602            }
603        }
604
605        // relative
606        for (int i = 0; i < 2; i++)
607        {
608            if (rel[i] < 0)
609                mouseAxes_[0 + 2*i].relVal_ = -rel[i] * totalMouseSensitivity_;
610            else
611                mouseAxes_[1 + 2*i].relVal_ =  rel[i] * totalMouseSensitivity_;
612        }
613    }
614
615    /**
616    @brief Event handler for the mouseScrolled Event.
617    @param abs The absolute position of the scroll wheel
618    @param rel The relative movement of the scroll wheel
619    */
620    void KeyBinder::mouseScrolled(int abs, int rel)
621    {
622        if (rel < 0)
623            for (int i = 0; i < -rel/mouseWheelStepSize_; i++)
624                mouseButtons_[8].execute(KeybindMode::OnPress, static_cast<float>(abs)/mouseWheelStepSize_);
625        else
626            for (int i = 0; i < rel/mouseWheelStepSize_; i++)
627                mouseButtons_[9].execute(KeybindMode::OnPress, static_cast<float>(abs)/mouseWheelStepSize_);
628    }
629
630    void KeyBinder::axisMoved(unsigned int device, unsigned int axisID, float value)
631    {
632        // Filter analog noise
633        if (this->bFilterAnalogNoise_ && std::abs(value) < this->analogThreshold_)
634            value = 0.0;
635        int i = axisID * 2;
636        JoyStickAxisVector& axis = *joyStickAxes_[device];
637        if (value < 0)
638        {
639            axis[i].absVal_ = -value;
640            axis[i].relVal_ = -value;
641            axis[i].hasChanged_ = true;
642            if (axis[i + 1].absVal_ > 0.0f)
643            {
644                axis[i + 1].absVal_ = -0.0f;
645                axis[i + 1].relVal_ = -0.0f;
646                axis[i + 1].hasChanged_ = true;
647            }
648        }
649        else
650        {
651            axis[i + 1].absVal_ = value;
652            axis[i + 1].relVal_ = value;
653            axis[i + 1].hasChanged_ = true;
654            if (axis[i].absVal_ > 0.0f)
655            {
656                axis[i].absVal_ = -0.0f;
657                axis[i].relVal_ = -0.0f;
658                axis[i].hasChanged_ = true;
659            }
660        }
661    }
662}
Note: See TracBrowser for help on using the repository browser.