Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Added and adjusted documentation for the devices.
Also removed one last ugliness where the InputManager was called from within a device (which should not even know about the InputManager).

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