summaryrefslogtreecommitdiff
path: root/src/input/joystick.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/input/joystick.cpp')
-rw-r--r--src/input/joystick.cpp291
1 files changed, 187 insertions, 104 deletions
diff --git a/src/input/joystick.cpp b/src/input/joystick.cpp
index 52d9a7525..ea1883ad0 100644
--- a/src/input/joystick.cpp
+++ b/src/input/joystick.cpp
@@ -47,21 +47,24 @@ bool Joystick::mInitialized = false;
Joystick::Joystick(const int no) :
mDirection(0),
+ mHatPosition(0),
mJoystick(nullptr),
- mUpTolerance(0),
- mDownTolerance(0),
- mLeftTolerance(0),
- mRightTolerance(0),
- mCalibrating(false),
+ mTolerance(0),
mNumber(no >= joystickCount ? joystickCount : no),
- mCalibrated(false),
+ mAxesNumber(MAX_AXES),
mButtonsNumber(MAX_BUTTONS),
+ mUseHatForMovement(true),
mUseInactive(false),
mHaveHats(false),
mKeyToAction(),
mKeyToId(),
mKeyTimeMap()
{
+ for (int i = 0; i < MAX_AXES; i++)
+ {
+ mIsTrigger[i] = false;
+ mAxesPositions[i] = 0;
+ }
for (int i = 0; i < MAX_BUTTONS; i++)
mActiveButtons[i] = false;
}
@@ -130,7 +133,9 @@ bool Joystick::open()
return false;
}
+ mAxesNumber = SDL_JoystickNumAxes(mJoystick);
mButtonsNumber = SDL_JoystickNumButtons(mJoystick);
+
logger->log("Joystick: %i ", mNumber);
#ifdef USE_SDL2
logger->log("Name: %s", SDL_JoystickName(mJoystick));
@@ -189,32 +194,31 @@ bool Joystick::open()
logger->log("Name: %s", SDL_JoystickName(mNumber));
#endif // USE_SDL2
- logger->log("Axes: %i ", SDL_JoystickNumAxes(mJoystick));
+ logger->log("Axes: %i ", mAxesNumber);
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 (mAxesNumber > MAX_AXES)
+ mAxesNumber = mAxesNumber;
+
if (mButtonsNumber > MAX_BUTTONS)
mButtonsNumber = MAX_BUTTONS;
-#ifdef __SWITCH__
- config.setValue("joystick" + toString(mNumber) + "calibrated", true);
- config.setValue("leftTolerance" + toString(mNumber), -10000);
- config.setValue("rightTolerance" + toString(mNumber), 10000);
- config.setValue("upTolerance" + toString(mNumber), -10000);
- config.setValue("downTolerance" + toString(mNumber), 10000);
-#endif
- 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));
+ mTolerance = config.getFloatValue("joystickTolerance");
+ mUseHatForMovement = config.getBoolValue("useHatForMovement");
mUseInactive = config.getBoolValue("useInactiveJoystick");
+ for (int i = 0; i < mAxesNumber; i++)
+ {
+ // heuristic to detect controller triggers.
+ // their resting position is at SDL_JOYSTICK_AXIS_MIN = -32768
+ if (SDL_JoystickGetAxis(mJoystick, i) == SDL_JOYSTICK_AXIS_MIN)
+ mIsTrigger[i] = true;
+ }
+
return true;
}
@@ -245,15 +249,7 @@ void Joystick::setNumber(const int n)
void Joystick::logic()
{
BLOCK_START("Joystick::logic")
- // When calibrating, don't bother the outside with our state
- if (mCalibrating)
- {
- doCalibration();
- BLOCK_END("Joystick::logic")
- return;
- }
-
- if (!mEnabled || !mCalibrated)
+ if (!mEnabled)
{
BLOCK_END("Joystick::logic")
return;
@@ -264,18 +260,28 @@ void Joystick::logic()
if (mUseInactive ||
settings.inputFocused != KeyboardFocus::Unfocused)
{
+ for (int i = 0; i < mAxesNumber; i++)
+ {
+ int position = SDL_JoystickGetAxis(mJoystick, i);
+ // transform range [SDL_JOYSTICK_AXIS_MIN, SDL_JOYSTICK_AXIS_MAX]
+ // to [0, SDL_JOYSTICK_AXIS_MAX]
+ if (mIsTrigger[i])
+ position = (position - SDL_JOYSTICK_AXIS_MIN) / 2;
+ mAxesPositions[i] = position;
+ }
+
// X-Axis
- int position = SDL_JoystickGetAxis(mJoystick, 0);
- if (position >= mRightTolerance)
+ int position = mAxesPositions[0];
+ if (position >= mTolerance * SDL_JOYSTICK_AXIS_MAX)
mDirection |= RIGHT;
- else if (position <= mLeftTolerance)
+ else if (position <= mTolerance * SDL_JOYSTICK_AXIS_MIN)
mDirection |= LEFT;
// Y-Axis
- position = SDL_JoystickGetAxis(mJoystick, 1);
- if (position <= mUpTolerance)
+ position = mAxesPositions[1];
+ if (position <= mTolerance * SDL_JOYSTICK_AXIS_MIN)
mDirection |= UP;
- else if (position >= mDownTolerance)
+ else if (position >= mTolerance * SDL_JOYSTICK_AXIS_MAX)
mDirection |= DOWN;
#ifdef DEBUG_JOYSTICK
@@ -287,18 +293,21 @@ void Joystick::logic()
logger->log("axis 4 pos: %d", SDL_JoystickGetAxis(mJoystick, 4));
#endif // DEBUG_JOYSTICK
- if ((mDirection == 0U) && mHaveHats)
+ if (mHaveHats)
{
// reading only hat 0
const uint8_t hat = SDL_JoystickGetHat(mJoystick, 0);
+ mHatPosition = 0;
if ((hat & SDL_HAT_RIGHT) != 0)
- mDirection |= RIGHT;
+ mHatPosition |= RIGHT;
else if ((hat & SDL_HAT_LEFT) != 0)
- mDirection |= LEFT;
+ mHatPosition |= LEFT;
if ((hat & SDL_HAT_UP) != 0)
- mDirection |= UP;
+ mHatPosition |= UP;
else if ((hat & SDL_HAT_DOWN) != 0)
- mDirection |= DOWN;
+ mHatPosition |= DOWN;
+ if ((mDirection == 0U) && mUseHatForMovement)
+ mDirection = mHatPosition;
}
// Buttons
@@ -316,52 +325,42 @@ void Joystick::logic()
}
else
{
+ mHatPosition = 0;
+ for (int i = 0; i < mAxesNumber; i++)
+ mAxesPositions[i] = 0;
for (int i = 0; i < mButtonsNumber; i++)
mActiveButtons[i] = false;
}
BLOCK_END("Joystick::logic")
}
-void Joystick::startCalibration()
-{
- mUpTolerance = 0;
- mDownTolerance = 0;
- mLeftTolerance = 0;
- mRightTolerance = 0;
- mCalibrating = true;
-}
-
-void Joystick::doCalibration()
+bool Joystick::buttonPressed(const int no) const
{
- // 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;
-}
+ if (!mEnabled)
+ return false;
+ const int button = getButton(no);
+ if (button >= 0)
+ {
+ if (button < mButtonsNumber)
+ return mActiveButtons[button];
+ if (button == KEY_UP)
+ return (mHatPosition & UP) != 0;
+ if (button == KEY_DOWN)
+ return (mHatPosition & DOWN) != 0;
+ if (button == KEY_LEFT)
+ return (mHatPosition & LEFT) != 0;
+ if (button == KEY_RIGHT)
+ return (mHatPosition & RIGHT) != 0;
+ }
+ const int naxis = getNegativeAxis(no);
+ if (naxis >= 0)
+ return mAxesPositions[naxis] < mTolerance * SDL_JOYSTICK_AXIS_MIN;
-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);
-}
+ const int paxis = getPositiveAxis(no);
+ if (paxis >= 0)
+ return mAxesPositions[paxis] > mTolerance * SDL_JOYSTICK_AXIS_MAX;
-bool Joystick::buttonPressed(const unsigned char no) const
-{
- return (mEnabled && no < MAX_BUTTONS) ? mActiveButtons[no] : false;
+ return false;
}
void Joystick::getNames(STD_VECTOR <std::string> &names)
@@ -377,33 +376,128 @@ void Joystick::update()
mKeyTimeMap, InputType::JOYSTICK);
}
+bool Joystick::isActionEvent(const SDL_Event &event)
+{
+ return getButtonFromEvent(event) >= 0;
+}
+
KeysVector *Joystick::getActionVector(const SDL_Event &event)
{
const int i = getButtonFromEvent(event);
-
- if (i < 0 || i >= mButtonsNumber)
- return nullptr;
-// logger->log("button triggerAction: %d", i);
- if (mKeyToAction.find(i) != mKeyToAction.end())
- return &mKeyToAction[i];
- return nullptr;
+ return getActionVectorByKey(i);
}
KeysVector *Joystick::getActionVectorByKey(const int i)
{
- if (i < 0 || i >= mButtonsNumber)
+ if (getButton(i) < 0
+ && getNegativeAxis(i) < 0
+ && getPositiveAxis(i) < 0)
+ {
return nullptr;
+ }
// logger->log("button triggerAction: %d", i);
- if (mKeyToAction.find(i) != mKeyToAction.end())
- return &mKeyToAction[i];
+
+ KeyToActionMapIter it = mKeyToAction.find(i);
+ if (it != mKeyToAction.end())
+ return &it->second;
+
return nullptr;
}
+InputActionT Joystick::getActionId(const SDL_Event &event)
+{
+ const int i = getButtonFromEvent(event);
+ if (i < 0)
+ return InputAction::NO_VALUE;
+
+ KeyToIdMapIter it = mKeyToId.find(i);
+ if (it != mKeyToId.end())
+ return it->second;
+
+ return InputAction::NO_VALUE;
+}
+
int Joystick::getButtonFromEvent(const SDL_Event &event) const
{
- if (event.jbutton.which != mNumber)
+ if (event.type == SDL_JOYBUTTONDOWN)
+ {
+ if (event.jbutton.which != mNumber)
+ return -1;
+ return event.jbutton.button;
+ }
+ if (!mUseHatForMovement && event.type == SDL_JOYHATMOTION)
+ {
+ // reading only hat 0
+ if (event.jhat.which != mNumber || event.jhat.hat != 0)
+ return -1;
+ const int value = event.jhat.value;
+ // SDL reports new hat position, not when d-pad button is pressed.
+ // because of that we have to compare it to previously known state.
+ if ((mHatPosition & UP) == 0 && (value & SDL_HAT_UP) != 0)
+ return KEY_UP;
+ if ((mHatPosition & DOWN) == 0 && (value & SDL_HAT_DOWN) != 0)
+ return KEY_DOWN;
+ if ((mHatPosition & LEFT) == 0 && (value & SDL_HAT_LEFT) != 0)
+ return KEY_LEFT;
+ if ((mHatPosition & RIGHT) == 0 && (value & SDL_HAT_RIGHT) != 0)
+ return KEY_RIGHT;
+ }
+ if (event.type == SDL_JOYAXISMOTION)
+ {
+ if (event.jaxis.which != mNumber)
+ return -1;
+ const int axis = event.jaxis.axis;
+ if (axis < RESERVED_AXES)
+ return -1;
+ int position = event.jaxis.value;
+ // transform range [SDL_JOYSTICK_AXIS_MIN, SDL_JOYSTICK_AXIS_MAX]
+ // to [0, SDL_JOYSTICK_AXIS_MAX]
+ if (mIsTrigger[axis])
+ position = (position - SDL_JOYSTICK_AXIS_MIN) / 2;
+ if (position < mTolerance * SDL_JOYSTICK_AXIS_MIN
+ && mAxesPositions[axis] > mTolerance * SDL_JOYSTICK_AXIS_MIN)
+ return KEY_NEGATIVE_AXIS_FIRST + axis;
+ if (position > mTolerance * SDL_JOYSTICK_AXIS_MAX
+ && mAxesPositions[axis] < mTolerance * SDL_JOYSTICK_AXIS_MAX)
+ return KEY_POSITIVE_AXIS_FIRST + axis;
+ }
+ return -1;
+}
+
+int Joystick::getButton(const int key) const
+{
+ if (key < 0
+ || (mButtonsNumber <= key && key < MAX_BUTTONS)
+ || (mUseHatForMovement && key >= MAX_BUTTONS)
+ || key >= KEY_NEGATIVE_AXIS_FIRST)
+ {
+ return -1;
+ }
+ return key;
+}
+
+int Joystick::getNegativeAxis(const int key) const
+{
+ if (key < KEY_NEGATIVE_AXIS_FIRST || key >= KEY_POSITIVE_AXIS_FIRST)
+ return -1;
+
+ const int axis = key - KEY_NEGATIVE_AXIS_FIRST;
+ if (axis < RESERVED_AXES || axis >= mAxesNumber)
+ return -1;
+
+ return axis;
+}
+
+int Joystick::getPositiveAxis(const int key) const
+{
+ if (key < KEY_POSITIVE_AXIS_FIRST || key >= KEY_END)
return -1;
- return event.jbutton.button;
+
+ const int axis = key - KEY_POSITIVE_AXIS_FIRST;
+ if (axis < RESERVED_AXES || axis >= mAxesNumber)
+ return -1;
+
+ return axis;
}
bool Joystick::isActionActive(const InputActionT index) const
@@ -417,19 +511,14 @@ bool Joystick::isActionActive(const InputActionT index) const
const InputItem &val = key.values[i];
if (val.type != InputType::JOYSTICK)
continue;
- const int value = val.value;
- if (value >= 0 && value < mButtonsNumber)
- {
- if (mActiveButtons[value])
- return true;
- }
+ return buttonPressed(val.value);
}
return false;
}
bool Joystick::validate() const
{
- if (mCalibrating || !mEnabled || !mCalibrated)
+ if (!mEnabled)
return false;
return mUseInactive ||
@@ -441,14 +530,8 @@ void Joystick::handleRepeat(const int time)
BLOCK_START("Joystick::handleRepeat")
FOR_EACH (KeyTimeMapIter, it, mKeyTimeMap)
{
- bool repeat(false);
const int key = (*it).first;
- if (key >= 0 && key < mButtonsNumber)
- {
- if (mActiveButtons[key])
- repeat = true;
- }
- if (repeat)
+ if (buttonPressed(key))
{
int &keyTime = (*it).second;
if (time > keyTime && abs(time - keyTime)