Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Extracted joy stick related code from InputManager to a new JoyStick class in order to make the InputManger less of a monster class and to apply a little bit more OO.

  • Property svn:eol-style set to native
File size: 11.9 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/**
30@file
31@brief
32    Implementation of the JoyStick wrapper class.
33*/
34
35#include "JoyStick.h"
36
37#include <ois/OISJoyStick.h>
38#include <ois/OISInputManager.h>
39#include <boost/foreach.hpp>
40
41#include "core/ConfigFileManager.h"
42#include "core/ConfigValueIncludes.h"
43#include "core/CoreIncludes.h"
44#include "util/Convert.h"
45#include "InputState.h"
46#include "InputManager.h"
47
48namespace orxonox
49{
50    /**
51    @brief
52        Helper function that loads the config value vector of one coefficient
53    */
54    void loadCalibration(std::vector<int>& list, const std::string& sectionName, const std::string& valueName, size_t size, int defaultValue);
55
56    JoyStick::JoyStick(const std::vector<InputState*>& states, unsigned int id)
57        : id_(id)
58        , bCalibrating_(false)
59        , inputStates_(states)
60    {
61        RegisterRootObject(JoyStick);
62        this->setConfigValues();
63
64        OIS::InputManager* system = InputManager::getInstance().getInputSystem();
65        oisJoyStick_ = static_cast<OIS::JoyStick*>(system->createInputObject(OIS::OISJoyStick, true));
66        oisJoyStick_->setEventCallback(this);
67
68        idString_ = "JoyStick_";
69        std::string name = oisJoyStick_->vendor();
70        replaceCharacters(name, ' ', '_');
71        idString_ += name + "_";
72        idString_ += multi_cast<std::string>(oisJoyStick_->getNumberOfComponents(OIS::OIS_Button))  + "_";
73        idString_ += multi_cast<std::string>(oisJoyStick_->getNumberOfComponents(OIS::OIS_Axis))    + "_";
74        idString_ += multi_cast<std::string>(oisJoyStick_->getNumberOfComponents(OIS::OIS_Slider))  + "_";
75        idString_ += multi_cast<std::string>(oisJoyStick_->getNumberOfComponents(OIS::OIS_POV));
76        //idString_ += multi_cast<std::string>(oisJoyStick_->getNumberOfComponents(OIS::OIS_Vector3));
77
78        if (InputManager::getInstance().checkJoyStickID(idString_) == false)
79        {
80            // Make the ID unique for this execution time.
81            idString_ += "_" + multi_cast<std::string>(id_);
82        }
83
84        COUT(4) << "Created OIS joy stick with ID " << idString_ << std::endl;
85
86        // Load calibration
87        size_t axes = sliderAxes_s + static_cast<size_t>(oisJoyStick_->getNumberOfComponents(OIS::OIS_Axis));
88        loadCalibration(configMinValues_,  idString_, "MinValue",  axes,  -32768);
89        loadCalibration(configMaxValues_,  idString_, "MaxValue",  axes,   32768);
90        loadCalibration(configZeroValues_, idString_, "ZeroValue", axes, 0);
91        this->evaluateCalibration();
92    }
93
94    JoyStick::~JoyStick()
95    {
96        try
97        {
98            OIS::InputManager* system = InputManager::getInstance().getInputSystem();
99            system->destroyInputObject(oisJoyStick_);
100        }
101        catch (...)
102        {
103            COUT(1) << "Joy stick destruction failed! Potential resource leak!" << std::endl;
104        }
105    }
106
107    /**
108    @brief
109        Callback for the joy stick calibration config file. @see setConfigValues.
110    */
111    void JoyStick::calibrationFileCallback()
112    {
113        ConfigFileManager::getInstance().setFilename(ConfigFileType::JoyStickCalibration, calibrationFilename_);
114    }
115
116    /**
117    @brief
118        Sets the configurable values.
119    */
120    void JoyStick::setConfigValues()
121    {
122        SetConfigValue(calibrationFilename_, "joystick_calibration.ini")
123            .description("Ini filename for the the joy stick calibration data.")
124            .callback(this, &JoyStick::calibrationFileCallback);
125    }
126
127    void loadCalibration(std::vector<int>& list, const std::string& sectionName, const std::string& valueName, size_t size, int defaultValue)
128    {
129        list.resize(size);
130        unsigned int configValueVectorSize = ConfigFileManager::getInstance().getVectorSize(ConfigFileType::JoyStickCalibration, sectionName, valueName);
131        if (configValueVectorSize > size)
132            configValueVectorSize = size;
133
134        for (unsigned int i = 0; i < configValueVectorSize; ++i)
135        {
136            list[i] = multi_cast<int>(ConfigFileManager::getInstance().getValue(
137                ConfigFileType::JoyStickCalibration, sectionName, valueName, i, multi_cast<std::string>(defaultValue), false));
138        }
139
140        // fill the rest with default values
141        for (unsigned int i = configValueVectorSize; i < size; ++i)
142        {
143            list[i] = defaultValue;
144        }
145    }
146
147    void JoyStick::startCalibration()
148    {
149        bCalibrating_ = true;
150
151        // Set initial values
152        BOOST_FOREACH(int& minVal, configMinValues_)
153            minVal = INT_MAX;
154        BOOST_FOREACH(int& minVal, configMaxValues_)
155            minVal = INT_MIN;
156        BOOST_FOREACH(int& zeroVal, configZeroValues_)
157            zeroVal = 0;
158    }
159
160    void JoyStick::stopCalibration()
161    {
162        // Get the middle positions now
163        unsigned int iAxis = 0;
164        for (unsigned int i = 0; i < sliderAxes_s/2; ++i)
165        {
166            configZeroValues_[iAxis++] = oisJoyStick_->getJoyStickState().mSliders[i].abX;
167            configZeroValues_[iAxis++] = oisJoyStick_->getJoyStickState().mSliders[i].abY;
168        }
169        // Note: joyStickMiddleValues_[iJoyStick] was already correctly resised in loadCalibration()
170        assert(oisJoyStick_->getJoyStickState().mAxes.size() == configZeroValues_.size() - sliderAxes_s);
171        for (unsigned int i = 0; i < configZeroValues_.size() - sliderAxes_s; ++i)
172            configZeroValues_[iAxis++] = oisJoyStick_->getJoyStickState().mAxes[i].abs;
173
174        for (unsigned int i = 0; i < configMinValues_.size(); ++i)
175        {
176            // Minimum values
177            if (configMinValues_[i] == INT_MAX)
178                configMinValues_[i] = -32768;
179            ConfigFileManager::getInstance().setValue(ConfigFileType::JoyStickCalibration,
180                idString_, "MinValue", i, multi_cast<std::string>(configMinValues_[i]), false);
181
182            // Maximum values
183            if (configMaxValues_[i] == INT_MIN)
184                configMaxValues_[i] = 32767;
185            ConfigFileManager::getInstance().setValue(ConfigFileType::JoyStickCalibration,
186                idString_, "MaxValue", i, multi_cast<std::string>(configMaxValues_[i]), false);
187
188            // Middle values
189            ConfigFileManager::getInstance().setValue(ConfigFileType::JoyStickCalibration,
190                idString_, "ZeroValue", i, multi_cast<std::string>(configZeroValues_[i]), false);
191        }
192
193        this->evaluateCalibration();
194
195        bCalibrating_ = false;
196    }
197
198    void JoyStick::evaluateCalibration()
199    {
200        for (unsigned int i = 0; i < configMinValues_.size(); i++)
201        {
202            zeroValues_[i] = configZeroValues_[i];
203            negativeCoeffs_[i] = - 1.0f / (configMinValues_[i] - configZeroValues_[i]);
204            positiveCoeffs_[i] =   1.0f / (configMaxValues_[i] - configZeroValues_[i]);
205        }
206    }
207
208    void JoyStick::clearBuffer()
209    {
210        pressedButtons_.clear();
211        for (int j = 0; j < 4; ++j)
212        {
213            povStates_[j] = 0;
214            sliderStates_[j][0] = 0;
215            sliderStates_[j][1] = 0;
216        }
217    }
218
219
220    // ###### Events ######
221
222    void JoyStick::capture()
223    {
224        oisJoyStick_->capture();
225
226        // call all the handlers for the held joy stick button events
227        for (unsigned int iButton = 0; iButton < pressedButtons_.size(); iButton++)
228        {
229            BOOST_FOREACH(InputState* state, inputStates_)
230                state->joyStickButtonHeld(id_, pressedButtons_[iButton]);
231        }
232    }
233
234    bool JoyStick::buttonPressed(const OIS::JoyStickEvent &arg, int button)
235    {
236        // check whether the button already is in the list (can happen when focus was lost)
237        unsigned int iButton = 0;
238        while (iButton < pressedButtons_.size() && pressedButtons_[iButton] != button)
239            iButton++;
240        if (iButton == pressedButtons_.size())
241            pressedButtons_.push_back(static_cast<JoyStickButtonCode::ByEnum>(button));
242
243        BOOST_FOREACH(InputState* state, inputStates_)
244            state->joyStickButtonPressed(id_, static_cast<JoyStickButtonCode::ByEnum>(button));
245
246        return true;
247    }
248
249    bool JoyStick::buttonReleased(const OIS::JoyStickEvent &arg, int button)
250    {
251        // remove the button from the pressedButtons_ list
252        for (unsigned int iButton = 0; iButton < pressedButtons_.size(); iButton++)
253        {
254            if (static_cast<int>(pressedButtons_[iButton]) == button)
255            {
256                pressedButtons_.erase(pressedButtons_.begin() + iButton);
257                break;
258            }
259        }
260
261        BOOST_FOREACH(InputState* state, inputStates_)
262            state->joyStickButtonPressed(id_, static_cast<JoyStickButtonCode::ByEnum>(button));
263
264        return true;
265    }
266
267    /**
268    @brief
269        Calls the states for a particular axis with our enumeration.
270        Used by OIS sliders and OIS axes.
271    */
272    void JoyStick::fireAxis(int axis, int value)
273    {
274        if (bCalibrating_)
275        {
276            if (value < configMinValues_[axis])
277                configMinValues_[axis] = value;
278            if (value > configMaxValues_[axis])
279                configMaxValues_[axis] = value;
280        }
281        else
282        {
283            float fValue = static_cast<float>(value - zeroValues_[axis]);
284            if (fValue > 0.0f)
285                fValue *= positiveCoeffs_[axis];
286            else
287                fValue *= negativeCoeffs_[axis];
288
289            BOOST_FOREACH(InputState* state, inputStates_)
290                state->joyStickAxisMoved(id_, axis, fValue);
291        }
292    }
293
294    bool JoyStick::axisMoved(const OIS::JoyStickEvent &arg, int axis)
295    {
296        // keep in mind that the first 8 axes are reserved for the sliders
297        this->fireAxis(axis + sliderAxes_s, arg.state.mAxes[axis].abs);
298
299        return true;
300    }
301
302    bool JoyStick::sliderMoved(const OIS::JoyStickEvent &arg, int id)
303    {
304        if (sliderStates_[id][0] != arg.state.mSliders[id].abX)
305            fireAxis(id * 2, arg.state.mSliders[id].abX);
306        else if (sliderStates_[id][1] != arg.state.mSliders[id].abY)
307            fireAxis(id * 2 + 1, arg.state.mSliders[id].abY);
308
309        return true;
310    }
311
312    bool JoyStick::povMoved(const OIS::JoyStickEvent &arg, int id)
313    {
314        // translate the POV into 8 simple buttons
315
316        int lastState = povStates_[id];
317        if (lastState & OIS::Pov::North)
318            buttonReleased(arg, 32 + id * 4 + 0);
319        if (lastState & OIS::Pov::South)
320            buttonReleased(arg, 32 + id * 4 + 1);
321        if (lastState & OIS::Pov::East)
322            buttonReleased(arg, 32 + id * 4 + 2);
323        if (lastState & OIS::Pov::West)
324            buttonReleased(arg, 32 + id * 4 + 3);
325
326        povStates_[id] = arg.state.mPOV[id].direction;
327
328        int currentState = povStates_[id];
329        if (currentState & OIS::Pov::North)
330            buttonPressed(arg, 32 + id * 4 + 0);
331        if (currentState & OIS::Pov::South)
332            buttonPressed(arg, 32 + id * 4 + 1);
333        if (currentState & OIS::Pov::East)
334            buttonPressed(arg, 32 + id * 4 + 2);
335        if (currentState & OIS::Pov::West)
336            buttonPressed(arg, 32 + id * 4 + 3);
337
338        return true;
339    }
340}
Note: See TracBrowser for help on using the repository browser.