Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Merged presentation2 branch back to trunk.
Major new features:

  • Actual GUI with settings, etc.
  • Improved space ship steering (human interaction)
  • Rocket fire and more particle effects
  • Advanced sound framework
  • Property svn:eol-style set to native
File size: 9.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#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().getVectorSize(ConfigFileType::JoyStickCalibration, 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().getValue(
115                ConfigFileType::JoyStickCalibration, 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().setValue(ConfigFileType::JoyStickCalibration,
156                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().setValue(ConfigFileType::JoyStickCalibration,
162                deviceName_, "MaxValue", i, multi_cast<std::string>(configMaxValues_[i]), false);
163
164            // Middle values
165            ConfigFileManager::getInstance().setValue(ConfigFileType::JoyStickCalibration,
166                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.