From c80176d20aa017723f36edd788cae685965f97c2 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Tue, 7 Jul 2020 22:30:25 +0200 Subject: [PATCH] preliminary support for joystick POV-hats --- Aquaria/AquariaMenuItem.cpp | 15 ++++- Aquaria/Avatar.cpp | 67 ++++++++++----------- Aquaria/Avatar.h | 2 +- BBGE/ActionInput.cpp | 75 +++++++++++++++++++++++- BBGE/ActionStatus.cpp | 113 ++++++++++++++++++++++-------------- BBGE/ActionStatus.h | 18 +++++- BBGE/Joystick.cpp | 23 +++++++- BBGE/Joystick.h | 13 ++++- 8 files changed, 243 insertions(+), 83 deletions(-) diff --git a/Aquaria/AquariaMenuItem.cpp b/Aquaria/AquariaMenuItem.cpp index 043b0b0..f80619c 100644 --- a/Aquaria/AquariaMenuItem.cpp +++ b/Aquaria/AquariaMenuItem.cpp @@ -867,7 +867,7 @@ void AquariaKeyConfig::onUpdate(float dt) } if(!ac) - for(int i = 0; i < MAX_JOYSTICK_AXIS; ++i) + for(size_t i = 0; i < MAX_JOYSTICK_AXIS; ++i) { float ax = j->getAxisUncalibrated(i); if(fabsf(ax) > JOY_AXIS_THRESHOLD) @@ -878,6 +878,19 @@ void AquariaKeyConfig::onUpdate(float dt) break; } } + + if(!ac) + for(size_t i = 0; i < MAX_JOYSTICK_HATS; ++i) + { + JoyHatDirection hd = j->getHat(i); + if(hd != JOY_HAT_DIR_CENTERED) + { + ac = joyHatToActionButton(i, hd); + while (j->getHat(i) != JOY_HAT_DIR_CENTERED) + dsq->run(0.1f, true); + break; + } + } } else clear = true; diff --git a/Aquaria/Avatar.cpp b/Aquaria/Avatar.cpp index d5016e8..8391c76 100644 --- a/Aquaria/Avatar.cpp +++ b/Aquaria/Avatar.cpp @@ -4169,48 +4169,49 @@ void Avatar::startWallBurst(bool useCursor) } } -Vector Avatar::getKeyDir() +bool Avatar::isActionAndGetDir(Vector& dir) { - Vector dir; - if (isActing(ACTION_SWIMLEFT, -1)) - dir += Vector(-1,0); - if (isActing(ACTION_SWIMRIGHT, -1)) - dir += Vector(1,0); - if (isActing(ACTION_SWIMUP, -1)) - dir += Vector(0,-1); - if (isActing(ACTION_SWIMDOWN, -1)) - dir += Vector(0,1); + bool dL = isActing(ACTION_SWIMLEFT, -1); + bool dR = isActing(ACTION_SWIMRIGHT, -1); + bool dU = isActing(ACTION_SWIMUP, -1); + bool dD = isActing(ACTION_SWIMDOWN, -1); + Vector a; + if (dL) + a += Vector(-1,0); + if (dR) + a += Vector(1,0); + if (dU) + a += Vector(0,-1); + if (dD) + a += Vector(0,1); - if (dir.x != 0 && dir.y != 0) - dir/=2; + if ((dL || dR) && (dU || dD)) + a *= 0.70710678f; // 1 / sqrt(2) - return dir; + dir += a; + return dL || dR || dU || dD; } Vector Avatar::getFakeCursorPosition() { - if (dsq->getInputMode() == INPUT_KEYBOARD) - { - return getKeyDir() * 350; - } - if (dsq->getInputMode() == INPUT_JOYSTICK) - { - float axisInput = 0; - Joystick *j = 0; - for(size_t i = 0; i < core->getNumJoysticks(); ++i) - if( ((j = core->getJoystick(i))) ) - if(j->isEnabled()) + Vector dir; + if(isActionAndGetDir(dir)) + return dir * 350; + + for(size_t i = 0; i < core->getNumJoysticks(); ++i) + if(Joystick *j = core->getJoystick(i)) + if(j->isEnabled()) + { + float axisInput = j->position.getLength2D(); + if(axisInput >= JOYSTICK_LOW_THRESHOLD) { - axisInput = j->position.getLength2D(); - if(axisInput >= JOYSTICK_LOW_THRESHOLD) - { - const float axisMult = (maxMouse - minMouse) / (JOYSTICK_HIGH_THRESHOLD - JOYSTICK_LOW_THRESHOLD); - const float distance = minMouse + ((axisInput - JOYSTICK_LOW_THRESHOLD) * axisMult); - return (j->position * (distance / axisInput)); - } + const float axisMult = (maxMouse - minMouse) / (JOYSTICK_HIGH_THRESHOLD - JOYSTICK_LOW_THRESHOLD); + const float distance = minMouse + ((axisInput - JOYSTICK_LOW_THRESHOLD) * axisMult); + return (j->position * (distance / axisInput)); } - } - return Vector(0,0,0); + } + + return dir; } Vector Avatar::getVectorToCursorFromScreenCentre() diff --git a/Aquaria/Avatar.h b/Aquaria/Avatar.h index 9d1e14e..1321bc8 100644 --- a/Aquaria/Avatar.h +++ b/Aquaria/Avatar.h @@ -175,7 +175,7 @@ public: void clearTargets(); bool singing; - Vector getKeyDir(); + bool isActionAndGetDir(Vector& dir); void startBurstCommon(); diff --git a/BBGE/ActionInput.cpp b/BBGE/ActionInput.cpp index 36377b5..8264c6f 100644 --- a/BBGE/ActionInput.cpp +++ b/BBGE/ActionInput.cpp @@ -64,6 +64,34 @@ static std::string inputcode2string(int k) os << "AX:-" << (k - JOY_AXIS_0_NEG); return os.str(); } + + if(k >= JOY_HAT_BEGIN && k < JOY_HAT_END) + { + if(k >= JOY_HAT_0_LEFT && k < JOY_HAT_END_LEFT) + { + std::ostringstream os; + os << "HL" << (k - JOY_HAT_0_LEFT); + return os.str(); + } + else if(k >= JOY_HAT_0_RIGHT && k < JOY_HAT_END_RIGHT) + { + std::ostringstream os; + os << "HR" << (k - JOY_HAT_0_RIGHT); + return os.str(); + } + else if(k >= JOY_HAT_0_UP && k < JOY_HAT_END_UP) + { + std::ostringstream os; + os << "HU" << (k - JOY_HAT_0_UP); + return os.str(); + } + else if(k >= JOY_HAT_0_DOWN && k < JOY_HAT_END_DOWN) + { + std::ostringstream os; + os << "HD" << (k - JOY_HAT_0_DOWN); + return os.str(); + } + } switch(k) { @@ -134,15 +162,44 @@ std::string getInputCodeToUserString(unsigned int k, size_t joystickID) else if(k >= JOY_BUTTON_0 && k < JOY_BUTTON_END) pretty = jbtnname(joystickID, k - JOY_BUTTON_0); + std::string s; if(pretty && *pretty) { - std::string s = pretty; + s = pretty; if(tail) s += tail; return s; } - std::string s = inputcode2string(k); + if(k >= JOY_HAT_BEGIN && k < JOY_HAT_END) + { + if(k >= JOY_HAT_0_LEFT && k < JOY_HAT_END_LEFT) + { + std::ostringstream os; + os << "H" << (k - JOY_HAT_0_LEFT) << "<"; + return os.str(); + } + else if(k >= JOY_HAT_0_RIGHT && k < JOY_HAT_END_RIGHT) + { + std::ostringstream os; + os << "H" << (k - JOY_HAT_0_RIGHT) << ">"; + return os.str(); + } + else if(k >= JOY_HAT_0_UP && k < JOY_HAT_END_UP) + { + std::ostringstream os; + os << "H" << (k - JOY_HAT_0_UP) << "^"; + return os.str(); + } + else if(k >= JOY_HAT_0_DOWN && k < JOY_HAT_END_DOWN) + { + std::ostringstream os; + os << "H" << (k - JOY_HAT_0_DOWN) << "v"; + return os.str(); + } + } + + s = inputcode2string(k); return s.empty() ? stringbank.get(SB_BBGE_NO_KEY) : s; } @@ -190,6 +247,20 @@ int getStringToInputCode(const std::string& s) return 0; } } + else if(s.length() > 2 && s[0] == 'H') // joystick hat + { + JoyHatDirection hd; + switch(s[1]) + { + case 'L': hd = JOY_HAT_DIR_LEFT; break; + case 'R': hd = JOY_HAT_DIR_RIGHT; break; + case 'U': hd = JOY_HAT_DIR_UP; break; + case 'D': hd = JOY_HAT_DIR_DOWN; break; + default: return 0; + } + unsigned hatID = atoi(s.c_str() + 2); + return joyHatToActionButton(hatID, hd); + } else { // Maybe we're upgrading from an old config? diff --git a/BBGE/ActionStatus.cpp b/BBGE/ActionStatus.cpp index 5d559cd..ec23836 100644 --- a/BBGE/ActionStatus.cpp +++ b/BBGE/ActionStatus.cpp @@ -73,51 +73,78 @@ void ActionButtonStatus::_queryAllStatus() bool ActionButtonStatus::_queryStatus(int k) const { - bool keyState = false; if (k > 0 && k < KEY_MAXARRAY) + return core->getKeyState(k); + + if (k == MOUSE_BUTTON_LEFT) + return core->mouse.buttons.left == DOWN; + + if (k == MOUSE_BUTTON_RIGHT) + return core->mouse.buttons.right == DOWN; + + if (k == MOUSE_BUTTON_MIDDLE) + return core->mouse.buttons.middle == DOWN; + + if (k >= MOUSE_BUTTON_EXTRA_START && k < MOUSE_BUTTON_EXTRA_END) + return core->mouse.buttons.extra[k - MOUSE_BUTTON_EXTRA_START]; + + // --- joystick from here --- + + Joystick *j = core->getJoystick(joystickID); + if(!j || !j->isEnabled()) + return false; + + if (k >= JOY_BUTTON_0 && k < JOY_BUTTON_END) + return j->getButton(k - JOY_BUTTON_0); + + if (k >= JOY_AXIS_0_POS && k < JOY_AXIS_END_POS) { - keyState = core->getKeyState(k); - } - else if (k == MOUSE_BUTTON_LEFT) - { - keyState = core->mouse.buttons.left == DOWN; - } - else if (k == MOUSE_BUTTON_RIGHT) - { - keyState = core->mouse.buttons.right == DOWN; - } - else if (k == MOUSE_BUTTON_MIDDLE) - { - keyState = core->mouse.buttons.middle == DOWN; - } - else if (k >= MOUSE_BUTTON_EXTRA_START && k < MOUSE_BUTTON_EXTRA_END) - { - keyState = core->mouse.buttons.extra[k - MOUSE_BUTTON_EXTRA_START]; - } - else if (k >= JOY_BUTTON_0 && k < JOY_BUTTON_END) - { - Joystick *j = core->getJoystick(joystickID); - if(j && j->isEnabled()) - keyState = j->getButton(k - JOY_BUTTON_0); - } - else if (k >= JOY_AXIS_0_POS && k < JOY_AXIS_END_POS) - { - Joystick *j = core->getJoystick(joystickID); - if(j && j->isEnabled()) - { - float ax = j->getAxisUncalibrated(k - JOY_AXIS_0_POS); - keyState = ax > JOY_AXIS_THRESHOLD; - } - } - else if (k >= JOY_AXIS_0_NEG && k < JOY_AXIS_END_NEG) - { - Joystick *j = core->getJoystick(joystickID); - if(j && j->isEnabled()) - { - float ax = j->getAxisUncalibrated(k - JOY_AXIS_0_NEG); - keyState = ax < -JOY_AXIS_THRESHOLD; - } + float ax = j->getAxisUncalibrated(k - JOY_AXIS_0_POS); + return ax > JOY_AXIS_THRESHOLD; } - return keyState; + if (k >= JOY_AXIS_0_NEG && k < JOY_AXIS_END_NEG) + { + float ax = j->getAxisUncalibrated(k - JOY_AXIS_0_NEG); + return ax < -JOY_AXIS_THRESHOLD; + } + + if(k >= JOY_HAT_BEGIN && k < JOY_HAT_END) + { + if (k >= JOY_HAT_0_LEFT && k < JOY_HAT_END_LEFT) + return j->getHat(k - JOY_HAT_0_LEFT); + + if (k >= JOY_HAT_0_RIGHT && k < JOY_HAT_END_RIGHT) + return j->getHat(k - JOY_HAT_0_RIGHT); + + if (k >= JOY_HAT_0_UP && k < JOY_HAT_END_UP) + return j->getHat(k - JOY_HAT_0_UP); + + if (k >= JOY_HAT_0_DOWN && k < JOY_HAT_END_DOWN) + return j->getHat(k - JOY_HAT_0_DOWN); + } + + return false; } + +ActionButtonType joyHatToActionButton(unsigned hatID, JoyHatDirection dir) +{ + unsigned ret = 0; + if(hatID < MAX_JOYSTICK_HATS) + { + if(dir & JOY_HAT_DIR_LEFT) + ret = JOY_HAT_0_LEFT; + else if(dir & JOY_HAT_DIR_RIGHT) + ret = JOY_HAT_0_RIGHT; + else if(dir & JOY_HAT_DIR_UP) + ret = JOY_HAT_0_UP; + else if(dir & JOY_HAT_DIR_DOWN) + ret = JOY_HAT_0_DOWN; + + if(ret) + ret += hatID; + } + + return (ActionButtonType)ret; +} + diff --git a/BBGE/ActionStatus.h b/BBGE/ActionStatus.h index 863fa1b..6f17fff 100644 --- a/BBGE/ActionStatus.h +++ b/BBGE/ActionStatus.h @@ -26,9 +26,25 @@ enum ActionButtonType JOY_AXIS_0_NEG = JOY_AXIS_END_POS, JOY_AXIS_END_NEG = JOY_AXIS_0_NEG + MAX_JOYSTICK_AXIS, - ACTION_BUTTON_ENUM_SIZE = JOY_AXIS_END_NEG + JOY_HAT_BEGIN = JOY_AXIS_END_NEG, + JOY_HAT_0_LEFT = JOY_HAT_BEGIN, + JOY_HAT_END_LEFT = JOY_HAT_0_LEFT + MAX_JOYSTICK_HATS, + + JOY_HAT_0_RIGHT = JOY_HAT_END_LEFT, + JOY_HAT_END_RIGHT = JOY_HAT_0_RIGHT + MAX_JOYSTICK_HATS, + + JOY_HAT_0_UP = JOY_HAT_END_RIGHT, + JOY_HAT_END_UP = JOY_HAT_0_UP + MAX_JOYSTICK_HATS, + + JOY_HAT_0_DOWN = JOY_HAT_END_UP, + JOY_HAT_END_DOWN = JOY_HAT_0_DOWN + MAX_JOYSTICK_HATS, + JOY_HAT_END = JOY_HAT_END_DOWN, + + ACTION_BUTTON_ENUM_SIZE = JOY_HAT_END }; +ActionButtonType joyHatToActionButton(unsigned hatID, JoyHatDirection dir); + class ActionButtonStatus { public: diff --git a/BBGE/Joystick.cpp b/BBGE/Joystick.cpp index b1f4c14..373d28c 100644 --- a/BBGE/Joystick.cpp +++ b/BBGE/Joystick.cpp @@ -334,11 +334,32 @@ unsigned Joystick::getNumHats() const return numHats; } -float Joystick::getAxisUncalibrated(int id) const +float Joystick::getAxisUncalibrated(unsigned id) const { return id < MAX_JOYSTICK_AXIS ? axisRaw[id] : 0.0f; } +JoyHatDirection Joystick::getHat(unsigned id) const +{ + unsigned dir = SDL_JoystickGetHat(sdl_joy, id); + unsigned ret = JOY_HAT_DIR_CENTERED; + switch(dir) + { + case SDL_HAT_UP: ret = JOY_HAT_DIR_UP; break; + case SDL_HAT_DOWN: ret = JOY_HAT_DIR_DOWN; break; + case SDL_HAT_LEFT: ret = JOY_HAT_DIR_LEFT; break; + case SDL_HAT_RIGHT: ret = JOY_HAT_DIR_RIGHT; break; + + case SDL_HAT_LEFTUP: ret = JOY_HAT_DIR_UP | JOY_HAT_DIR_LEFT; break; + case SDL_HAT_RIGHTUP: ret = JOY_HAT_DIR_UP | JOY_HAT_DIR_RIGHT; break; + case SDL_HAT_LEFTDOWN: ret = JOY_HAT_DIR_DOWN | JOY_HAT_DIR_LEFT; break; + case SDL_HAT_RIGHTDOWN: ret = JOY_HAT_DIR_DOWN | JOY_HAT_DIR_RIGHT; break; + + default: ; + } + return (JoyHatDirection)ret; +} + const char *Joystick::getAxisName(unsigned axis) const { if(axis >= numJoyAxes) diff --git a/BBGE/Joystick.h b/BBGE/Joystick.h index be500a5..3e4bddb 100644 --- a/BBGE/Joystick.h +++ b/BBGE/Joystick.h @@ -15,6 +15,16 @@ #define MAX_JOYSTICK_AXIS 32 #define MAX_JOYSTICK_HATS 8 +enum JoyHatDirection // bitmask +{ + JOY_HAT_DIR_CENTERED = 0, + JOY_HAT_DIR_UP = 1, + JOY_HAT_DIR_DOWN = 2, + JOY_HAT_DIR_LEFT = 4, + JOY_HAT_DIR_RIGHT = 8 +}; + + const static float JOY_AXIS_THRESHOLD = 0.6f; class Joystick @@ -38,7 +48,8 @@ public: void calibrate(Vector &vec, float dead); bool anyButton() const; bool getButton(size_t id) const { return !!(buttonBitmask & (1u << id)); } - float getAxisUncalibrated(int id) const; + float getAxisUncalibrated(unsigned id) const; + JoyHatDirection getHat(unsigned id) const; unsigned getNumAxes() const; unsigned getNumButtons() const; unsigned getNumHats() const;