Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/input/JoyStick.cc @ 6536

Last change on this file since 6536 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: 10.0 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 "JoyStick.h"
30
31#include <climits>
32#include <ois/OISJoyStick.h>
33#include <boost/foreach.hpp>
34
35#include "util/StringUtils.h"
36#include "core/ConfigFileManager.h"
37#include "core/ConfigValueIncludes.h"
38#include "core/CoreIncludes.h"
39#include "util/Convert.h"
40#include "InputState.h"
41
42namespace orxonox
43{
44    //! Helper function that loads the config value vector of one coefficient
45    void loadCalibration(std::vector<int>& list, const std::string& sectionName, const std::string& valueName, size_t size, int defaultValue);
46
47    std::vector<std::string> JoyStick::deviceNames_s;
48
49    JoyStick::JoyStick(unsigned int id, OIS::InputManager* oisInputManager)
50        : super(id, oisInputManager)
51    {
52        RegisterRootObject(JoyStick);
53        this->setConfigValues();
54        // Initialise POV and Slider states
55        this->clearBuffersImpl();
56
57        // Generate unique name
58        if (oisDevice_->vendor().empty())
59            deviceName_ = "Unknown_";
60        else
61        {
62            std::string name = oisDevice_->vendor();
63            replaceCharacters(name, ' ', '_');
64            deviceName_ = name + '_';
65        }
66        deviceName_ += multi_cast<std::string>(oisDevice_->getNumberOfComponents(OIS::OIS_Button))  + '_';
67        deviceName_ += multi_cast<std::string>(oisDevice_->getNumberOfComponents(OIS::OIS_Axis))    + '_';
68        deviceName_ += multi_cast<std::string>(oisDevice_->getNumberOfComponents(OIS::OIS_Slider))  + '_';
69        deviceName_ += multi_cast<std::string>(oisDevice_->getNumberOfComponents(OIS::OIS_POV));
70        //deviceName_ += multi_cast<std::string>(oisDevice_->getNumberOfComponents(OIS::OIS_Vector3));
71
72        BOOST_FOREACH(std::string& idString, deviceNames_s)
73        {
74            if (deviceName_ == idString)
75            {
76                // Make the ID unique for this execution time.
77                deviceName_ += '_' + multi_cast<std::string>(this->getDeviceName());
78                break;
79            }
80        }
81
82        COUT(4) << "Created OIS joy stick with ID " << deviceName_ << std::endl;
83
84        // Load calibration
85        size_t axes = sliderAxes_s + static_cast<size_t>(oisDevice_->getNumberOfComponents(OIS::OIS_Axis));
86        loadCalibration(configMinValues_,  deviceName_, "MinValue",  axes,  -32768);
87        loadCalibration(configMaxValues_,  deviceName_, "MaxValue",  axes,   32768);
88        loadCalibration(configZeroValues_, deviceName_, "ZeroValue", axes, 0);
89        this->evaluateCalibration();
90    }
91
92    //! Callback for the joy stick calibration config file.
93    void JoyStick::calibrationFileCallback()
94    {
95        ConfigFileManager::getInstance().setFilename(ConfigFileType::JoyStickCalibration, calibrationFilename_);
96    }
97
98    void JoyStick::setConfigValues()
99    {
100        SetConfigValue(calibrationFilename_, "joystick_calibration.ini")
101            .description("Ini filename for the the joy stick calibration data.")
102            .callback(this, &JoyStick::calibrationFileCallback);
103    }
104
105    void loadCalibration(std::vector<int>& list, const std::string& sectionName, const std::string& valueName, size_t size, int defaultValue)
106    {
107        list.resize(size);
108        unsigned int configValueVectorSize = ConfigFileManager::getInstance().getConfigFile(ConfigFileType::JoyStickCalibration)->getVectorSize(sectionName, valueName);
109        if (configValueVectorSize > size)
110            configValueVectorSize = size;
111
112        for (unsigned int i = 0; i < configValueVectorSize; ++i)
113        {
114            list[i] = multi_cast<int>(ConfigFileManager::getInstance().getConfigFile(ConfigFileType::JoyStickCalibration)
115                ->getOrCreateValue(sectionName, valueName, i, multi_cast<std::string>(defaultValue), false));
116        }
117
118        // fill the rest with default values
119        for (unsigned int i = configValueVectorSize; i < size; ++i)
120            list[i] = defaultValue;
121    }
122
123    //! Called by InputDevice when calibration mode has started
124    void JoyStick::calibrationStarted()
125    {
126        // Set initial values
127        BOOST_FOREACH(int& minVal, configMinValues_)
128            minVal = INT_MAX;
129        BOOST_FOREACH(int& minVal, configMaxValues_)
130            minVal = INT_MIN;
131        BOOST_FOREACH(int& zeroVal, configZeroValues_)
132            zeroVal = 0;
133    }
134
135    //! Called by InputDevice when calibration mode has stopped
136    void JoyStick::calibrationStopped()
137    {
138        // Get the middle positions now
139        unsigned int iAxis = 0;
140        for (unsigned int i = 0; i < sliderAxes_s/2; ++i)
141        {
142            configZeroValues_[iAxis++] = oisDevice_->getJoyStickState().mSliders[i].abX;
143            configZeroValues_[iAxis++] = oisDevice_->getJoyStickState().mSliders[i].abY;
144        }
145        // Note: joyStickZeroValues_[iJoyStick] was already correctly resised in loadCalibration()
146        assert(oisDevice_->getJoyStickState().mAxes.size() == configZeroValues_.size() - sliderAxes_s);
147        for (unsigned int i = 0; i < configZeroValues_.size() - sliderAxes_s; ++i)
148            configZeroValues_[iAxis++] = oisDevice_->getJoyStickState().mAxes[i].abs;
149
150        for (unsigned int i = 0; i < configMinValues_.size(); ++i)
151        {
152            // Minimum values
153            if (configMinValues_[i] == INT_MAX)
154                configMinValues_[i] = -32768;
155            ConfigFileManager::getInstance().getConfigFile(ConfigFileType::JoyStickCalibration)
156                ->getOrCreateValue(deviceName_, "MinValue", i, multi_cast<std::string>(configMinValues_[i]), false);
157
158            // Maximum values
159            if (configMaxValues_[i] == INT_MIN)
160                configMaxValues_[i] = 32767;
161            ConfigFileManager::getInstance().getConfigFile(ConfigFileType::JoyStickCalibration)
162                ->getOrCreateValue(deviceName_, "MaxValue", i, multi_cast<std::string>(configMaxValues_[i]), false);
163
164            // Middle values
165            ConfigFileManager::getInstance().getConfigFile(ConfigFileType::JoyStickCalibration)
166                ->getOrCreateValue(deviceName_, "ZeroValue", i, multi_cast<std::string>(configZeroValues_[i]), false);
167        }
168
169        this->evaluateCalibration();
170    }
171
172    //! Evaluates the accumulated values during calibration
173    void JoyStick::evaluateCalibration()
174    {
175        for (unsigned int i = 0; i < configMinValues_.size(); i++)
176        {
177            zeroValues_[i] = configZeroValues_[i];
178            negativeCoeffs_[i] = - 1.0f / (configMinValues_[i] - configZeroValues_[i]);
179            positiveCoeffs_[i] =   1.0f / (configMaxValues_[i] - configZeroValues_[i]);
180        }
181    }
182
183    //! Resets the pov states
184    void JoyStick::clearBuffersImpl()
185    {
186        for (int j = 0; j < 4; ++j)
187            povStates_[j] = 0;
188    }
189
190    //! Generic method to forward axis events
191    void JoyStick::fireAxis(int axis, int value)
192    {
193        if (this->isCalibrating())
194        {
195            if (value < configMinValues_[axis])
196                configMinValues_[axis] = value;
197            if (value > configMaxValues_[axis])
198                configMaxValues_[axis] = value;
199        }
200        else
201        {
202            float fValue = static_cast<float>(value - zeroValues_[axis]);
203            if (fValue > 0.0f)
204                fValue *= positiveCoeffs_[axis];
205            else
206                fValue *= negativeCoeffs_[axis];
207
208            BOOST_FOREACH(InputState* state, inputStates_)
209                state->joyStickAxisMoved(this->getDeviceID(), axis, fValue);
210        }
211    }
212
213    //! OIS joy stick axis event handler
214    bool JoyStick::axisMoved(const OIS::JoyStickEvent &arg, int axis)
215    {
216        // keep in mind that the first 8 axes are reserved for the sliders
217        this->fireAxis(axis + sliderAxes_s, arg.state.mAxes[axis].abs);
218
219        return true;
220    }
221
222    //! A Slider always has an X and an Y direction!
223    bool JoyStick::sliderMoved(const OIS::JoyStickEvent &arg, int id)
224    {
225        if (sliderStates_[id][0] != arg.state.mSliders[id].abX)
226            fireAxis(id * 2, arg.state.mSliders[id].abX);
227        else if (sliderStates_[id][1] != arg.state.mSliders[id].abY)
228            fireAxis(id * 2 + 1, arg.state.mSliders[id].abY);
229
230        return true;
231    }
232
233    //! A POV is the big button that can point in all directions (but only in one at once)
234    bool JoyStick::povMoved(const OIS::JoyStickEvent &arg, int id)
235    {
236        // translate the POV into 8 simple buttons
237
238        int lastState = povStates_[id];
239        if (lastState & OIS::Pov::North)
240            buttonReleased(arg, 32 + id * 4 + 0);
241        if (lastState & OIS::Pov::South)
242            buttonReleased(arg, 32 + id * 4 + 1);
243        if (lastState & OIS::Pov::East)
244            buttonReleased(arg, 32 + id * 4 + 2);
245        if (lastState & OIS::Pov::West)
246            buttonReleased(arg, 32 + id * 4 + 3);
247
248        povStates_[id] = arg.state.mPOV[id].direction;
249
250        int currentState = povStates_[id];
251        if (currentState & OIS::Pov::North)
252            buttonPressed(arg, 32 + id * 4 + 0);
253        if (currentState & OIS::Pov::South)
254            buttonPressed(arg, 32 + id * 4 + 1);
255        if (currentState & OIS::Pov::East)
256            buttonPressed(arg, 32 + id * 4 + 2);
257        if (currentState & OIS::Pov::West)
258            buttonPressed(arg, 32 + id * 4 + 3);
259
260        return true;
261    }
262}
Note: See TracBrowser for help on using the repository browser.