Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7290 was 6536, checked in by rgrieder, 14 years ago

Merged revisions 6430-6440 from the gamestate branch to the trunk.
This adds keybindings merging functionality.

(from log of r6437)
When running development builds, the keybinder will merge the local file and the one from the data folder.
Catch: if you want to remove a binding, you'll have to write "NoBinding" (not case sensitive) to override the default command

The keybind command already does that for you though.

  • Property svn:eol-style set to native
File size: 21.7 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
[1413]29#include "KeyBinder.h"
[2662]30
[6417]31#include <algorithm>
32#include <sstream>
[1293]33#include "util/Convert.h"
[1747]34#include "util/Debug.h"
[5929]35#include "util/Exception.h"
[1519]36#include "core/ConfigValueIncludes.h"
37#include "core/CoreIncludes.h"
[1795]38#include "core/ConfigFileManager.h"
[6536]39#include "core/PathConfig.h"
[1520]40#include "InputCommands.h"
[3327]41#include "JoyStick.h"
[971]42
43namespace orxonox
44{
[1755]45    /**
46    @brief
47        Constructor that does as little as necessary.
48    */
[5929]49    KeyBinder::KeyBinder(const std::string& filename)
[3327]50        : deriveTime_(0.0f)
[5929]51        , filename_(filename)
[6536]52        , configFile_(NULL)
53        , fallbackConfigFile_(NULL)
[1755]54    {
55        mouseRelative_[0] = 0;
56        mouseRelative_[1] = 0;
[6417]57        mousePosition_[0] = 0.0;
58        mousePosition_[1] = 0.0;
[1391]59
[1755]60        RegisterRootObject(KeyBinder);
[1293]61
[6428]62        // initialise all buttons and half axes to avoid creating everything with 'new'
[1755]63        // keys
[1887]64        for (unsigned int i = 0; i < KeyCode::numberOfKeys; i++)
[1755]65        {
[6417]66            const std::string& keyname = KeyCode::ByString[i];
[1887]67            if (!keyname.empty())
68                keys_[i].name_ = std::string("Key") + keyname;
69            else
[6417]70                keys_[i].name_.clear();
[1887]71            keys_[i].paramCommandBuffer_ = &paramCommandBuffer_;
72            keys_[i].groupName_ = "Keys";
[1755]73        }
[1887]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++)
[1755]77        {
[1887]78            std::string nameSuffix;
79            if (i < MouseButtonCode::numberOfButtons)
80                nameSuffix = MouseButtonCode::ByString[i];
81            else
82                nameSuffix = mouseWheelNames[i - MouseButtonCode::numberOfButtons];
[3327]83            mouseButtons_[i].name_ = nameSuffix;
[1887]84            mouseButtons_[i].paramCommandBuffer_ = &paramCommandBuffer_;
85            mouseButtons_[i].groupName_ = "MouseButtons";
[1755]86        }
[1887]87        // mouse axes
88        for (unsigned int i = 0; i < MouseAxisCode::numberOfAxes * 2; i++)
89        {
[3327]90            mouseAxes_[i].name_ = MouseAxisCode::ByString[i / 2];
[1887]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        }
[1755]98
[1887]99        // initialise joy sticks separatly to allow for reloading
[3327]100        this->JoyStickQuantityChanged(this->getJoyStickList());
[1887]101
102        // set them here to use allHalfAxes_
103        setConfigValues();
[5929]104
105        // Load the bindings if filename was given
106        if (!this->filename_.empty())
107            this->loadBindings();
[1413]108    }
109
[1755]110    /**
111    @brief
112        Destructor
113    */
114    KeyBinder::~KeyBinder()
[1413]115    {
[1755]116        // almost no destructors required because most of the arrays are static.
117        clearBindings(); // does some destruction work
[6536]118        if (this->configFile_)
119            delete this->configFile_;
120        if (this->fallbackConfigFile_)
121            delete this->fallbackConfigFile_;
[1413]122    }
123
[1755]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.");
[2087]132        SetConfigValue(bFilterAnalogNoise_, false)
133            .description("Specifies whether to filter small analog values like joy stick fluctuations.");
[6417]134        SetConfigValue(mouseSensitivity_, 3.0f)
[1755]135            .description("Mouse sensitivity.");
[6417]136        this->totalMouseSensitivity_ = this->mouseSensitivity_ / this->mouseClippingSize_;
[1755]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.");
[2087]143        SetConfigValue(mouseWheelStepSize_, 120)
[1887]144            .description("Equals one step of the mousewheel.");
[1755]145        SetConfigValue(buttonThreshold_, 0.80f)
[1887]146            .description("Threshold for analog axes until which the button is not pressed.")
147            .callback(this, &KeyBinder::buttonThresholdChanged);
148    }
[973]149
[1887]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_;
[1755]155    }
[1293]156
[3327]157    void KeyBinder::JoyStickQuantityChanged(const std::vector<JoyStick*>& joyStickList)
[1755]158    {
[3327]159        unsigned int oldValue = joySticks_.size();
160        joySticks_ = joyStickList;
[1887]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
[6536]169        if (configFile_ != NULL)
[1755]170        {
[3327]171            for (unsigned int iDev = oldValue; iDev < joySticks_.size(); ++iDev)
[1887]172            {
173                for (unsigned int i = 0; i < JoyStickButtonCode::numberOfButtons; ++i)
[6536]174                    (*joyStickButtons_[iDev])[i].readBinding(this->configFile_, this->fallbackConfigFile_);
[1887]175                for (unsigned int i = 0; i < JoyStickAxisCode::numberOfAxes * 2; ++i)
[6536]176                    (*joyStickAxes_[iDev])[i].readBinding(this->configFile_, this->fallbackConfigFile_);
[1887]177            }
[1755]178        }
[1293]179
[1887]180        // Set the button threshold for potential new axes
181        buttonThresholdChanged();
182    }
183
184    void KeyBinder::initialiseJoyStickBindings()
185    {
[5695]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
[3327]191        this->joyStickAxes_.resize(joySticks_.size());
192        this->joyStickButtons_.resize(joySticks_.size());
[1887]193
[6417]194        // reinitialise all joy stick bindings (doesn't overwrite the old ones)
[3327]195        for (unsigned int iDev = 0; iDev < joySticks_.size(); iDev++)
[1755]196        {
[6417]197            const std::string& deviceName = joySticks_[iDev]->getDeviceName();
[1887]198            // joy stick buttons
199            for (unsigned int i = 0; i < JoyStickButtonCode::numberOfButtons; i++)
200            {
[5695]201                (*joyStickButtons_[iDev])[i].name_ = JoyStickButtonCode::ByString[i];
202                (*joyStickButtons_[iDev])[i].paramCommandBuffer_ = &paramCommandBuffer_;
203                (*joyStickButtons_[iDev])[i].groupName_ = "JoyStickButtons_" + deviceName;
[1887]204            }
205            // joy stick axes
206            for (unsigned int i = 0; i < JoyStickAxisCode::numberOfAxes * 2; i++)
207            {
[5695]208                (*joyStickAxes_[iDev])[i].name_ = JoyStickAxisCode::ByString[i / 2];
[1887]209                if (i & 1)
[5695]210                    (*joyStickAxes_[iDev])[i].name_ += "Pos";
[1887]211                else
[5695]212                    (*joyStickAxes_[iDev])[i].name_ += "Neg";
213                (*joyStickAxes_[iDev])[i].paramCommandBuffer_ = &paramCommandBuffer_;
214                (*joyStickAxes_[iDev])[i].groupName_ = "JoyStickAxes_" + deviceName;
[1887]215            }
216        }
217    }
[973]218
[1887]219    void KeyBinder::compilePointerLists()
220    {
221        allButtons_.clear();
222        allHalfAxes_.clear();
223
[2662]224        // Note: Don't include the dummy keys which don't actually exist in OIS but have a number
[1887]225        for (unsigned int i = 0; i < KeyCode::numberOfKeys; i++)
[2662]226            if (!keys_[i].name_.empty())
[6417]227                allButtons_[keys_[i].groupName_ + '.' + keys_[i].name_] = keys_ + i;
[1887]228        for (unsigned int i = 0; i < numberOfMouseButtons_; i++)
[6417]229            allButtons_[mouseButtons_[i].groupName_ + '.' + mouseButtons_[i].name_] = mouseButtons_ + i;
[1887]230        for (unsigned int i = 0; i < MouseAxisCode::numberOfAxes * 2; i++)
231        {
[6417]232            allButtons_[mouseAxes_[i].groupName_ + '.' + mouseAxes_[i].name_] = mouseAxes_ + i;
[1887]233            allHalfAxes_.push_back(mouseAxes_ + i);
[1755]234        }
[3327]235        for (unsigned int iDev = 0; iDev < joySticks_.size(); iDev++)
[1887]236        {
237            for (unsigned int i = 0; i < JoyStickButtonCode::numberOfButtons; i++)
[6417]238                allButtons_[(*joyStickButtons_[iDev])[i].groupName_ + '.' + (*joyStickButtons_[iDev])[i].name_] = &((*joyStickButtons_[iDev])[i]);
[1887]239            for (unsigned int i = 0; i < JoyStickAxisCode::numberOfAxes * 2; i++)
240            {
[6417]241                allButtons_[(*joyStickAxes_[iDev])[i].groupName_ + '.' + (*joyStickAxes_[iDev])[i].name_] = &((*joyStickAxes_[iDev])[i]);
[5695]242                allHalfAxes_.push_back(&((*joyStickAxes_[iDev])[i]));
[1887]243            }
244        }
[1349]245    }
246
[1755]247    /**
248    @brief
[1887]249        Loads the key and button bindings.
[1755]250    */
[5929]251    void KeyBinder::loadBindings()
[1349]252    {
[1887]253        COUT(3) << "KeyBinder: Loading key bindings..." << std::endl;
[1428]254
[6536]255        this->configFile_ = new ConfigFile(this->filename_, !PathConfig::isDevelopmentRun());
256        this->configFile_->load();
[1293]257
[6536]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        }
[3280]271
[1887]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)
[6417]274        {
[6536]275            it->second->readBinding(this->configFile_, this->fallbackConfigFile_);
[6417]276            addButtonToCommand(it->second->bindingString_, it->second);
277        }
[1349]278
[1887]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        {
[6417]287            addButtonToCommand(binding, it->second);
[6536]288            std::string str = binding;
289            if (PathConfig::isDevelopmentRun() && binding.empty())
290                str = "NoBinding";
291            it->second->setBinding(this->configFile_, this->fallbackConfigFile_, binding, bTemporary);
[1887]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
[6417]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());
[6422]308        if (it != oldKeynames.end())
[6417]309            oldKeynames.erase(it);
310
311        if (!command.empty())
312        {
313            std::vector<std::string>& keynames = this->allCommands_[command];
[6422]314            if (std::find(keynames.begin(), keynames.end(), stream.str()) == keynames.end())
[6417]315                this->allCommands_[command].push_back(stream.str());
316        }
317     }
318
[1887]319    /**
320    @brief
[6417]321        Return the first key name for a specific command
322    */
323    const std::string& KeyBinder::getBinding(const std::string& commandName)
324    {
[6422]325        if (this->allCommands_.find(commandName) != this->allCommands_.end())
[6417]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    {
[6422]344        if (this->allCommands_.find(commandName) != this->allCommands_.end())
[6417]345        {
346            std::vector<std::string>& keynames = this->allCommands_[commandName];
[6422]347            if (index < keynames.size())
[6417]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    {
[6422]364        if (this->allCommands_.find(commandName) != this->allCommands_.end())
[6417]365        {
366            std::vector<std::string>& keynames = this->allCommands_[commandName];
367            return keynames.size();
368        }
369
370        return 0;
371    }
372
373    /**
374    @brief
[1887]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
[1755]382        for (unsigned int i = 0; i < paramCommandBuffer_.size(); i++)
383            delete paramCommandBuffer_[i];
384        paramCommandBuffer_.clear();
385    }
[1349]386
[1755]387    void KeyBinder::resetJoyStickAxes()
[1461]388    {
[3327]389        for (unsigned int iDev = 0; iDev < joySticks_.size(); ++iDev)
[1755]390        {
[1887]391            for (unsigned int i = 0; i < JoyStickAxisCode::numberOfAxes * 2; i++)
392            {
[5695]393                (*joyStickAxes_[iDev])[i].absVal_ = 0.0f;
394                (*joyStickAxes_[iDev])[i].relVal_ = 0.0f;
[1887]395            }
[1755]396        }
[1461]397    }
398
[3327]399    void KeyBinder::mouseUpdated(float dt)
[1349]400    {
[1755]401        if (bDeriveMouseInput_)
[1349]402        {
[2662]403            // only update when derivation dt has passed
[1755]404            if (deriveTime_ > derivePeriod_)
405            {
406                for (int i = 0; i < 2; i++)
407                {
[2662]408                    if (mouseRelative_[i] < 0)
[1755]409                    {
[1887]410                        mouseAxes_[2*i + 0].absVal_
[3196]411                            = -mouseRelative_[i] / deriveTime_ * 0.0005f * mouseSensitivityDerived_;
[1887]412                        mouseAxes_[2*i + 1].absVal_ = 0.0f;
[1755]413                    }
[2662]414                    else if (mouseRelative_[i] > 0)
[1755]415                    {
[1887]416                        mouseAxes_[2*i + 0].absVal_ = 0.0f;
417                        mouseAxes_[2*i + 1].absVal_
[3196]418                            =  mouseRelative_[i] / deriveTime_ * 0.0005f * mouseSensitivityDerived_;
[1755]419                    }
420                    else
421                    {
[1887]422                        mouseAxes_[2*i + 0].absVal_ = 0.0f;
423                        mouseAxes_[2*i + 1].absVal_ = 0.0f;
[1755]424                    }
425                    mouseRelative_[i] = 0;
[1887]426                    mouseAxes_[2*i + 0].hasChanged_ = true;
427                    mouseAxes_[2*i + 1].hasChanged_ = true;
[1755]428                }
429                deriveTime_ = 0.0f;
430            }
431            else
432                deriveTime_ += dt;
[1349]433        }
[1219]434
[2087]435        for (unsigned int i = 0; i < MouseAxisCode::numberOfAxes * 2; i++)
[1349]436        {
[2087]437            // Why dividing relative value by dt? The reason lies in the simple fact, that when you
438            // press a button that has relative movement, that value has to be multiplied by dt to be
[2896]439            // frame rate independent. This can easily (and only) be done in updateInput(float).
[2087]440            // Hence we need to divide by dt here for the mouse to compensate, because the relative
441            // move movements have nothing to do with dt.
442            if (dt != 0.0f)
[1755]443            {
[2087]444                // just ignore if dt == 0.0 because we have multiplied by 0.0 anyway..
445                mouseAxes_[i].relVal_ /= dt;
[1755]446            }
447
[2087]448            tickHalfAxis(mouseAxes_[i]);
449        }
450    }
451
[3327]452    void KeyBinder::joyStickUpdated(unsigned int joyStick, float dt)
[2087]453    {
454        for (unsigned int i = 0; i < JoyStickAxisCode::numberOfAxes * 2; i++)
455        {
[5695]456            tickHalfAxis((*joyStickAxes_[joyStick])[i]);
[2087]457        }
458    }
459
460    void KeyBinder::tickHalfAxis(HalfAxis& halfAxis)
461    {
462        // button mode
463        // TODO: optimize out all the half axes that don't act as a button at the moment
464        if (halfAxis.hasChanged_)
465        {
466            if (!halfAxis.pressed_ && halfAxis.absVal_ > halfAxis.buttonThreshold_)
[1755]467            {
[2087]468                // key pressed event
469                halfAxis.pressed_ = true;
470                if (halfAxis.nCommands_[KeybindMode::OnPress])
471                    halfAxis.execute(KeybindMode::OnPress);
[1755]472            }
[2087]473            else if (halfAxis.pressed_ && halfAxis.absVal_ < halfAxis.buttonThreshold_)
[1755]474            {
[2087]475                // key released event
476                halfAxis.pressed_ = false;
477                if (halfAxis.nCommands_[KeybindMode::OnRelease])
478                    halfAxis.execute(KeybindMode::OnRelease);
[1755]479            }
[2087]480            halfAxis.hasChanged_ = false;
[1349]481        }
[2087]482
483        if (halfAxis.pressed_)
484        {
485            // key held event
486            if (halfAxis.nCommands_[KeybindMode::OnHold])
487                halfAxis.execute(KeybindMode::OnHold);
488        }
489
490        // these are the actually useful axis bindings for analog input
[6417]491        halfAxis.execute();
[1349]492    }
493
[1755]494    /**
495    @brief
496        Event handler for the mouseMoved Event.
497    @param e
498        Mouse state information
499    */
500    void KeyBinder::mouseMoved(IntVector2 abs_, IntVector2 rel_, IntVector2 clippingSize)
501    {
502        // y axis of mouse input is inverted
503        int rel[] = { rel_.x, -rel_.y };
[1349]504
[2087]505        if (bDeriveMouseInput_)
[1755]506        {
[2087]507            mouseRelative_[0] += rel[0];
508            mouseRelative_[1] += rel[1];
509        }
510        else
511        {
[1755]512            for (int i = 0; i < 2; i++)
513            {
[2662]514                if (rel[i]) // performance opt. for the case that rel[i] == 0
[1755]515                {
[1887]516                    // write absolute values
517                    mouseAxes_[2*i + 0].hasChanged_ = true;
518                    mouseAxes_[2*i + 1].hasChanged_ = true;
[6417]519                    mousePosition_[i] += rel[i] * totalMouseSensitivity_;
[1349]520
[1887]521                    // clip absolute position
[6417]522                    if (mousePosition_[i] > 1.0)
523                        mousePosition_[i] =  1.0;
524                    if (mousePosition_[i] < -1.0)
525                        mousePosition_[i] = -1.0;
[1428]526
[6417]527                    if (mousePosition_[i] < 0.0)
[1755]528                    {
[6417]529                        mouseAxes_[2*i + 0].absVal_ = -mousePosition_[i];
[3301]530                        mouseAxes_[2*i + 1].absVal_ = 0.0f;
[1755]531                    }
532                    else
533                    {
[3301]534                        mouseAxes_[2*i + 0].absVal_ = 0.0f;
[6417]535                        mouseAxes_[2*i + 1].absVal_ =  mousePosition_[i];
[1755]536                    }
537                }
538            }
539        }
[1428]540
[1755]541        // relative
542        for (int i = 0; i < 2; i++)
543        {
[2662]544            if (rel[i] < 0)
[6417]545                mouseAxes_[0 + 2*i].relVal_ = -rel[i] * totalMouseSensitivity_;
[1755]546            else
[6417]547                mouseAxes_[1 + 2*i].relVal_ =  rel[i] * totalMouseSensitivity_;
[1349]548        }
549    }
[1428]550
[1755]551    /**
[1349]552    @brief Event handler for the mouseScrolled Event.
553    @param e Mouse state information
[1755]554    */
555    void KeyBinder::mouseScrolled(int abs, int rel)
[1349]556    {
[2662]557        if (rel < 0)
558            for (int i = 0; i < -rel/mouseWheelStepSize_; i++)
[3301]559                mouseButtons_[8].execute(KeybindMode::OnPress, static_cast<float>(abs)/mouseWheelStepSize_);
[1755]560        else
[2662]561            for (int i = 0; i < rel/mouseWheelStepSize_; i++)
[3301]562                mouseButtons_[9].execute(KeybindMode::OnPress, static_cast<float>(abs)/mouseWheelStepSize_);
[1349]563    }
[1755]564
[3327]565    void KeyBinder::axisMoved(unsigned int device, unsigned int axisID, float value)
[1349]566    {
[6417]567        // Filter analog noise
568        if (this->bFilterAnalogNoise_ && std::abs(value) < this->analogThreshold_)
569            value = 0.0;
[3327]570        int i = axisID * 2;
[5695]571        JoyStickAxisVector& axis = *joyStickAxes_[device];
[2662]572        if (value < 0)
[1755]573        {
[3327]574            axis[i].absVal_ = -value;
575            axis[i].relVal_ = -value;
576            axis[i].hasChanged_ = true;
577            if (axis[i + 1].absVal_ > 0.0f)
[1755]578            {
[3327]579                axis[i + 1].absVal_ = -0.0f;
580                axis[i + 1].relVal_ = -0.0f;
581                axis[i + 1].hasChanged_ = true;
[1755]582            }
583        }
584        else
585        {
[3327]586            axis[i + 1].absVal_ = value;
587            axis[i + 1].relVal_ = value;
588            axis[i + 1].hasChanged_ = true;
589            if (axis[i].absVal_ > 0.0f)
[1755]590            {
[3327]591                axis[i].absVal_ = -0.0f;
592                axis[i].relVal_ = -0.0f;
593                axis[i].hasChanged_ = true;
[1755]594            }
595        }
[1349]596    }
[971]597}
Note: See TracBrowser for help on using the repository browser.