~ubuntu-branches/ubuntu/trusty/manaplus/trusty-proposed

« back to all changes in this revision

Viewing changes to src/joystick.cpp

  • Committer: Package Import Robot
  • Author(s): Patrick Matthäi
  • Date: 2013-09-17 10:35:51 UTC
  • mfrom: (1.1.10)
  • Revision ID: package-import@ubuntu.com-20130917103551-az7p3nz9jgxwqjfn
Tags: 1.3.9.15-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  The ManaPlus Client
3
 
 *  Copyright (C) 2004-2009  The Mana World Development Team
4
 
 *  Copyright (C) 2009-2010  The Mana Developers
5
 
 *  Copyright (C) 2011-2013  The ManaPlus Developers
6
 
 *
7
 
 *  This file is part of The ManaPlus Client.
8
 
 *
9
 
 *  This program is free software; you can redistribute it and/or modify
10
 
 *  it under the terms of the GNU General Public License as published by
11
 
 *  the Free Software Foundation; either version 2 of the License, or
12
 
 *  any later version.
13
 
 *
14
 
 *  This program is distributed in the hope that it will be useful,
15
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 
 *  GNU General Public License for more details.
18
 
 *
19
 
 *  You should have received a copy of the GNU General Public License
20
 
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 
 */
22
 
 
23
 
#include "joystick.h"
24
 
 
25
 
#include "client.h"
26
 
#include "configuration.h"
27
 
#include "inputmanager.h"
28
 
#include "logger.h"
29
 
#include "sdlshared.h"
30
 
 
31
 
#include "debug.h"
32
 
 
33
 
int Joystick::joystickCount = 0;
34
 
bool Joystick::mEnabled = false;
35
 
 
36
 
Joystick::Joystick(const int no):
37
 
    mDirection(0),
38
 
    mJoystick(nullptr),
39
 
    mUpTolerance(0),
40
 
    mDownTolerance(0),
41
 
    mLeftTolerance(0),
42
 
    mRightTolerance(0),
43
 
    mCalibrating(false),
44
 
    mNumber(no >= joystickCount ? joystickCount : no),
45
 
    mCalibrated(false),
46
 
    mButtonsNumber(MAX_BUTTONS),
47
 
    mUseInactive(false),
48
 
    mHaveHats(false),
49
 
    mKeyToAction(),
50
 
    mKeyToId(),
51
 
    mKeyTimeMap()
52
 
{
53
 
    for (int i = 0; i < MAX_BUTTONS; i++)
54
 
        mActiveButtons[i] = false;
55
 
}
56
 
 
57
 
Joystick::~Joystick()
58
 
{
59
 
    close();
60
 
}
61
 
 
62
 
void Joystick::init()
63
 
{
64
 
    SDL_InitSubSystem(SDL_INIT_JOYSTICK);
65
 
    SDL_JoystickEventState(SDL_ENABLE);
66
 
    joystickCount = SDL_NumJoysticks();
67
 
    logger->log("%i joysticks/gamepads found", joystickCount);
68
 
    for (int i = 0; i < joystickCount; i++)
69
 
        logger->log("- %s", SDL_JoystickNameForIndex(i));
70
 
 
71
 
    mEnabled = config.getBoolValue("joystickEnabled");
72
 
 
73
 
    if (joystickCount > 0)
74
 
    {
75
 
        joystick = new Joystick(config.getIntValue("selectedJoystick"));
76
 
        if (mEnabled)
77
 
            joystick->open();
78
 
    }
79
 
}
80
 
 
81
 
bool Joystick::open()
82
 
{
83
 
    if (mNumber >= joystickCount)
84
 
        mNumber = joystickCount - 1;
85
 
    if (mNumber < 0)
86
 
    {
87
 
        logger->log1("error: incorrect joystick selection");
88
 
        return false;
89
 
    }
90
 
    logger->log("open joystick %d", mNumber);
91
 
 
92
 
    mJoystick = SDL_JoystickOpen(mNumber);
93
 
 
94
 
    if (!mJoystick)
95
 
    {
96
 
        logger->log("Couldn't open joystick: %s", SDL_GetError());
97
 
        return false;
98
 
    }
99
 
 
100
 
    mButtonsNumber = SDL_JoystickNumButtons(mJoystick);
101
 
    logger->log("Joystick: %i ", mNumber);
102
 
    logger->log("Axes: %i ", SDL_JoystickNumAxes(mJoystick));
103
 
    logger->log("Balls: %i", SDL_JoystickNumBalls(mJoystick));
104
 
    logger->log("Hats: %i", SDL_JoystickNumHats(mJoystick));
105
 
    logger->log("Buttons: %i", mButtonsNumber);
106
 
 
107
 
    mHaveHats = (SDL_JoystickNumHats(mJoystick) > 0);
108
 
 
109
 
    if (mButtonsNumber > MAX_BUTTONS)
110
 
        mButtonsNumber = MAX_BUTTONS;
111
 
 
112
 
    mCalibrated = config.getValueBool("joystick"
113
 
        + toString(mNumber) + "calibrated", false);
114
 
    mUpTolerance = config.getIntValue("upTolerance" + toString(mNumber));
115
 
    mDownTolerance = config.getIntValue("downTolerance" + toString(mNumber));
116
 
    mLeftTolerance = config.getIntValue("leftTolerance" + toString(mNumber));
117
 
    mRightTolerance = config.getIntValue("rightTolerance" + toString(mNumber));
118
 
    mUseInactive = config.getBoolValue("useInactiveJoystick");
119
 
 
120
 
    return true;
121
 
}
122
 
 
123
 
void Joystick::close()
124
 
{
125
 
    logger->log("close joystick %d", mNumber);
126
 
    if (mJoystick)
127
 
    {
128
 
        SDL_JoystickClose(mJoystick);
129
 
        mJoystick = nullptr;
130
 
    }
131
 
}
132
 
 
133
 
void Joystick::reload()
134
 
{
135
 
    joystickCount = SDL_NumJoysticks();
136
 
    setNumber(mNumber);
137
 
}
138
 
 
139
 
void Joystick::setNumber(const int n)
140
 
{
141
 
    if (mJoystick)
142
 
    {
143
 
        SDL_JoystickClose(mJoystick);
144
 
        mNumber = n;
145
 
        open();
146
 
    }
147
 
    else
148
 
    {
149
 
        mNumber = n;
150
 
    }
151
 
}
152
 
 
153
 
void Joystick::logic()
154
 
{
155
 
    // When calibrating, don't bother the outside with our state
156
 
    if (mCalibrating)
157
 
    {
158
 
        doCalibration();
159
 
        return;
160
 
    };
161
 
 
162
 
    if (!mEnabled || !mCalibrated)
163
 
        return;
164
 
 
165
 
    mDirection = 0;
166
 
 
167
 
    if (mUseInactive || client->getInputFocused())
168
 
    {
169
 
        // X-Axis
170
 
        int position = SDL_JoystickGetAxis(mJoystick, 0);
171
 
        if (position >= mRightTolerance)
172
 
            mDirection |= RIGHT;
173
 
        else if (position <= mLeftTolerance)
174
 
            mDirection |= LEFT;
175
 
 
176
 
        // Y-Axis
177
 
        position = SDL_JoystickGetAxis(mJoystick, 1);
178
 
        if (position <= mUpTolerance)
179
 
            mDirection |= UP;
180
 
        else if (position >= mDownTolerance)
181
 
            mDirection |= DOWN;
182
 
 
183
 
#ifdef DEBUG_JOYSTICK
184
 
        if (SDL_JoystickGetAxis(mJoystick, 2))
185
 
            logger->log("axis 2 pos: %d", SDL_JoystickGetAxis(mJoystick, 2));
186
 
        if (SDL_JoystickGetAxis(mJoystick, 3))
187
 
            logger->log("axis 3 pos: %d", SDL_JoystickGetAxis(mJoystick, 3));
188
 
        if (SDL_JoystickGetAxis(mJoystick, 4))
189
 
            logger->log("axis 4 pos: %d", SDL_JoystickGetAxis(mJoystick, 4));
190
 
#endif
191
 
 
192
 
        if (!mDirection && mHaveHats)
193
 
        {
194
 
            // reading only hat 0
195
 
            const uint8_t hat = SDL_JoystickGetHat(mJoystick, 0);
196
 
            if (hat & SDL_HAT_RIGHT)
197
 
                mDirection |= RIGHT;
198
 
            else if (hat & SDL_HAT_LEFT)
199
 
                mDirection |= LEFT;
200
 
            if (hat & SDL_HAT_UP)
201
 
                mDirection |= UP;
202
 
            else if (hat & SDL_HAT_DOWN)
203
 
                mDirection |= DOWN;
204
 
        }
205
 
 
206
 
        // Buttons
207
 
        for (int i = 0; i < mButtonsNumber; i++)
208
 
        {
209
 
            const bool state = (SDL_JoystickGetButton(mJoystick, i) == 1);
210
 
            mActiveButtons[i] = state;
211
 
            if (!state)
212
 
                resetRepeat(i);
213
 
#ifdef DEBUG_JOYSTICK
214
 
            if (mActiveButtons[i])
215
 
                logger->log("button: %d", i);
216
 
#endif
217
 
        }
218
 
    }
219
 
    else
220
 
    {
221
 
        for (int i = 0; i < mButtonsNumber; i++)
222
 
            mActiveButtons[i] = false;
223
 
    }
224
 
}
225
 
 
226
 
void Joystick::startCalibration()
227
 
{
228
 
    mUpTolerance = 0;
229
 
    mDownTolerance = 0;
230
 
    mLeftTolerance = 0;
231
 
    mRightTolerance = 0;
232
 
    mCalibrating = true;
233
 
}
234
 
 
235
 
void Joystick::doCalibration()
236
 
{
237
 
    // X-Axis
238
 
    int position = SDL_JoystickGetAxis(mJoystick, 0);
239
 
    if (position > mRightTolerance)
240
 
        mRightTolerance = position;
241
 
    else if (position < mLeftTolerance)
242
 
        mLeftTolerance = position;
243
 
 
244
 
    // Y-Axis
245
 
    position = SDL_JoystickGetAxis(mJoystick, 1);
246
 
    if (position > mDownTolerance)
247
 
        mDownTolerance = position;
248
 
    else if (position < mUpTolerance)
249
 
        mUpTolerance = position;
250
 
}
251
 
 
252
 
void Joystick::finishCalibration()
253
 
{
254
 
    mCalibrated = true;
255
 
    mCalibrating = false;
256
 
    config.setValue("joystick" + toString(mNumber) + "calibrated", true);
257
 
    config.setValue("leftTolerance" + toString(mNumber), mLeftTolerance);
258
 
    config.setValue("rightTolerance" + toString(mNumber), mRightTolerance);
259
 
    config.setValue("upTolerance" + toString(mNumber), mUpTolerance);
260
 
    config.setValue("downTolerance" + toString(mNumber), mDownTolerance);
261
 
}
262
 
 
263
 
bool Joystick::buttonPressed(const unsigned char no) const
264
 
{
265
 
    return (mEnabled && no < MAX_BUTTONS) ? mActiveButtons[no] : false;
266
 
}
267
 
 
268
 
void Joystick::getNames(std::vector <std::string> &names)
269
 
{
270
 
    names.clear();
271
 
    for (int i = 0; i < joystickCount; i++)
272
 
        names.push_back(SDL_JoystickNameForIndex(i));
273
 
}
274
 
 
275
 
void Joystick::update()
276
 
{
277
 
    inputManager.updateKeyActionMap(mKeyToAction, mKeyToId,
278
 
        mKeyTimeMap, INPUT_JOYSTICK);
279
 
}
280
 
 
281
 
KeysVector *Joystick::getActionVector(const SDL_Event &event)
282
 
{
283
 
    const int i = getButtonFromEvent(event);
284
 
 
285
 
    if (i < 0 || i >= mButtonsNumber)
286
 
        return nullptr;
287
 
//    logger->log("button triggerAction: %d", i);
288
 
    if (mKeyToAction.find(i) != mKeyToAction.end())
289
 
        return &mKeyToAction[i];
290
 
    return nullptr;
291
 
}
292
 
 
293
 
KeysVector *Joystick::getActionVectorByKey(const int i)
294
 
{
295
 
    if (i < 0 || i >= mButtonsNumber)
296
 
        return nullptr;
297
 
//    logger->log("button triggerAction: %d", i);
298
 
    if (mKeyToAction.find(i) != mKeyToAction.end())
299
 
        return &mKeyToAction[i];
300
 
    return nullptr;
301
 
}
302
 
 
303
 
int Joystick::getButtonFromEvent(const SDL_Event &event) const
304
 
{
305
 
    if (event.jbutton.which != mNumber)
306
 
        return -1;
307
 
    return event.jbutton.button;
308
 
}
309
 
 
310
 
bool Joystick::isActionActive(const int index) const
311
 
{
312
 
    if (!validate())
313
 
        return false;
314
 
 
315
 
    const KeyFunction &key = inputManager.getKey(index);
316
 
    for (size_t i = 0; i < KeyFunctionSize; i ++)
317
 
    {
318
 
        const KeyItem &val = key.values[i];
319
 
        if (val.type != INPUT_JOYSTICK)
320
 
            continue;
321
 
        const int value = val.value;
322
 
        if (value >= 0 && value < mButtonsNumber)
323
 
        {
324
 
            if (mActiveButtons[value])
325
 
                return true;
326
 
        }
327
 
    }
328
 
    return false;
329
 
}
330
 
 
331
 
bool Joystick::validate() const
332
 
{
333
 
    if (mCalibrating || !mEnabled || !mCalibrated)
334
 
        return false;
335
 
 
336
 
    return (mUseInactive || client->getInputFocused());
337
 
}
338
 
 
339
 
void Joystick::handleRepeat(const int time)
340
 
{
341
 
    FOR_EACH (KeyTimeMapIter, it, mKeyTimeMap)
342
 
    {
343
 
        bool repeat(false);
344
 
        const int key = (*it).first;
345
 
        int &keyTime = (*it).second;
346
 
        if (key >= 0 && key < mButtonsNumber)
347
 
        {
348
 
            if (mActiveButtons[key])
349
 
                repeat = true;
350
 
        }
351
 
        if (repeat)
352
 
        {
353
 
            if (time > keyTime && abs(time - keyTime)
354
 
                > SDL_DEFAULT_REPEAT_DELAY * 10)
355
 
            {
356
 
                keyTime = time;
357
 
                inputManager.triggerAction(getActionVectorByKey(key));
358
 
            }
359
 
        }
360
 
    }
361
 
}
362
 
 
363
 
void Joystick::resetRepeat(const int key)
364
 
{
365
 
    const KeyTimeMapIter it = mKeyTimeMap.find(key);
366
 
    if (it != mKeyTimeMap.end())
367
 
        (*it).second = tick_time;
368
 
}