Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core4/src/core/input/JoyStick.cc @ 3864

Last change on this file since 3864 was 3306, checked in by rgrieder, 15 years ago

Keybindings should now map to the correct joy stick by device name (like "WingMan Action Pad" or so).

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