/*
* The ManaPlus Client
* Copyright (C) 2004-2009 The Mana World Development Team
* Copyright (C) 2009-2010 The Mana Developers
* Copyright (C) 2011 The ManaPlus Developers
*
* This file is part of The ManaPlus Client.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "joystick.h"
#include "client.h"
#include "configuration.h"
#include "logger.h"
#include "debug.h"
int Joystick::joystickCount = 0;
bool Joystick::mEnabled = false;
void Joystick::init()
{
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
SDL_JoystickEventState(SDL_ENABLE);
joystickCount = SDL_NumJoysticks();
logger->log("%i joysticks/gamepads found", joystickCount);
for (int i = 0; i < joystickCount; i++)
logger->log("- %s", SDL_JoystickName(i));
mEnabled = config.getBoolValue("joystickEnabled");
if (Joystick::getNumberOfJoysticks() > 0)
{
joystick = new Joystick(config.getIntValue("selectedJoystick"));
if (mEnabled)
joystick->open();
}
}
Joystick::Joystick(int no):
mDirection(0),
mJoystick(nullptr),
mUpTolerance(0),
mDownTolerance(0),
mLeftTolerance(0),
mRightTolerance(0),
mCalibrating(false),
mCalibrated(false),
mButtonsNumber(MAX_BUTTONS),
mUseInactive(false),
mHaveHats(false)
{
if (no >= joystickCount)
no = joystickCount;
mNumber = no;
for (int i = 0; i < MAX_BUTTONS; i++)
mButtons[i] = false;
}
Joystick::~Joystick()
{
close();
}
bool Joystick::open()
{
logger->log("open joystick %d", mNumber);
mJoystick = SDL_JoystickOpen(mNumber);
// TODO Bail out!
if (!mJoystick)
{
logger->log("Couldn't open joystick: %s", SDL_GetError());
return false;
}
mButtonsNumber = SDL_JoystickNumButtons(mJoystick);
logger->log("Joystick: %i ", mNumber);
logger->log("Axes: %i ", SDL_JoystickNumAxes(mJoystick));
logger->log("Balls: %i", SDL_JoystickNumBalls(mJoystick));
logger->log("Hats: %i", SDL_JoystickNumHats(mJoystick));
logger->log("Buttons: %i", mButtonsNumber);
mHaveHats = (SDL_JoystickNumHats(mJoystick) > 0);
if (mButtonsNumber > MAX_BUTTONS)
mButtonsNumber = MAX_BUTTONS;
mCalibrated = config.getValueBool("joystick"
+ toString(mNumber) + "calibrated", false);
mUpTolerance = config.getIntValue("upTolerance" + toString(mNumber));
mDownTolerance = config.getIntValue("downTolerance" + toString(mNumber));
mLeftTolerance = config.getIntValue("leftTolerance" + toString(mNumber));
mRightTolerance = config.getIntValue("rightTolerance" + toString(mNumber));
mUseInactive = config.getBoolValue("useInactiveJoystick");
return true;
}
void Joystick::close()
{
logger->log("close joystick %d", mNumber);
if (mJoystick)
{
SDL_JoystickClose(mJoystick);
mJoystick = nullptr;
}
}
void Joystick::setNumber(int n)
{
if (mJoystick)
{
SDL_JoystickClose(mJoystick);
mNumber = n;
}
else
{
mNumber = n;
}
open();
}
void Joystick::update()
{
mDirection = 0;
// When calibrating, don't bother the outside with our state
if (mCalibrating)
{
doCalibration();
return;
};
if (!mEnabled || !mCalibrated)
return;
if (mUseInactive || Client::getInputFocused())
{
// X-Axis
int position = SDL_JoystickGetAxis(mJoystick, 0);
if (position >= mRightTolerance)
mDirection |= RIGHT;
else if (position <= mLeftTolerance)
mDirection |= LEFT;
// Y-Axis
position = SDL_JoystickGetAxis(mJoystick, 1);
if (position <= mUpTolerance)
mDirection |= UP;
else if (position >= mDownTolerance)
mDirection |= DOWN;
#ifdef DEBUG_JOYSTICK
if (SDL_JoystickGetAxis(mJoystick, 2))
logger->log("axis 2 pos: %d", SDL_JoystickGetAxis(mJoystick, 2));
if (SDL_JoystickGetAxis(mJoystick, 3))
logger->log("axis 3 pos: %d", SDL_JoystickGetAxis(mJoystick, 3));
if (SDL_JoystickGetAxis(mJoystick, 4))
logger->log("axis 4 pos: %d", SDL_JoystickGetAxis(mJoystick, 4));
#endif
if (!mDirection && mHaveHats)
{
// reading only hat 0
Uint8 hat = SDL_JoystickGetHat(mJoystick, 0);
if (hat & SDL_HAT_RIGHT)
mDirection |= RIGHT;
else if (hat & SDL_HAT_LEFT)
mDirection |= LEFT;
if (hat & SDL_HAT_UP)
mDirection |= UP;
else if (hat & SDL_HAT_DOWN)
mDirection |= DOWN;
}
// Buttons
for (int i = 0; i < mButtonsNumber; i++)
{
mButtons[i] = (SDL_JoystickGetButton(mJoystick, i) == 1);
#ifdef DEBUG_JOYSTICK
if (mButtons[i])
logger->log("button: %d", i);
#endif
}
}
else
{
for (int i = 0; i < mButtonsNumber; i++)
mButtons[i] = false;
}
}
void Joystick::startCalibration()
{
mUpTolerance = 0;
mDownTolerance = 0;
mLeftTolerance = 0;
mRightTolerance = 0;
mCalibrating = true;
}
void Joystick::doCalibration()
{
// X-Axis
int position = SDL_JoystickGetAxis(mJoystick, 0);
if (position > mRightTolerance)
mRightTolerance = position;
else if (position < mLeftTolerance)
mLeftTolerance = position;
// Y-Axis
position = SDL_JoystickGetAxis(mJoystick, 1);
if (position > mDownTolerance)
mDownTolerance = position;
else if (position < mUpTolerance)
mUpTolerance = position;
}
void Joystick::finishCalibration()
{
mCalibrated = true;
mCalibrating = false;
config.setValue("joystick" + toString(mNumber) + "calibrated", true);
config.setValue("leftTolerance" + toString(mNumber), mLeftTolerance);
config.setValue("rightTolerance" + toString(mNumber), mRightTolerance);
config.setValue("upTolerance" + toString(mNumber), mUpTolerance);
config.setValue("downTolerance" + toString(mNumber), mDownTolerance);
}
bool Joystick::buttonPressed(unsigned char no) const
{
return (mEnabled && no < MAX_BUTTONS) ? mButtons[no] : false;
}
void Joystick::getNames(std::vector &names)
{
names.clear();
for (int i = 0; i < joystickCount; i++)
names.push_back(SDL_JoystickName(i));
}