Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 12160 was 11071, checked in by landauf, 9 years ago

merged branch cpp11_v3 back to trunk

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