Added hot-pluggability for controllers.

Fixed loss of controller after a game has been run when unloadSDL = true.
This commit is contained in:
Pieter Hulshoff 2017-07-14 13:09:16 +02:00
parent 9c099a8997
commit 3486226798
7 changed files with 96 additions and 34 deletions

View File

@ -16,7 +16,7 @@ void JoyAxisHandler::reset()
bool JoyAxisHandler::update(SDL_Event &e)
{
if(e.type != SDL_JOYAXISMOTION || e.jaxis.which != joyid_ || e.jaxis.axis != axis_) return false;
if(e.type != SDL_JOYAXISMOTION || (joyid_ != -1 && e.jaxis.which != joyid_) || e.jaxis.axis != axis_) return false;
pressed_ = (min_ <= e.jaxis.value && e.jaxis.value <= max_);
return true;

View File

@ -16,7 +16,7 @@ bool JoyButtonHandler::update(SDL_Event &e)
{
if(e.type != SDL_JOYBUTTONUP && e.type != SDL_JOYBUTTONDOWN) return false;
if(e.jbutton.which == joynum_ && e.jbutton.button == button_)
if((joynum_ == -1 || e.jbutton.which == joynum_) && e.jbutton.button == button_)
{
pressed_ = (e.type == SDL_JOYBUTTONDOWN) ? true : false;
return true;

View File

@ -15,7 +15,7 @@ void JoyHatHandler::reset()
bool JoyHatHandler::update(SDL_Event &e)
{
if(e.type != SDL_JOYHATMOTION || e.jhat.which != joynum_ || e.jhat.hat != hatnum_) return false;
if(e.type != SDL_JOYHATMOTION || (joynum_ != -1 && e.jhat.which != joynum_) || e.jhat.hat != hatnum_) return false;
pressed_ = (e.jhat.value == direction_);
return true;

View File

@ -32,6 +32,10 @@ UserInput::UserInput(Configuration &c)
currentKeyState_[i] = false;
lastKeyState_[i] = false;
}
for ( unsigned int i = 0; i < cMaxJoy; i++ )
{
joysticks_[i] = -1;
}
}
UserInput::~UserInput()
@ -43,15 +47,6 @@ UserInput::~UserInput()
delete keyHandlers_[i].first;
}
}
// This code causes an exception when a controller is attached; it's disabled to prevent crashes on exit.
// for(std::vector<SDL_Joystick *>::iterator it = joysticks_.begin(); it != joysticks_.end(); it++)
// {
// if(*it)
// {
// SDL_JoystickClose(*it);
// }
// }
}
bool UserInput::initialize()
@ -93,12 +88,6 @@ bool UserInput::initialize()
// retVal = MapKey("admin", KeyCodeAdminMode) && retVal;
// retVal = MapKey("remove", KeyCodeHideItem) && retVal;
for(int i = 0; i < SDL_NumJoysticks(); ++i)
{
joysticks_.push_back(SDL_JoystickOpen(i));
}
return retVal;
}
@ -167,12 +156,18 @@ bool UserInput::MapKey(std::string keyDescription, KeyCode_E key, bool required)
else if (token.find("joy") == 0)
{
std::string joydesc = Utils::replace(Utils::toLower(token), "joy", "");
std::stringstream ssjoy;
ssjoy << joydesc.at(0);
int joynum;
ssjoy >> joynum;
joydesc = joydesc.erase(0, 1);
if ( std::isdigit( joydesc.at( 0 ) ) )
{
std::stringstream ssjoy;
ssjoy << joydesc.at(0);
ssjoy >> joynum;
joydesc = joydesc.erase(0, 1);
}
else
{
joynum = -1;
}
if (joydesc.find("button") == 0)
{
@ -271,27 +266,76 @@ void UserInput::resetStates()
}
}
bool UserInput::update(SDL_Event &e)
bool UserInput::update( SDL_Event &e )
{
bool updated = false;
memcpy(lastKeyState_, currentKeyState_, sizeof(lastKeyState_));
memset(currentKeyState_, 0, sizeof(currentKeyState_));
memcpy( lastKeyState_, currentKeyState_, sizeof( lastKeyState_ ) );
memset( currentKeyState_, 0, sizeof( currentKeyState_ ) );
for (unsigned int i = 0; i < keyHandlers_.size(); ++i)
// Handle adding a joystick
if ( e.type == SDL_JOYDEVICEADDED )
{
SDL_JoystickID id = SDL_JoystickInstanceID( SDL_JoystickOpen( e.jdevice.which ) );
for ( unsigned int i = 0; i < cMaxJoy; i++ )
{
if ( joysticks_[i] == -1 )
{
joysticks_[i] = id;
break;
}
}
}
// Handle removing a joystick
if ( e.type == SDL_JOYDEVICEREMOVED )
{
for ( unsigned int i = 0; i < cMaxJoy; i++ )
{
if ( joysticks_[i] == e.jdevice.which )
{
joysticks_[i] = -1;
break;
}
}
SDL_JoystickClose( SDL_JoystickFromInstanceID( e.jdevice.which ) );
}
// Remap joystick events
if ( e.type == SDL_JOYAXISMOTION ||
e.type == SDL_JOYBUTTONUP ||
e.type == SDL_JOYBUTTONDOWN ||
e.type == SDL_JOYHATMOTION )
{
for ( unsigned int i = 0; i < cMaxJoy; i++ )
{
if ( joysticks_[i] == e.jdevice.which )
{
e.jdevice.which = i;
e.jaxis.which = i;
e.jbutton.which = i;
e.jhat.which = i;
break;
}
}
}
for ( unsigned int i = 0; i < keyHandlers_.size( ); ++i )
{
InputHandler *h = keyHandlers_[i].first;
if(h)
if ( h )
{
if(h->update(e)) updated = true;
if ( h->update( e ) ) updated = true;
currentKeyState_[keyHandlers_[i].second] |= h->pressed();
currentKeyState_[keyHandlers_[i].second] |= h->pressed( );
}
}
return updated;
}
bool UserInput::keystate(KeyCode_E code)
{
return currentKeyState_[code];
@ -302,3 +346,11 @@ bool UserInput::newKeyPressed(KeyCode_E code)
return currentKeyState_[code] && !lastKeyState_[code];
}
void UserInput::clearJoysticks( )
{
for ( unsigned int i = 0; i < cMaxJoy; i++ )
{
joysticks_[i] = -1;
}
}

View File

@ -20,6 +20,8 @@
#include <string>
#include <vector>
const int cMaxJoy = 4;
class Configuration;
class InputHandler;
@ -58,12 +60,13 @@ public:
bool update(SDL_Event &e);
bool keystate(KeyCode_E);
bool newKeyPressed(KeyCode_E code);
void clearJoysticks( );
private:
bool MapKey(std::string keyDescription, KeyCode_E key);
bool MapKey(std::string keyDescription, KeyCode_E key, bool required);
Configuration &config_;
std::vector<SDL_Joystick *> joysticks_;
SDL_JoystickID joysticks_[cMaxJoy];
std::vector<std::pair<InputHandler *, KeyCode_E> > keyHandlers_;
bool lastKeyState_[KeyCodeMax];
bool currentKeyState_[KeyCodeMax];

View File

@ -159,9 +159,15 @@ void RetroFE::launchExit( )
SDL_RaiseWindow( SDL::getWindow( ) );
SDL_SetWindowGrab( SDL::getWindow( ), SDL_TRUE );
// Empty event queue
// Empty event queue, but handle joystick add/remove events
SDL_Event e;
while ( SDL_PollEvent( &e ) );
while ( SDL_PollEvent( &e ) )
{
if ( e.type == SDL_JOYDEVICEADDED || e.type == SDL_JOYDEVICEREMOVED )
{
input_.update( e );
}
}
input_.resetStates( );
attract_.reset( );
@ -189,6 +195,7 @@ void RetroFE::freeGraphicsMemory( )
{
currentPage_->deInitializeFonts( );
SDL::deInitialize( );
input_.clearJoysticks( );
}
}

View File

@ -21,7 +21,7 @@
std::string retrofe_version_major = "0";
std::string retrofe_version_minor = "8";
std::string retrofe_version_build = "12";
std::string retrofe_version_build = "13";
std::string Version::getString( )