diff --git a/32blit-sdl/Input.cpp b/32blit-sdl/Input.cpp index 946bcada8..c1d65f0e8 100644 --- a/32blit-sdl/Input.cpp +++ b/32blit-sdl/Input.cpp @@ -68,6 +68,25 @@ int Input::find_button(int button) { } Input::Input(System *target) : target(target) { + // Open all joysticks as game controllers + for(int n = 0; n < SDL_NumJoysticks(); n++) { + + if(SDL_IsGameController(n)) { + + auto gc = SDL_GameControllerOpen(n); + if(gc != nullptr) { + _add_controller(gc); + } + } + } +} + +Input::~Input() { + for (auto gc : game_controllers) + { + _remove_controller(gc.gc_id); + } + game_controllers.clear(); } bool Input::handle_mouse(int button, bool state, int x, int y) { @@ -132,6 +151,34 @@ bool Input::handle_controller_motion(int axis, int value) { return false; } +void Input::handle_controller_added(Sint32 joystick_index) { + + SDL_GameController* gc = SDL_GameControllerOpen(joystick_index); + if (gc != nullptr) { + _add_controller(gc); + } +} + +void Input::handle_controller_removed(Sint32 joystick_index) { + + auto gc_removed = SDL_GameControllerFromInstanceID(joystick_index); + if(gc_removed != nullptr) { + _remove_controller(gc_removed); + } +} + +void Input::rumble_controllers(const float& volume) { + + if(volume > 0) { + for (auto gc : game_controllers) { + if(gc.can_rumble) { + auto frequency = volume * 0xFFFF; + SDL_GameControllerRumble(gc.gc_id, frequency, frequency, 50); + } + } + } +} + void Input::_virtual_tilt(int x, int y, int half_w, int half_h) { float z = 80.0f; x = x - half_w; @@ -149,3 +196,21 @@ void Input::_virtual_analog(int x, int y, int half_w, int half_h) { target->set_joystick(0, jx); target->set_joystick(1, jy); } + +void Input::_add_controller(SDL_GameController* gc) { + // welcome rumble to test if it can rumble + auto can_rumble = SDL_GameControllerRumble(gc, 0xFFFF, 0xFFFF, 200); + + GameController gcs = {gc, can_rumble == 0}; + game_controllers.push_back(gcs); +} + +void Input::_remove_controller(SDL_GameController* gc) { + game_controllers.erase( + std::remove_if(game_controllers.begin(), game_controllers.end(), [&](GameController const & controller) { + return controller.gc_id == gc; + }), + game_controllers.end()); + + SDL_GameControllerClose(gc); +} diff --git a/32blit-sdl/Input.hpp b/32blit-sdl/Input.hpp index 5e80c2eb2..8cfecb269 100644 --- a/32blit-sdl/Input.hpp +++ b/32blit-sdl/Input.hpp @@ -1,15 +1,24 @@ #include +#include +#include class System; +struct GameController +{ + SDL_GameController* gc_id; + bool can_rumble; +}; + class Input { public: static std::map keys; static std::map buttons; - static int find_key(int key); + static int find_key(int key); static int find_button(int button); - Input(System *system); + explicit Input(System *system); + ~Input(); // Input handlers return true if they handled the event bool handle_mouse(int button, bool state, int x, int y); @@ -17,11 +26,22 @@ class Input { bool handle_controller_button(int button, bool state); bool handle_controller_motion(int axis, int value); - private: + // controller specific functions + void handle_controller_added(Sint32 joystick_index); + void handle_controller_removed(Sint32 joystick_index); + + void rumble_controllers(const float& volume); + +private: System *target; - void _virtual_analog(int, int, int, int); + std::vector game_controllers; + + void _virtual_analog(int, int, int, int); void _virtual_tilt(int, int, int, int); + void _add_controller(SDL_GameController* gc); + void _remove_controller(SDL_GameController* gc); + bool left_ctrl = false; }; diff --git a/32blit-sdl/Main.cpp b/32blit-sdl/Main.cpp index bf79075e0..c043fb0ef 100644 --- a/32blit-sdl/Main.cpp +++ b/32blit-sdl/Main.cpp @@ -88,11 +88,11 @@ void handle_event(SDL_Event &event) { break; case SDL_CONTROLLERDEVICEADDED: - SDL_GameControllerOpen(event.cdevice.which); + blit_input->handle_controller_added(event.cdevice.which); break; case SDL_CONTROLLERDEVICEREMOVED: - SDL_GameControllerClose(SDL_GameControllerFromInstanceID(event.cdevice.which)); + blit_input->handle_controller_removed(event.cdevice.which); break; case SDL_RENDER_TARGETS_RESET: @@ -233,13 +233,8 @@ int main(int argc, char *argv[]) { SDL_SetWindowPosition(window, x, y); } - // Open all joysticks as game controllers - for(int n=0; nstop(); delete blit_system; + delete blit_input; delete blit_multiplayer; delete blit_renderer; diff --git a/32blit-sdl/System.cpp b/32blit-sdl/System.cpp index b58df1501..2687ae117 100644 --- a/32blit-sdl/System.cpp +++ b/32blit-sdl/System.cpp @@ -5,6 +5,7 @@ #include "File.hpp" #include "System.hpp" +#include "Input.hpp" #include "32blit.hpp" #include "UserCode.hpp" #include "JPEG.hpp" @@ -12,6 +13,8 @@ #include "engine/api_private.hpp" +extern Input *blit_input; + // blit framebuffer memory static uint8_t framebuffer[320 * 240 * 3]; static blit::Pen palette[256]; @@ -303,7 +306,8 @@ void System::loop() blit::joystick.y = shadow_joystick[1]; SDL_UnlockMutex(m_input); blit::tick(::now()); - blit::render(::now()); + blit_input->rumble_controllers(blit::vibration); + blit::render(::now()); blit_multiplayer->update(); }