blawar / ooot

GNU General Public License v2.0
698 stars 92 forks source link

Added basic support for detecting when controllers are connected and disconnected #332

Closed faha223 closed 2 years ago

blawar commented 2 years ago

This is close, however I presume there would be a bug if a controller is connected, disconnected, and then reconnected as the controller objects are never freed or reset (scan was only designed to be called once).

you should modify the scan method in the controller SDL controller class to check if the controller index (represented by the variable "i" in that method) is already present in the m_controllers vector, and if so skip it:

https://github.com/blawar/ooot/blob/dev/src/port/controller/sdl.cpp#L500

blawar commented 2 years ago

Another possibility, which would solve the disconnect problem, would be to just add a new method to the Players class called detachAll() which would just loop through each player in object in m_players, calling Player::detachControllers(). After you did that, you could run call scan like you're doing now if you mdoify scan to resize the m_controllers vector to 0 at the beginning of every call.

faha223 commented 2 years ago

I like that suggestion. I was thinking it might also be a good idea to pause the game in the event that the controller becomes disconnected, but in that case it might be best to ensure that this only happens if the specific controller that was disconnected was the one that the player was using and no other controller has become assigned to the player.

faha223 commented 2 years ago

I tried detaching all, and that caused the keyboard to get detached as well. So that seemed a bit heavy-handed. Instead I decided to implement a rescan method on the SDL driver class that clears out all the existing SDL controllers from both the driver's m_controllers collection as well as the players. Then it calls scan like before. This seems to work well and doesn't leave lingering duplicates.

blawar commented 2 years ago

You can’t dynamically cast the driver to sdl, sometimes it’s not SDL. I’m not sure rescan is needed, why not just perform your logic in the scan() call?

faha223 commented 2 years ago

I don't have a good reason not to perform that logic in the scan() call.

I used dynamic_cast to safely cast from a Driver pointer to an SDL pointer. If the driver isn't SDL then it returns null. If you'd prefer that I just call oot::hid::controllers().scan() then that's ok, but I was trying to avoid calling scan on drivers other than the SDL one.

blawar commented 2 years ago

Just call scan(), individual drivers can check themselves if it’s a rescan or not.

xoascf commented 2 years ago

The changes to this pull request have already been incorporated in #333.